diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2018-12-27 17:45:04 +0000 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2018-12-27 17:45:04 +0000 |
commit | 6aa82888e61d3e2232926ee68e764f17eae2e7e1 (patch) | |
tree | 17b2fb350da15d1d097f22dc7e2e7d20db1bd486 /resolv | |
parent | ffbe9c552a1009167ec7a765c1543c7f3e4169d6 (diff) | |
parent | 963c37d5c0eb62b38f8764b23931c0dcdd497a13 (diff) |
Merge commit 'refs/top-bases/t/sendmsg-SCM_RIGHTS' into t/sendmsg-SCM_RIGHTS
Diffstat (limited to 'resolv')
91 files changed, 12576 insertions, 3797 deletions
diff --git a/resolv/Banner b/resolv/Banner deleted file mode 100644 index e585ed8532..0000000000 --- a/resolv/Banner +++ /dev/null @@ -1 +0,0 @@ -BIND-8.2.3-T5B diff --git a/resolv/Depend b/resolv/Depend index 6c1aa44e6e..ba64a2d899 100644 --- a/resolv/Depend +++ b/resolv/Depend @@ -1 +1,2 @@ nptl +htl diff --git a/resolv/Makefile b/resolv/Makefile index 8be41d3ae1..ea395ac3eb 100644 --- a/resolv/Makefile +++ b/resolv/Makefile @@ -1,4 +1,4 @@ -# Copyright (C) 1994-2016 Free Software Foundation, Inc. +# Copyright (C) 1994-2018 Free Software Foundation, Inc. # This file is part of the GNU C Library. # The GNU C Library is free software; you can redistribute it and/or @@ -22,13 +22,14 @@ subdir := resolv include ../Makeconfig -headers := resolv.h \ +headers := resolv.h bits/types/res_state.h \ netdb.h bits/netdb.h \ arpa/nameser.h arpa/nameser_compat.h \ sys/bitypes.h routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \ - res_hconf res_libc res-state + res_hconf res_libc res-state res_randomid res-close \ + resolv_context resolv_conf tests = tst-aton tst-leaks tst-inet_ntop xtests = tst-leaks2 @@ -39,14 +40,68 @@ extra-libs := libresolv libnss_dns ifeq ($(have-thread-library),yes) extra-libs += libanl routines += gai_sigqueue -tests += tst-res_hconf_reorder + +tests += \ + tst-bug18665 \ + tst-bug18665-tcp \ + tst-ns_name \ + tst-ns_name_compress \ + tst-ns_name_pton \ + tst-res_hconf_reorder \ + tst-res_hnok \ + tst-res_use_inet6 \ + tst-resolv-basic \ + tst-resolv-binary \ + tst-resolv-edns \ + tst-resolv-network \ + tst-resolv-res_init-multi \ + tst-resolv-search \ + +# These tests need libdl. +ifeq (yes,$(build-shared)) +tests += \ + tst-resolv-ai_idn \ + tst-resolv-ai_idn-latin1 \ + tst-resolv-ai_idn-nolibidn2 \ + tst-resolv-canonname \ + +# uses DEPRECATED_RES_USE_INET6 from <resolv-internal.h>. +tests-internal += \ + tst-resolv-res_init \ + tst-resolv-res_init-thread \ + +# Needs resolv_context. +tests-internal += \ + tst-resolv-res_ninit \ + tst-resolv-threads \ + +# Used by tst-resolv-ai_idn-nolibidn2 to disable libidn2 (by not +# providing any functions in libidn2.so.0). +modules-names += tst-no-libidn2 +extra-test-objs += tst-no-libidn2.os +LDFLAGS-tst-no-libidn2.so = -Wl,-soname,libidn2.so.0 + +endif # $(build-shared) + +# This test accesses __inet_ntop_length, an internal libc function. +tests-internal += tst-inet_pton + +# This test accesses the __p_secstodate compat symbol. +tests-internal += tst-p_secstodate + +# This test sends millions of packets and is rather slow. +xtests += tst-resolv-qtypes + +# This test has dropped packet tests and runs for a long time. +xtests += tst-resolv-rotate endif extra-libs-others = $(extra-libs) -libresolv-routines := gethnamaddr res_comp res_debug \ +libresolv-routines := res_comp res_debug \ res_data res_mkquery res_query res_send \ inet_net_ntop inet_net_pton inet_neta base64 \ ns_parse ns_name ns_netint ns_ttl ns_print \ - ns_samedomain ns_date + ns_samedomain ns_date \ + compat-hooks compat-gethnamaddr libanl-routines := gai_cancel gai_error gai_misc gai_notify gai_suspend \ getaddrinfo_a @@ -61,14 +116,11 @@ routines += $(libnss_dns-routines) $(libresolv-routines) static-only-routines += $(libnss_dns-routines) $(libresolv-routines) endif -ifeq (yesyes,$(build-shared)$(have-thread-library)) -tests: $(objpfx)ga_test -endif - ifeq ($(run-built-tests),yes) ifneq (no,$(PERL)) tests-special += $(objpfx)mtrace-tst-leaks.out xtests-special += $(objpfx)mtrace-tst-leaks2.out +tests-special += $(objpfx)mtrace-tst-resolv-res_ninit.out endif endif @@ -80,21 +132,15 @@ headers += rpc/netdb.h endif generated += mtrace-tst-leaks.out tst-leaks.mtrace \ - mtrace-tst-leaks2.out tst-leaks2.mtrace + mtrace-tst-leaks2.out tst-leaks2.mtrace \ + mtrace-tst-resolv-res_ninit.out tst-resolv-res_ninit.mtrace \ include ../Rules -CPPFLAGS += -Dgethostbyname=res_gethostbyname \ - -Dgethostbyname2=res_gethostbyname2 \ - -Dgethostbyaddr=res_gethostbyaddr \ - -Dgetnetbyname=res_getnetbyname \ - -Dgetnetbyaddr=res_getnetbyaddr +LOCALES := en_US.UTF-8 en_US.ISO-8859-1 +include ../gen-locales.mk -CFLAGS-libresolv += $(stack-protector) -CFLAGS-res_hconf.c = -fexceptions - -# The BIND code elicits some harmless warnings. -+cflags += -Wno-write-strings +CFLAGS-res_hconf.c += -fexceptions # The DNS NSS modules needs the resolver. $(objpfx)libnss_dns.so: $(objpfx)libresolv.so @@ -102,8 +148,6 @@ $(objpfx)libnss_dns.so: $(objpfx)libresolv.so # The asynchronous name lookup code needs the thread library. $(objpfx)libanl.so: $(shared-thread-library) -$(objpfx)ga_test: $(objpfx)libanl.so $(shared-thread-library) - $(objpfx)tst-res_hconf_reorder: $(libdl) $(shared-thread-library) tst-res_hconf_reorder-ENV = RESOLV_REORDER=on @@ -117,3 +161,50 @@ tst-leaks2-ENV = MALLOC_TRACE=$(objpfx)tst-leaks2.mtrace $(objpfx)mtrace-tst-leaks2.out: $(objpfx)tst-leaks2.out $(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@; \ $(evaluate-test) + +tst-resolv-res_ninit-ENV = MALLOC_TRACE=$(objpfx)tst-resolv-res_ninit.mtrace +$(objpfx)mtrace-tst-resolv-res_ninit.out: $(objpfx)tst-resolv-res_ninit.out + $(common-objpfx)malloc/mtrace \ + $(objpfx)tst-resolv-res_ninit.mtrace > $@; \ + $(evaluate-test) + +$(objpfx)tst-bug18665-tcp: $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-bug18665: $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-res_use_inet6: $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-resolv-ai_idn: \ + $(libdl) $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-resolv-ai_idn-latin1: \ + $(libdl) $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-resolv-ai_idn-nolibidn2: \ + $(libdl) $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-resolv-ai_idn.out: $(gen-locales) +$(objpfx)tst-resolv-ai_idn-latin1.out: $(gen-locales) +$(objpfx)tst-resolv-ai_idn-nolibidn2.out: \ + $(gen-locales) $(objpfx)tst-no-libidn2.so +$(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-resolv-binary: $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-resolv-res_init: $(libdl) $(objpfx)libresolv.so +$(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \ + $(shared-thread-library) +$(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \ + $(shared-thread-library) +$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-resolv-threads: \ + $(libdl) $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-resolv-canonname: \ + $(libdl) $(objpfx)libresolv.so $(shared-thread-library) + +$(objpfx)tst-ns_name: $(objpfx)libresolv.so +$(objpfx)tst-ns_name.out: tst-ns_name.data +$(objpfx)tst-ns_name_compress: $(objpfx)libresolv.so +$(objpfx)tst-ns_name_pton: $(objpfx)libresolv.so +$(objpfx)tst-res_hnok: $(objpfx)libresolv.so +$(objpfx)tst-p_secstodate: $(objpfx)libresolv.so + + +# This test case uses the deprecated RES_USE_INET6 resolver option. +CFLAGS-tst-res_use_inet6.c += -Wno-error diff --git a/resolv/README b/resolv/README index dbb15108ae..514e9bb617 100644 --- a/resolv/README +++ b/resolv/README @@ -18,10 +18,6 @@ Differences The resolver in the GNU C Library still differs from what's in BIND 8.2.3-T5B: -* The resolver in glibc strictly adheres to the recommendations in RFC - 1535. BIND 8.2.3-T5B seems to relax those rules a bit (see the code - that's wrapped in `#ifndef RFC1535'). - * The RES_DEBUG option (`options debug' in /etc/resolv.conf) has been disabled. @@ -84,11 +80,7 @@ code: * In Multi-threaded that manipulate the _res structure, calls to functions like `gethostbyname' in threads other than the "main" - thread won't be influenced by the those changes anymore. So if you - set RES_USE_INET6, a call to `gethostbyname' won't return any IPv6 - hosts anymore. If you recompile such programs, manipulating the - _res structure will affect the thread in which you do so instead of - the "main" thread. + thread won't be influenced by the those changes anymore. We recommend to use the new thread-safe interfaces in new code, since the traditional interfaces have been deprecated by the BIND folks. @@ -122,7 +114,6 @@ src/lib/resolv/ res_comp.c res_data.c res_debug.c - res_debug.h res_init.c res_mkquery.c res_query.c @@ -149,8 +140,7 @@ src/lib/isc/ base64.c Some of these files have been optimised a bit, and adaptations have -been made to make them fit in with the rest of glibc. The more -non-obvious changes are wrapped in something like `#ifdef _LIBC'. +been made to make them fit in with the rest of glibc. res_libc.c is home-brewn, although parts of it are taken from res_data.c. diff --git a/resolv/Versions b/resolv/Versions index e561bce1a4..b05778d965 100644 --- a/resolv/Versions +++ b/resolv/Versions @@ -26,7 +26,12 @@ libc { __h_errno; __resp; - __res_maybe_init; __res_iclose; + __res_iclose; + __inet_pton_length; + __resolv_context_get; + __resolv_context_get_preinit; + __resolv_context_get_override; + __resolv_context_put; } } @@ -78,7 +83,9 @@ libresolv { # Needed in libnss_dns. __ns_name_unpack; __ns_name_ntop; __ns_get16; __ns_get32; - __libc_res_nquery; __libc_res_nsearch; + __res_context_query; + __res_context_search; + __res_context_hostalias; } } diff --git a/resolv/arpa/nameser.h b/resolv/arpa/nameser.h index fb8513ba9b..a99d5ec508 100644 --- a/resolv/arpa/nameser.h +++ b/resolv/arpa/nameser.h @@ -45,34 +45,13 @@ * SOFTWARE. */ -/* - * $BINDId: nameser.h,v 8.37 2000/03/30 21:16:49 vixie Exp $ - */ - #ifndef _ARPA_NAMESER_H_ #define _ARPA_NAMESER_H_ -/*! \file */ - -#define BIND_4_COMPAT - #include <sys/param.h> -#if (!defined(BSD)) || (BSD < 199306) -# include <sys/bitypes.h> -#else -# include <sys/types.h> -#endif -#include <sys/cdefs.h> +#include <sys/types.h> +#include <stdint.h> -/*% - * Revision information. This is the release date in YYYYMMDD format. - * It can change every day so the right thing to do with it is use it - * in preprocessor commands such as "#if (__NAMESER > 19931104)". Do not - * compare for equality; rather, use it to determine whether your libbind.a - * contains a new enough lib/nameser/ to support the feature you need. - */ - -#define __NAMESER 19991006 /*%< New interface version stamp. */ /* * Define constants based on RFC 883, RFC 1034, RFC 1035 */ @@ -84,9 +63,9 @@ #define NS_HFIXEDSZ 12 /*%< #/bytes of fixed data in header */ #define NS_QFIXEDSZ 4 /*%< #/bytes of fixed data in query */ #define NS_RRFIXEDSZ 10 /*%< #/bytes of fixed data in r record */ -#define NS_INT32SZ 4 /*%< #/bytes of data in a u_int32_t */ -#define NS_INT16SZ 2 /*%< #/bytes of data in a u_int16_t */ -#define NS_INT8SZ 1 /*%< #/bytes of data in a u_int8_t */ +#define NS_INT32SZ 4 /*%< #/bytes of data in a uint32_t */ +#define NS_INT16SZ 2 /*%< #/bytes of data in a uint16_t */ +#define NS_INT8SZ 1 /*%< #/bytes of data in a uint8_t */ #define NS_INADDRSZ 4 /*%< IPv4 T_A */ #define NS_IN6ADDRSZ 16 /*%< IPv6 T_AAAA */ #define NS_CMPRSFLGS 0xc0 /*%< Flag bits indicating name compression. */ @@ -112,12 +91,12 @@ typedef enum __ns_sect { * leading _'s on the member names. Use the accessor functions, not the _'s. */ typedef struct __ns_msg { - const u_char *_msg, *_eom; - u_int16_t _id, _flags, _counts[ns_s_max]; - const u_char *_sections[ns_s_max]; - ns_sect _sect; - int _rrnum; - const u_char *_msg_ptr; + const unsigned char *_msg, *_eom; + uint16_t _id, _flags, _counts[ns_s_max]; + const unsigned char *_sections[ns_s_max]; + ns_sect _sect; + int _rrnum; + const unsigned char *_msg_ptr; } ns_msg; /* Private data structure - do not use from outside library. */ @@ -136,12 +115,12 @@ extern const struct _ns_flagdata _ns_flagdata[]; * This is a parsed record. It is caller allocated and has no dynamic data. */ typedef struct __ns_rr { - char name[NS_MAXDNAME]; - u_int16_t type; - u_int16_t rr_class; - u_int32_t ttl; - u_int16_t rdlength; - const u_char * rdata; + char name[NS_MAXDNAME]; + uint16_t type; + uint16_t rr_class; + uint32_t ttl; + uint16_t rdlength; + const unsigned char * rdata; } ns_rr; /* Accessor macros - this is part of the public interface. */ @@ -249,71 +228,97 @@ typedef struct ns_tcp_tsig_state ns_tcp_tsig_state; /*% * Currently defined type values for resources and queries. */ -typedef enum __ns_type { - ns_t_invalid = 0, /*%< Cookie. */ - ns_t_a = 1, /*%< Host address. */ - ns_t_ns = 2, /*%< Authoritative server. */ - ns_t_md = 3, /*%< Mail destination. */ - ns_t_mf = 4, /*%< Mail forwarder. */ - ns_t_cname = 5, /*%< Canonical name. */ - ns_t_soa = 6, /*%< Start of authority zone. */ - ns_t_mb = 7, /*%< Mailbox domain name. */ - ns_t_mg = 8, /*%< Mail group member. */ - ns_t_mr = 9, /*%< Mail rename name. */ - ns_t_null = 10, /*%< Null resource record. */ - ns_t_wks = 11, /*%< Well known service. */ - ns_t_ptr = 12, /*%< Domain name pointer. */ - ns_t_hinfo = 13, /*%< Host information. */ - ns_t_minfo = 14, /*%< Mailbox information. */ - ns_t_mx = 15, /*%< Mail routing information. */ - ns_t_txt = 16, /*%< Text strings. */ - ns_t_rp = 17, /*%< Responsible person. */ - ns_t_afsdb = 18, /*%< AFS cell database. */ - ns_t_x25 = 19, /*%< X_25 calling address. */ - ns_t_isdn = 20, /*%< ISDN calling address. */ - ns_t_rt = 21, /*%< Router. */ - ns_t_nsap = 22, /*%< NSAP address. */ - ns_t_nsap_ptr = 23, /*%< Reverse NSAP lookup (deprecated). */ - ns_t_sig = 24, /*%< Security signature. */ - ns_t_key = 25, /*%< Security key. */ - ns_t_px = 26, /*%< X.400 mail mapping. */ - ns_t_gpos = 27, /*%< Geographical position (withdrawn). */ - ns_t_aaaa = 28, /*%< Ip6 Address. */ - ns_t_loc = 29, /*%< Location Information. */ - ns_t_nxt = 30, /*%< Next domain (security). */ - ns_t_eid = 31, /*%< Endpoint identifier. */ - ns_t_nimloc = 32, /*%< Nimrod Locator. */ - ns_t_srv = 33, /*%< Server Selection. */ - ns_t_atma = 34, /*%< ATM Address */ - ns_t_naptr = 35, /*%< Naming Authority PoinTeR */ - ns_t_kx = 36, /*%< Key Exchange */ - ns_t_cert = 37, /*%< Certification record */ - ns_t_a6 = 38, /*%< IPv6 address (deprecated, use ns_t_aaaa) */ - ns_t_dname = 39, /*%< Non-terminal DNAME (for IPv6) */ - ns_t_sink = 40, /*%< Kitchen sink (experimentatl) */ - ns_t_opt = 41, /*%< EDNS0 option (meta-RR) */ - ns_t_apl = 42, /*%< Address prefix list (RFC3123) */ - ns_t_tkey = 249, /*%< Transaction key */ - ns_t_tsig = 250, /*%< Transaction signature. */ - ns_t_ixfr = 251, /*%< Incremental zone transfer. */ - ns_t_axfr = 252, /*%< Transfer zone of authority. */ - ns_t_mailb = 253, /*%< Transfer mailbox records. */ - ns_t_maila = 254, /*%< Transfer mail agent records. */ - ns_t_any = 255, /*%< Wildcard match. */ - ns_t_zxfr = 256, /*%< BIND-specific, nonstandard. */ - ns_t_max = 65536 -} ns_type; - -/* Exclusively a QTYPE? (not also an RTYPE) */ -#define ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \ - (t) == ns_t_mailb || (t) == ns_t_maila) -/* Some kind of meta-RR? (not a QTYPE, but also not an RTYPE) */ -#define ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt) -/* Exclusively an RTYPE? (not also a QTYPE or a meta-RR) */ -#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t)) -#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr) -#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \ - (t) == ns_t_zxfr) +typedef enum __ns_type + { + ns_t_invalid = 0, + + ns_t_a = 1, + ns_t_ns = 2, + ns_t_md = 3, + ns_t_mf = 4, + ns_t_cname = 5, + ns_t_soa = 6, + ns_t_mb = 7, + ns_t_mg = 8, + ns_t_mr = 9, + ns_t_null = 10, + ns_t_wks = 11, + ns_t_ptr = 12, + ns_t_hinfo = 13, + ns_t_minfo = 14, + ns_t_mx = 15, + ns_t_txt = 16, + ns_t_rp = 17, + ns_t_afsdb = 18, + ns_t_x25 = 19, + ns_t_isdn = 20, + ns_t_rt = 21, + ns_t_nsap = 22, + ns_t_nsap_ptr = 23, + ns_t_sig = 24, + ns_t_key = 25, + ns_t_px = 26, + ns_t_gpos = 27, + ns_t_aaaa = 28, + ns_t_loc = 29, + ns_t_nxt = 30, + ns_t_eid = 31, + ns_t_nimloc = 32, + ns_t_srv = 33, + ns_t_atma = 34, + ns_t_naptr = 35, + ns_t_kx = 36, + ns_t_cert = 37, + ns_t_a6 = 38, + ns_t_dname = 39, + ns_t_sink = 40, + ns_t_opt = 41, + ns_t_apl = 42, + ns_t_ds = 43, + ns_t_sshfp = 44, + ns_t_ipseckey = 45, + ns_t_rrsig = 46, + ns_t_nsec = 47, + ns_t_dnskey = 48, + ns_t_dhcid = 49, + ns_t_nsec3 = 50, + ns_t_nsec3param = 51, + ns_t_tlsa = 52, + ns_t_smimea = 53, + ns_t_hip = 55, + ns_t_ninfo = 56, + ns_t_rkey = 57, + ns_t_talink = 58, + ns_t_cds = 59, + ns_t_cdnskey = 60, + ns_t_openpgpkey = 61, + ns_t_csync = 62, + ns_t_spf = 99, + ns_t_uinfo = 100, + ns_t_uid = 101, + ns_t_gid = 102, + ns_t_unspec = 103, + ns_t_nid = 104, + ns_t_l32 = 105, + ns_t_l64 = 106, + ns_t_lp = 107, + ns_t_eui48 = 108, + ns_t_eui64 = 109, + ns_t_tkey = 249, + ns_t_tsig = 250, + ns_t_ixfr = 251, + ns_t_axfr = 252, + ns_t_mailb = 253, + ns_t_maila = 254, + ns_t_any = 255, + ns_t_uri = 256, + ns_t_caa = 257, + ns_t_avc = 258, + ns_t_ta = 32768, + ns_t_dlv = 32769, + + ns_t_max = 65536 + } ns_type; /*% * Values for class field @@ -330,15 +335,7 @@ typedef enum __ns_class { ns_c_max = 65536 } ns_class; -/* DNSSEC constants. */ - -typedef enum __ns_key_types { - ns_kt_rsa = 1, /*%< key type RSA/MD5 */ - ns_kt_dh = 2, /*%< Diffie Hellman */ - ns_kt_dsa = 3, /*%< Digital Signature Standard (MANDATORY) */ - ns_kt_private = 254 /*%< Private key type starts with OID */ -} ns_key_types; - +/* Certificate type values in CERT resource records. */ typedef enum __ns_cert_types { cert_t_pkix = 1, /*%< PKIX (X.509v3) */ cert_t_spki = 2, /*%< SPKI */ @@ -347,82 +344,6 @@ typedef enum __ns_cert_types { cert_t_oid = 254 /*%< OID private type */ } ns_cert_types; -/* Flags field of the KEY RR rdata. */ -#define NS_KEY_TYPEMASK 0xC000 /*%< Mask for "type" bits */ -#define NS_KEY_TYPE_AUTH_CONF 0x0000 /*%< Key usable for both */ -#define NS_KEY_TYPE_CONF_ONLY 0x8000 /*%< Key usable for confidentiality */ -#define NS_KEY_TYPE_AUTH_ONLY 0x4000 /*%< Key usable for authentication */ -#define NS_KEY_TYPE_NO_KEY 0xC000 /*%< No key usable for either; no key */ -/* The type bits can also be interpreted independently, as single bits: */ -#define NS_KEY_NO_AUTH 0x8000 /*%< Key unusable for authentication */ -#define NS_KEY_NO_CONF 0x4000 /*%< Key unusable for confidentiality */ -#define NS_KEY_RESERVED2 0x2000 /* Security is *mandatory* if bit=0 */ -#define NS_KEY_EXTENDED_FLAGS 0x1000 /*%< reserved - must be zero */ -#define NS_KEY_RESERVED4 0x0800 /*%< reserved - must be zero */ -#define NS_KEY_RESERVED5 0x0400 /*%< reserved - must be zero */ -#define NS_KEY_NAME_TYPE 0x0300 /*%< these bits determine the type */ -#define NS_KEY_NAME_USER 0x0000 /*%< key is assoc. with user */ -#define NS_KEY_NAME_ENTITY 0x0200 /*%< key is assoc. with entity eg host */ -#define NS_KEY_NAME_ZONE 0x0100 /*%< key is zone key */ -#define NS_KEY_NAME_RESERVED 0x0300 /*%< reserved meaning */ -#define NS_KEY_RESERVED8 0x0080 /*%< reserved - must be zero */ -#define NS_KEY_RESERVED9 0x0040 /*%< reserved - must be zero */ -#define NS_KEY_RESERVED10 0x0020 /*%< reserved - must be zero */ -#define NS_KEY_RESERVED11 0x0010 /*%< reserved - must be zero */ -#define NS_KEY_SIGNATORYMASK 0x000F /*%< key can sign RR's of same name */ -#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \ - NS_KEY_RESERVED4 | \ - NS_KEY_RESERVED5 | \ - NS_KEY_RESERVED8 | \ - NS_KEY_RESERVED9 | \ - NS_KEY_RESERVED10 | \ - NS_KEY_RESERVED11 ) -#define NS_KEY_RESERVED_BITMASK2 0xFFFF /*%< no bits defined here */ -/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */ -#define NS_ALG_MD5RSA 1 /*%< MD5 with RSA */ -#define NS_ALG_DH 2 /*%< Diffie Hellman KEY */ -#define NS_ALG_DSA 3 /*%< DSA KEY */ -#define NS_ALG_DSS NS_ALG_DSA -#define NS_ALG_EXPIRE_ONLY 253 /*%< No alg, no security */ -#define NS_ALG_PRIVATE_OID 254 /*%< Key begins with OID giving alg */ -/* Protocol values */ -/* value 0 is reserved */ -#define NS_KEY_PROT_TLS 1 -#define NS_KEY_PROT_EMAIL 2 -#define NS_KEY_PROT_DNSSEC 3 -#define NS_KEY_PROT_IPSEC 4 -#define NS_KEY_PROT_ANY 255 - -/* Signatures */ -#define NS_MD5RSA_MIN_BITS 512 /*%< Size of a mod or exp in bits */ -#define NS_MD5RSA_MAX_BITS 4096 - /* Total of binary mod and exp */ -#define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3) - /* Max length of text sig block */ -#define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4) -#define NS_MD5RSA_MIN_SIZE ((NS_MD5RSA_MIN_BITS+7)/8) -#define NS_MD5RSA_MAX_SIZE ((NS_MD5RSA_MAX_BITS+7)/8) - -#define NS_DSA_SIG_SIZE 41 -#define NS_DSA_MIN_SIZE 213 -#define NS_DSA_MAX_BYTES 405 - -/* Offsets into SIG record rdata to find various values */ -#define NS_SIG_TYPE 0 /*%< Type flags */ -#define NS_SIG_ALG 2 /*%< Algorithm */ -#define NS_SIG_LABELS 3 /*%< How many labels in name */ -#define NS_SIG_OTTL 4 /*%< Original TTL */ -#define NS_SIG_EXPIR 8 /*%< Expiration time */ -#define NS_SIG_SIGNED 12 /*%< Signature time */ -#define NS_SIG_FOOT 16 /*%< Key footprint */ -#define NS_SIG_SIGNER 18 /*%< Domain name of who signed it */ -/* How RR types are represented as bit-flags in NXT records */ -#define NS_NXT_BITS 8 -#define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS))) -#define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS))) -#define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS))) -#define NS_NXT_MAX 127 - /*% * EDNS0 extended flags and option codes, host order. */ @@ -433,34 +354,34 @@ typedef enum __ns_cert_types { * Inline versions of get/put short/long. Pointer is advanced. */ #define NS_GET16(s, cp) do { \ - const u_char *t_cp = (const u_char *)(cp); \ - (s) = ((u_int16_t)t_cp[0] << 8) \ - | ((u_int16_t)t_cp[1]) \ + const unsigned char *t_cp = (const unsigned char *)(cp); \ + (s) = ((uint16_t)t_cp[0] << 8) \ + | ((uint16_t)t_cp[1]) \ ; \ (cp) += NS_INT16SZ; \ } while (0) #define NS_GET32(l, cp) do { \ - const u_char *t_cp = (const u_char *)(cp); \ - (l) = ((u_int32_t)t_cp[0] << 24) \ - | ((u_int32_t)t_cp[1] << 16) \ - | ((u_int32_t)t_cp[2] << 8) \ - | ((u_int32_t)t_cp[3]) \ + const unsigned char *t_cp = (const unsigned char *)(cp); \ + (l) = ((uint32_t)t_cp[0] << 24) \ + | ((uint32_t)t_cp[1] << 16) \ + | ((uint32_t)t_cp[2] << 8) \ + | ((uint32_t)t_cp[3]) \ ; \ (cp) += NS_INT32SZ; \ } while (0) #define NS_PUT16(s, cp) do { \ - u_int16_t t_s = (u_int16_t)(s); \ - u_char *t_cp = (u_char *)(cp); \ + uint16_t t_s = (uint16_t)(s); \ + unsigned char *t_cp = (unsigned char *)(cp); \ *t_cp++ = t_s >> 8; \ *t_cp = t_s; \ (cp) += NS_INT16SZ; \ } while (0) #define NS_PUT32(l, cp) do { \ - u_int32_t t_l = (u_int32_t)(l); \ - u_char *t_cp = (u_char *)(cp); \ + uint32_t t_l = (uint32_t)(l); \ + unsigned char *t_cp = (unsigned char *)(cp); \ *t_cp++ = t_l >> 24; \ *t_cp++ = t_l >> 16; \ *t_cp++ = t_l >> 8; \ @@ -470,66 +391,53 @@ typedef enum __ns_cert_types { __BEGIN_DECLS int ns_msg_getflag (ns_msg, int) __THROW; -u_int ns_get16 (const u_char *) __THROW; -u_long ns_get32 (const u_char *) __THROW; -void ns_put16 (u_int, u_char *) __THROW; -void ns_put32 (u_long, u_char *) __THROW; -int ns_initparse (const u_char *, int, ns_msg *) __THROW; -int ns_skiprr (const u_char *, const u_char *, ns_sect, int) - __THROW; +unsigned int ns_get16 (const unsigned char *) __THROW; +unsigned long ns_get32 (const unsigned char *) __THROW; +void ns_put16 (unsigned int, unsigned char *) __THROW; +void ns_put32 (unsigned long, unsigned char *) __THROW; +int ns_initparse (const unsigned char *, int, ns_msg *) __THROW; +int ns_skiprr (const unsigned char *, const unsigned char *, + ns_sect, int) __THROW; int ns_parserr (ns_msg *, ns_sect, int, ns_rr *) __THROW; int ns_sprintrr (const ns_msg *, const ns_rr *, const char *, const char *, char *, size_t) __THROW; -int ns_sprintrrf (const u_char *, size_t, const char *, - ns_class, ns_type, u_long, const u_char *, - size_t, const char *, const char *, - char *, size_t) __THROW; -int ns_format_ttl (u_long, char *, size_t) __THROW; -int ns_parse_ttl (const char *, u_long *) __THROW; -u_int32_t ns_datetosecs (const char *, int *) __THROW; -int ns_name_ntol (const u_char *, u_char *, size_t) __THROW; -int ns_name_ntop (const u_char *, char *, size_t) __THROW; -int ns_name_pton (const char *, u_char *, size_t) __THROW; -int ns_name_unpack (const u_char *, const u_char *, - const u_char *, u_char *, size_t) __THROW; -int ns_name_pack (const u_char *, u_char *, int, - const u_char **, const u_char **) __THROW; -int ns_name_uncompress (const u_char *, const u_char *, - const u_char *, char *, size_t) __THROW; -int ns_name_compress (const char *, u_char *, size_t, - const u_char **, const u_char **) __THROW; -int ns_name_skip (const u_char **, const u_char *) __THROW; -void ns_name_rollback (const u_char *, const u_char **, - const u_char **) __THROW; -int ns_sign (u_char *, int *, int, int, void *, - const u_char *, int, u_char *, int *, time_t) __THROW; -int ns_sign2 (u_char *, int *, int, int, void *, - const u_char *, int, u_char *, int *, time_t, - u_char **, u_char **) __THROW; -int ns_sign_tcp (u_char *, int *, int, int, - ns_tcp_tsig_state *, int) __THROW; -int ns_sign_tcp2 (u_char *, int *, int, int, - ns_tcp_tsig_state *, int, - u_char **, u_char **) __THROW; -int ns_sign_tcp_init (void *, const u_char *, int, - ns_tcp_tsig_state *) __THROW; -u_char *ns_find_tsig (u_char *, u_char *) __THROW; -int ns_verify (u_char *, int *, void *, const u_char *, int, - u_char *, int *, time_t *, int) __THROW; -int ns_verify_tcp (u_char *, int *, ns_tcp_tsig_state *, int) +int ns_sprintrrf (const unsigned char *, size_t, const char *, + ns_class, ns_type, unsigned long, + const unsigned char *, size_t, const char *, + const char *, char *, size_t) __THROW; +int ns_format_ttl (unsigned long, char *, size_t) __THROW; +int ns_parse_ttl (const char *, unsigned long *) __THROW; +uint32_t ns_datetosecs (const char *, int *) __THROW; +int ns_name_ntol (const unsigned char *, unsigned char *, size_t) + __THROW; +int ns_name_ntop (const unsigned char *, char *, size_t) __THROW; +int ns_name_pton (const char *, unsigned char *, size_t) __THROW; +int ns_name_unpack (const unsigned char *, const unsigned char *, + const unsigned char *, unsigned char *, size_t) + __THROW; +int ns_name_pack (const unsigned char *, unsigned char *, int, + const unsigned char **, const unsigned char **) + __THROW; +int ns_name_uncompress (const unsigned char *, + const unsigned char *, + const unsigned char *, + char *, size_t) __THROW; +int ns_name_compress (const char *, unsigned char *, size_t, + const unsigned char **, + const unsigned char **) __THROW; +int ns_name_skip (const unsigned char **, const unsigned char *) __THROW; -int ns_verify_tcp_init (void *, const u_char *, int, - ns_tcp_tsig_state *) __THROW; +void ns_name_rollback (const unsigned char *, + const unsigned char **, + const unsigned char **) __THROW; int ns_samedomain (const char *, const char *) __THROW; int ns_subdomain (const char *, const char *) __THROW; int ns_makecanon (const char *, char *, size_t) __THROW; int ns_samename (const char *, const char *) __THROW; __END_DECLS -#ifdef BIND_4_COMPAT #include <arpa/nameser_compat.h> -#endif #endif /* !_ARPA_NAMESER_H_ */ /*! \file */ diff --git a/resolv/arpa/nameser_compat.h b/resolv/arpa/nameser_compat.h index d59c9e41b3..f1c390f3b9 100644 --- a/resolv/arpa/nameser_compat.h +++ b/resolv/arpa/nameser_compat.h @@ -26,16 +26,9 @@ * SUCH DAMAGE. */ -/*% - * from nameser.h 8.1 (Berkeley) 6/2/93 - * $BINDId: nameser_compat.h,v 8.11 1999/01/02 08:00:58 vixie Exp $ - */ - #ifndef _ARPA_NAMESER_COMPAT_ #define _ARPA_NAMESER_COMPAT_ -#define __BIND 19950621 /*%< (DEAD) interface version stamp. */ - #include <endian.h> /*% @@ -47,7 +40,7 @@ typedef struct { unsigned id :16; /*%< query identification number */ -#if BYTE_ORDER == BIG_ENDIAN +#if __BYTE_ORDER == __BIG_ENDIAN /* fields in third byte */ unsigned qr: 1; /*%< response flag */ unsigned opcode: 4; /*%< purpose of message */ @@ -61,7 +54,7 @@ typedef struct { unsigned cd: 1; /*%< checking disabled by resolver */ unsigned rcode :4; /*%< response code */ #endif -#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN +#if __BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __PDP_ENDIAN /* fields in third byte */ unsigned rd :1; /*%< recursion desired */ unsigned tc :1; /*%< truncated message */ @@ -127,49 +120,90 @@ typedef struct { #define DELETE ns_uop_delete #define ADD ns_uop_add -#define T_A ns_t_a -#define T_NS ns_t_ns -#define T_MD ns_t_md -#define T_MF ns_t_mf -#define T_CNAME ns_t_cname -#define T_SOA ns_t_soa -#define T_MB ns_t_mb -#define T_MG ns_t_mg -#define T_MR ns_t_mr -#define T_NULL ns_t_null -#define T_WKS ns_t_wks -#define T_PTR ns_t_ptr -#define T_HINFO ns_t_hinfo -#define T_MINFO ns_t_minfo -#define T_MX ns_t_mx -#define T_TXT ns_t_txt -#define T_RP ns_t_rp -#define T_AFSDB ns_t_afsdb -#define T_X25 ns_t_x25 -#define T_ISDN ns_t_isdn -#define T_RT ns_t_rt -#define T_NSAP ns_t_nsap -#define T_NSAP_PTR ns_t_nsap_ptr -#define T_SIG ns_t_sig -#define T_KEY ns_t_key -#define T_PX ns_t_px -#define T_GPOS ns_t_gpos -#define T_AAAA ns_t_aaaa -#define T_LOC ns_t_loc -#define T_NXT ns_t_nxt -#define T_EID ns_t_eid -#define T_NIMLOC ns_t_nimloc -#define T_SRV ns_t_srv -#define T_ATMA ns_t_atma -#define T_NAPTR ns_t_naptr -#define T_A6 ns_t_a6 -#define T_DNAME ns_t_dname -#define T_TSIG ns_t_tsig -#define T_IXFR ns_t_ixfr -#define T_AXFR ns_t_axfr -#define T_MAILB ns_t_mailb -#define T_MAILA ns_t_maila -#define T_ANY ns_t_any +#define T_A ns_t_a +#define T_NS ns_t_ns +#define T_MD ns_t_md +#define T_MF ns_t_mf +#define T_CNAME ns_t_cname +#define T_SOA ns_t_soa +#define T_MB ns_t_mb +#define T_MG ns_t_mg +#define T_MR ns_t_mr +#define T_NULL ns_t_null +#define T_WKS ns_t_wks +#define T_PTR ns_t_ptr +#define T_HINFO ns_t_hinfo +#define T_MINFO ns_t_minfo +#define T_MX ns_t_mx +#define T_TXT ns_t_txt +#define T_RP ns_t_rp +#define T_AFSDB ns_t_afsdb +#define T_X25 ns_t_x25 +#define T_ISDN ns_t_isdn +#define T_RT ns_t_rt +#define T_NSAP ns_t_nsap +#define T_NSAP_PTR ns_t_nsap_ptr +#define T_SIG ns_t_sig +#define T_KEY ns_t_key +#define T_PX ns_t_px +#define T_GPOS ns_t_gpos +#define T_AAAA ns_t_aaaa +#define T_LOC ns_t_loc +#define T_NXT ns_t_nxt +#define T_EID ns_t_eid +#define T_NIMLOC ns_t_nimloc +#define T_SRV ns_t_srv +#define T_ATMA ns_t_atma +#define T_NAPTR ns_t_naptr +#define T_KX ns_t_kx +#define T_CERT ns_t_cert +#define T_A6 ns_t_a6 +#define T_DNAME ns_t_dname +#define T_SINK ns_t_sink +#define T_OPT ns_t_opt +#define T_APL ns_t_apl +#define T_DS ns_t_ds +#define T_SSHFP ns_t_sshfp +#define T_IPSECKEY ns_t_ipseckey +#define T_RRSIG ns_t_rrsig +#define T_NSEC ns_t_nsec +#define T_DNSKEY ns_t_dnskey +#define T_DHCID ns_t_dhcid +#define T_NSEC3 ns_t_nsec3 +#define T_NSEC3PARAM ns_t_nsec3param +#define T_TLSA ns_t_tlsa +#define T_SMIMEA ns_t_smimea +#define T_HIP ns_t_hip +#define T_NINFO ns_t_ninfo +#define T_RKEY ns_t_rkey +#define T_TALINK ns_t_talink +#define T_CDS ns_t_cds +#define T_CDNSKEY ns_t_cdnskey +#define T_OPENPGPKEY ns_t_openpgpkey +#define T_CSYNC ns_t_csync +#define T_SPF ns_t_spf +#define T_UINFO ns_t_uinfo +#define T_UID ns_t_uid +#define T_GID ns_t_gid +#define T_UNSPEC ns_t_unspec +#define T_NID ns_t_nid +#define T_L32 ns_t_l32 +#define T_L64 ns_t_l64 +#define T_LP ns_t_lp +#define T_EUI48 ns_t_eui48 +#define T_EUI64 ns_t_eui64 +#define T_TKEY ns_t_tkey +#define T_TSIG ns_t_tsig +#define T_IXFR ns_t_ixfr +#define T_AXFR ns_t_axfr +#define T_MAILB ns_t_mailb +#define T_MAILA ns_t_maila +#define T_ANY ns_t_any +#define T_URI ns_t_uri +#define T_CAA ns_t_caa +#define T_AVC ns_t_avc +#define T_TA ns_t_ta +#define T_DLV ns_t_dlv #define C_IN ns_c_in #define C_CHAOS ns_c_chaos diff --git a/resolv/bits/types/res_state.h b/resolv/bits/types/res_state.h new file mode 100644 index 0000000000..2544a627f6 --- /dev/null +++ b/resolv/bits/types/res_state.h @@ -0,0 +1,61 @@ +#ifndef __res_state_defined +#define __res_state_defined 1 + +#include <sys/types.h> +#include <netinet/in.h> + +/* res_state: the global state used by the resolver stub. */ +#define MAXNS 3 /* max # name servers we'll track */ +#define MAXDFLSRCH 3 /* # default domain levels to try */ +#define MAXDNSRCH 6 /* max # domains in search path */ +#define MAXRESOLVSORT 10 /* number of net to sort on */ + +struct __res_state { + int retrans; /* retransmition time interval */ + int retry; /* number of times to retransmit */ + unsigned long options; /* option flags - see below. */ + int nscount; /* number of name servers */ + struct sockaddr_in + nsaddr_list[MAXNS]; /* address of name server */ + unsigned short id; /* current message id */ + /* 2 byte hole here. */ + char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */ + char defdname[256]; /* default domain (deprecated) */ + unsigned long pfcode; /* RES_PRF_ flags - see below. */ + unsigned ndots:4; /* threshold for initial abs. query */ + unsigned nsort:4; /* number of elements in sort_list[] */ + unsigned ipv6_unavail:1; /* connecting to IPv6 server failed */ + unsigned unused:23; + struct { + struct in_addr addr; + uint32_t mask; + } sort_list[MAXRESOLVSORT]; + /* 4 byte hole here on 64-bit architectures. */ + void * __glibc_unused_qhook; + void * __glibc_unused_rhook; + int res_h_errno; /* last one set for this context */ + int _vcsock; /* PRIVATE: for res_send VC i/o */ + unsigned int _flags; /* PRIVATE: see below */ + /* 4 byte hole here on 64-bit architectures. */ + union { + char pad[52]; /* On an i386 this means 512b total. */ + struct { + uint16_t nscount; + uint16_t nsmap[MAXNS]; + int nssocks[MAXNS]; + uint16_t nscount6; + uint16_t nsinit; + struct sockaddr_in6 *nsaddrs[MAXNS]; +#ifdef _LIBC + unsigned long long int __glibc_extension_index + __attribute__((packed)); +#else + unsigned int __glibc_reserved[2]; +#endif + } _ext; + } _u; +}; + +typedef struct __res_state *res_state; + +#endif /* __res_state_defined */ diff --git a/resolv/gethnamaddr.c b/resolv/compat-gethnamaddr.c index 3a8e9b1490..259378b2be 100644 --- a/resolv/gethnamaddr.c +++ b/resolv/compat-gethnamaddr.c @@ -54,54 +54,27 @@ it exports symbols in the libresolv ABI. The file is not maintained any more, nor are these functions. */ -#if defined(LIBC_SCCS) && !defined(lint) -static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/socket.h> -#include <netinet/in.h> -#include <arpa/inet.h> -#include <arpa/nameser.h> - -#include <stdio.h> -#include <netdb.h> -#include <resolv.h> -#include <ctype.h> -#include <errno.h> -#include <syslog.h> - -#define RESOLVSORT - -#ifndef LOG_AUTH -# define LOG_AUTH 0 -#endif - -#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */ - -#if defined(BSD) && (BSD >= 199103) && defined(AF_INET6) +#include <shlib-compat.h> +#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_25) + +# include <sys/types.h> +# include <sys/param.h> +# include <sys/socket.h> +# include <netinet/in.h> +# include <arpa/inet.h> +# include <arpa/nameser.h> + +# include <stdio.h> +# include <netdb.h> +# include <resolv/resolv-internal.h> +# include <resolv/resolv_context.h> +# include <ctype.h> +# include <errno.h> # include <stdlib.h> # include <string.h> -#else -# include "../conf/portability.h" -#endif -#if defined(USE_OPTIONS_H) -# include <../conf/options.h> -#endif - -#ifdef SPRINTF_CHAR -# define SPRINTF(x) strlen(sprintf/**/x) -#else -# define SPRINTF(x) ((size_t)sprintf x) -#endif - -#define MAXALIASES 35 -#define MAXADDRS 35 - -static const char AskedForGot[] = - "gethostby*.getanswer: asked for \"%s\", got \"%s\""; +# define MAXALIASES 35 +# define MAXADDRS 35 static char *h_addr_ptrs[MAXADDRS + 1]; @@ -112,24 +85,25 @@ static u_char host_addr[16]; /* IPv4 or IPv6 */ static FILE *hostf = NULL; static int stayopen = 0; +static struct hostent *res_gethostbyname2_context (struct resolv_context *, + const char *name, int af); + static void map_v4v6_address (const char *src, char *dst) __THROW; static void map_v4v6_hostent (struct hostent *hp, char **bp, int *len) __THROW; -#ifdef RESOLVSORT extern void addrsort (char **, int) __THROW; -#endif -#if PACKETSZ > 65536 -#define MAXPACKET PACKETSZ -#else -#define MAXPACKET 65536 -#endif +# if PACKETSZ > 65536 +# define MAXPACKET PACKETSZ +# else +# define MAXPACKET 65536 +# endif /* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */ -#ifdef MAXHOSTNAMELEN -# undef MAXHOSTNAMELEN -#endif -#define MAXHOSTNAMELEN 256 +# ifdef MAXHOSTNAMELEN +# undef MAXHOSTNAMELEN +# endif +# define MAXHOSTNAMELEN 256 typedef union { HEADER hdr; @@ -141,11 +115,11 @@ typedef union { char ac; } align; -#ifndef h_errno +# ifndef h_errno extern int h_errno; -#endif +# endif -#ifdef DEBUG +# ifdef DEBUG static void Dprintf (char *msg, int num) { @@ -156,11 +130,11 @@ Dprintf (char *msg, int num) __set_errno (save); } } -#else -# define Dprintf(msg, num) /*nada*/ -#endif +# else +# define Dprintf(msg, num) /*nada*/ +# endif -#define BOUNDED_INCR(x) \ +# define BOUNDED_INCR(x) \ do { \ cp += x; \ if (cp > eom) { \ @@ -169,7 +143,7 @@ Dprintf (char *msg, int num) } \ } while (0) -#define BOUNDS_CHECK(ptr, count) \ +# define BOUNDS_CHECK(ptr, count) \ do { \ if ((ptr) + (count) > eom) { \ __set_h_errno (NO_RECOVERY); \ @@ -335,20 +309,12 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype) * uses many different types in responses that do not * match QTYPE. */ - if ((_res.options & RES_USE_DNSSEC) == 0) { - syslog(LOG_NOTICE|LOG_AUTH, - "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"", - qname, p_class(C_IN), p_type(qtype), - p_type(type)); - } cp += n; continue; /* XXX - had_error++ ? */ } switch (type) { case T_PTR: if (strcasecmp(tname, bp) != 0) { - syslog(LOG_NOTICE|LOG_AUTH, - AskedForGot, qname, bp); cp += n; continue; /* XXX - had_error++ ? */ } @@ -357,7 +323,6 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype) had_error++; break; } -#if MULTI_PTRS_ARE_ALIASES cp += n; if (cp != erdata) { __set_h_errno (NO_RECOVERY); @@ -379,26 +344,9 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype) buflen -= n; } break; -#else - host.h_name = bp; - if (_res.options & RES_USE_INET6) { - n = strlen(bp) + 1; /* for the \0 */ - if (n >= MAXHOSTNAMELEN) { - had_error++; - break; - } - bp += n; - buflen -= n; - map_v4v6_hostent(&host, &bp, &buflen); - } - __set_h_errno (NETDB_SUCCESS); - return (&host); -#endif case T_A: case T_AAAA: if (strcasecmp(host.h_name, bp) != 0) { - syslog(LOG_NOTICE|LOG_AUTH, - AskedForGot, host.h_name, bp); cp += n; continue; /* XXX - had_error++ ? */ } @@ -452,7 +400,6 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype) if (haveanswer) { *ap = NULL; *hap = NULL; -# if defined(RESOLVSORT) /* * Note: we sort even if host can take only one address * in its return structures - should give it the "best" @@ -460,7 +407,6 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype) */ if (_res.nsort && haveanswer > 1 && qtype == T_A) addrsort(h_addr_ptrs, haveanswer); -# endif /*RESOLVSORT*/ if (!host.h_name) { n = strlen(qname) + 1; /* for the \0 */ if (n > buflen || n >= MAXHOSTNAMELEN) @@ -470,7 +416,7 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype) bp += n; buflen -= n; } - if (_res.options & RES_USE_INET6) + if (res_use_inet6 ()) map_v4v6_hostent(&host, &bp, &buflen); __set_h_errno (NETDB_SUCCESS); return (&host); @@ -480,28 +426,37 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype) return (NULL); } -extern struct hostent *gethostbyname2(const char *name, int af); -libresolv_hidden_proto (gethostbyname2) +extern struct hostent *res_gethostbyname2(const char *name, int af); +libresolv_hidden_proto (res_gethostbyname2) struct hostent * -gethostbyname (const char *name) +res_gethostbyname (const char *name) { - struct hostent *hp; - - if (__res_maybe_init (&_res, 0) == -1) { - __set_h_errno (NETDB_INTERNAL); - return (NULL); - } - if (_res.options & RES_USE_INET6) { - hp = gethostbyname2(name, AF_INET6); - if (hp) - return (hp); + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { + __set_h_errno (NETDB_INTERNAL); + return NULL; + } + + if (res_use_inet6 ()) + { + struct hostent *hp = res_gethostbyname2_context (ctx, name, AF_INET6); + if (hp != NULL) + { + __resolv_context_put (ctx); + return hp; } - return (gethostbyname2(name, AF_INET)); + } + struct hostent *hp = res_gethostbyname2_context (ctx, name, AF_INET); + __resolv_context_put (ctx); + return hp; } +compat_symbol (libresolv, res_gethostbyname, res_gethostbyname, GLIBC_2_0); -struct hostent * -gethostbyname2 (const char *name, int af) +static struct hostent * +res_gethostbyname2_context (struct resolv_context *ctx, + const char *name, int af) { union { @@ -514,11 +469,6 @@ gethostbyname2 (const char *name, int af) int n, size, type, len; struct hostent *ret; - if (__res_maybe_init (&_res, 0) == -1) { - __set_h_errno (NETDB_INTERNAL); - return (NULL); - } - switch (af) { case AF_INET: size = INADDRSZ; @@ -542,8 +492,10 @@ gethostbyname2 (const char *name, int af) * this is also done in res_query() since we are not the only * function that looks up host names. */ - if (!strchr(name, '.') && (cp = __hostalias(name))) - name = cp; + char abuf[MAXDNAME]; + if (strchr (name, '.') != NULL + && (cp = __res_context_hostalias (ctx, name, abuf, sizeof (abuf)))) + name = cp; /* * disallow names consisting only of digits/dots, unless @@ -573,7 +525,7 @@ gethostbyname2 (const char *name, int af) h_addr_ptrs[0] = (char *)host_addr; h_addr_ptrs[1] = NULL; host.h_addr_list = h_addr_ptrs; - if (_res.options & RES_USE_INET6) + if (res_use_inet6 ()) map_v4v6_hostent(&host, &bp, &len); __set_h_errno (NETDB_SUCCESS); return (&host); @@ -615,8 +567,9 @@ gethostbyname2 (const char *name, int af) buf.buf = origbuf = (querybuf *) alloca (1024); - if ((n = __libc_res_nsearch(&_res, name, C_IN, type, buf.buf->buf, 1024, - &buf.ptr, NULL, NULL, NULL, NULL)) < 0) { + if ((n = __res_context_search + (ctx, name, C_IN, type, buf.buf->buf, 1024, + &buf.ptr, NULL, NULL, NULL, NULL)) < 0) { if (buf.buf != origbuf) free (buf.buf); Dprintf("res_nsearch failed (%d)\n", n); @@ -629,10 +582,26 @@ gethostbyname2 (const char *name, int af) free (buf.buf); return ret; } -libresolv_hidden_def (gethostbyname2) struct hostent * -gethostbyaddr (const void *addr, socklen_t len, int af) +res_gethostbyname2 (const char *name, int af) +{ + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { + __set_h_errno (NETDB_INTERNAL); + return NULL; + } + struct hostent *hp = res_gethostbyname2_context (ctx, name, AF_INET); + __resolv_context_put (ctx); + return hp; +} +libresolv_hidden_def (res_gethostbyname2) +compat_symbol (libresolv, res_gethostbyname2, res_gethostbyname2, GLIBC_2_0); + +static struct hostent * +res_gethostbyaddr_context (struct resolv_context *ctx, + const void *addr, socklen_t len, int af) { const u_char *uaddr = (const u_char *)addr; static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; @@ -647,17 +616,7 @@ gethostbyaddr (const void *addr, socklen_t len, int af) querybuf *orig_buf; struct hostent *hp; char qbuf[MAXDNAME+1], *qp = NULL; -#ifdef SUNSECURITY - struct hostent *rhp; - char **haddr; - u_long old_options; - char hname2[MAXDNAME+1]; -#endif /*SUNSECURITY*/ - - if (__res_maybe_init (&_res, 0) == -1) { - __set_h_errno (NETDB_INTERNAL); - return (NULL); - } + if (af == AF_INET6 && len == IN6ADDRSZ && (!memcmp(uaddr, mapped, sizeof mapped) || !memcmp(uaddr, tunnelled, sizeof tunnelled))) { @@ -695,9 +654,9 @@ gethostbyaddr (const void *addr, socklen_t len, int af) case AF_INET6: qp = qbuf; for (n = IN6ADDRSZ - 1; n >= 0; n--) { - qp += SPRINTF((qp, "%x.%x.", - uaddr[n] & 0xf, - (uaddr[n] >> 4) & 0xf)); + qp += sprintf(qp, "%x.%x.", + uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf); } strcpy(qp, "ip6.arpa"); break; @@ -707,14 +666,8 @@ gethostbyaddr (const void *addr, socklen_t len, int af) buf.buf = orig_buf = (querybuf *) alloca (1024); - n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, 1024, - &buf.ptr, NULL, NULL, NULL, NULL); - if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) { - strcpy(qp, "ip6.int"); - n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, - buf.buf != orig_buf ? MAXPACKET : 1024, - &buf.ptr, NULL, NULL, NULL, NULL); - } + n = __res_context_query (ctx, qbuf, C_IN, T_PTR, buf.buf->buf, 1024, + &buf.ptr, NULL, NULL, NULL, NULL); if (n < 0) { if (buf.buf != orig_buf) free (buf.buf); @@ -728,44 +681,12 @@ gethostbyaddr (const void *addr, socklen_t len, int af) free (buf.buf); if (!hp) return (NULL); /* h_errno was set by getanswer() */ -#ifdef SUNSECURITY - if (af == AF_INET) { - /* - * turn off search as the name should be absolute, - * 'localhost' should be matched by defnames - */ - strncpy(hname2, hp->h_name, MAXDNAME); - hname2[MAXDNAME] = '\0'; - old_options = _res.options; - _res.options &= ~RES_DNSRCH; - _res.options |= RES_DEFNAMES; - if (!(rhp = gethostbyname(hname2))) { - syslog(LOG_NOTICE|LOG_AUTH, - "gethostbyaddr: No A record for %s (verifying [%s])", - hname2, inet_ntoa(*((struct in_addr *)addr))); - _res.options = old_options; - __set_h_errno (HOST_NOT_FOUND); - return (NULL); - } - _res.options = old_options; - for (haddr = rhp->h_addr_list; *haddr; haddr++) - if (!memcmp(*haddr, addr, INADDRSZ)) - break; - if (!*haddr) { - syslog(LOG_NOTICE|LOG_AUTH, - "gethostbyaddr: A record of %s != PTR record [%s]", - hname2, inet_ntoa(*((struct in_addr *)addr))); - __set_h_errno (HOST_NOT_FOUND); - return (NULL); - } - } -#endif /*SUNSECURITY*/ hp->h_addrtype = af; hp->h_length = len; memmove(host_addr, addr, len); h_addr_ptrs[0] = (char *)host_addr; h_addr_ptrs[1] = NULL; - if (af == AF_INET && (_res.options & RES_USE_INET6)) { + if (af == AF_INET && res_use_inet6 ()) { map_v4v6_address((char*)host_addr, (char*)host_addr); hp->h_addrtype = AF_INET6; hp->h_length = IN6ADDRSZ; @@ -774,6 +695,21 @@ gethostbyaddr (const void *addr, socklen_t len, int af) return (hp); } +struct hostent * +res_gethostbyaddr (const void *addr, socklen_t len, int af) +{ + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { + __set_h_errno (NETDB_INTERNAL); + return NULL; + } + struct hostent *hp = res_gethostbyaddr_context (ctx, addr, len, af); + __resolv_context_put (ctx); + return hp; +} +compat_symbol (libresolv, res_gethostbyaddr, res_gethostbyaddr, GLIBC_2_0); + void _sethtent (int f) { @@ -784,8 +720,9 @@ _sethtent (int f) stayopen = f; } libresolv_hidden_def (_sethtent) +compat_symbol (libresolv, _sethtent, _sethtent, GLIBC_2_0); -void +static void _endhtent (void) { if (hostf && !stayopen) { @@ -822,7 +759,7 @@ _gethtent (void) af = AF_INET6; len = IN6ADDRSZ; } else if (inet_pton(AF_INET, p, host_addr) > 0) { - if (_res.options & RES_USE_INET6) { + if (res_use_inet6 ()) { map_v4v6_address((char*)host_addr, (char*)host_addr); af = AF_INET6; len = IN6ADDRSZ; @@ -859,19 +796,21 @@ _gethtent (void) return (&host); } libresolv_hidden_def (_gethtent) +compat_symbol (libresolv, _gethtent, _gethtent, GLIBC_2_0); struct hostent * _gethtbyname (const char *name) { struct hostent *hp; - if (_res.options & RES_USE_INET6) { + if (res_use_inet6 ()) { hp = _gethtbyname2(name, AF_INET6); if (hp) return (hp); } return (_gethtbyname2(name, AF_INET)); } +compat_symbol (libresolv, _gethtbyname, _gethtbyname, GLIBC_2_0); struct hostent * _gethtbyname2 (const char *name, int af) @@ -894,6 +833,7 @@ _gethtbyname2 (const char *name, int af) return (p); } libresolv_hidden_def (_gethtbyname2) +compat_symbol (libresolv, _gethtbyname2, _gethtbyname2, GLIBC_2_0); struct hostent * _gethtbyaddr (const char *addr, size_t len, int af) @@ -908,6 +848,7 @@ _gethtbyaddr (const char *addr, size_t len, int af) return (p); } libresolv_hidden_def (_gethtbyaddr) +compat_symbol (libresolv, _gethtbyaddr, _gethtbyaddr, GLIBC_2_0); static void map_v4v6_address (const char *src, char *dst) @@ -953,7 +894,6 @@ map_v4v6_hostent (struct hostent *hp, char **bpp, int *lenp) } } -#ifdef RESOLVSORT extern void addrsort (char **ap, int num) { @@ -994,50 +934,5 @@ addrsort (char **ap, int num) needsort++; } } -#endif - -#if defined(BSD43_BSD43_NFS) || defined(sun) -/* some libc's out there are bound internally to these names (UMIPS) */ -void -ht_sethostent (int stayopen) -{ - _sethtent(stayopen); -} - -void -ht_endhostent (void) -{ - _endhtent(); -} - -struct hostent * -ht_gethostbyname (char *name) -{ - return (_gethtbyname(name)); -} - -struct hostent * -ht_gethostbyaddr (const char *addr, size_t len, int af) -{ - return (_gethtbyaddr(addr, len, af)); -} -struct hostent * -gethostent (void) -{ - return (_gethtent()); -} - -void -dns_service (void) -{ - return; -} - -#undef dn_skipname -dn_skipname(comp_dn, eom) - const u_char *comp_dn, *eom; -{ - return (__dn_skipname(comp_dn, eom)); -} -#endif /*old-style libc with yp junk in it*/ +#endif /* SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_25) */ diff --git a/resolv/compat-hooks.c b/resolv/compat-hooks.c new file mode 100644 index 0000000000..75228647ce --- /dev/null +++ b/resolv/compat-hooks.c @@ -0,0 +1,56 @@ +/* Compatibility functions for obsolete libresolv hooks. + Copyright (C) 1999-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* + * Copyright (c) 1995-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include <resolv.h> + +#include <shlib-compat.h> + +#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_25) + +void +attribute_compat_text_section +res_send_setqhook(void *hook) { + _res.__glibc_unused_qhook = hook; +} +compat_symbol (libresolv, res_send_setqhook, res_send_setqhook, GLIBC_2_0); + +void +attribute_compat_text_section +res_send_setrhook(void *hook) { + _res.__glibc_unused_rhook = hook; +} +compat_symbol (libresolv, res_send_setrhook, res_send_setrhook, GLIBC_2_0); + +#endif diff --git a/resolv/ga_test.c b/resolv/ga_test.c deleted file mode 100644 index 673162f015..0000000000 --- a/resolv/ga_test.c +++ /dev/null @@ -1,99 +0,0 @@ -#include <arpa/inet.h> -#include <netinet/in.h> -#include <netdb.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> - - -int -main (void) -{ -#define N 10 - struct gaicb reqmem[N]; - struct gaicb *req[N]; - int n; - - for (n = 0; n < N; ++n) - { - asprintf (&reqmem[n].ar_name, "test%d.test.redhat.com", 140 + n); - reqmem[n].ar_service = NULL; - reqmem[n].ar_request = NULL; - reqmem[n].ar_result = NULL; - req[n] = &reqmem[n]; - } - - if (getaddrinfo_a (GAI_NOWAIT, req, N, NULL) != 0) - { - puts ("queue call failed"); - exit (1); - } - else - puts ("queue call successful"); - - while (1) - { - int any = 0; - - for (n = 0; n < N; ++n) - if (req[n] != NULL && gai_error (req[n]) != EAI_INPROGRESS) - { - if (gai_error (req[n]) == 0) - { - struct addrinfo *runp = req[n]->ar_result; - - while (runp != NULL) - { - switch (runp->ai_family) - { - case PF_INET: - { - struct sockaddr_in *sinp; - - sinp = (struct sockaddr_in *) runp->ai_addr; - printf ("%2d: %s = %s\n", n, - req[n]->ar_name, inet_ntoa (sinp->sin_addr)); - } - break; - default: - printf ("%2d: family %d\n", n, runp->ai_family); - break; - } - runp = runp->ai_next; - } - } - else - printf ("error for %d: %s\n", n, - gai_strerror (gai_error (req[n]))); - req[n] = NULL; - break; - } - else if (req[n] != NULL) - any = 1; - - if (n == N) - { - if (any) - gai_suspend (req, N, NULL); - else - break; - } - } - - __libc_write(1,"got all\n", 8); - - for (n = 0; n < N; ++n) - if (gai_error (&reqmem[n]) == 0) - { - struct addrinfo *runp = reqmem[n].ar_result; - - while (runp != NULL) - { - struct addrinfo *oldp = runp; - runp = runp->ai_next; - freeaddrinfo (oldp); - } - } - - return 0; -} diff --git a/resolv/gai_cancel.c b/resolv/gai_cancel.c index a2b33f46cf..07e5dd97e6 100644 --- a/resolv/gai_cancel.c +++ b/resolv/gai_cancel.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2016 Free Software Foundation, Inc. +/* Copyright (C) 2001-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. diff --git a/resolv/gai_error.c b/resolv/gai_error.c index 330426f11c..48fda59f89 100644 --- a/resolv/gai_error.c +++ b/resolv/gai_error.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2016 Free Software Foundation, Inc. +/* Copyright (C) 2001-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. diff --git a/resolv/gai_misc.c b/resolv/gai_misc.c index 8b142f23bd..e7c3b63cc5 100644 --- a/resolv/gai_misc.c +++ b/resolv/gai_misc.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2016 Free Software Foundation, Inc. +/* Copyright (C) 2001-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. @@ -152,7 +152,6 @@ get_elem (void) struct requestlist * -internal_function __gai_find_request (const struct gaicb *gaicbp) { struct requestlist *runp; @@ -169,7 +168,6 @@ __gai_find_request (const struct gaicb *gaicbp) int -internal_function __gai_remove_request (struct gaicb *gaicbp) { struct requestlist *runp; @@ -212,7 +210,6 @@ static void *handle_requests (void *arg); /* The main function of the async I/O handling. It enqueues requests and if necessary starts and handles threads. */ struct requestlist * -internal_function __gai_enqueue_request (struct gaicb *gaicbp) { struct requestlist *newp; diff --git a/resolv/gai_misc.h b/resolv/gai_misc.h index a250c0262f..b788ffc483 100644 --- a/resolv/gai_misc.h +++ b/resolv/gai_misc.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2016 Free Software Foundation, Inc. +/* Copyright (C) 2001-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. @@ -76,26 +76,25 @@ extern pthread_mutex_t __gai_requests_mutex; /* Enqueue request. */ extern struct requestlist *__gai_enqueue_request (struct gaicb *gaicbp) - internal_function; + attribute_hidden; /* Find request on wait list. */ extern struct requestlist *__gai_find_request (const struct gaicb *gaicbp) - internal_function; + attribute_hidden; /* Remove request from waitlist. */ extern int __gai_remove_request (struct gaicb *gaicbp) - internal_function; + attribute_hidden; /* Notify initiator of request and tell this everybody listening. */ extern void __gai_notify (struct requestlist *req) - internal_function; + attribute_hidden; /* Notify initiator of request. */ extern int __gai_notify_only (struct sigevent *sigev, pid_t caller_pid) - internal_function; + attribute_hidden; /* Send the signal. */ -extern int __gai_sigqueue (int sig, const union sigval val, pid_t caller_pid) - internal_function; +extern int __gai_sigqueue (int sig, const union sigval val, pid_t caller_pid); #endif /* gai_misc.h */ diff --git a/resolv/gai_notify.c b/resolv/gai_notify.c index db99bf7db0..dad2546802 100644 --- a/resolv/gai_notify.c +++ b/resolv/gai_notify.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2016 Free Software Foundation, Inc. +/* Copyright (C) 2001-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. @@ -42,7 +42,6 @@ notify_func_wrapper (void *arg) int -internal_function __gai_notify_only (struct sigevent *sigev, pid_t caller_pid) { int result = 0; @@ -94,7 +93,6 @@ __gai_notify_only (struct sigevent *sigev, pid_t caller_pid) void -internal_function __gai_notify (struct requestlist *req) { struct waitlist *waitlist; diff --git a/resolv/gai_sigqueue.c b/resolv/gai_sigqueue.c index 4b0c08f6e5..f087e1cefa 100644 --- a/resolv/gai_sigqueue.c +++ b/resolv/gai_sigqueue.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2016 Free Software Foundation, Inc. +/* Copyright (C) 2001-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/resolv/gai_suspend.c b/resolv/gai_suspend.c index accb8704c1..1da7108118 100644 --- a/resolv/gai_suspend.c +++ b/resolv/gai_suspend.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2016 Free Software Foundation, Inc. +/* Copyright (C) 2001-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. @@ -141,7 +141,7 @@ gai_suspend (const struct gaicb *const list[], int ent, /* An error occurred. Possibly it's EINTR. We have to translate the timeout error report of `pthread_cond_timedwait' to the form expected from `gai_suspend'. */ - if (__builtin_expect (result, ETIMEDOUT) == ETIMEDOUT) + if (__glibc_likely (result == ETIMEDOUT)) result = EAI_AGAIN; else if (result == EINTR) result = EAI_INTR; diff --git a/resolv/getaddrinfo_a.c b/resolv/getaddrinfo_a.c index 4d147e6935..60e3140553 100644 --- a/resolv/getaddrinfo_a.c +++ b/resolv/getaddrinfo_a.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2001-2016 Free Software Foundation, Inc. +/* Copyright (C) 2001-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. diff --git a/resolv/herror.c b/resolv/herror.c index 0aaf29f9db..45c0a5dbda 100644 --- a/resolv/herror.c +++ b/resolv/herror.c @@ -44,11 +44,6 @@ * SOFTWARE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static const char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "$BINDId: herror.c,v 8.11 1999/10/13 16:39:39 vixie Exp $"; -#endif /* LIBC_SCCS and not lint */ - #include <sys/types.h> #include <sys/param.h> #include <sys/uio.h> @@ -85,16 +80,16 @@ herror(const char *s) { v->iov_base = (/*noconst*/ char *)s; v->iov_len = strlen(s); v++; - v->iov_base = ": "; + v->iov_base = (char *) ": "; v->iov_len = 2; v++; } v->iov_base = (char *)hstrerror(h_errno); v->iov_len = strlen(v->iov_base); v++; - v->iov_base = "\n"; + v->iov_base = (char *) "\n"; v->iov_len = 1; - writev_not_cancel_no_status(STDERR_FILENO, iov, (v - iov) + 1); + __writev_nocancel_nostatus(STDERR_FILENO, iov, (v - iov) + 1); } /* diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c index ee42093754..022f7ea084 100644 --- a/resolv/inet_addr.c +++ b/resolv/inet_addr.c @@ -64,11 +64,6 @@ * SOFTWARE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static const char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93"; -static const char rcsid[] = "$BINDId: inet_addr.c,v 8.11 1999/10/13 16:39:25 vixie Exp $"; -#endif /* LIBC_SCCS and not lint */ - #include <sys/types.h> #include <sys/param.h> @@ -77,13 +72,11 @@ static const char rcsid[] = "$BINDId: inet_addr.c,v 8.11 1999/10/13 16:39:25 vix #include <ctype.h> -#ifdef _LIBC -# include <endian.h> -# include <stdint.h> -# include <stdlib.h> -# include <limits.h> -# include <errno.h> -#endif +#include <endian.h> +#include <stdint.h> +#include <stdlib.h> +#include <limits.h> +#include <errno.h> /* * Ascii internet address interpretation routine. @@ -111,9 +104,6 @@ __inet_aton(const char *cp, struct in_addr *addr) { static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff }; in_addr_t val; -#ifndef _LIBC - int base; -#endif char c; union iaddr { uint8_t bytes[4]; @@ -122,10 +112,8 @@ __inet_aton(const char *cp, struct in_addr *addr) uint8_t *pp = res.bytes; int digit; -#ifdef _LIBC int saved_errno = errno; __set_errno (0); -#endif res.word = 0; @@ -138,7 +126,6 @@ __inet_aton(const char *cp, struct in_addr *addr) */ if (!isdigit(c)) goto ret_0; -#ifdef _LIBC { char *endp; unsigned long ul = strtoul (cp, (char **) &endp, 0); @@ -151,33 +138,6 @@ __inet_aton(const char *cp, struct in_addr *addr) cp = endp; } c = *cp; -#else - val = 0; base = 10; digit = 0; - if (c == '0') { - c = *++cp; - if (c == 'x' || c == 'X') - base = 16, c = *++cp; - else { - base = 8; - digit = 1 ; - } - } - for (;;) { - if (isascii(c) && isdigit(c)) { - if (base == 8 && (c == '8' || c == '9')) - return (0); - val = (val * base) + (c - '0'); - c = *++cp; - digit = 1; - } else if (base == 16 && isascii(c) && isxdigit(c)) { - val = (val << 4) | - (c + 10 - (islower(c) ? 'a' : 'A')); - c = *++cp; - digit = 1; - } else - break; - } -#endif if (c == '.') { /* * Internet format: @@ -211,15 +171,11 @@ __inet_aton(const char *cp, struct in_addr *addr) if (addr != NULL) addr->s_addr = res.word | htonl (val); -#ifdef _LIBC __set_errno (saved_errno); -#endif return (1); ret_0: -#ifdef _LIBC __set_errno (saved_errno); -#endif return (0); } weak_alias (__inet_aton, inet_aton) diff --git a/resolv/inet_net_ntop.c b/resolv/inet_net_ntop.c index 2d57ae3030..aaa78f664b 100644 --- a/resolv/inet_net_ntop.c +++ b/resolv/inet_net_ntop.c @@ -15,10 +15,6 @@ * SOFTWARE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$BINDId: inet_net_ntop.c,v 1.6 1999/01/08 19:23:42 vixie Exp $"; -#endif - #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> diff --git a/resolv/inet_net_pton.c b/resolv/inet_net_pton.c index 75a8515c15..aab9b7b582 100644 --- a/resolv/inet_net_pton.c +++ b/resolv/inet_net_pton.c @@ -15,10 +15,6 @@ * SOFTWARE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$BINDId: inet_net_pton.c,v 1.11 1999/01/08 19:23:44 vixie Exp $"; -#endif - #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> diff --git a/resolv/inet_neta.c b/resolv/inet_neta.c index b9f256b9e5..f26932cdee 100644 --- a/resolv/inet_neta.c +++ b/resolv/inet_neta.c @@ -15,10 +15,6 @@ * SOFTWARE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$BINDId: inet_neta.c,v 1.6 1999/01/08 19:23:45 vixie Exp $"; -#endif - #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> @@ -46,7 +42,7 @@ static const char rcsid[] = "$BINDId: inet_neta.c,v 1.6 1999/01/08 19:23:45 vixi * Paul Vixie (ISC), July 1996 */ char * -inet_neta (u_int32_t src, char *dst, size_t size) +inet_neta (uint32_t src, char *dst, size_t size) { char *odst = dst; char *tp; diff --git a/resolv/inet_ntop.c b/resolv/inet_ntop.c index 32338c58b0..c4d38c0f95 100644 --- a/resolv/inet_ntop.c +++ b/resolv/inet_ntop.c @@ -15,10 +15,6 @@ * SOFTWARE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$BINDId: inet_ntop.c,v 1.8 1999/10/13 16:39:28 vixie Exp $"; -#endif /* LIBC_SCCS and not lint */ - #include <sys/param.h> #include <sys/types.h> #include <sys/socket.h> @@ -42,10 +38,8 @@ static const char rcsid[] = "$BINDId: inet_ntop.c,v 1.8 1999/10/13 16:39:28 vixi * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. */ -static const char *inet_ntop4 (const u_char *src, char *dst, socklen_t size) - internal_function; -static const char *inet_ntop6 (const u_char *src, char *dst, socklen_t size) - internal_function; +static const char *inet_ntop4 (const u_char *src, char *dst, socklen_t size); +static const char *inet_ntop6 (const u_char *src, char *dst, socklen_t size); /* char * * inet_ntop(af, src, dst, size) @@ -83,7 +77,6 @@ libc_hidden_def (inet_ntop) * Paul Vixie, 1996. */ static const char * -internal_function inet_ntop4 (const u_char *src, char *dst, socklen_t size) { static const char fmt[] = "%u.%u.%u.%u"; @@ -103,7 +96,6 @@ inet_ntop4 (const u_char *src, char *dst, socklen_t size) * Paul Vixie, 1996. */ static const char * -internal_function inet_ntop6 (const u_char *src, char *dst, socklen_t size) { /* diff --git a/resolv/inet_pton.c b/resolv/inet_pton.c index 0d18e9acb5..9cb21f9f82 100644 --- a/resolv/inet_pton.c +++ b/resolv/inet_pton.c @@ -1,3 +1,20 @@ +/* Copyright (C) 1996-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + /* * Copyright (c) 1996,1999 by Internet Software Consortium. * @@ -15,202 +32,203 @@ * SOFTWARE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$BINDId: inet_pton.c,v 1.7 1999/10/13 16:39:28 vixie Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/param.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <netinet/in.h> #include <arpa/inet.h> #include <arpa/nameser.h> #include <ctype.h> -#include <string.h> #include <errno.h> +#include <netinet/in.h> +#include <resolv/resolv-internal.h> +#include <string.h> +#include <sys/socket.h> +#include <sys/types.h> -/* - * WARNING: Don't even consider trying to compile this on a system where - * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. - */ +static int inet_pton4 (const char *src, const char *src_end, u_char *dst); +static int inet_pton6 (const char *src, const char *src_end, u_char *dst); -static int inet_pton4 (const char *src, u_char *dst) internal_function; -static int inet_pton6 (const char *src, u_char *dst) internal_function; - -/* int - * inet_pton(af, src, dst) - * convert from presentation format (which usually means ASCII printable) - * to network format (which is usually some kind of binary format). - * return: - * 1 if the address was valid for the specified address family - * 0 if the address wasn't valid (`dst' is untouched in this case) - * -1 if some other error occurred (`dst' is untouched in this case, too) - * author: - * Paul Vixie, 1996. - */ +int +__inet_pton_length (int af, const char *src, size_t srclen, void *dst) +{ + switch (af) + { + case AF_INET: + return inet_pton4 (src, src + srclen, dst); + case AF_INET6: + return inet_pton6 (src, src + srclen, dst); + default: + __set_errno (EAFNOSUPPORT); + return -1; + } +} +libc_hidden_def (__inet_pton_length) + +/* Like __inet_pton_length, but use strlen (SRC) as the length of + SRC. */ int __inet_pton (int af, const char *src, void *dst) { - switch (af) { - case AF_INET: - return (inet_pton4(src, dst)); - case AF_INET6: - return (inet_pton6(src, dst)); - default: - __set_errno (EAFNOSUPPORT); - return (-1); - } - /* NOTREACHED */ + return __inet_pton_length (af, src, strlen (src), dst); } libc_hidden_def (__inet_pton) weak_alias (__inet_pton, inet_pton) libc_hidden_weak (inet_pton) -/* int - * inet_pton4(src, dst) - * like inet_aton() but without all the hexadecimal, octal (with the - * exception of 0) and shorthand. - * return: - * 1 if `src' is a valid dotted quad, else 0. - * notice: - * does not touch `dst' unless it's returning 1. - * author: - * Paul Vixie, 1996. - */ +/* Like inet_aton but without all the hexadecimal, octal and shorthand + (and trailing garbage is not ignored). Return 1 if SRC is a valid + dotted quad, else 0. This function does not touch DST unless it's + returning 1. + Author: Paul Vixie, 1996. */ static int -internal_function -inet_pton4 (const char *src, u_char *dst) +inet_pton4 (const char *src, const char *end, unsigned char *dst) { - int saw_digit, octets, ch; - u_char tmp[NS_INADDRSZ], *tp; - - saw_digit = 0; - octets = 0; - *(tp = tmp) = 0; - while ((ch = *src++) != '\0') { - - if (ch >= '0' && ch <= '9') { - u_int new = *tp * 10 + (ch - '0'); - - if (saw_digit && *tp == 0) - return (0); - if (new > 255) - return (0); - *tp = new; - if (! saw_digit) { - if (++octets > 4) - return (0); - saw_digit = 1; - } - } else if (ch == '.' && saw_digit) { - if (octets == 4) - return (0); - *++tp = 0; - saw_digit = 0; - } else - return (0); - } - if (octets < 4) - return (0); - memcpy(dst, tmp, NS_INADDRSZ); - return (1); + int saw_digit, octets, ch; + unsigned char tmp[NS_INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while (src < end) + { + ch = *src++; + if (ch >= '0' && ch <= '9') + { + unsigned int new = *tp * 10 + (ch - '0'); + + if (saw_digit && *tp == 0) + return 0; + if (new > 255) + return 0; + *tp = new; + if (! saw_digit) + { + if (++octets > 4) + return 0; + saw_digit = 1; + } + } + else if (ch == '.' && saw_digit) + { + if (octets == 4) + return 0; + *++tp = 0; + saw_digit = 0; + } + else + return 0; + } + if (octets < 4) + return 0; + memcpy (dst, tmp, NS_INADDRSZ); + return 1; } -/* int - * inet_pton6(src, dst) - * convert presentation level address to network order binary form. - * return: - * 1 if `src' is a valid [RFC1884 2.2] address, else 0. - * notice: - * (1) does not touch `dst' unless it's returning 1. - * (2) :: in a full address is silently ignored. - * credit: - * inspired by Mark Andrews. - * author: - * Paul Vixie, 1996. - */ +/* Return the value of CH as a hexademical digit, or -1 if it is a + different type of character. */ +static int +hex_digit_value (char ch) +{ + if ('0' <= ch && ch <= '9') + return ch - '0'; + if ('a' <= ch && ch <= 'f') + return ch - 'a' + 10; + if ('A' <= ch && ch <= 'F') + return ch - 'A' + 10; + return -1; +} + +/* Convert presentation-level IPv6 address to network order binary + form. Return 1 if SRC is a valid [RFC1884 2.2] address, else 0. + This function does not touch DST unless it's returning 1. + Author: Paul Vixie, 1996. Inspired by Mark Andrews. */ static int -internal_function -inet_pton6 (const char *src, u_char *dst) +inet_pton6 (const char *src, const char *src_endp, unsigned char *dst) { - static const char xdigits[] = "0123456789abcdef"; - u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; - const char *curtok; - int ch, saw_xdigit; - u_int val; - - tp = memset(tmp, '\0', NS_IN6ADDRSZ); - endp = tp + NS_IN6ADDRSZ; - colonp = NULL; - /* Leading :: requires some special handling. */ - if (*src == ':') - if (*++src != ':') - return (0); - curtok = src; - saw_xdigit = 0; - val = 0; - while ((ch = tolower (*src++)) != '\0') { - const char *pch; - - pch = strchr(xdigits, ch); - if (pch != NULL) { - val <<= 4; - val |= (pch - xdigits); - if (val > 0xffff) - return (0); - saw_xdigit = 1; - continue; - } - if (ch == ':') { - curtok = src; - if (!saw_xdigit) { - if (colonp) - return (0); - colonp = tp; - continue; - } else if (*src == '\0') { - return (0); - } - if (tp + NS_INT16SZ > endp) - return (0); - *tp++ = (u_char) (val >> 8) & 0xff; - *tp++ = (u_char) val & 0xff; - saw_xdigit = 0; - val = 0; - continue; - } - if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) && - inet_pton4(curtok, tp) > 0) { - tp += NS_INADDRSZ; - saw_xdigit = 0; - break; /* '\0' was seen by inet_pton4(). */ - } - return (0); + unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *curtok; + int ch; + size_t xdigits_seen; /* Number of hex digits since colon. */ + unsigned int val; + + tp = memset (tmp, '\0', NS_IN6ADDRSZ); + endp = tp + NS_IN6ADDRSZ; + colonp = NULL; + + /* Leading :: requires some special handling. */ + if (src == src_endp) + return 0; + if (*src == ':') + { + ++src; + if (src == src_endp || *src != ':') + return 0; + } + + curtok = src; + xdigits_seen = 0; + val = 0; + while (src < src_endp) + { + ch = *src++; + int digit = hex_digit_value (ch); + if (digit >= 0) + { + if (xdigits_seen == 4) + return 0; + val <<= 4; + val |= digit; + if (val > 0xffff) + return 0; + ++xdigits_seen; + continue; } - if (saw_xdigit) { - if (tp + NS_INT16SZ > endp) - return (0); - *tp++ = (u_char) (val >> 8) & 0xff; - *tp++ = (u_char) val & 0xff; + if (ch == ':') + { + curtok = src; + if (xdigits_seen == 0) + { + if (colonp) + return 0; + colonp = tp; + continue; + } + else if (src == src_endp) + return 0; + if (tp + NS_INT16SZ > endp) + return 0; + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + xdigits_seen = 0; + val = 0; + continue; } - if (colonp != NULL) { - /* - * Since some memmove()'s erroneously fail to handle - * overlapping regions, we'll do the shift by hand. - */ - const int n = tp - colonp; - int i; - - if (tp == endp) - return (0); - for (i = 1; i <= n; i++) { - endp[- i] = colonp[n - i]; - colonp[n - i] = 0; - } - tp = endp; + if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) + && inet_pton4 (curtok, src_endp, tp) > 0) + { + tp += NS_INADDRSZ; + xdigits_seen = 0; + break; /* '\0' was seen by inet_pton4. */ } - if (tp != endp) - return (0); - memcpy(dst, tmp, NS_IN6ADDRSZ); - return (1); + return 0; + } + if (xdigits_seen > 0) + { + if (tp + NS_INT16SZ > endp) + return 0; + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + } + if (colonp != NULL) + { + /* Replace :: with zeros. */ + if (tp == endp) + /* :: would expand to a zero-width field. */ + return 0; + size_t n = tp - colonp; + memmove (endp - n, colonp, n); + memset (colonp, 0, endp - n - colonp); + tp = endp; + } + if (tp != endp) + return 0; + memcpy (dst, tmp, NS_IN6ADDRSZ); + return 1; } diff --git a/resolv/netdb.h b/resolv/netdb.h index 3aba530932..003800e882 100644 --- a/resolv/netdb.h +++ b/resolv/netdb.h @@ -1,4 +1,4 @@ - /* Copyright (C) 1996-2016 Free Software Foundation, Inc. + /* Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -25,7 +25,7 @@ #include <features.h> #include <netinet/in.h> -#include <stdint.h> +#include <bits/stdint-uintn.h> #ifdef __USE_MISC /* This is necessary to make this include file properly replace the Sun version. */ @@ -33,10 +33,8 @@ #endif #ifdef __USE_GNU -# define __need_sigevent_t -# include <bits/siginfo.h> -# define __need_timespec -# include <time.h> +# include <bits/types/sigevent_t.h> +# include <bits/types/struct_timespec.h> #endif #include <bits/netdb.h> @@ -607,10 +605,10 @@ struct gaicb in the current locale's character set) before looking it up. */ # define AI_CANONIDN 0x0080 /* Translate canonical name from IDN format. */ -# define AI_IDN_ALLOW_UNASSIGNED 0x0100 /* Don't reject unassigned Unicode - code points. */ -# define AI_IDN_USE_STD3_ASCII_RULES 0x0200 /* Validate strings according to - STD3 rules. */ +# define AI_IDN_ALLOW_UNASSIGNED \ + __glibc_macro_warning ("AI_IDN_ALLOW_UNASSIGNED is deprecated") 0x0100 +# define AI_IDN_USE_STD3_ASCII_RULES \ + __glibc_macro_warning ("AI_IDN_USE_STD3_ASCII_RULES is deprecated") 0x0200 # endif # define AI_NUMERICSERV 0x0400 /* Don't use name resolution. */ @@ -648,10 +646,10 @@ struct gaicb # define NI_DGRAM 16 /* Look up UDP service rather than TCP. */ # ifdef __USE_GNU # define NI_IDN 32 /* Convert name from IDN format. */ -# define NI_IDN_ALLOW_UNASSIGNED 64 /* Don't reject unassigned Unicode - code points. */ -# define NI_IDN_USE_STD3_ASCII_RULES 128 /* Validate strings according to - STD3 rules. */ +# define NI_IDN_ALLOW_UNASSIGNED \ + __glibc_macro_warning ("NI_IDN_ALLOW_UNASSIGNED is deprecated") 64 +# define NI_IDN_USE_STD3_ASCII_RULES \ + __glibc_macro_warning ("NI_IDN_USE_STD3_ASCII_RULES is deprecated") 128 # endif /* Translate name of a service location and/or a service name to set of diff --git a/resolv/ns_date.c b/resolv/ns_date.c index 9801ac46d4..8e94d1c4e8 100644 --- a/resolv/ns_date.c +++ b/resolv/ns_date.c @@ -15,10 +15,6 @@ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#if !defined(_LIBC) && !defined(lint) -static const char rcsid[] = "$Id$"; -#endif - /* Import. */ #include <arpa/nameser.h> @@ -43,10 +39,10 @@ static int datepart(const char *, int, int, int, int *); * digits required, no spaces allowed. */ -u_int32_t +uint32_t ns_datetosecs(const char *cp, int *errp) { struct tm time; - u_int32_t result; + uint32_t result; int mdays, i; static const int days_per_month[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; @@ -72,7 +68,7 @@ ns_datetosecs(const char *cp, int *errp) { * we will do it by hand. Roll up sleeves, curse the gods, begin! */ -#define SECS_PER_DAY ((u_int32_t)24*60*60) +#define SECS_PER_DAY ((uint32_t)24*60*60) #define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) result = time.tm_sec; /*%< Seconds */ diff --git a/resolv/ns_name.c b/resolv/ns_name.c index f355cf3444..73213fee2d 100644 --- a/resolv/ns_name.c +++ b/resolv/ns_name.c @@ -15,10 +15,6 @@ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#if !defined(_LIBC) && !defined(lint) -static const char rcsid[] = "$BINDId: ns_name.c,v 8.15 2000/03/30 22:53:46 vixie Exp $"; -#endif - #include <sys/types.h> #include <netinet/in.h> @@ -33,32 +29,10 @@ static const char rcsid[] = "$BINDId: ns_name.c,v 8.15 2000/03/30 22:53:46 vixie # define SPRINTF(x) ((size_t)sprintf x) -#define NS_TYPE_ELT 0x40 /*%< EDNS0 extended label type */ -#define DNS_LABELTYPE_BITSTRING 0x41 - /* Data. */ static const char digits[] = "0123456789"; -static const char digitvalue[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/ - 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/ - -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/ - -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/ - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/ -}; - /* Forward. */ static int special(int); @@ -66,12 +40,7 @@ static int printable(int); static int dn_find(const u_char *, const u_char *, const u_char * const *, const u_char * const *); -static int encode_bitstring(const char **, const char *, - unsigned char **, unsigned char **, - unsigned const char *); static int labellen(const u_char *); -static int decode_bitstring(const unsigned char **, - char *, const char *); /* Public. */ @@ -119,22 +88,6 @@ ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) __set_errno (EMSGSIZE); return (-1); } - if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) { - int m; - - if (n != DNS_LABELTYPE_BITSTRING) { - /* XXX: labellen should reject this case */ - __set_errno (EINVAL); - return(-1); - } - if ((m = decode_bitstring(&cp, dn, eom)) < 0) - { - __set_errno (EMSGSIZE); - return(-1); - } - dn += m; - continue; - } for ((void)NULL; l > 0; l--) { c = *cp++; if (special(c)) { @@ -196,7 +149,7 @@ int ns_name_pton(const char *src, u_char *dst, size_t dstsiz) { u_char *label, *bp, *eom; - int c, n, escaped, e = 0; + int c, n, escaped; char *cp; escaped = 0; @@ -206,28 +159,7 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz) while ((c = *src++) != 0) { if (escaped) { - if (c == '[') { /*%< start a bit string label */ - if ((cp = strchr(src, ']')) == NULL) { - __set_errno (EINVAL); - return(-1); - } - if ((e = encode_bitstring(&src, cp + 2, - &label, &bp, eom)) - != 0) { - __set_errno (e); - return(-1); - } - escaped = 0; - label = bp++; - if ((c = *src++) == 0) - goto done; - else if (c != '.') { - __set_errno (EINVAL); - return(-1); - } - continue; - } - else if ((cp = strchr(digits, c)) != NULL) { + if ((cp = strchr(digits, c)) != NULL) { n = (cp - digits) * 100; if ((c = *src++) == 0 || (cp = strchr(digits, c)) == NULL) { @@ -290,12 +222,16 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz) } *bp++ = (u_char)c; } + if (escaped) { + /* Trailing backslash. */ + __set_errno (EMSGSIZE); + return -1; + } c = (bp - label - 1); if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */ __set_errno (EMSGSIZE); return (-1); } - done: if (label >= eom) { __set_errno (EMSGSIZE); return (-1); @@ -398,7 +334,6 @@ ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, /* Check for indirection. */ switch (n & NS_CMPRSFLGS) { case 0: - case NS_TYPE_ELT: /* Limit checks. */ if ((l = labellen(srcp - 1)) < 0) { __set_errno (EMSGSIZE); @@ -545,7 +480,7 @@ ns_name_pack(const u_char *src, u_char *dst, int dstsiz, goto cleanup; } n = labellen(srcp); - if (dstp + 1 + n >= eob) { + if (n + 1 > eob - dstp) { goto cleanup; } memcpy(dstp, srcp, n + 1); @@ -643,7 +578,6 @@ ns_name_skip(const u_char **ptrptr, const u_char *eom) { const u_char *cp; u_int n; - int l; cp = *ptrptr; while (cp < eom && (n = *cp++) != 0) { @@ -652,13 +586,6 @@ ns_name_skip(const u_char **ptrptr, const u_char *eom) case 0: /*%< normal case, n == len */ cp += n; continue; - case NS_TYPE_ELT: /*%< EDNS0 extended label */ - if ((l = labellen(cp - 1)) < 0) { - __set_errno (EMSGSIZE); - return(-1); - } - cp += l; - continue; case NS_CMPRSFLGS: /*%< indirection */ cp++; break; @@ -795,180 +722,14 @@ dn_find(const u_char *domain, const u_char *msg, return (-1); } +/* Return the length of the encoded label starting at LP, or -1 for + compression references and extended label types. */ static int -decode_bitstring(const unsigned char **cpp, char *dn, const char *eom) -{ - const unsigned char *cp = *cpp; - char *beg = dn, tc; - int b, blen, plen, i; - - if ((blen = (*cp & 0xff)) == 0) - blen = 256; - plen = (blen + 3) / 4; - plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1); - if (dn + plen >= eom) - return(-1); - - cp++; - i = SPRINTF((dn, "\\[x")); - if (i < 0) - return (-1); - dn += i; - for (b = blen; b > 7; b -= 8, cp++) { - i = SPRINTF((dn, "%02x", *cp & 0xff)); - if (i < 0) - return (-1); - dn += i; - } - if (b > 4) { - tc = *cp++; - i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b)))); - if (i < 0) - return (-1); - dn += i; - } else if (b > 0) { - tc = *cp++; - i = SPRINTF((dn, "%1x", - ((tc >> 4) & 0x0f) & (0x0f << (4 - b)))); - if (i < 0) - return (-1); - dn += i; - } - i = SPRINTF((dn, "/%d]", blen)); - if (i < 0) - return (-1); - dn += i; - - *cpp = cp; - return(dn - beg); -} - -static int -encode_bitstring(const char **bp, const char *end, unsigned char **labelp, - unsigned char ** dst, unsigned const char *eom) +labellen (const unsigned char *lp) { - int afterslash = 0; - const char *cp = *bp; - unsigned char *tp; - char c; - const char *beg_blen; - char *end_blen = NULL; - int value = 0, count = 0, tbcount = 0, blen = 0; - - beg_blen = end_blen = NULL; - - /* a bitstring must contain at least 2 characters */ - if (end - cp < 2) - return(EINVAL); - - /* XXX: currently, only hex strings are supported */ - if (*cp++ != 'x') - return(EINVAL); - if (!isxdigit((*cp) & 0xff)) /*%< reject '\[x/BLEN]' */ - return(EINVAL); - - for (tp = *dst + 1; cp < end && tp < eom; cp++) { - switch((c = *cp)) { - case ']': /*%< end of the bitstring */ - if (afterslash) { - if (beg_blen == NULL) - return(EINVAL); - blen = (int)strtol(beg_blen, &end_blen, 10); - if (*end_blen != ']') - return(EINVAL); - } - if (count) - *tp++ = ((value << 4) & 0xff); - cp++; /*%< skip ']' */ - goto done; - case '/': - afterslash = 1; - break; - default: - if (afterslash) { - if (!isdigit(c&0xff)) - return(EINVAL); - if (beg_blen == NULL) { - - if (c == '0') { - /* blen never begings with 0 */ - return(EINVAL); - } - beg_blen = cp; - } - } else { - if (!isxdigit(c&0xff)) - return(EINVAL); - value <<= 4; - value += digitvalue[(int)c]; - count += 4; - tbcount += 4; - if (tbcount > 256) - return(EINVAL); - if (count == 8) { - *tp++ = value; - count = 0; - } - } - break; - } - } - done: - if (cp >= end || tp >= eom) - return(EMSGSIZE); - - /* - * bit length validation: - * If a <length> is present, the number of digits in the <bit-data> - * MUST be just sufficient to contain the number of bits specified - * by the <length>. If there are insignificant bits in a final - * hexadecimal or octal digit, they MUST be zero. - * RFC2673, Section 3.2. - */ - if (blen > 0) { - int traillen; - - if (((blen + 3) & ~3) != tbcount) - return(EINVAL); - traillen = tbcount - blen; /*%< between 0 and 3 */ - if (((value << (8 - traillen)) & 0xff) != 0) - return(EINVAL); - } - else - blen = tbcount; - if (blen == 256) - blen = 0; - - /* encode the type and the significant bit fields */ - **labelp = DNS_LABELTYPE_BITSTRING; - **dst = blen; - - *bp = cp; - *dst = tp; - - return(0); -} - -static int -labellen(const u_char *lp) -{ - int bitlen; - u_char l = *lp; - - if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) { - /* should be avoided by the caller */ - return(-1); - } - - if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) { - if (l == DNS_LABELTYPE_BITSTRING) { - if ((bitlen = *(lp + 1)) == 0) - bitlen = 256; - return((bitlen + 7 ) / 8 + 1); - } - return(-1); /*%< unknwon ELT */ - } - return(l); + if (*lp <= 63) + return *lp; + return -1; } /*! \file */ diff --git a/resolv/ns_netint.c b/resolv/ns_netint.c index 4318f18879..6a365a3b8c 100644 --- a/resolv/ns_netint.c +++ b/resolv/ns_netint.c @@ -15,10 +15,6 @@ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#if !defined(_LIBC) && !defined(lint) -static const char rcsid[] = "$BINDId: ns_netint.c,v 8.4 1999/10/13 16:39:35 vixie Exp $"; -#endif - /* Import. */ #include <arpa/nameser.h> diff --git a/resolv/ns_parse.c b/resolv/ns_parse.c index 712469be1d..863b20a9f7 100644 --- a/resolv/ns_parse.c +++ b/resolv/ns_parse.c @@ -15,10 +15,6 @@ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#if !defined(_LIBC) && !defined(lint) -static const char rcsid[] = "$BINDId: ns_parse.c,v 8.13 1999/10/13 16:39:35 vixie Exp $"; -#endif - /* Import. */ #include <sys/types.h> diff --git a/resolv/ns_print.c b/resolv/ns_print.c index 800680d371..d61f5044b1 100644 --- a/resolv/ns_print.c +++ b/resolv/ns_print.c @@ -16,10 +16,6 @@ * SOFTWARE. */ -#if !defined(_LIBC) && !defined(lint) -static const char rcsid[] = "$BINDId: ns_print.c,v 8.18 2000/02/29 05:48:12 vixie Exp $"; -#endif - /* Import. */ #include <sys/types.h> @@ -51,8 +47,6 @@ static int addstr(const char *src, size_t len, static int addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen); -static u_int16_t dst_s_dns_key_id(const u_char *, const int); - /* Macros. */ #define T(x) \ @@ -440,124 +434,6 @@ ns_sprintrrf(const u_char *msg, size_t msglen, break; } - case ns_t_key: { - char base64_key[NS_MD5RSA_MAX_BASE64]; - u_int keyflags, protocol, algorithm, key_id; - const char *leader; - int n; - - if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ) - goto formerr; - - /* Key flags, Protocol, Algorithm. */ - key_id = dst_s_dns_key_id(rdata, edata-rdata); - keyflags = ns_get16(rdata); rdata += NS_INT16SZ; - protocol = *rdata++; - algorithm = *rdata++; - len = SPRINTF((tmp, "0x%04x %u %u", - keyflags, protocol, algorithm)); - T(addstr(tmp, len, &buf, &buflen)); - - /* Public key data. */ - len = b64_ntop(rdata, edata - rdata, - base64_key, sizeof base64_key); - if (len < 0) - goto formerr; - if (len > 15) { - T(addstr(" (", 2, &buf, &buflen)); - leader = "\n\t\t"; - spaced = 0; - } else - leader = " "; - for (n = 0; n < len; n += 48) { - T(addstr(leader, strlen(leader), &buf, &buflen)); - T(addstr(base64_key + n, MIN(len - n, 48), - &buf, &buflen)); - } - if (len > 15) - T(addstr(" )", 2, &buf, &buflen)); - n = SPRINTF((tmp, " ; key_tag= %u", key_id)); - T(addstr(tmp, n, &buf, &buflen)); - - break; - } - - case ns_t_sig: { - char base64_key[NS_MD5RSA_MAX_BASE64]; - u_int type, algorithm, labels, footprint; - const char *leader; - u_long t; - int n; - - if (rdlen < 22U) - goto formerr; - - /* Type covered, Algorithm, Label count, Original TTL. */ - type = ns_get16(rdata); rdata += NS_INT16SZ; - algorithm = *rdata++; - labels = *rdata++; - t = ns_get32(rdata); rdata += NS_INT32SZ; - len = SPRINTF((tmp, "%s %d %d %lu ", - p_type(type), algorithm, labels, t)); - T(addstr(tmp, len, &buf, &buflen)); - if (labels > (u_int)dn_count_labels(name)) - goto formerr; - - /* Signature expiry. */ - t = ns_get32(rdata); rdata += NS_INT32SZ; - len = SPRINTF((tmp, "%s ", p_secstodate(t))); - T(addstr(tmp, len, &buf, &buflen)); - - /* Time signed. */ - t = ns_get32(rdata); rdata += NS_INT32SZ; - len = SPRINTF((tmp, "%s ", p_secstodate(t))); - T(addstr(tmp, len, &buf, &buflen)); - - /* Signature Footprint. */ - footprint = ns_get16(rdata); rdata += NS_INT16SZ; - len = SPRINTF((tmp, "%u ", footprint)); - T(addstr(tmp, len, &buf, &buflen)); - - /* Signer's name. */ - T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); - - /* Signature. */ - len = b64_ntop(rdata, edata - rdata, - base64_key, sizeof base64_key); - if (len > 15) { - T(addstr(" (", 2, &buf, &buflen)); - leader = "\n\t\t"; - spaced = 0; - } else - leader = " "; - if (len < 0) - goto formerr; - for (n = 0; n < len; n += 48) { - T(addstr(leader, strlen(leader), &buf, &buflen)); - T(addstr(base64_key + n, MIN(len - n, 48), - &buf, &buflen)); - } - if (len > 15) - T(addstr(" )", 2, &buf, &buflen)); - break; - } - - case ns_t_nxt: { - int n, c; - - /* Next domain name. */ - T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); - - /* Type bit map. */ - n = edata - rdata; - for (c = 0; c < n*8; c++) - if (NS_NXT_BIT_ISSET(c, rdata)) { - len = SPRINTF((tmp, " %s", p_type(c))); - T(addstr(tmp, len, &buf, &buflen)); - } - break; - } - case ns_t_cert: { u_int c_type, key_tag, alg; int n; @@ -612,12 +488,12 @@ ns_sprintrrf(const u_char *msg, size_t msglen, /* Inception. */ t = ns_get32(rdata); rdata += NS_INT32SZ; - len = SPRINTF((tmp, "%s ", p_secstodate(t))); + len = SPRINTF((tmp, "%lu ", t)); T(addstr(tmp, len, &buf, &buflen)); /* Experation. */ t = ns_get32(rdata); rdata += NS_INT32SZ; - len = SPRINTF((tmp, "%s ", p_secstodate(t))); + len = SPRINTF((tmp, "%lu ", t)); T(addstr(tmp, len, &buf, &buflen)); /* Mode , Error, Key Size. */ @@ -891,81 +767,3 @@ addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { } return (spaced); } - -/* DST algorithm codes */ -#define KEY_RSA 1 -#define KEY_HMAC_MD5 157 - -/*% - * calculates a checksum used in dst for an id. - * takes an array of bytes and a length. - * returns a 16 bit checksum. - */ -static u_int16_t -dst_s_id_calc(const u_char *key, const int keysize) -{ - u_int32_t ac; - const u_char *kp = key; - int size = keysize; - - if (!key || (keysize <= 0)) - return (0xffffU); - - for (ac = 0; size > 1; size -= 2, kp += 2) - ac += ((*kp) << 8) + *(kp + 1); - - if (size > 0) - ac += ((*kp) << 8); - ac += (ac >> 16) & 0xffff; - - return (ac & 0xffff); -} - -/*% - * dst_s_get_int16 - * This routine extracts a 16 bit integer from a two byte character - * string. The character string is assumed to be in network byte - * order and may be unaligned. The number returned is in host order. - * Parameter - * buf A two byte character string. - * Return - * The converted integer value. - */ - -static u_int16_t -dst_s_get_int16(const u_char *buf) -{ - u_int16_t a = 0; - a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1])); - return (a); -} - -/*% - * dst_s_dns_key_id() Function to calculate DNSSEC footprint from KEY record - * rdata - * Input: - * dns_key_rdata: the raw data in wire format - * rdata_len: the size of the input data - * Output: - * the key footprint/id calculated from the key data - */ -static u_int16_t -dst_s_dns_key_id(const u_char *dns_key_rdata, const int rdata_len) -{ - if (!dns_key_rdata) - return 0; - - /* compute id */ - if (dns_key_rdata[3] == KEY_RSA) /*%< Algorithm RSA */ - return dst_s_get_int16((const u_char *) - &dns_key_rdata[rdata_len - 3]); - else if (dns_key_rdata[3] == KEY_HMAC_MD5) - /* compatibility */ - return 0; - else - /* compute a checksum on the key part of the key rr */ - return dst_s_id_calc(dns_key_rdata, rdata_len); -} - - -/*! \file */ diff --git a/resolv/ns_samedomain.c b/resolv/ns_samedomain.c index df6a4a26fb..5d1bf39fc7 100644 --- a/resolv/ns_samedomain.c +++ b/resolv/ns_samedomain.c @@ -16,10 +16,6 @@ * SOFTWARE. */ -#if !defined(_LIBC) && !defined(lint) -static const char rcsid[] = "$BINDId: ns_samedomain.c,v 8.9 1999/10/15 21:06:51 vixie Exp $"; -#endif - #include <sys/types.h> #include <arpa/nameser.h> #include <errno.h> diff --git a/resolv/ns_ttl.c b/resolv/ns_ttl.c index d4c98bcf3a..079948790b 100644 --- a/resolv/ns_ttl.c +++ b/resolv/ns_ttl.c @@ -16,10 +16,6 @@ * SOFTWARE. */ -#if !defined(_LIBC) && !defined(lint) -static const char rcsid[] = "$BINDId: ns_ttl.c,v 8.8 1999/10/13 16:39:36 vixie Exp $"; -#endif - /* Import. */ #include <arpa/nameser.h> diff --git a/resolv/nsap_addr.c b/resolv/nsap_addr.c index 7041e5282e..9a1d3f7fdc 100644 --- a/resolv/nsap_addr.c +++ b/resolv/nsap_addr.c @@ -15,10 +15,6 @@ * SOFTWARE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$BINDId: nsap_addr.c,v 8.10 1999/10/13 16:39:28 vixie Exp $"; -#endif /* LIBC_SCCS and not lint */ - #include <sys/types.h> #include <sys/param.h> #include <sys/socket.h> diff --git a/resolv/nss_dns/dns-canon.c b/resolv/nss_dns/dns-canon.c index 27255fda58..b9e32cae52 100644 --- a/resolv/nss_dns/dns-canon.c +++ b/resolv/nss_dns/dns-canon.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2004-2016 Free Software Foundation, Inc. +/* Copyright (C) 2004-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. @@ -23,7 +23,8 @@ #include <stdint.h> #include <arpa/nameser.h> #include <nsswitch.h> - +#include <resolv/resolv_context.h> +#include <resolv/resolv-internal.h> #if PACKETSZ > 65536 # define MAXPACKET PACKETSZ @@ -58,11 +59,19 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen, } ansp = { .ptr = buf }; enum nss_status status = NSS_STATUS_UNAVAIL; + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { + *errnop = errno; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } + for (int i = 0; i < nqtypes; ++i) { - int r = __libc_res_nquery (&_res, name, ns_c_in, qtypes[i], - buf, sizeof (buf), &ansp.ptr, NULL, NULL, - NULL, NULL); + int r = __res_context_query (ctx, name, ns_c_in, qtypes[i], + buf, sizeof (buf), &ansp.ptr, NULL, NULL, + NULL, NULL); if (r > 0) { /* We need to decode the response. Just one question record. @@ -103,6 +112,11 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen, ptr += s; + /* Check that there are enough bytes for the RR + metadata. */ + if (endptr - ptr < 10) + goto unavail; + /* Check whether type and class match. */ uint_fast16_t type; NS_GET16 (type, ptr); @@ -137,13 +151,25 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen, if (__ns_get16 (ptr) != ns_c_in) goto unavail; - /* Also skip over the TTL. */ + /* Also skip over class and TTL. */ ptr += sizeof (uint16_t) + sizeof (uint32_t); - /* Skip over the data length and data. */ - ptr += sizeof (uint16_t) + __ns_get16 (ptr); + /* Skip over RDATA length and RDATA itself. */ + uint16_t rdatalen = __ns_get16 (ptr); + ptr += sizeof (uint16_t); + /* Not enough room for RDATA. */ + if (endptr - ptr < rdatalen) + goto unavail; + ptr += rdatalen; } } + + /* Restore original buffer before retry. */ + if (ansp.ptr != buf) + { + free (ansp.ptr); + ansp.ptr = buf; + } } out: @@ -151,6 +177,6 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen, if (ansp.ptr != buf) free (ansp.ptr); - + __resolv_context_put (ctx); return status; } diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c index 8599f4c6a6..5dc2829cd1 100644 --- a/resolv/nss_dns/dns-host.c +++ b/resolv/nss_dns/dns-host.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2016 Free Software Foundation, Inc. +/* Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -78,11 +78,14 @@ #include <stdlib.h> #include <stddef.h> #include <string.h> -#include <sys/syslog.h> #include "nsswitch.h" +#include <arpa/nameser.h> -/* Get implementation for some internal functions. */ +#include <resolv/resolv-internal.h> +#include <resolv/resolv_context.h> + +/* Get implementations of some internal functions. */ #include <resolv/mapv4v6addr.h> #include <resolv/mapv4v6hostent.h> @@ -99,10 +102,6 @@ #endif #define MAXHOSTNAMELEN 256 -static const char AskedForGot[] = "\ -gethostby*.getanswer: asked for \"%s\", got \"%s\""; - - /* We need this time later. */ typedef union querybuf { @@ -110,14 +109,8 @@ typedef union querybuf u_char buf[MAXPACKET]; } querybuf; -/* These functions are defined in res_comp.c. */ -#define NS_MAXCDNAME 255 /* maximum compressed domain name */ -extern int __ns_name_ntop (const u_char *, char *, size_t); -extern int __ns_name_unpack (const u_char *, const u_char *, - const u_char *, u_char *, size_t); - - -static enum nss_status getanswer_r (const querybuf *answer, int anslen, +static enum nss_status getanswer_r (struct resolv_context *ctx, + const querybuf *answer, int anslen, const char *qname, int qtype, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, @@ -131,19 +124,55 @@ static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1, int *errnop, int *h_errnop, int32_t *ttlp); -extern enum nss_status _nss_dns_gethostbyname3_r (const char *name, int af, - struct hostent *result, - char *buffer, size_t buflen, - int *errnop, int *h_errnop, - int32_t *ttlp, - char **canonp); -hidden_proto (_nss_dns_gethostbyname3_r) +static enum nss_status gethostbyname3_context (struct resolv_context *ctx, + const char *name, int af, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp, + char **canonp); + +/* Return the expected RDATA length for an address record type (A or + AAAA). */ +static int +rrtype_to_rdata_length (int type) +{ + switch (type) + { + case T_A: + return INADDRSZ; + case T_AAAA: + return IN6ADDRSZ; + default: + return -1; + } +} + enum nss_status _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, int32_t *ttlp, char **canonp) { + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { + *errnop = errno; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } + enum nss_status status = gethostbyname3_context + (ctx, name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp); + __resolv_context_put (ctx); + return status; +} + +static enum nss_status +gethostbyname3_context (struct resolv_context *ctx, + const char *name, int af, struct hostent *result, + char *buffer, size_t buflen, int *errnop, + int *h_errnop, int32_t *ttlp, char **canonp) +{ union { querybuf *buf; @@ -157,9 +186,6 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result, int olderr = errno; enum nss_status status; - if (__res_maybe_init (&_res, 0) == -1) - return NSS_STATUS_UNAVAIL; - switch (af) { case AF_INET: size = INADDRSZ; @@ -184,13 +210,13 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result, * function that looks up host names. */ if (strchr (name, '.') == NULL - && (cp = res_hostalias (&_res, name, tmp, sizeof (tmp))) != NULL) + && (cp = __res_context_hostalias (ctx, name, tmp, sizeof (tmp))) != NULL) name = cp; host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024); - n = __libc_res_nsearch (&_res, name, C_IN, type, host_buffer.buf->buf, - 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); + n = __res_context_search (ctx, name, C_IN, type, host_buffer.buf->buf, + 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); if (n < 0) { switch (errno) @@ -221,11 +247,11 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result, /* If we are looking for an IPv6 address and mapping is enabled by having the RES_USE_INET6 bit in _res.options set, we try another lookup. */ - if (af == AF_INET6 && (_res.options & RES_USE_INET6)) - n = __libc_res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf->buf, - host_buffer.buf != orig_host_buffer - ? MAXPACKET : 1024, &host_buffer.ptr, - NULL, NULL, NULL, NULL); + if (af == AF_INET6 && res_use_inet6 ()) + n = __res_context_search (ctx, name, C_IN, T_A, host_buffer.buf->buf, + host_buffer.buf != orig_host_buffer + ? MAXPACKET : 1024, &host_buffer.ptr, + NULL, NULL, NULL, NULL); if (n < 0) { @@ -240,14 +266,13 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result, result->h_length = INADDRSZ; } - status = getanswer_r (host_buffer.buf, n, name, type, result, buffer, buflen, - errnop, h_errnop, map, ttlp, canonp); + status = getanswer_r + (ctx, host_buffer.buf, n, name, type, result, buffer, buflen, + errnop, h_errnop, map, ttlp, canonp); if (host_buffer.buf != orig_host_buffer) free (host_buffer.buf); return status; } -hidden_def (_nss_dns_gethostbyname3_r) - enum nss_status _nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result, @@ -264,15 +289,21 @@ _nss_dns_gethostbyname_r (const char *name, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop) { + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { + *errnop = errno; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } enum nss_status status = NSS_STATUS_NOTFOUND; - - if (_res.options & RES_USE_INET6) - status = _nss_dns_gethostbyname3_r (name, AF_INET6, result, buffer, - buflen, errnop, h_errnop, NULL, NULL); + if (res_use_inet6 ()) + status = gethostbyname3_context (ctx, name, AF_INET6, result, buffer, + buflen, errnop, h_errnop, NULL, NULL); if (status == NSS_STATUS_NOTFOUND) - status = _nss_dns_gethostbyname3_r (name, AF_INET, result, buffer, - buflen, errnop, h_errnop, NULL, NULL); - + status = gethostbyname3_context (ctx, name, AF_INET, result, buffer, + buflen, errnop, h_errnop, NULL, NULL); + __resolv_context_put (ctx); return status; } @@ -282,8 +313,13 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, char *buffer, size_t buflen, int *errnop, int *herrnop, int32_t *ttlp) { - if (__res_maybe_init (&_res, 0) == -1) - return NSS_STATUS_UNAVAIL; + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { + *errnop = errno; + *herrnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } /* * if there aren't any dots, it could be a user-level alias. @@ -293,7 +329,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, if (strchr (name, '.') == NULL) { char *tmp = alloca (NS_MAXDNAME); - const char *cp = res_hostalias (&_res, name, tmp, NS_MAXDNAME); + const char *cp = __res_context_hostalias (ctx, name, tmp, NS_MAXDNAME); if (cp != NULL) name = cp; } @@ -312,9 +348,9 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, int olderr = errno; enum nss_status status; - int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC, - host_buffer.buf->buf, 2048, &host_buffer.ptr, - &ans2p, &nans2p, &resplen2, &ans2p_malloced); + int n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA, + host_buffer.buf->buf, 2048, &host_buffer.ptr, + &ans2p, &nans2p, &resplen2, &ans2p_malloced); if (n >= 0) { status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p, @@ -357,6 +393,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat, if (host_buffer.buf != orig_host_buffer) free (host_buffer.buf); + __resolv_context_put (ctx); return status; } @@ -409,8 +446,13 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, host_data = (struct host_data *) buffer; - if (__res_maybe_init (&_res, 0) == -1) - return NSS_STATUS_UNAVAIL; + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { + *errnop = errno; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } if (af == AF_INET6 && len == IN6ADDRSZ && (memcmp (uaddr, mapped, sizeof mapped) == 0 @@ -435,12 +477,14 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, default: *errnop = EAFNOSUPPORT; *h_errnop = NETDB_INTERNAL; + __resolv_context_put (ctx); return NSS_STATUS_UNAVAIL; } if (size > len) { *errnop = EAFNOSUPPORT; *h_errnop = NETDB_INTERNAL; + __resolv_context_put (ctx); return NSS_STATUS_UNAVAIL; } @@ -453,19 +497,6 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff)); break; case AF_INET6: - /* Only lookup with the byte string format if the user wants it. */ - if (__glibc_unlikely (_res.options & RES_USEBSTRING)) - { - qp = stpcpy (qbuf, "\\[x"); - for (n = 0; n < IN6ADDRSZ; ++n) - qp += sprintf (qp, "%02hhx", uaddr[n]); - strcpy (qp, "].ip6.arpa"); - n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, - host_buffer.buf->buf, 1024, &host_buffer.ptr, - NULL, NULL, NULL, NULL); - if (n >= 0) - goto got_it_already; - } qp = qbuf; for (n = IN6ADDRSZ - 1; n >= 0; n--) { @@ -482,55 +513,36 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, break; } - n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf, - 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); - if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) - { - strcpy (qp, "ip6.int"); - n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf, - host_buffer.buf != orig_host_buffer - ? MAXPACKET : 1024, &host_buffer.ptr, - NULL, NULL, NULL, NULL); - } + n = __res_context_query (ctx, qbuf, C_IN, T_PTR, host_buffer.buf->buf, + 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL); if (n < 0) { *h_errnop = h_errno; __set_errno (olderr); if (host_buffer.buf != orig_host_buffer) free (host_buffer.buf); + __resolv_context_put (ctx); return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND; } - got_it_already: - status = getanswer_r (host_buffer.buf, n, qbuf, T_PTR, result, buffer, buflen, - errnop, h_errnop, 0 /* XXX */, ttlp, NULL); + status = getanswer_r + (ctx, host_buffer.buf, n, qbuf, T_PTR, result, buffer, buflen, + errnop, h_errnop, 0 /* XXX */, ttlp, NULL); if (host_buffer.buf != orig_host_buffer) free (host_buffer.buf); if (status != NSS_STATUS_SUCCESS) - return status; - -#ifdef SUNSECURITY - This is not implemented because it is not possible to use the current - source from bind in a multi-threaded program. -#endif + { + __resolv_context_put (ctx); + return status; + } result->h_addrtype = af; result->h_length = len; memcpy (host_data->host_addr, addr, len); host_data->h_addr_ptrs[0] = (char *) host_data->host_addr; host_data->h_addr_ptrs[1] = NULL; -#if 0 - /* XXX I think this is wrong. Why should an IPv4 address be - converted to IPv6 if the user explicitly asked for IPv4? */ - if (af == AF_INET && (_res.options & RES_USE_INET6)) - { - map_v4v6_address ((char *) host_data->host_addr, - (char *) host_data->host_addr); - result->h_addrtype = AF_INET6; - result->h_length = IN6ADDRSZ; - } -#endif *h_errnop = NETDB_SUCCESS; + __resolv_context_put (ctx); return NSS_STATUS_SUCCESS; } hidden_def (_nss_dns_gethostbyaddr2_r) @@ -545,26 +557,27 @@ _nss_dns_gethostbyaddr_r (const void *addr, socklen_t len, int af, errnop, h_errnop, NULL); } -#ifdef RESOLVSORT -static void addrsort (char **ap, int num); - static void -addrsort (char **ap, int num) +addrsort (struct resolv_context *ctx, char **ap, int num) { int i, j; char **p; short aval[MAX_NR_ADDRS]; int needsort = 0; + size_t nsort = __resolv_context_sort_count (ctx); p = ap; if (num > MAX_NR_ADDRS) num = MAX_NR_ADDRS; for (i = 0; i < num; i++, p++) { - for (j = 0 ; (unsigned)j < _res.nsort; j++) - if (_res.sort_list[j].addr.s_addr == - (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask)) - break; + for (j = 0 ; (unsigned)j < nsort; j++) + { + struct resolv_sortlist_entry e + = __resolv_context_sort_entry (ctx, j); + if (e.addr.s_addr == (((struct in_addr *)(*p))->s_addr & e.mask)) + break; + } aval[i] = j; if (needsort == 0 && i > 0 && j < aval[i-1]) needsort = i; @@ -589,10 +602,10 @@ addrsort (char **ap, int num) else break; } -#endif static enum nss_status -getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, +getanswer_r (struct resolv_context *ctx, + const querybuf *answer, int anslen, const char *qname, int qtype, struct hostent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, int map, int32_t *ttlp, char **canonp) { @@ -653,7 +666,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, ancount = ntohs (hp->ancount); qdcount = ntohs (hp->qdcount); cp = answer->buf + HFIXEDSZ; - if (__builtin_expect (qdcount, 1) != 1) + if (__glibc_unlikely (qdcount != 1)) { *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; @@ -667,7 +680,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, packtmp, sizeof packtmp); if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1) { - if (__builtin_expect (errno, 0) == EMSGSIZE) + if (__glibc_unlikely (errno == EMSGSIZE)) goto too_small; n = -1; @@ -676,13 +689,19 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, if (n > 0 && bp[0] == '.') bp[0] = '\0'; - if (__builtin_expect (n < 0 || ((*name_ok) (bp) == 0 && (errno = EBADMSG)), - 0)) + if (__glibc_unlikely (n < 0)) { *errnop = errno; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; } + if (__glibc_unlikely (name_ok (bp) == 0)) + { + errno = EBADMSG; + *errnop = EBADMSG; + *h_errnop = NO_RECOVERY; + return NSS_STATUS_UNAVAIL; + } cp += n + QFIXEDSZ; if (qtype == T_A || qtype == T_AAAA) @@ -724,7 +743,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, packtmp, sizeof packtmp); if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1) { - if (__builtin_expect (errno, 0) == EMSGSIZE) + if (__glibc_unlikely (errno == EMSGSIZE)) goto too_small; n = -1; @@ -751,6 +770,14 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, cp += INT32SZ; /* TTL */ n = __ns_get16 (cp); cp += INT16SZ; /* len */ + + if (end_of_message - cp < n) + { + /* RDATA extends beyond the end of the packet. */ + ++had_error; + continue; + } + if (__glibc_unlikely (class != C_IN)) { /* XXX - debug? syslog? */ @@ -776,7 +803,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, /* Store alias. */ *ap++ = bp; n = strlen (bp) + 1; /* For the \0. */ - if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN) + if (__glibc_unlikely (n >= MAXHOSTNAMELEN)) { ++had_error; continue; @@ -787,7 +814,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, n = strlen (tbuf) + 1; /* For the \0. */ if (__glibc_unlikely (n > linebuflen)) goto too_small; - if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN) + if (__glibc_unlikely (n >= MAXHOSTNAMELEN)) { ++had_error; continue; @@ -815,7 +842,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, n = strlen (tbuf) + 1; /* For the \0. */ if (__glibc_unlikely (n > linebuflen)) goto too_small; - if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN) + if (__glibc_unlikely (n >= MAXHOSTNAMELEN)) { ++had_error; continue; @@ -830,14 +857,6 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, have_to_map = 1; else if (__glibc_unlikely (type != qtype)) { - /* Log a low priority message if we get an unexpected record, but - skip it if we are using DNSSEC since it uses many different types - in responses that do not match QTYPE. */ - if ((_res.options & RES_USE_DNSSEC) == 0) - syslog (LOG_NOTICE | LOG_AUTH, - "gethostby*.getanswer: asked for \"%s %s %s\", " - "got type \"%s\"", - qname, p_class (C_IN), p_type (qtype), p_type (type)); cp += n; continue; /* XXX - had_error++ ? */ } @@ -847,7 +866,6 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, case T_PTR: if (__glibc_unlikely (strcasecmp (tname, bp) != 0)) { - syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, qname, bp); cp += n; continue; /* XXX - had_error++ ? */ } @@ -856,7 +874,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, packtmp, sizeof packtmp); if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1) { - if (__builtin_expect (errno, 0) == EMSGSIZE) + if (__glibc_unlikely (errno == EMSGSIZE)) goto too_small; n = -1; @@ -872,29 +890,24 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, /* bind would put multiple PTR records as aliases, but we don't do that. */ result->h_name = bp; - if (have_to_map) - { - n = strlen (bp) + 1; /* for the \0 */ - if (__glibc_unlikely (n >= MAXHOSTNAMELEN)) - { - ++had_error; - break; - } - bp += n; - linebuflen -= n; - if (map_v4v6_hostent (result, &bp, &linebuflen)) - goto too_small; - } *h_errnop = NETDB_SUCCESS; return NSS_STATUS_SUCCESS; case T_A: case T_AAAA: - if (__builtin_expect (strcasecmp (result->h_name, bp), 0) != 0) + if (__glibc_unlikely (strcasecmp (result->h_name, bp) != 0)) { - syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, result->h_name, bp); cp += n; continue; /* XXX - had_error++ ? */ } + + /* Stop parsing at a record whose length is incorrect. */ + if (n != rrtype_to_rdata_length (type)) + { + ++had_error; + break; + } + + /* Skip records of the wrong type. */ if (n != result->h_length) { cp += n; @@ -937,15 +950,14 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype, { *ap = NULL; *hap = NULL; -#if defined RESOLVSORT /* * Note: we sort even if host can take only one address * in its return structures - should give it the "best" * address in that case, not some random one */ - if (_res.nsort && haveanswer > 1 && qtype == T_A) - addrsort (host_data->h_addr_ptrs, haveanswer); -#endif /*RESOLVSORT*/ + if (haveanswer > 1 && qtype == T_A + && __resolv_context_sort_count (ctx) > 0) + addrsort (ctx, host_data->h_addr_ptrs, haveanswer); if (result->h_name == NULL) { @@ -1004,7 +1016,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, it later. */ if (n != -1 && __ns_name_ntop (packtmp, buffer, buflen) == -1) { - if (__builtin_expect (errno, 0) == EMSGSIZE) + if (__glibc_unlikely (errno == EMSGSIZE)) { too_small: *errnop = ERANGE; @@ -1015,13 +1027,19 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, n = -1; } - if (__builtin_expect (n < 0 || (res_hnok (buffer) == 0 - && (errno = EBADMSG)), 0)) + if (__glibc_unlikely (n < 0)) { *errnop = errno; *h_errnop = NO_RECOVERY; return NSS_STATUS_UNAVAIL; } + if (__glibc_unlikely (res_hnok (buffer) == 0)) + { + errno = EBADMSG; + *errnop = EBADMSG; + *h_errnop = NO_RECOVERY; + return NSS_STATUS_UNAVAIL; + } cp += n + QFIXEDSZ; int haveanswer = 0; @@ -1043,7 +1061,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, if (n != -1 && (h_namelen = __ns_name_ntop (packtmp, buffer, buflen)) == -1) { - if (__builtin_expect (errno, 0) == EMSGSIZE) + if (__glibc_unlikely (errno == EMSGSIZE)) goto too_small; n = -1; @@ -1077,6 +1095,13 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, n = __ns_get16 (cp); cp += INT16SZ; /* len */ + if (end_of_message - cp < n) + { + /* RDATA extends beyond the end of the packet. */ + ++had_error; + continue; + } + if (class != C_IN) { cp += n; @@ -1124,32 +1149,25 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, } continue; } -#if 1 - // We should not see any types other than those explicitly listed - // below. Some types sent by server seem missing, though. Just - // collect the data for now. - if (__glibc_unlikely (type != T_A && type != T_AAAA)) -#else - if (__builtin_expect (type == T_SIG, 0) - || __builtin_expect (type == T_KEY, 0) - || __builtin_expect (type == T_NXT, 0) - || __builtin_expect (type == T_PTR, 0) - || __builtin_expect (type == T_DNAME, 0)) -#endif - { - /* We don't support DNSSEC yet. For now, ignore the record - and send a low priority message to syslog. - We also don't expect T_PTR or T_DNAME messages. */ - syslog (LOG_DEBUG | LOG_AUTH, - "getaddrinfo*.gaih_getanswer: got type \"%s\"", - p_type (type)); + /* Stop parsing if we encounter a record with incorrect RDATA + length. */ + if (type == T_A || type == T_AAAA) + { + if (n != rrtype_to_rdata_length (type)) + { + ++had_error; + continue; + } + } + else + { + /* Skip unknown records. */ cp += n; continue; } - if (type != T_A && type != T_AAAA) - abort (); + assert (type == T_A || type == T_AAAA); if (*pat == NULL) { uintptr_t pad = (-(uintptr_t) buffer @@ -1157,8 +1175,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, buffer += pad; buflen = buflen > pad ? buflen - pad : 0; - if (__builtin_expect (buflen < sizeof (struct gaih_addrtuple), - 0)) + if (__glibc_unlikely (buflen < sizeof (struct gaih_addrtuple))) goto too_small; *pat = (struct gaih_addrtuple *) buffer; @@ -1183,12 +1200,6 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, } (*pat)->family = type == T_A ? AF_INET : AF_INET6; - if (__builtin_expect ((type == T_A && n != INADDRSZ) - || (type == T_AAAA && n != IN6ADDRSZ), 0)) - { - ++had_error; - continue; - } memcpy ((*pat)->addr, cp, n); cp += n; (*pat)->scopeid = 0; diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c index 2eb2f67e66..61bddd754f 100644 --- a/resolv/nss_dns/dns-network.c +++ b/resolv/nss_dns/dns-network.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2016 Free Software Foundation, Inc. +/* Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996. @@ -62,9 +62,13 @@ #include <stdlib.h> #include <string.h> #include <stdint.h> +#include <stddef.h> #include "nsswitch.h" #include <arpa/inet.h> +#include <arpa/nameser.h> +#include <resolv/resolv-internal.h> +#include <resolv/resolv_context.h> /* Maximum number of aliases we allow. */ #define MAX_NR_ALIASES 48 @@ -91,13 +95,6 @@ typedef union querybuf u_char buf[MAXPACKET]; } querybuf; -/* These functions are defined in res_comp.c. */ -#define NS_MAXCDNAME 255 /* maximum compressed domain name */ -extern int __ns_name_ntop (const u_char *, char *, size_t) __THROW; -extern int __ns_name_unpack (const u_char *, const u_char *, - const u_char *, u_char *, size_t) __THROW; - - /* Prototypes for local functions. */ static enum nss_status getanswer_r (const querybuf *answer, int anslen, struct netent *result, char *buffer, @@ -118,24 +115,28 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result, } net_buffer; querybuf *orig_net_buffer; int anslen; - char *qbuf; enum nss_status status; - if (__res_maybe_init (&_res, 0) == -1) - return NSS_STATUS_UNAVAIL; - - qbuf = strdupa (name); + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { + *errnop = errno; + *herrnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); - anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf, - 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); + anslen = __res_context_search + (ctx, name, C_IN, T_PTR, net_buffer.buf->buf, + 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); if (anslen < 0) { /* Nothing found. */ *errnop = errno; if (net_buffer.buf != orig_net_buffer) free (net_buffer.buf); + __resolv_context_put (ctx); return (errno == ECONNREFUSED || errno == EPFNOSUPPORT || errno == EAFNOSUPPORT) @@ -146,6 +147,7 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result, errnop, herrnop, BYNAME); if (net_buffer.buf != orig_net_buffer) free (net_buffer.buf); + __resolv_context_put (ctx); return status; } @@ -166,17 +168,22 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result, unsigned int net_bytes[4]; char qbuf[MAXDNAME]; int cnt, anslen; - u_int32_t net2; + uint32_t net2; int olderr = errno; /* No net address lookup for IPv6 yet. */ if (type != AF_INET) return NSS_STATUS_UNAVAIL; - if (__res_maybe_init (&_res, 0) == -1) - return NSS_STATUS_UNAVAIL; + struct resolv_context *ctx = __resolv_context_get (); + if (ctx == NULL) + { + *errnop = errno; + *herrnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } - net2 = (u_int32_t) net; + net2 = (uint32_t) net; for (cnt = 4; net2 != 0; net2 >>= 8) net_bytes[--cnt] = net2 & 0xff; @@ -204,8 +211,8 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result, net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); - anslen = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf, - 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); + anslen = __res_context_query (ctx, qbuf, C_IN, T_PTR, net_buffer.buf->buf, + 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL); if (anslen < 0) { /* Nothing found. */ @@ -213,6 +220,7 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result, __set_errno (olderr); if (net_buffer.buf != orig_net_buffer) free (net_buffer.buf); + __resolv_context_put (ctx); return (err == ECONNREFUSED || err == EPFNOSUPPORT || err == EAFNOSUPPORT) @@ -233,13 +241,11 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result, result->n_net = u_net; } + __resolv_context_put (ctx); return status; } -#undef offsetof -#define offsetof(Type, Member) ((size_t) &((Type *) NULL)->Member) - static enum nss_status getanswer_r (const querybuf *answer, int anslen, struct netent *result, char *buffer, size_t buflen, int *errnop, int *h_errnop, @@ -329,11 +335,8 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result, while (--answer_count >= 0 && cp < end_of_message) { - int n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen); - int type, class; - - n = __ns_name_unpack (answer->buf, end_of_message, cp, - packtmp, sizeof packtmp); + int n = __ns_name_unpack (answer->buf, end_of_message, cp, + packtmp, sizeof packtmp); if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1) { if (errno == EMSGSIZE) @@ -348,10 +351,24 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result, if (n < 0 || res_dnok (bp) == 0) break; cp += n; + + if (end_of_message - cp < 10) + { + __set_h_errno (NO_RECOVERY); + return NSS_STATUS_UNAVAIL; + } + + int type, class; GETSHORT (type, cp); GETSHORT (class, cp); cp += INT32SZ; /* TTL */ - GETSHORT (n, cp); + uint16_t rdatalen; + GETSHORT (rdatalen, cp); + if (end_of_message - cp < rdatalen) + { + __set_h_errno (NO_RECOVERY); + return NSS_STATUS_UNAVAIL; + } if (class == C_IN && type == T_PTR) { @@ -373,7 +390,7 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result, cp += n; return NSS_STATUS_UNAVAIL; } - cp += n; + cp += rdatalen; if (alias_pointer + 2 < &net_data->aliases[MAX_NR_ALIASES]) { *alias_pointer++ = bp; @@ -384,6 +401,9 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result, ++have_answer; } } + else + /* Skip over unknown record data. */ + cp += rdatalen; } if (have_answer) diff --git a/resolv/res-close.c b/resolv/res-close.c new file mode 100644 index 0000000000..1c36dd5f1d --- /dev/null +++ b/resolv/res-close.c @@ -0,0 +1,144 @@ +/* Deallocation functions for the resolver state. + Copyright (C) 1995-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* + * Copyright (c) 1985, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include <resolv-internal.h> +#include <resolv_context.h> +#include <resolv_conf.h> +#include <not-cancel.h> +#include <stdlib.h> + +/* Close all open sockets. If FREE_ADDR is true, deallocate any + separately allocated name server addresses. */ +void +__res_iclose (res_state statp, bool free_addr) +{ + if (statp->_vcsock >= 0) + { + __close_nocancel_nostatus (statp->_vcsock); + statp->_vcsock = -1; + statp->_flags &= ~(RES_F_VC | RES_F_CONN); + } + for (int ns = 0; ns < statp->nscount; ns++) + if (statp->_u._ext.nsaddrs[ns] != NULL) + { + if (statp->_u._ext.nssocks[ns] != -1) + { + __close_nocancel_nostatus (statp->_u._ext.nssocks[ns]); + statp->_u._ext.nssocks[ns] = -1; + } + if (free_addr) + { + free (statp->_u._ext.nsaddrs[ns]); + statp->_u._ext.nsaddrs[ns] = NULL; + } + } + if (free_addr) + __resolv_conf_detach (statp); +} +libc_hidden_def (__res_iclose) + +void +res_nclose (res_state statp) +{ + __res_iclose (statp, true); +} +libc_hidden_def (__res_nclose) + +/* This is called when a thread is exiting to free resources held in _res. */ +void +__res_thread_freeres (void) +{ + __resolv_context_freeres (); + + if (_res.nscount == 0) + /* Never called res_ninit. */ + return; + + __res_iclose (&_res, true); /* Close any VC sockets. */ + + /* Make sure we do a full re-initialization the next time. */ + _res.options = 0; +} +/* Also must be called when the main thread exits. */ +text_set_element (__libc_subfreeres, __res_thread_freeres); diff --git a/resolv/res-state.c b/resolv/res-state.c index 1eb83523ff..010ae3707d 100644 --- a/resolv/res-state.c +++ b/resolv/res-state.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1996-2016 Free Software Foundation, Inc. +/* Copyright (C) 1996-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/resolv/res_comp.c b/resolv/res_comp.c index 2ff7ddb1cd..367ca3017d 100644 --- a/resolv/res_comp.c +++ b/resolv/res_comp.c @@ -1,3 +1,21 @@ +/* Domain name processing functions. + Copyright (C) 1995-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + /* * Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. @@ -64,11 +82,6 @@ * SOFTWARE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static const char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "$BINDId: res_comp.c,v 8.15 1999/10/13 16:39:39 vixie Exp $"; -#endif /* LIBC_SCCS and not lint */ - #include <sys/types.h> #include <sys/param.h> #include <netinet/in.h> @@ -126,114 +139,121 @@ dn_skipname(const u_char *ptr, const u_char *eom) { } libresolv_hidden_def (dn_skipname) -/* - * Verify that a domain name uses an acceptable character set. - */ +/* Return true if the string consists of printable ASCII characters + only. */ +static bool +printable_string (const char *dn) +{ + while (true) + { + char ch = *dn; + if (ch == '\0') + return true; + if (ch <= ' ' || ch > '~') + return false; + ++dn; + } +} -/* - * Note the conspicuous absence of ctype macros in these definitions. On - * non-ASCII hosts, we can't depend on string literals or ctype macros to - * tell us anything about network-format data. The rest of the BIND system - * is not careful about this, but for some reason, we're doing it right here. - */ -#define PERIOD 0x2e -#define hyphenchar(c) ((c) == 0x2d) -#define underscorechar(c) ((c) == 0x5f) -#define bslashchar(c) ((c) == 0x5c) -#define periodchar(c) ((c) == PERIOD) -#define asterchar(c) ((c) == 0x2a) -#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \ - || ((c) >= 0x61 && (c) <= 0x7a)) -#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) +/* Return true if DN points to a name consisting only of [0-9a-zA-Z_-] + characters. DN must be in DNS wire format, without + compression. */ +static bool +binary_hnok (const unsigned char *dn) +{ + while (true) + { + size_t label_length = *dn; + if (label_length == 0) + break; + ++dn; + const unsigned char *label_end = dn + label_length; + do + { + unsigned char ch = *dn; + if (!(('0' <= ch && ch <= '9') + || ('A' <= ch && ch <= 'Z') + || ('a' <= ch && ch <= 'z') + || ch == '-' || ch == '_')) + return false; + ++dn; + } + while (dn < label_end); + } + return true; +} -#define borderchar(c) (alphachar(c) || digitchar(c)) -#define middlechar(c) (borderchar(c) || hyphenchar(c) || underscorechar(c)) -#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) +/* Return true if the binary domain name has a first labels which + starts with '-'. */ +static inline bool +binary_leading_dash (const unsigned char *dn) +{ + return dn[0] > 0 && dn[1] == '-'; +} +/* Return 1 if res_hnok is a valid host name. Labels must only + contain [0-9a-zA-Z_-] characters, and the name must not start with + a '-'. The latter is to avoid confusion with program options. */ int -res_hnok(const char *dn) { - int pch = PERIOD, ch = *dn++; - - while (ch != '\0') { - int nch = *dn++; - - if (periodchar(ch)) { - (void)NULL; - } else if (periodchar(pch)) { - if (!borderchar(ch)) - return (0); - } else if (periodchar(nch) || nch == '\0') { - if (!borderchar(ch)) - return (0); - } else { - if (!middlechar(ch)) - return (0); - } - pch = ch, ch = nch; - } - return (1); +res_hnok (const char *dn) +{ + unsigned char buf[NS_MAXCDNAME]; + if (!printable_string (dn) + || ns_name_pton (dn, buf, sizeof (buf)) < 0 + || binary_leading_dash (buf)) + return 0; + return binary_hnok (buf); } libresolv_hidden_def (res_hnok) -/* - * hostname-like (A, MX, WKS) owners can have "*" as their first label - * but must otherwise be as a host name. - */ +/* Hostname-like (A, MX, WKS) owners can have "*" as their first label + but must otherwise be as a host name. */ int -res_ownok(const char *dn) { - if (asterchar(dn[0])) { - if (periodchar(dn[1])) - return (res_hnok(dn+2)); - if (dn[1] == '\0') - return (1); - } - return (res_hnok(dn)); +res_ownok (const char *dn) +{ + unsigned char buf[NS_MAXCDNAME]; + if (!printable_string (dn) + || ns_name_pton (dn, buf, sizeof (buf)) < 0 + || binary_leading_dash (buf)) + return 0; + if (buf[0] == 1 && buf [1] == '*') + /* Skip over the leading "*." part. */ + return binary_hnok (buf + 2); + else + return binary_hnok (buf); } -/* - * SOA RNAMEs and RP RNAMEs can have any printable character in their first - * label, but the rest of the name has to look like a host name. - */ +/* SOA RNAMEs and RP RNAMEs can have any byte in their first label, + but the rest of the name has to look like a host name. */ int -res_mailok(const char *dn) { - int ch, escaped = 0; - - /* "." is a valid missing representation */ - if (*dn == '\0') - return (1); - - /* otherwise <label>.<hostname> */ - while ((ch = *dn++) != '\0') { - if (!domainchar(ch)) - return (0); - if (!escaped && periodchar(ch)) - break; - if (escaped) - escaped = 0; - else if (bslashchar(ch)) - escaped = 1; - } - if (periodchar(ch)) - return (res_hnok(dn)); - return (0); +res_mailok (const char *dn) +{ + unsigned char buf[NS_MAXCDNAME]; + if (!printable_string (dn) + || ns_name_pton (dn, buf, sizeof (buf)) < 0) + return 0; + unsigned char label_length = buf[0]; + /* "." is a valid missing representation */ + if (label_length == 0) + return 1; + /* Skip over the first label. */ + unsigned char *tail = buf + 1 + label_length; + if (*tail == 0) + /* More than one label is required (except for "."). */ + return 0; + return binary_hnok (tail); } -/* - * This function is quite liberal, since RFC 1034's character sets are only - * recommendations. - */ +/* Return 1 if DN is a syntactically valid domain name. Empty names + are accepted. */ int -res_dnok(const char *dn) { - int ch; - - while ((ch = *dn++) != '\0') - if (!domainchar(ch)) - return (0); - return (1); +res_dnok (const char *dn) +{ + unsigned char buf[NS_MAXCDNAME]; + return printable_string (dn) && ns_name_pton (dn, buf, sizeof (buf)) >= 0; } libresolv_hidden_def (res_dnok) -#ifdef BIND_4_COMPAT /* * This module must export the following externally-visible symbols: * ___putlong @@ -242,15 +262,12 @@ libresolv_hidden_def (res_dnok) * __getshort * Note that one _ comes from C and the others come from us. */ -void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); } +void __putlong(uint32_t src, u_char *dst) { ns_put32(src, dst); } libresolv_hidden_def (__putlong) -void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); } +void __putshort(uint16_t src, u_char *dst) { ns_put16(src, dst); } libresolv_hidden_def (__putshort) -#ifndef __ultrix__ -u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); } -u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); } -#endif /*__ultrix__*/ -#endif /*BIND_4_COMPAT*/ +uint32_t _getlong(const u_char *src) { return (ns_get32(src)); } +uint16_t _getshort(const u_char *src) { return (ns_get16(src)); } #include <shlib-compat.h> diff --git a/resolv/res_data.c b/resolv/res_data.c index 81c9ae5bfd..e586d96dc6 100644 --- a/resolv/res_data.c +++ b/resolv/res_data.c @@ -1,3 +1,21 @@ +/* Miscellaneous definitions for libresolv. + Copyright (C) 1995-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + /* * Copyright (c) 1995-1999 by Internet Software Consortium. * @@ -15,322 +33,22 @@ * SOFTWARE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static const char rcsid[] = "$BINDId: res_data.c,v 8.17 1999/10/13 17:11:31 vixie Exp $"; -#endif /* LIBC_SCCS and not lint */ - -#include <sys/types.h> -#include <sys/param.h> -#include <sys/socket.h> -#include <sys/time.h> - -#include <netinet/in.h> -#include <arpa/inet.h> -#include <arpa/nameser.h> - -#include <ctype.h> -#include <netdb.h> #include <resolv.h> -#ifdef BIND_UPDATE -#include <res_update.h> -#endif -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -const char *_res_opcodes[] = { - "QUERY", - "IQUERY", - "CQUERYM", - "CQUERYU", /* experimental */ - "NOTIFY", /* experimental */ - "UPDATE", - "6", - "7", - "8", - "9", - "10", - "11", - "12", - "13", - "ZONEINIT", - "ZONEREF", -}; -libresolv_hidden_data_def (_res_opcodes) - -#ifdef BIND_UPDATE -const char *_res_sectioncodes[] attribute_hidden = { - "ZONE", - "PREREQUISITES", - "UPDATE", - "ADDITIONAL", -}; -#endif - -#ifndef __BIND_NOSTATIC -#ifdef _LIBC -/* The definition has been moved to res_libc.c. */ -#else -#undef _res -struct __res_state _res -# if defined(__BIND_RES_TEXT) - = { RES_TIMEOUT, } /* Motorola, et al. */ -# endif - ; -#endif - -/* Proto. */ -#ifndef _LIBC -int res_ourserver_p(const res_state, const struct sockaddr_in *); -void res_pquery(const res_state, const u_char *, int, FILE *); -#endif - -#ifndef _LIBC -/* Moved to res_libc.c since res_init() should go into libc.so but the - rest of this file not. */ -int -res_init(void) { - extern int __res_vinit(res_state, int); - - /* - * These three fields used to be statically initialized. This made - * it hard to use this code in a shared library. It is necessary, - * now that we're doing dynamic initialization here, that we preserve - * the old semantics: if an application modifies one of these three - * fields of _res before res_init() is called, res_init() will not - * alter them. Of course, if an application is setting them to - * _zero_ before calling res_init(), hoping to override what used - * to be the static default, we can't detect it and unexpected results - * will follow. Zero for any of these fields would make no sense, - * so one can safely assume that the applications were already getting - * unexpected results. - * - * _res.options is tricky since some apps were known to diddle the bits - * before res_init() was first called. We can't replicate that semantic - * with dynamic initialization (they may have turned bits off that are - * set in RES_DEFAULT). Our solution is to declare such applications - * "broken". They could fool us by setting RES_INIT but none do (yet). - */ - if (!_res.retrans) - _res.retrans = RES_TIMEOUT; - if (!_res.retry) - _res.retry = 4; - if (!(_res.options & RES_INIT)) - _res.options = RES_DEFAULT; - - /* - * This one used to initialize implicitly to zero, so unless the app - * has set it to something in particular, we can randomize it now. - */ - if (!_res.id) - _res.id = res_randomid(); - - return (__res_vinit(&_res, 1)); -} -#endif +/* This function belongs to libresolv, which is why it is not included + in res-close.c. */ void -p_query(const u_char *msg) { - fp_query(msg, stdout); -} - -void -fp_query(const u_char *msg, FILE *file) { - fp_nquery(msg, PACKETSZ, file); -} -libresolv_hidden_def (fp_query) - -void -fp_nquery(const u_char *msg, int len, FILE *file) { - if (__res_maybe_init (&_res, 0) == -1) - return; - - res_pquery(&_res, msg, len, file); -} -libresolv_hidden_def (fp_nquery) - -int -res_mkquery(int op, /* opcode of query */ - const char *dname, /* domain name */ - int class, int type, /* class and type of query */ - const u_char *data, /* resource record data */ - int datalen, /* length of data */ - const u_char *newrr_in, /* new rr for modify or append */ - u_char *buf, /* buffer to put query */ - int buflen) /* size of buffer */ +__res_close (void) { - if (__res_maybe_init (&_res, 1) == -1) { - RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); - return (-1); - } - return (res_nmkquery(&_res, op, dname, class, type, - data, datalen, - newrr_in, buf, buflen)); + /* Some programs call res_close before res_init. Since _res._vcsock + isn't explicitly initialized, these means that we could call + close (0), which might lead to some security problems. Therefore + we check if res_init was called before by looking at the RES_INIT + bit in _res.options. If it hasn't been set we bail out + early. */ + if ((_res.options & RES_INIT) == 0) + return; + /* We don't free the name server addresses because we never did it + and it would be done implicitly on shutdown. */ + __res_iclose (&_res, false); } - -#ifdef BIND_UPDATE -int -res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) { - if (__res_maybe_init (&_res, 1) == -1) { - RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); - return (-1); - } - - return (res_nmkupdate(&_res, rrecp_in, buf, buflen)); -} -#endif - -int -res_query(const char *name, /* domain name */ - int class, int type, /* class and type of query */ - u_char *answer, /* buffer to put answer */ - int anslen) /* size of answer buffer */ -{ - if (__res_maybe_init (&_res, 1) == -1) { - RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); - return (-1); - } - return (res_nquery(&_res, name, class, type, answer, anslen)); -} - -void -res_send_setqhook(res_send_qhook hook) { - _res.qhook = hook; -} - -void -res_send_setrhook(res_send_rhook hook) { - _res.rhook = hook; -} - -int -res_isourserver(const struct sockaddr_in *inp) { - return (res_ourserver_p(&_res, (const struct sockaddr_in6 *) inp)); -} - -int -res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) { - if (__res_maybe_init (&_res, 1) == -1) { - /* errno should have been set by res_init() in this case. */ - return (-1); - } - - return (res_nsend(&_res, buf, buflen, ans, anssiz)); -} - -#ifndef _LIBC -int -res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key, - u_char *ans, int anssiz) -{ - if (__res_maybe_init (&_res, 1) == -1) { - /* errno should have been set by res_init() in this case. */ - return (-1); - } - - return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz)); -} -#endif - -void -res_close(void) { -#ifdef _LIBC - /* - * Some stupid programs out there call res_close() before res_init(). - * Since _res._vcsock isn't explicitly initialized, these means that - * we could do a close(0), which might lead to some security problems. - * Therefore we check if res_init() was called before by looking at - * the RES_INIT bit in _res.options. If it hasn't been set we bail out - * early. */ - if ((_res.options & RES_INIT) == 0) - return; -#endif - /* We don't free the name server addresses because we never - did it and it would be done implicitly on shutdown. */ - __res_iclose(&_res, false); -} - -#ifdef BIND_UPDATE -int -res_update(ns_updrec *rrecp_in) { - if (__res_maybe_init (&_res, 1) == -1) { - RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); - return (-1); - } - - return (res_nupdate(&_res, rrecp_in, NULL)); -} -#endif - -int -res_search(const char *name, /* domain name */ - int class, int type, /* class and type of query */ - u_char *answer, /* buffer to put answer */ - int anslen) /* size of answer */ -{ - if (__res_maybe_init (&_res, 1) == -1) { - RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); - return (-1); - } - - return (res_nsearch(&_res, name, class, type, answer, anslen)); -} - -int -res_querydomain(const char *name, - const char *domain, - int class, int type, /* class and type of query */ - u_char *answer, /* buffer to put answer */ - int anslen) /* size of answer */ -{ - if (__res_maybe_init (&_res, 1) == -1) { - RES_SET_H_ERRNO(&_res, NETDB_INTERNAL); - return (-1); - } - - return (res_nquerydomain(&_res, name, domain, - class, type, - answer, anslen)); -} - -const char * -hostalias(const char *name) { - static char abuf[MAXDNAME]; - - return (res_hostalias(&_res, name, abuf, sizeof abuf)); -} -libresolv_hidden_def (hostalias) - -#ifdef ultrix -int -local_hostname_length(const char *hostname) { - int len_host, len_domain; - - if (!*_res.defdname) - res_init(); - len_host = strlen(hostname); - len_domain = strlen(_res.defdname); - if (len_host > len_domain && - !strcasecmp(hostname + len_host - len_domain, _res.defdname) && - hostname[len_host - len_domain - 1] == '.') - return (len_host - len_domain - 1); - return (0); -} -#endif /*ultrix*/ - -#endif - - -#include <shlib-compat.h> - -#if SHLIB_COMPAT(libresolv, GLIBC_2_0, GLIBC_2_2) -# undef res_mkquery -# undef res_query -# undef res_querydomain -# undef res_search -weak_alias (__res_mkquery, res_mkquery); -weak_alias (__res_query, res_query); -weak_alias (__res_querydomain, res_querydomain); -weak_alias (__res_search, res_search); -#endif diff --git a/resolv/res_debug.c b/resolv/res_debug.c index 68a407a033..7681ad4639 100644 --- a/resolv/res_debug.c +++ b/resolv/res_debug.c @@ -89,11 +89,6 @@ * SOFTWARE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "$BINDId: res_debug.c,v 8.34 2000/02/29 05:30:55 vixie Exp $"; -#endif /* LIBC_SCCS and not lint */ - #include <sys/types.h> #include <sys/param.h> #include <sys/socket.h> @@ -106,11 +101,13 @@ static const char rcsid[] = "$BINDId: res_debug.c,v 8.34 2000/02/29 05:30:55 vix #include <errno.h> #include <math.h> #include <netdb.h> -#include <resolv.h> +#include <resolv/resolv-internal.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> +#include <shlib-compat.h> +#include <libc-diag.h> #ifdef SPRINTF_CHAR # define SPRINTF(x) strlen(sprintf/**/x) @@ -120,6 +117,36 @@ static const char rcsid[] = "$BINDId: res_debug.c,v 8.34 2000/02/29 05:30:55 vix extern const char *_res_sectioncodes[] attribute_hidden; +/* _res_opcodes was exported by accident as a variable. */ +#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_26) +static const char *res_opcodes[] = +#else +static const char res_opcodes[][9] = +#endif + { + "QUERY", + "IQUERY", + "CQUERYM", + "CQUERYU", /* experimental */ + "NOTIFY", /* experimental */ + "UPDATE", + "6", + "7", + "8", + "9", + "10", + "11", + "12", + "13", + "ZONEINIT", + "ZONEREF", + }; +#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_26) +strong_alias (res_opcodes, _res_opcodes) +#endif + +static const char *p_section(int section, int opcode); + /* * Print the current options. */ @@ -135,9 +162,7 @@ fp_resstat(const res_state statp, FILE *file) { } static void -do_section(const res_state statp, - ns_msg *handle, ns_sect section, - int pflag, FILE *file) +do_section (int pfcode, ns_msg *handle, ns_sect section, int pflag, FILE *file) { int n, sflag, rrnum; static int buflen = 2048; @@ -148,8 +173,8 @@ do_section(const res_state statp, /* * Print answer records. */ - sflag = (statp->pfcode & pflag); - if (statp->pfcode && !sflag) + sflag = (pfcode & pflag); + if (pfcode && !sflag) return; buf = malloc(buflen); @@ -166,11 +191,11 @@ do_section(const res_state statp, fprintf(file, ";; ns_parserr: %s\n", strerror(errno)); else if (rrnum > 0 && sflag != 0 && - (statp->pfcode & RES_PRF_HEAD1)) + (pfcode & RES_PRF_HEAD1)) putc('\n', file); goto cleanup; } - if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1)) + if (rrnum == 0 && sflag != 0 && (pfcode & RES_PRF_HEAD1)) fprintf(file, ";; %s SECTION:\n", p_section(section, opcode)); if (section == ns_s_qd) @@ -212,11 +237,19 @@ do_section(const res_state statp, * This is intended to be primarily a debugging routine. */ void -res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) { +fp_nquery (const unsigned char *msg, int len, FILE *file) +{ ns_msg handle; int qdcount, ancount, nscount, arcount; u_int opcode, rcode, id; + /* There is no need to initialize _res: If _res is not yet + initialized, _res.pfcode is zero. But initialization will + leave it at zero, too. _res.pfcode is an unsigned long, + but the code here assumes that the flags fit into an int, + so use that. */ + int pfcode = _res.pfcode; + if (ns_initparse(msg, len, &handle) < 0) { fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); return; @@ -232,13 +265,13 @@ res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) { /* * Print header fields. */ - if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode) + if ((!pfcode) || (pfcode & RES_PRF_HEADX) || rcode) fprintf(file, ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n", - _res_opcodes[opcode], p_rcode(rcode), id); - if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX)) + res_opcodes[opcode], p_rcode(rcode), id); + if ((!pfcode) || (pfcode & RES_PRF_HEADX)) putc(';', file); - if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) { + if ((!pfcode) || (pfcode & RES_PRF_HEAD2)) { fprintf(file, "; flags:"); if (ns_msg_getflag(handle, ns_f_qr)) fprintf(file, " qr"); @@ -257,7 +290,7 @@ res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) { if (ns_msg_getflag(handle, ns_f_cd)) fprintf(file, " cd"); } - if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) { + if ((!pfcode) || (pfcode & RES_PRF_HEAD1)) { fprintf(file, "; %s: %d", p_section(ns_s_qd, opcode), qdcount); fprintf(file, ", %s: %d", @@ -267,21 +300,35 @@ res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) { fprintf(file, ", %s: %d", p_section(ns_s_ar, opcode), arcount); } - if ((!statp->pfcode) || (statp->pfcode & + if ((!pfcode) || (pfcode & (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) { putc('\n',file); } /* * Print the various sections. */ - do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file); - do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file); - do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file); - do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file); + do_section (pfcode, &handle, ns_s_qd, RES_PRF_QUES, file); + do_section (pfcode, &handle, ns_s_an, RES_PRF_ANS, file); + do_section (pfcode, &handle, ns_s_ns, RES_PRF_AUTH, file); + do_section (pfcode, &handle, ns_s_ar, RES_PRF_ADD, file); if (qdcount == 0 && ancount == 0 && nscount == 0 && arcount == 0) putc('\n', file); } +libresolv_hidden_def (fp_nquery) + +void +fp_query (const unsigned char *msg, FILE *file) +{ + fp_nquery (msg, PACKETSZ, file); +} +libresolv_hidden_def (fp_query) + +void +p_query (const unsigned char *msg) +{ + fp_query (msg, stdout); +} const u_char * p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) { @@ -347,13 +394,13 @@ p_fqname(const u_char *cp, const u_char *msg, FILE *file) { extern const struct res_sym __p_class_syms[]; libresolv_hidden_proto (__p_class_syms) const struct res_sym __p_class_syms[] = { - {C_IN, "IN"}, - {C_CHAOS, "CHAOS"}, - {C_HS, "HS"}, - {C_HS, "HESIOD"}, - {C_ANY, "ANY"}, - {C_NONE, "NONE"}, - {C_IN, (char *)0} + {C_IN, (char *) "IN"}, + {C_CHAOS, (char *) "CHAOS"}, + {C_HS, (char *) "HS"}, + {C_HS, (char *) "HESIOD"}, + {C_ANY, (char *) "ANY"}, + {C_NONE, (char *) "NONE"}, + {C_IN, NULL, NULL} }; libresolv_hidden_data_def (__p_class_syms) @@ -361,93 +408,75 @@ libresolv_hidden_data_def (__p_class_syms) * Names of message sections. */ const struct res_sym __p_default_section_syms[] attribute_hidden = { - {ns_s_qd, "QUERY"}, - {ns_s_an, "ANSWER"}, - {ns_s_ns, "AUTHORITY"}, - {ns_s_ar, "ADDITIONAL"}, - {0, (char *)0} + {ns_s_qd, (char *) "QUERY"}, + {ns_s_an, (char *) "ANSWER"}, + {ns_s_ns, (char *) "AUTHORITY"}, + {ns_s_ar, (char *) "ADDITIONAL"}, + {0, NULL, NULL} }; const struct res_sym __p_update_section_syms[] attribute_hidden = { - {S_ZONE, "ZONE"}, - {S_PREREQ, "PREREQUISITE"}, - {S_UPDATE, "UPDATE"}, - {S_ADDT, "ADDITIONAL"}, - {0, (char *)0} -}; - -const struct res_sym __p_key_syms[] attribute_hidden = { - {NS_ALG_MD5RSA, "RSA", "RSA KEY with MD5 hash"}, - {NS_ALG_DH, "DH", "Diffie Hellman"}, - {NS_ALG_DSA, "DSA", "Digital Signature Algorithm"}, - {NS_ALG_EXPIRE_ONLY, "EXPIREONLY", "No algorithm"}, - {NS_ALG_PRIVATE_OID, "PRIVATE", "Algorithm obtained from OID"}, - {0, NULL, NULL} -}; - -const struct res_sym __p_cert_syms[] attribute_hidden = { - {cert_t_pkix, "PKIX", "PKIX (X.509v3) Certificate"}, - {cert_t_spki, "SPKI", "SPKI certificate"}, - {cert_t_pgp, "PGP", "PGP certificate"}, - {cert_t_url, "URL", "URL Private"}, - {cert_t_oid, "OID", "OID Private"}, - {0, NULL, NULL} + {S_ZONE, (char *) "ZONE"}, + {S_PREREQ, (char *) "PREREQUISITE"}, + {S_UPDATE, (char *) "UPDATE"}, + {S_ADDT, (char *) "ADDITIONAL"}, + {0, NULL, NULL} }; /* - * Names of RR types and qtypes. Types and qtypes are the same, except - * that T_ANY is a qtype but not a type. (You can ask for records of type - * T_ANY, but you can't have any records of that type in the database.) + * Names of RR types and qtypes. The list is incomplete because its + * size is part of the ABI. */ extern const struct res_sym __p_type_syms[]; libresolv_hidden_proto (__p_type_syms) const struct res_sym __p_type_syms[] = { - {ns_t_a, "A", "address"}, - {ns_t_ns, "NS", "name server"}, - {ns_t_md, "MD", "mail destination (deprecated)"}, - {ns_t_mf, "MF", "mail forwarder (deprecated)"}, - {ns_t_cname, "CNAME", "canonical name"}, - {ns_t_soa, "SOA", "start of authority"}, - {ns_t_mb, "MB", "mailbox"}, - {ns_t_mg, "MG", "mail group member"}, - {ns_t_mr, "MR", "mail rename"}, - {ns_t_null, "NULL", "null"}, - {ns_t_wks, "WKS", "well-known service (deprecated)"}, - {ns_t_ptr, "PTR", "domain name pointer"}, - {ns_t_hinfo, "HINFO", "host information"}, - {ns_t_minfo, "MINFO", "mailbox information"}, - {ns_t_mx, "MX", "mail exchanger"}, - {ns_t_txt, "TXT", "text"}, - {ns_t_rp, "RP", "responsible person"}, - {ns_t_afsdb, "AFSDB", "DCE or AFS server"}, - {ns_t_x25, "X25", "X25 address"}, - {ns_t_isdn, "ISDN", "ISDN address"}, - {ns_t_rt, "RT", "router"}, - {ns_t_nsap, "NSAP", "nsap address"}, - {ns_t_nsap_ptr, "NSAP_PTR", "domain name pointer"}, - {ns_t_sig, "SIG", "signature"}, - {ns_t_key, "KEY", "key"}, - {ns_t_px, "PX", "mapping information"}, - {ns_t_gpos, "GPOS", "geographical position (withdrawn)"}, - {ns_t_aaaa, "AAAA", "IPv6 address"}, - {ns_t_loc, "LOC", "location"}, - {ns_t_nxt, "NXT", "next valid name (unimplemented)"}, - {ns_t_eid, "EID", "endpoint identifier (unimplemented)"}, - {ns_t_nimloc, "NIMLOC", "NIMROD locator (unimplemented)"}, - {ns_t_srv, "SRV", "server selection"}, - {ns_t_atma, "ATMA", "ATM address (unimplemented)"}, - {ns_t_dname, "DNAME", "Non-terminal DNAME (for IPv6)"}, - {ns_t_tsig, "TSIG", "transaction signature"}, - {ns_t_ixfr, "IXFR", "incremental zone transfer"}, - {ns_t_axfr, "AXFR", "zone transfer"}, - {ns_t_zxfr, "ZXFR", "compressed zone transfer"}, - {ns_t_mailb, "MAILB", "mailbox-related data (deprecated)"}, - {ns_t_maila, "MAILA", "mail agent (deprecated)"}, - {ns_t_naptr, "NAPTR", "URN Naming Authority"}, - {ns_t_kx, "KX", "Key Exchange"}, - {ns_t_cert, "CERT", "Certificate"}, - {ns_t_any, "ANY", "\"any\""}, - {0, NULL, NULL} + {ns_t_a, (char *) "A", (char *) "address"}, + {ns_t_ns, (char *) "NS", (char *) "name server"}, + {ns_t_md, (char *) "MD", (char *) "mail destination (deprecated)"}, + {ns_t_mf, (char *) "MF", (char *) "mail forwarder (deprecated)"}, + {ns_t_cname, (char *) "CNAME", (char *) "canonical name"}, + {ns_t_soa, (char *) "SOA", (char *) "start of authority"}, + {ns_t_mb, (char *) "MB", (char *) "mailbox"}, + {ns_t_mg, (char *) "MG", (char *) "mail group member"}, + {ns_t_mr, (char *) "MR", (char *) "mail rename"}, + {ns_t_null, (char *) "NULL", (char *) "null"}, + {ns_t_wks, (char *) "WKS", (char *) "well-known service (deprecated)"}, + {ns_t_ptr, (char *) "PTR", (char *) "domain name pointer"}, + {ns_t_hinfo, (char *) "HINFO", (char *) "host information"}, + {ns_t_minfo, (char *) "MINFO", (char *) "mailbox information"}, + {ns_t_mx, (char *) "MX", (char *) "mail exchanger"}, + {ns_t_txt, (char *) "TXT", (char *) "text"}, + {ns_t_rp, (char *) "RP", (char *) "responsible person"}, + {ns_t_afsdb, (char *) "AFSDB", (char *) "DCE or AFS server"}, + {ns_t_x25, (char *) "X25", (char *) "X25 address"}, + {ns_t_isdn, (char *) "ISDN", (char *) "ISDN address"}, + {ns_t_rt, (char *) "RT", (char *) "router"}, + {ns_t_nsap, (char *) "NSAP", (char *) "nsap address"}, + {ns_t_nsap_ptr, (char *) "NSAP_PTR", (char *) "domain name pointer"}, + {ns_t_sig, (char *) "SIG", (char *) "signature"}, + {ns_t_key, (char *) "KEY", (char *) "key"}, + {ns_t_px, (char *) "PX", (char *) "mapping information"}, + {ns_t_gpos, (char *) "GPOS", + (char *) "geographical position (withdrawn)"}, + {ns_t_aaaa, (char *) "AAAA", (char *) "IPv6 address"}, + {ns_t_loc, (char *) "LOC", (char *) "location"}, + {ns_t_nxt, (char *) "NXT", (char *) "next valid name (unimplemented)"}, + {ns_t_eid, (char *) "EID", (char *) "endpoint identifier (unimplemented)"}, + {ns_t_nimloc, (char *) "NIMLOC", (char *) "NIMROD locator (unimplemented)"}, + {ns_t_srv, (char *) "SRV", (char *) "server selection"}, + {ns_t_atma, (char *) "ATMA", (char *) "ATM address (unimplemented)"}, + {ns_t_dname, (char *) "DNAME", (char *) "Non-terminal DNAME (for IPv6)"}, + {ns_t_tsig, (char *) "TSIG", (char *) "transaction signature"}, + {ns_t_ixfr, (char *) "IXFR", (char *) "incremental zone transfer"}, + {ns_t_axfr, (char *) "AXFR", (char *) "zone transfer"}, + {ns_t_mailb, (char *) "MAILB", (char *) "mailbox-related data (deprecated)"}, + {ns_t_maila, (char *) "MAILA", (char *) "mail agent (deprecated)"}, + {ns_t_naptr, (char *) "NAPTR", (char *) "URN Naming Authority"}, + {ns_t_kx, (char *) "KX", (char *) "Key Exchange"}, + {ns_t_cert, (char *) "CERT", (char *) "Certificate"}, + {ns_t_any, (char *) "ANY", (char *) "\"any\""}, + {0, NULL, NULL}, /* Padding to preserve ABI. */ + {0, NULL, NULL} }; libresolv_hidden_data_def (__p_type_syms) @@ -455,22 +484,22 @@ libresolv_hidden_data_def (__p_type_syms) * Names of DNS rcodes. */ const struct res_sym __p_rcode_syms[] attribute_hidden = { - {ns_r_noerror, "NOERROR", "no error"}, - {ns_r_formerr, "FORMERR", "format error"}, - {ns_r_servfail, "SERVFAIL", "server failed"}, - {ns_r_nxdomain, "NXDOMAIN", "no such domain name"}, - {ns_r_notimpl, "NOTIMP", "not implemented"}, - {ns_r_refused, "REFUSED", "refused"}, - {ns_r_yxdomain, "YXDOMAIN", "domain name exists"}, - {ns_r_yxrrset, "YXRRSET", "rrset exists"}, - {ns_r_nxrrset, "NXRRSET", "rrset doesn't exist"}, - {ns_r_notauth, "NOTAUTH", "not authoritative"}, - {ns_r_notzone, "NOTZONE", "Not in zone"}, - {ns_r_max, "", ""}, - {ns_r_badsig, "BADSIG", "bad signature"}, - {ns_r_badkey, "BADKEY", "bad key"}, - {ns_r_badtime, "BADTIME", "bad time"}, - {0, NULL, NULL} + {ns_r_noerror, (char *) "NOERROR", (char *) "no error"}, + {ns_r_formerr, (char *) "FORMERR", (char *) "format error"}, + {ns_r_servfail, (char *) "SERVFAIL", (char *) "server failed"}, + {ns_r_nxdomain, (char *) "NXDOMAIN", (char *) "no such domain name"}, + {ns_r_notimpl, (char *) "NOTIMP", (char *) "not implemented"}, + {ns_r_refused, (char *) "REFUSED", (char *) "refused"}, + {ns_r_yxdomain, (char *) "YXDOMAIN", (char *) "domain name exists"}, + {ns_r_yxrrset, (char *) "YXRRSET", (char *) "rrset exists"}, + {ns_r_nxrrset, (char *) "NXRRSET", (char *) "rrset doesn't exist"}, + {ns_r_notauth, (char *) "NOTAUTH", (char *) "not authoritative"}, + {ns_r_notzone, (char *) "NOTZONE", (char *) "Not in zone"}, + {ns_r_max, (char *) "", (char *) ""}, + {ns_r_badsig, (char *) "BADSIG", (char *) "bad signature"}, + {ns_r_badkey, (char *) "BADKEY", (char *) "bad key"}, + {ns_r_badtime, (char *) "BADTIME", (char *) "bad time"}, + {0, NULL, NULL} }; int @@ -535,7 +564,7 @@ libresolv_hidden_def (p_type) /* * Return a string for the type. */ -const char * +static const char * p_section(int section, int opcode) { const struct res_sym *symbols; @@ -569,9 +598,7 @@ p_option(u_long option) { switch (option) { case RES_INIT: return "init"; case RES_DEBUG: return "debug"; - case RES_AAONLY: return "aaonly(unimpl)"; case RES_USEVC: return "use-vc"; - case RES_PRIMARY: return "primry(unimpl)"; case RES_IGNTC: return "igntc"; case RES_RECURSE: return "recurs"; case RES_DEFNAMES: return "defnam"; @@ -580,18 +607,14 @@ p_option(u_long option) { case RES_INSECURE1: return "insecure1"; case RES_INSECURE2: return "insecure2"; case RES_NOALIASES: return "noaliases"; - case RES_USE_INET6: return "inet6"; + case DEPRECATED_RES_USE_INET6: return "inet6"; case RES_ROTATE: return "rotate"; - case RES_NOCHECKNAME: return "no-check-names(unimpl)"; - case RES_KEEPTSIG: return "keeptsig(unimpl)"; - case RES_BLAST: return "blast"; - case RES_USEBSTRING: return "ip6-bytestring"; - case RES_NOIP6DOTINT: return "no-ip6-dotint"; case RES_USE_EDNS0: return "edns0"; case RES_SNGLKUP: return "single-request"; case RES_SNGLKUPREOP: return "single-request-reopen"; case RES_USE_DNSSEC: return "dnssec"; case RES_NOTLDQUERY: return "no-tld-query"; + case RES_NORELOAD: return "no-reload"; /* XXX nonreentrant */ default: sprintf(nbuf, "?0x%lx?", (u_long)option); return (nbuf); @@ -603,7 +626,7 @@ libresolv_hidden_def (p_option) * Return a mnemonic for a time to live. */ const char * -p_time(u_int32_t value) { +p_time(uint32_t value) { static char nbuf[40]; /* XXX nonreentrant */ if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0) @@ -632,7 +655,7 @@ static const unsigned int poweroften[10]= /* takes an XeY precision/size value, returns a string representation. */ static const char * -precsize_ntoa (u_int8_t prec) +precsize_ntoa (uint8_t prec) { static char retbuf[sizeof "90000000.00"]; /* XXX nonreentrant */ unsigned long val; @@ -648,11 +671,11 @@ precsize_ntoa (u_int8_t prec) } /* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */ -static u_int8_t +static uint8_t precsize_aton (const char **strptr) { unsigned int mval = 0, cmval = 0; - u_int8_t retval = 0; + uint8_t retval = 0; const char *cp; int exponent; int mantissa; @@ -689,11 +712,11 @@ precsize_aton (const char **strptr) } /* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */ -static u_int32_t +static uint32_t latlon2ul (const char **latlonstrptr, int *which) { const char *cp; - u_int32_t retval; + uint32_t retval; int deg = 0, min = 0, secs = 0, secsfrac = 0; cp = *latlonstrptr; @@ -792,12 +815,12 @@ loc_aton (const char *ascii, u_char *binary) const char *cp, *maxcp; u_char *bcp; - u_int32_t latit = 0, longit = 0, alt = 0; - u_int32_t lltemp1 = 0, lltemp2 = 0; + uint32_t latit = 0, longit = 0, alt = 0; + uint32_t lltemp1 = 0, lltemp2 = 0; int altmeters = 0, altfrac = 0, altsign = 1; - u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */ - u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */ - u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */ + uint8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */ + uint8_t vp = 0x13; /* default = 1e3 cm = 10.00m */ + uint8_t siz = 0x12; /* default = 1e2 cm = 1.00m */ int which1 = 0, which2 = 0; cp = ascii; @@ -883,7 +906,7 @@ loc_aton (const char *ascii, u_char *binary) defaults: bcp = binary; - *bcp++ = (u_int8_t) 0; /* version byte */ + *bcp++ = (uint8_t) 0; /* version byte */ *bcp++ = siz; *bcp++ = hp; *bcp++ = vp; @@ -908,11 +931,11 @@ loc_ntoa (const u_char *binary, char *ascii) char northsouth, eastwest; int altmeters, altfrac, altsign; - const u_int32_t referencealt = 100000 * 100; + const uint32_t referencealt = 100000 * 100; int32_t latval, longval, altval; - u_int32_t templ; - u_int8_t sizeval, hpval, vpval, versionval; + uint32_t templ; + uint8_t sizeval, hpval, vpval, versionval; char *sizestr, *hpstr, *vpstr; @@ -1029,29 +1052,47 @@ dn_count_labels(const char *name) { libresolv_hidden_def (__dn_count_labels) +#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_27) /* * Make dates expressed in seconds-since-Jan-1-1970 easy to read. * SIG records are required to be printed like this, by the Secure DNS RFC. + * This is an obsolescent function and does not handle dates outside the + * signed 32-bit range. */ char * -p_secstodate (u_long secs) { +__p_secstodate (u_long secs) { /* XXX nonreentrant */ static char output[15]; /* YYYYMMDDHHMMSS and null */ time_t clock = secs; struct tm *time; -#ifdef HAVE_TIME_R struct tm timebuf; - - time = gmtime_r(&clock, &timebuf); -#else - time = gmtime(&clock); -#endif + /* The call to __gmtime_r can never produce a year overflowing + the range of int, given the check on SECS, but check for a + NULL return anyway to avoid a null pointer dereference in + case there are any other unspecified errors. */ + if (secs > 0x7fffffff + || (time = __gmtime_r (&clock, &timebuf)) == NULL) { + strcpy (output, "<overflow>"); + __set_errno (EOVERFLOW); + return output; + } time->tm_year += 1900; time->tm_mon += 1; + /* The struct tm fields, given the above range check, + must have values that mean this sprintf exactly fills the + buffer. But as of GCC 8 of 2017-11-21, GCC cannot tell + that, even given range checks on all fields with + __builtin_unreachable called for out-of-range values. */ + DIAG_PUSH_NEEDS_COMMENT; +# if __GNUC_PREREQ (7, 0) + DIAG_IGNORE_NEEDS_COMMENT (8, "-Wformat-overflow="); +# endif sprintf(output, "%04d%02d%02d%02d%02d%02d", time->tm_year, time->tm_mon, time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec); + DIAG_POP_NEEDS_COMMENT; return (output); } -libresolv_hidden_def (__p_secstodate) +compat_symbol (libresolv, __p_secstodate, __p_secstodate, GLIBC_2_0); +#endif diff --git a/resolv/res_debug.h b/resolv/res_debug.h deleted file mode 100644 index 2d8ad15d60..0000000000 --- a/resolv/res_debug.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 1999 by Internet Software Consortium. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS - * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE - * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR - * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS - * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS - * SOFTWARE. - */ - -#ifndef _RES_DEBUG_H_ -#define _RES_DEBUG_H_ - -#ifndef DEBUG -# define Dprint(cond, args) /*empty*/ -# define DprintQ(cond, args, query, size) /*empty*/ -# define Aerror(statp, file, string, error, address) /*empty*/ -# define Perror(statp, file, string, error) /*empty*/ -#else -# define Dprint(cond, args) if (cond) {fprintf args;} else {} -# define DprintQ(cond, args, query, size) if (cond) {\ - fprintf args;\ - res_pquery(statp, query, size, stdout);\ - } else {} -#endif - -#endif /* _RES_DEBUG_H_ */ diff --git a/resolv/res_hconf.c b/resolv/res_hconf.c index 5cd128916d..50b6d78711 100644 --- a/resolv/res_hconf.c +++ b/resolv/res_hconf.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993-2016 Free Software Foundation, Inc. +/* Copyright (C) 1993-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by David Mosberger (davidm@azstarnet.com). @@ -21,9 +21,6 @@ Though mostly compatibly, the following differences exist compared to the original implementation: - - new command "spoof" takes an arguments like RESOLV_SPOOF_CHECK - environment variable (i.e., `off', `nowarn', or `warn'). - - line comments can appear anywhere (not just at the beginning of a line) */ @@ -55,7 +52,6 @@ /* Environment vars that all user to override default behavior: */ #define ENV_HOSTCONF "RESOLV_HOST_CONF" -#define ENV_SPOOF "RESOLV_SPOOF_CHECK" #define ENV_TRIM_OVERR "RESOLV_OVERRIDE_TRIM_DOMAINS" #define ENV_TRIM_ADD "RESOLV_ADD_TRIM_DOMAINS" #define ENV_MULTI "RESOLV_MULTI" @@ -65,7 +61,6 @@ enum parse_cbs { CB_none, CB_arg_trimdomain_list, - CB_arg_spoof, CB_arg_bool }; @@ -78,10 +73,7 @@ static const struct cmd { {"order", CB_none, 0}, {"trim", CB_arg_trimdomain_list, 0}, - {"spoof", CB_arg_spoof, 0}, {"multi", CB_arg_bool, HCONF_FLAG_MULTI}, - {"nospoof", CB_arg_bool, HCONF_FLAG_SPOOF}, - {"spoofalert", CB_arg_bool, HCONF_FLAG_SPOOFALERT}, {"reorder", CB_arg_bool, HCONF_FLAG_REORDER} }; @@ -164,28 +156,6 @@ arg_trimdomain_list (const char *fname, int line_num, const char *args) static const char * -arg_spoof (const char *fname, int line_num, const char *args) -{ - const char *start = args; - size_t len; - - args = skip_string (args); - len = args - start; - - if (len == 3 && __strncasecmp (start, "off", len) == 0) - _res_hconf.flags &= ~(HCONF_FLAG_SPOOF | HCONF_FLAG_SPOOFALERT); - else - { - _res_hconf.flags |= (HCONF_FLAG_SPOOF | HCONF_FLAG_SPOOFALERT); - if ((len == 6 && __strncasecmp (start, "nowarn", len) == 0) - || !(len == 4 && __strncasecmp (start, "warn", len) == 0)) - _res_hconf.flags &= ~HCONF_FLAG_SPOOFALERT; - } - return args; -} - - -static const char * arg_bool (const char *fname, int line_num, const char *args, unsigned flag) { if (__strncasecmp (args, "on", 2) == 0) @@ -261,8 +231,6 @@ parse_line (const char *fname, int line_num, const char *str) if (c->cb == CB_arg_trimdomain_list) str = arg_trimdomain_list (fname, line_num, str); - else if (c->cb == CB_arg_spoof) - str = arg_spoof (fname, line_num, str); else if (c->cb == CB_arg_bool) str = arg_bool (fname, line_num, str, c->arg); else @@ -325,10 +293,6 @@ do_init (void) fclose (fp); } - envval = getenv (ENV_SPOOF); - if (envval) - arg_spoof (ENV_SPOOF, 1, envval); - envval = getenv (ENV_MULTI); if (envval) arg_bool (ENV_MULTI, 1, envval, HCONF_FLAG_MULTI); @@ -348,7 +312,8 @@ do_init (void) arg_trimdomain_list (ENV_TRIM_OVERR, 1, envval); } - _res_hconf.initialized = 1; + /* See comments on the declaration of _res_hconf. */ + atomic_store_release (&_res_hconf.initialized, 1); } @@ -374,8 +339,8 @@ static struct netaddr { struct { - u_int32_t addr; - u_int32_t mask; + uint32_t addr; + uint32_t mask; } ipv4; } u; } *ifaddrs); @@ -423,7 +388,7 @@ _res_hconf_reorder_addrs (struct hostent *hp) /* Initialize interface table. */ /* The SIOCGIFNETMASK ioctl will only work on an AF_INET socket. */ - sd = __socket (AF_INET, SOCK_DGRAM, 0); + sd = __socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); if (sd < 0) return; @@ -544,8 +509,8 @@ _res_hconf_reorder_addrs (struct hostent *hp) for (j = 0; j < num_ifs_local; ++j) { - u_int32_t if_addr = ifaddrs[j].u.ipv4.addr; - u_int32_t if_netmask = ifaddrs[j].u.ipv4.mask; + uint32_t if_addr = ifaddrs[j].u.ipv4.addr; + uint32_t if_netmask = ifaddrs[j].u.ipv4.mask; if (((haddr->s_addr ^ if_addr) & if_netmask) == 0) { diff --git a/resolv/res_hconf.h b/resolv/res_hconf.h index b97734df9e..49096b1f90 100644 --- a/resolv/res_hconf.h +++ b/resolv/res_hconf.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1993-2016 Free Software Foundation, Inc. +/* Copyright (C) 1993-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by David Mosberger (davidm@azstarnet.com). @@ -25,6 +25,15 @@ struct hconf { + /* We keep the INITIALIZED member only for backwards compatibility. New + code should just call _res_hconf_init unconditionally. For this field + to be used safely, users must ensure that either (1) a call to + _res_hconf_init happens-before any load from INITIALIZED, or (2) an + assignment of zero to INITIALIZED happens-before any load from it, and + these loads use acquire MO if the intent is to skip calling + _res_hconf_init if the load returns a nonzero value. Such acquire MO + loads will then synchronize with the release MO store to INITIALIZED + in do_init in res_hconf.c; see pthread_once for more detail. */ int initialized; int unused1; int unused2[4]; @@ -32,14 +41,12 @@ struct hconf const char *trimdomain[TRIMDOMAINS_MAX]; unsigned int flags; # define HCONF_FLAG_INITED (1 << 0) /* initialized? */ -# define HCONF_FLAG_SPOOF (1 << 1) /* refuse spoofed addresses */ -# define HCONF_FLAG_SPOOFALERT (1 << 2) /* syslog warning of spoofed */ # define HCONF_FLAG_REORDER (1 << 3) /* list best address first */ # define HCONF_FLAG_MULTI (1 << 4) /* see comments for gethtbyname() */ }; extern struct hconf _res_hconf; -extern void _res_hconf_init (void); +extern void _res_hconf_init (void) attribute_hidden; extern void _res_hconf_trim_domain (char *domain); extern void _res_hconf_trim_domains (struct hostent *hp); extern void _res_hconf_reorder_addrs (struct hostent *hp); diff --git a/resolv/res_init.c b/resolv/res_init.c index e0b6a80dc7..f5e52cbbb9 100644 --- a/resolv/res_init.c +++ b/resolv/res_init.c @@ -1,3 +1,21 @@ +/* Resolver state initialization and resolv.conf parsing. + Copyright (C) 1995-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + /* * Copyright (c) 1985, 1989, 1993 * The Regents of the University of California. All rights reserved. @@ -64,14 +82,10 @@ * SOFTWARE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93"; -static const char rcsid[] = "$BINDId: res_init.c,v 8.16 2000/05/09 07:10:12 vixie Exp $"; -#endif /* LIBC_SCCS and not lint */ - #include <ctype.h> #include <netdb.h> -#include <resolv.h> +#include <resolv/resolv-internal.h> +#include <res_hconf.h> #include <stdio.h> #include <stdio_ext.h> #include <stdlib.h> @@ -86,553 +100,608 @@ static const char rcsid[] = "$BINDId: res_init.c,v 8.16 2000/05/09 07:10:12 vixi #include <sys/socket.h> #include <sys/time.h> #include <sys/types.h> +#include <inet/net-internal.h> +#include <errno.h> +#include <resolv_conf.h> -#include <not-cancel.h> +static uint32_t net_mask (struct in_addr); -/* Options. Should all be left alone. */ -#define RESOLVSORT -#define RFC1535 -/* #undef DEBUG */ +int +res_ninit (res_state statp) +{ + return __res_vinit (statp, 0); +} +libc_hidden_def (__res_ninit) -static void res_setoptions (res_state, const char *, const char *) - internal_function; +/* Return true if CH separates the netmask in the "sortlist" + directive. */ +static inline bool +is_sort_mask (char ch) +{ + return ch == '/' || ch == '&'; +} -#ifdef RESOLVSORT -static const char sort_mask_chars[] = "/&"; -#define ISSORTMASK(ch) (strchr(sort_mask_chars, ch) != NULL) -static u_int32_t net_mask (struct in_addr) __THROW; -#endif +/* Array of name server addresses. */ +#define DYNARRAY_STRUCT nameserver_list +#define DYNARRAY_ELEMENT const struct sockaddr * +#define DYNARRAY_ELEMENT_FREE(e) free ((struct sockaddr *) *(e)) +#define DYNARRAY_INITIAL_SIZE 3 +#define DYNARRAY_PREFIX nameserver_list_ +#include <malloc/dynarray-skeleton.c> + +/* Array of strings for the search array. The backing store is + managed separately. */ +#define DYNARRAY_STRUCT search_list +#define DYNARRAY_ELEMENT const char * +#define DYNARRAY_INITIAL_SIZE 6 +#define DYNARRAY_PREFIX search_list_ +#include <malloc/dynarray-skeleton.c> + +/* Array of name server addresses. */ +#define DYNARRAY_STRUCT sort_list +#define DYNARRAY_ELEMENT struct resolv_sortlist_entry +#define DYNARRAY_INITIAL_SIZE 0 +#define DYNARRAY_PREFIX sort_list_ +#include <malloc/dynarray-skeleton.c> + +/* resolv.conf parser state and results. */ +struct resolv_conf_parser +{ + char *buffer; /* Temporary buffer for reading lines. */ -#if !defined(isascii) /* XXX - could be a function */ -# define isascii(c) (!(c & 0200)) -#endif + struct nameserver_list nameserver_list; /* Nameserver addresses. */ -#ifdef _LIBC -unsigned long long int __res_initstamp attribute_hidden; -#endif + char *search_list_store; /* Backing storage for search list entries. */ + struct search_list search_list; /* Points into search_list_store. */ -/* - * Resolver state default settings. - */ + struct sort_list sort_list; /* Address preference sorting list. */ -/* - * Set up default settings. If the configuration file exist, the values - * there will have precedence. Otherwise, the server address is set to - * INADDR_ANY and the default domain name comes from the gethostname(). - * - * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1 - * rather than INADDR_ANY ("0.0.0.0") as the default name server address - * since it was noted that INADDR_ANY actually meant ``the first interface - * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface, - * it had to be "up" in order for you to reach your own name server. It - * was later decided that since the recommended practice is to always - * install local static routes through 127.0.0.1 for all your network - * interfaces, that we could solve this problem without a code change. - * - * The configuration file should always be used, since it is the only way - * to specify a default domain. If you are running a server on your local - * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1" - * in the configuration file. - * - * Return 0 if completes successfully, -1 on error - */ -int -res_ninit(res_state statp) { - extern int __res_vinit(res_state, int); + /* Configuration template. The non-array elements are filled in + directly. The array elements are updated prior to the call to + __resolv_conf_attach. */ + struct resolv_conf template; +}; - return (__res_vinit(statp, 0)); +/* Return true if *PREINIT contains actual preinitialization. */ +static bool +has_preinit_values (const struct __res_state *preinit) +{ + return (preinit->retrans != 0 && preinit->retrans != RES_TIMEOUT) + || (preinit->retry != 0 && preinit->retry != RES_DFLRETRY) + || (preinit->options != 0 + && (preinit->options & ~RES_INIT) != RES_DEFAULT); } -#ifdef _LIBC -libc_hidden_def (__res_ninit) -#endif -/* This function has to be reachable by res_data.c but not publically. */ -int -__res_vinit(res_state statp, int preinit) { - FILE *fp; - char *cp, **pp; - int n; - char buf[BUFSIZ]; - int nserv = 0; /* number of nameservers read from file */ - int have_serv6 = 0; - int haveenv = 0; - int havesearch = 0; -#ifdef RESOLVSORT - int nsort = 0; - char *net; -#endif -#ifndef RFC1535 - int dots; -#endif -#ifdef _LIBC - statp->_u._ext.initstamp = __res_initstamp; -#endif - - if (!preinit) { - statp->retrans = RES_TIMEOUT; - statp->retry = RES_DFLRETRY; - statp->options = RES_DEFAULT; - statp->id = res_randomid(); - } - - statp->nscount = 0; - statp->defdname[0] = '\0'; - statp->ndots = 1; - statp->pfcode = 0; - statp->_vcsock = -1; - statp->_flags = 0; - statp->qhook = NULL; - statp->rhook = NULL; - statp->_u._ext.nscount = 0; - for (n = 0; n < MAXNS; n++) - statp->_u._ext.nsaddrs[n] = NULL; - - /* Allow user to override the local domain definition */ - if ((cp = getenv("LOCALDOMAIN")) != NULL) { - (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); - statp->defdname[sizeof(statp->defdname) - 1] = '\0'; - haveenv++; - - /* - * Set search list to be blank-separated strings - * from rest of env value. Permits users of LOCALDOMAIN - * to still have a search list, and anyone to set the - * one that they want to use as an individual (even more - * important now that the rfc1535 stuff restricts searches) - */ - cp = statp->defdname; - pp = statp->dnsrch; - *pp++ = cp; - for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { - if (*cp == '\n') /* silly backwards compat */ - break; - else if (*cp == ' ' || *cp == '\t') { - *cp = 0; - n = 1; - } else if (n) { - *pp++ = cp; - n = 0; - havesearch = 1; - } - } - /* null terminate last domain if there are excess */ - while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n') - cp++; - *cp = '\0'; - *pp++ = 0; - } - -#define MATCH(line, name) \ - (!strncmp(line, name, sizeof(name) - 1) && \ - (line[sizeof(name) - 1] == ' ' || \ - line[sizeof(name) - 1] == '\t')) - - if ((fp = fopen(_PATH_RESCONF, "rce")) != NULL) { - /* No threads use this stream. */ - __fsetlocking (fp, FSETLOCKING_BYCALLER); - /* read the config file */ - while (__fgets_unlocked(buf, sizeof(buf), fp) != NULL) { - /* skip comments */ - if (*buf == ';' || *buf == '#') - continue; - /* read default domain name */ - if (MATCH(buf, "domain")) { - if (haveenv) /* skip if have from environ */ - continue; - cp = buf + sizeof("domain") - 1; - while (*cp == ' ' || *cp == '\t') - cp++; - if ((*cp == '\0') || (*cp == '\n')) - continue; - strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); - statp->defdname[sizeof(statp->defdname) - 1] = '\0'; - if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL) - *cp = '\0'; - havesearch = 0; - continue; - } - /* set search list */ - if (MATCH(buf, "search")) { - if (haveenv) /* skip if have from environ */ - continue; - cp = buf + sizeof("search") - 1; - while (*cp == ' ' || *cp == '\t') - cp++; - if ((*cp == '\0') || (*cp == '\n')) - continue; - strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1); - statp->defdname[sizeof(statp->defdname) - 1] = '\0'; - if ((cp = strchr(statp->defdname, '\n')) != NULL) - *cp = '\0'; - /* - * Set search list to be blank-separated strings - * on rest of line. - */ - cp = statp->defdname; - pp = statp->dnsrch; - *pp++ = cp; - for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) { - if (*cp == ' ' || *cp == '\t') { - *cp = 0; - n = 1; - } else if (n) { - *pp++ = cp; - n = 0; - } - } - /* null terminate last domain if there are excess */ - while (*cp != '\0' && *cp != ' ' && *cp != '\t') - cp++; - *cp = '\0'; - *pp++ = 0; - havesearch = 1; - continue; - } - /* read nameservers to query */ - if (MATCH(buf, "nameserver") && nserv < MAXNS) { - struct in_addr a; - - cp = buf + sizeof("nameserver") - 1; - while (*cp == ' ' || *cp == '\t') - cp++; - if ((*cp != '\0') && (*cp != '\n') - && __inet_aton(cp, &a)) { - statp->nsaddr_list[nserv].sin_addr = a; - statp->nsaddr_list[nserv].sin_family = AF_INET; - statp->nsaddr_list[nserv].sin_port = - htons(NAMESERVER_PORT); - nserv++; -#ifdef _LIBC - } else { - struct in6_addr a6; - char *el; - - if ((el = strpbrk(cp, " \t\n")) != NULL) - *el = '\0'; - if ((el = strchr(cp, SCOPE_DELIMITER)) != NULL) - *el = '\0'; - if ((*cp != '\0') && - (__inet_pton(AF_INET6, cp, &a6) > 0)) { - struct sockaddr_in6 *sa6; - - sa6 = malloc(sizeof(*sa6)); - if (sa6 != NULL) { - sa6->sin6_family = AF_INET6; - sa6->sin6_port = htons(NAMESERVER_PORT); - sa6->sin6_flowinfo = 0; - sa6->sin6_addr = a6; - - if (__glibc_likely (el == NULL)) - sa6->sin6_scope_id = 0; - else { - int try_numericscope = 1; - if (IN6_IS_ADDR_LINKLOCAL (&a6) - || IN6_IS_ADDR_MC_LINKLOCAL (&a6)) { - sa6->sin6_scope_id - = __if_nametoindex (el + 1); - if (sa6->sin6_scope_id != 0) - try_numericscope = 0; - } - - if (try_numericscope) { - char *end; - sa6->sin6_scope_id - = (uint32_t) strtoul (el + 1, &end, - 10); - if (*end != '\0') - sa6->sin6_scope_id = 0; - } - } - - statp->nsaddr_list[nserv].sin_family = 0; - statp->_u._ext.nsaddrs[nserv] = sa6; - statp->_u._ext.nssocks[nserv] = -1; - have_serv6 = 1; - nserv++; - } - } -#endif - } - continue; - } -#ifdef RESOLVSORT - if (MATCH(buf, "sortlist")) { - struct in_addr a; - - cp = buf + sizeof("sortlist") - 1; - while (nsort < MAXRESOLVSORT) { - while (*cp == ' ' || *cp == '\t') - cp++; - if (*cp == '\0' || *cp == '\n' || *cp == ';') - break; - net = cp; - while (*cp && !ISSORTMASK(*cp) && *cp != ';' && - isascii(*cp) && !isspace(*cp)) - cp++; - n = *cp; - *cp = 0; - if (__inet_aton(net, &a)) { - statp->sort_list[nsort].addr = a; - if (ISSORTMASK(n)) { - *cp++ = n; - net = cp; - while (*cp && *cp != ';' && - isascii(*cp) && !isspace(*cp)) - cp++; - n = *cp; - *cp = 0; - if (__inet_aton(net, &a)) { - statp->sort_list[nsort].mask = a.s_addr; - } else { - statp->sort_list[nsort].mask = - net_mask(statp->sort_list[nsort].addr); - } - } else { - statp->sort_list[nsort].mask = - net_mask(statp->sort_list[nsort].addr); - } - nsort++; - } - *cp = n; - } - continue; - } -#endif - if (MATCH(buf, "options")) { - res_setoptions(statp, buf + sizeof("options") - 1, "conf"); - continue; - } - } - statp->nscount = nserv; -#ifdef _LIBC - if (have_serv6) { - /* We try IPv6 servers again. */ - statp->ipv6_unavail = false; - } -#endif -#ifdef RESOLVSORT - statp->nsort = nsort; -#endif - (void) fclose(fp); - } - if (__builtin_expect(statp->nscount == 0, 0)) { - statp->nsaddr.sin_addr = __inet_makeaddr(IN_LOOPBACKNET, 1); - statp->nsaddr.sin_family = AF_INET; - statp->nsaddr.sin_port = htons(NAMESERVER_PORT); - statp->nscount = 1; - } - if (statp->defdname[0] == 0 && - __gethostname(buf, sizeof(statp->defdname) - 1) == 0 && - (cp = strchr(buf, '.')) != NULL) - strcpy(statp->defdname, cp + 1); - - /* find components of local domain that might be searched */ - if (havesearch == 0) { - pp = statp->dnsrch; - *pp++ = statp->defdname; - *pp = NULL; - -#ifndef RFC1535 - dots = 0; - for (cp = statp->defdname; *cp; cp++) - dots += (*cp == '.'); - - cp = statp->defdname; - while (pp < statp->dnsrch + MAXDFLSRCH) { - if (dots < LOCALDOMAINPARTS) - break; - cp = __rawmemchr(cp, '.') + 1; /* we know there is one */ - *pp++ = cp; - dots--; - } - *pp = NULL; -#ifdef DEBUG - if (statp->options & RES_DEBUG) { - printf(";; res_init()... default dnsrch list:\n"); - for (pp = statp->dnsrch; *pp; pp++) - printf(";;\t%s\n", *pp); - printf(";;\t..END..\n"); - } -#endif -#endif /* !RFC1535 */ - } - - if ((cp = getenv("RES_OPTIONS")) != NULL) - res_setoptions(statp, cp, "env"); - statp->options |= RES_INIT; - return (0); +static void +resolv_conf_parser_init (struct resolv_conf_parser *parser, + const struct __res_state *preinit) +{ + parser->buffer = NULL; + parser->search_list_store = NULL; + nameserver_list_init (&parser->nameserver_list); + search_list_init (&parser->search_list); + sort_list_init (&parser->sort_list); + + if (preinit != NULL) + { + parser->template.retrans = preinit->retrans; + parser->template.retry = preinit->retry; + parser->template.options = preinit->options | RES_INIT; + } + else + { + parser->template.retrans = RES_TIMEOUT; + parser->template.retry = RES_DFLRETRY; + parser->template.options = RES_DEFAULT | RES_INIT; + } + parser->template.ndots = 1; } static void -internal_function -res_setoptions(res_state statp, const char *options, const char *source) { - const char *cp = options; - int i; - -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; res_setoptions(\"%s\", \"%s\")...\n", - options, source); -#endif - while (*cp) { - /* skip leading and inner runs of spaces */ - while (*cp == ' ' || *cp == '\t') - cp++; - /* search for and process individual options */ - if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) { - i = atoi(cp + sizeof("ndots:") - 1); - if (i <= RES_MAXNDOTS) - statp->ndots = i; - else - statp->ndots = RES_MAXNDOTS; -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";;\tndots=%d\n", statp->ndots); -#endif - } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) { - i = atoi(cp + sizeof("timeout:") - 1); - if (i <= RES_MAXRETRANS) - statp->retrans = i; - else - statp->retrans = RES_MAXRETRANS; - } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){ - i = atoi(cp + sizeof("attempts:") - 1); - if (i <= RES_MAXRETRY) - statp->retry = i; - else - statp->retry = RES_MAXRETRY; - } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) { -#ifdef DEBUG - if (!(statp->options & RES_DEBUG)) { - printf(";; res_setoptions(\"%s\", \"%s\")..\n", - options, source); - statp->options |= RES_DEBUG; - } - printf(";;\tdebug\n"); -#endif - } else { - static const struct - { - char str[22]; - uint8_t len; - uint8_t clear; - unsigned long int flag; - } options[] = { -#define STRnLEN(str) str, sizeof (str) - 1 - { STRnLEN ("inet6"), 0, RES_USE_INET6 }, - { STRnLEN ("ip6-bytestring"), 0, RES_USEBSTRING }, - { STRnLEN ("no-ip6-dotint"), 0, RES_NOIP6DOTINT }, - { STRnLEN ("ip6-dotint"), 1, ~RES_NOIP6DOTINT }, - { STRnLEN ("rotate"), 0, RES_ROTATE }, - { STRnLEN ("no-check-names"), 0, RES_NOCHECKNAME }, - { STRnLEN ("edns0"), 0, RES_USE_EDNS0 }, - { STRnLEN ("single-request-reopen"), 0, RES_SNGLKUPREOP }, - { STRnLEN ("single-request"), 0, RES_SNGLKUP }, - { STRnLEN ("no_tld_query"), 0, RES_NOTLDQUERY }, - { STRnLEN ("no-tld-query"), 0, RES_NOTLDQUERY }, - { STRnLEN ("use-vc"), 0, RES_USEVC } - }; -#define noptions (sizeof (options) / sizeof (options[0])) - int i; - for (i = 0; i < noptions; ++i) - if (strncmp (cp, options[i].str, options[i].len) == 0) - { - if (options[i].clear) - statp->options &= options[i].flag; - else - statp->options |= options[i].flag; - break; - } - if (i == noptions) { - /* XXX - print a warning here? */ - } - } - /* skip to next run of spaces */ - while (*cp && *cp != ' ' && *cp != '\t') - cp++; - } +resolv_conf_parser_free (struct resolv_conf_parser *parser) +{ + free (parser->buffer); + free (parser->search_list_store); + nameserver_list_free (&parser->nameserver_list); + search_list_free (&parser->search_list); + sort_list_free (&parser->sort_list); } -#ifdef RESOLVSORT -/* XXX - should really support CIDR which means explicit masks always. */ -/* XXX - should really use system's version of this */ -static u_int32_t -net_mask (struct in_addr in) +/* Allocate a struct sockaddr_in object on the heap, with the + specified address and port. */ +static struct sockaddr * +allocate_address_v4 (struct in_addr a, uint16_t port) { - u_int32_t i = ntohl(in.s_addr); - - if (IN_CLASSA(i)) - return (htonl(IN_CLASSA_NET)); - else if (IN_CLASSB(i)) - return (htonl(IN_CLASSB_NET)); - return (htonl(IN_CLASSC_NET)); + struct sockaddr_in *sa4 = malloc (sizeof (*sa4)); + if (sa4 == NULL) + return NULL; + sa4->sin_family = AF_INET; + sa4->sin_addr = a; + sa4->sin_port = htons (port); + return (struct sockaddr *) sa4; } -#endif -u_int -res_randomid(void) { - return 0xffff & __getpid(); +/* Try to obtain the domain name from the host name and store it in + *RESULT. Return false on memory allocation failure. If the domain + name cannot be determined for any other reason, write NULL to + *RESULT and return true. */ +static bool +domain_from_hostname (char **result) +{ + char buf[256]; + /* gethostbyname may not terminate the buffer. */ + buf[sizeof (buf) - 1] = '\0'; + if (__gethostname (buf, sizeof (buf) - 1) == 0) + { + char *dot = strchr (buf, '.'); + if (dot != NULL) + { + *result = __strdup (dot + 1); + if (*result == NULL) + return false; + return true; + } + } + *result = NULL; + return true; } -#ifdef _LIBC -libc_hidden_def (__res_randomid) -#endif +static void res_setoptions (struct resolv_conf_parser *, const char *options); -/* - * This routine is for closing the socket if a virtual circuit is used and - * the program wants to close it. This provides support for endhostent() - * which expects to close the socket. - * - * This routine is not expected to be user visible. - */ -void -__res_iclose(res_state statp, bool free_addr) { - int ns; - - if (statp->_vcsock >= 0) { - close_not_cancel_no_status(statp->_vcsock); - statp->_vcsock = -1; - statp->_flags &= ~(RES_F_VC | RES_F_CONN); - } - for (ns = 0; ns < statp->_u._ext.nscount; ns++) - if (statp->_u._ext.nsaddrs[ns]) { - if (statp->_u._ext.nssocks[ns] != -1) { - close_not_cancel_no_status(statp->_u._ext.nssocks[ns]); - statp->_u._ext.nssocks[ns] = -1; - } - if (free_addr) { - free (statp->_u._ext.nsaddrs[ns]); - statp->_u._ext.nsaddrs[ns] = NULL; - } - } +/* Internal helper function for __res_vinit, to aid with resource + deallocation and error handling. Return true on success, false on + failure. */ +static bool +res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser) +{ + char *cp; + size_t buffer_size = 0; + bool haveenv = false; + + /* Allow user to override the local domain definition. */ + if ((cp = getenv ("LOCALDOMAIN")) != NULL) + { + /* The code below splits the string in place. */ + cp = __strdup (cp); + if (cp == NULL) + return false; + free (parser->search_list_store); + parser->search_list_store = cp; + haveenv = true; + + /* The string will be truncated as needed below. */ + search_list_add (&parser->search_list, cp); + + /* Set search list to be blank-separated strings from rest of + env value. Permits users of LOCALDOMAIN to still have a + search list, and anyone to set the one that they want to use + as an individual (even more important now that the rfc1535 + stuff restricts searches). */ + for (bool in_name = true; *cp != '\0'; cp++) + { + if (*cp == '\n') + { + *cp = '\0'; + break; + } + else if (*cp == ' ' || *cp == '\t') + { + *cp = '\0'; + in_name = false; + } + else if (!in_name) + { + search_list_add (&parser->search_list, cp); + in_name = true; + } + } + } + +#define MATCH(line, name) \ + (!strncmp ((line), name, sizeof (name) - 1) \ + && ((line)[sizeof (name) - 1] == ' ' \ + || (line)[sizeof (name) - 1] == '\t')) + + if (fp != NULL) + { + /* No threads use this stream. */ + __fsetlocking (fp, FSETLOCKING_BYCALLER); + /* Read the config file. */ + while (true) + { + { + ssize_t ret = __getline (&parser->buffer, &buffer_size, fp); + if (ret <= 0) + { + if (_IO_ferror_unlocked (fp)) + return false; + else + break; + } + } + + /* Skip comments. */ + if (*parser->buffer == ';' || *parser->buffer == '#') + continue; + /* Read default domain name. */ + if (MATCH (parser->buffer, "domain")) + { + if (haveenv) + /* LOCALDOMAIN overrides the configuration file. */ + continue; + cp = parser->buffer + sizeof ("domain") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((*cp == '\0') || (*cp == '\n')) + continue; + + cp = __strdup (cp); + if (cp == NULL) + return false; + free (parser->search_list_store); + parser->search_list_store = cp; + search_list_clear (&parser->search_list); + search_list_add (&parser->search_list, cp); + /* Replace trailing whitespace. */ + if ((cp = strpbrk (cp, " \t\n")) != NULL) + *cp = '\0'; + continue; + } + /* Set search list. */ + if (MATCH (parser->buffer, "search")) + { + if (haveenv) + /* LOCALDOMAIN overrides the configuration file. */ + continue; + cp = parser->buffer + sizeof ("search") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + if ((*cp == '\0') || (*cp == '\n')) + continue; + + { + char *p = strchr (cp, '\n'); + if (p != NULL) + *p = '\0'; + } + cp = __strdup (cp); + if (cp == NULL) + return false; + free (parser->search_list_store); + parser->search_list_store = cp; + + /* The string is truncated below. */ + search_list_clear (&parser->search_list); + search_list_add (&parser->search_list, cp); + + /* Set search list to be blank-separated strings on rest + of line. */ + for (bool in_name = true; *cp != '\0'; cp++) + { + if (*cp == ' ' || *cp == '\t') + { + *cp = '\0'; + in_name = false; + } + else if (!in_name) + { + search_list_add (&parser->search_list, cp); + in_name = true; + } + } + continue; + } + /* Read nameservers to query. */ + if (MATCH (parser->buffer, "nameserver")) + { + struct in_addr a; + + cp = parser->buffer + sizeof ("nameserver") - 1; + while (*cp == ' ' || *cp == '\t') + cp++; + struct sockaddr *sa; + if ((*cp != '\0') && (*cp != '\n') && __inet_aton (cp, &a)) + { + sa = allocate_address_v4 (a, NAMESERVER_PORT); + if (sa == NULL) + return false; + } + else + { + struct in6_addr a6; + char *el; + + if ((el = strpbrk (cp, " \t\n")) != NULL) + *el = '\0'; + if ((el = strchr (cp, SCOPE_DELIMITER)) != NULL) + *el = '\0'; + if ((*cp != '\0') && (__inet_pton (AF_INET6, cp, &a6) > 0)) + { + struct sockaddr_in6 *sa6; + + sa6 = malloc (sizeof (*sa6)); + if (sa6 == NULL) + return false; + + sa6->sin6_family = AF_INET6; + sa6->sin6_port = htons (NAMESERVER_PORT); + sa6->sin6_flowinfo = 0; + sa6->sin6_addr = a6; + + sa6->sin6_scope_id = 0; + if (__glibc_likely (el != NULL)) + /* Ignore errors, for backwards + compatibility. */ + __inet6_scopeid_pton + (&a6, el + 1, &sa6->sin6_scope_id); + sa = (struct sockaddr *) sa6; + } + else + /* IPv6 address parse failure. */ + sa = NULL; + } + if (sa != NULL) + { + const struct sockaddr **p = nameserver_list_emplace + (&parser->nameserver_list); + if (p != NULL) + *p = sa; + else + { + free (sa); + return false; + } + } + continue; + } + if (MATCH (parser->buffer, "sortlist")) + { + struct in_addr a; + + cp = parser->buffer + sizeof ("sortlist") - 1; + while (true) + { + while (*cp == ' ' || *cp == '\t') + cp++; + if (*cp == '\0' || *cp == '\n' || *cp == ';') + break; + char *net = cp; + while (*cp && !is_sort_mask (*cp) && *cp != ';' + && isascii (*cp) && !isspace (*cp)) + cp++; + char separator = *cp; + *cp = 0; + struct resolv_sortlist_entry e; + if (__inet_aton (net, &a)) + { + e.addr = a; + if (is_sort_mask (separator)) + { + *cp++ = separator; + net = cp; + while (*cp && *cp != ';' + && isascii (*cp) && !isspace (*cp)) + cp++; + separator = *cp; + *cp = 0; + if (__inet_aton (net, &a)) + e.mask = a.s_addr; + else + e.mask = net_mask (e.addr); + } + else + e.mask = net_mask (e.addr); + sort_list_add (&parser->sort_list, e); + } + *cp = separator; + } + continue; + } + if (MATCH (parser->buffer, "options")) + { + res_setoptions (parser, parser->buffer + sizeof ("options") - 1); + continue; + } + } + fclose (fp); + } + if (__glibc_unlikely (nameserver_list_size (&parser->nameserver_list) == 0)) + { + const struct sockaddr **p + = nameserver_list_emplace (&parser->nameserver_list); + if (p == NULL) + return false; + *p = allocate_address_v4 (__inet_makeaddr (IN_LOOPBACKNET, 1), + NAMESERVER_PORT); + if (*p == NULL) + return false; + } + + if (search_list_size (&parser->search_list) == 0) + { + char *domain; + if (!domain_from_hostname (&domain)) + return false; + if (domain != NULL) + { + free (parser->search_list_store); + parser->search_list_store = domain; + search_list_add (&parser->search_list, domain); + } + } + + if ((cp = getenv ("RES_OPTIONS")) != NULL) + res_setoptions (parser, cp); + + if (nameserver_list_has_failed (&parser->nameserver_list) + || search_list_has_failed (&parser->search_list) + || sort_list_has_failed (&parser->sort_list)) + { + __set_errno (ENOMEM); + return false; + } + + return true; } -libc_hidden_def (__res_iclose) -void -res_nclose(res_state statp) +struct resolv_conf * +__resolv_conf_load (struct __res_state *preinit) { - __res_iclose (statp, true); + /* Ensure that /etc/hosts.conf has been loaded (once). */ + _res_hconf_init (); + + FILE *fp = fopen (_PATH_RESCONF, "rce"); + if (fp == NULL) + switch (errno) + { + case EACCES: + case EISDIR: + case ELOOP: + case ENOENT: + case ENOTDIR: + case EPERM: + /* Ignore these errors. They are persistent errors caused + by file system contents. */ + break; + default: + /* Other errors refer to resource allocation problems and + need to be handled by the application. */ + return NULL; + } + + struct resolv_conf_parser parser; + resolv_conf_parser_init (&parser, preinit); + + struct resolv_conf *conf = NULL; + if (res_vinit_1 (fp, &parser)) + { + parser.template.nameserver_list + = nameserver_list_begin (&parser.nameserver_list); + parser.template.nameserver_list_size + = nameserver_list_size (&parser.nameserver_list); + parser.template.search_list = search_list_begin (&parser.search_list); + parser.template.search_list_size + = search_list_size (&parser.search_list); + parser.template.sort_list = sort_list_begin (&parser.sort_list); + parser.template.sort_list_size = sort_list_size (&parser.sort_list); + conf = __resolv_conf_allocate (&parser.template); + } + resolv_conf_parser_free (&parser); + + return conf; } -#ifdef _LIBC -libc_hidden_def (__res_nclose) -#endif - -#ifdef _LIBC -# ifdef _LIBC_REENTRANT -/* This is called when a thread is exiting to free resources held in _res. */ -static void __attribute__ ((section ("__libc_thread_freeres_fn"))) -res_thread_freeres (void) + +/* Set up default settings. If the /etc/resolv.conf configuration + file exist, the values there will have precedence. Otherwise, the + server address is set to INADDR_LOOPBACK and the default domain + name comes from gethostname. The RES_OPTIONS and LOCALDOMAIN + environment variables can be used to override some settings. + Return 0 if completes successfully, -1 on error. */ +int +__res_vinit (res_state statp, int preinit) { - if (_res.nscount == 0) - /* Never called res_ninit. */ - return; + struct resolv_conf *conf; + if (preinit && has_preinit_values (statp)) + /* For the preinit case, we cannot use the cached configuration + because some settings could be different. */ + conf = __resolv_conf_load (statp); + else + conf = __resolv_conf_get_current (); + if (conf == NULL) + return -1; + + bool ok = __resolv_conf_attach (statp, conf); + __resolv_conf_put (conf); + if (ok) + { + if (preinit) + statp->id = res_randomid (); + return 0; + } + else + return -1; +} - __res_iclose (&_res, true); /* Close any VC sockets. */ +static void +res_setoptions (struct resolv_conf_parser *parser, const char *options) +{ + const char *cp = options; + + while (*cp) + { + /* Skip leading and inner runs of spaces. */ + while (*cp == ' ' || *cp == '\t') + cp++; + /* Search for and process individual options. */ + if (!strncmp (cp, "ndots:", sizeof ("ndots:") - 1)) + { + int i = atoi (cp + sizeof ("ndots:") - 1); + if (i <= RES_MAXNDOTS) + parser->template.ndots = i; + else + parser->template.ndots = RES_MAXNDOTS; + } + else if (!strncmp (cp, "timeout:", sizeof ("timeout:") - 1)) + { + int i = atoi (cp + sizeof ("timeout:") - 1); + if (i <= RES_MAXRETRANS) + parser->template.retrans = i; + else + parser->template.retrans = RES_MAXRETRANS; + } + else if (!strncmp (cp, "attempts:", sizeof ("attempts:") - 1)) + { + int i = atoi (cp + sizeof ("attempts:") - 1); + if (i <= RES_MAXRETRY) + parser->template.retry = i; + else + parser->template.retry = RES_MAXRETRY; + } + else + { + static const struct + { + char str[22]; + uint8_t len; + uint8_t clear; + unsigned long int flag; + } options[] = { +#define STRnLEN(str) str, sizeof (str) - 1 + { STRnLEN ("inet6"), 0, DEPRECATED_RES_USE_INET6 }, + { STRnLEN ("rotate"), 0, RES_ROTATE }, + { STRnLEN ("edns0"), 0, RES_USE_EDNS0 }, + { STRnLEN ("single-request-reopen"), 0, RES_SNGLKUPREOP }, + { STRnLEN ("single-request"), 0, RES_SNGLKUP }, + { STRnLEN ("no_tld_query"), 0, RES_NOTLDQUERY }, + { STRnLEN ("no-tld-query"), 0, RES_NOTLDQUERY }, + { STRnLEN ("no-reload"), 0, RES_NORELOAD }, + { STRnLEN ("use-vc"), 0, RES_USEVC } + }; +#define noptions (sizeof (options) / sizeof (options[0])) + for (int i = 0; i < noptions; ++i) + if (strncmp (cp, options[i].str, options[i].len) == 0) + { + if (options[i].clear) + parser->template.options &= options[i].flag; + else + parser->template.options |= options[i].flag; + break; + } + } + /* Skip to next run of spaces. */ + while (*cp && *cp != ' ' && *cp != '\t') + cp++; + } +} + +static uint32_t +net_mask (struct in_addr in) +{ + uint32_t i = ntohl (in.s_addr); - /* Make sure we do a full re-initialization the next time. */ - _res.options = 0; + if (IN_CLASSA (i)) + return htonl (IN_CLASSA_NET); + else if (IN_CLASSB (i)) + return htonl (IN_CLASSB_NET); + return htonl (IN_CLASSC_NET); } -text_set_element (__libc_thread_subfreeres, res_thread_freeres); -text_set_element (__libc_subfreeres, res_thread_freeres); -# endif -#endif diff --git a/resolv/res_libc.c b/resolv/res_libc.c index a8394e0e7b..6d3e1d2c1a 100644 --- a/resolv/res_libc.c +++ b/resolv/res_libc.c @@ -1,3 +1,21 @@ +/* Definitions related to res_init linked into libc instead of libresolv. + Copyright (C) 1995-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + /* * Copyright (c) 1995-1999 by Internet Software Consortium. * @@ -22,98 +40,46 @@ #include <arpa/nameser.h> #include <resolv.h> #include <libc-lock.h> - - -/* The following bit is copied from res_data.c (where it is #ifdef'ed - out) since res_init() should go into libc.so but the rest of that - file should not. */ - -extern unsigned long long int __res_initstamp attribute_hidden; -/* We have atomic increment operations on 64-bit platforms. */ -#if __WORDSIZE == 64 -# define atomicinclock(lock) (void) 0 -# define atomicincunlock(lock) (void) 0 -# define atomicinc(var) catomic_increment (&(var)) -#else -__libc_lock_define_initialized (static, lock); -# define atomicinclock(lock) __libc_lock_lock (lock) -# define atomicincunlock(lock) __libc_lock_unlock (lock) -# define atomicinc(var) ++var -#endif +#include <resolv-internal.h> int -res_init(void) { - extern int __res_vinit(res_state, int); - - /* - * These three fields used to be statically initialized. This made - * it hard to use this code in a shared library. It is necessary, - * now that we're doing dynamic initialization here, that we preserve - * the old semantics: if an application modifies one of these three - * fields of _res before res_init() is called, res_init() will not - * alter them. Of course, if an application is setting them to - * _zero_ before calling res_init(), hoping to override what used - * to be the static default, we can't detect it and unexpected results - * will follow. Zero for any of these fields would make no sense, - * so one can safely assume that the applications were already getting - * unexpected results. - * - * _res.options is tricky since some apps were known to diddle the bits - * before res_init() was first called. We can't replicate that semantic - * with dynamic initialization (they may have turned bits off that are - * set in RES_DEFAULT). Our solution is to declare such applications - * "broken". They could fool us by setting RES_INIT but none do (yet). - */ - if (!_res.retrans) - _res.retrans = RES_TIMEOUT; - if (!_res.retry) - _res.retry = 4; - if (!(_res.options & RES_INIT)) - _res.options = RES_DEFAULT; - else if (_res.nscount > 0) - __res_iclose (&_res, true); /* Close any VC sockets. */ - - /* - * This one used to initialize implicitly to zero, so unless the app - * has set it to something in particular, we can randomize it now. - */ - if (!_res.id) - _res.id = res_randomid(); +res_init (void) +{ + /* These three fields used to be statically initialized. This made + it hard to use this code in a shared library. It is necessary, + now that we're doing dynamic initialization here, that we + preserve the old semantics: if an application modifies one of + these three fields of _res before res_init is called, + res_init will not alter them. Of course, if an application is + setting them to _zero_ before calling res_init, hoping to + override what used to be the static default, we can't detect it + and unexpected results will follow. Zero for any of these fields + would make no sense, so one can safely assume that the + applications were already getting unexpected results. - atomicinclock (lock); - /* Request all threads to re-initialize their resolver states, - resolv.conf might have changed. */ - atomicinc (__res_initstamp); - atomicincunlock (lock); + _res.options is tricky since some apps were known to diddle the + bits before res_init was first called. We can't replicate that + semantic with dynamic initialization (they may have turned bits + off that are set in RES_DEFAULT). Our solution is to declare + such applications "broken". They could fool us by setting + RES_INIT but none do (yet). */ + if (!_res.retrans) + _res.retrans = RES_TIMEOUT; + if (!_res.retry) + _res.retry = RES_DFLRETRY; + if (!(_res.options & RES_INIT)) + _res.options = RES_DEFAULT; + else if (_res.nscount > 0) + __res_iclose (&_res, true); /* Close any VC sockets. */ - return (__res_vinit(&_res, 1)); -} + /* This one used to initialize implicitly to zero, so unless the app + has set it to something in particular, we can randomize it * + now. */ + if (!_res.id) + _res.id = res_randomid (); -/* Initialize resp if RES_INIT is not yet set or if res_init in some other - thread requested re-initializing. */ -int -__res_maybe_init (res_state resp, int preinit) -{ - if (resp->options & RES_INIT) { - if (__res_initstamp != resp->_u._ext.initstamp) { - if (resp->nscount > 0) - __res_iclose (resp, true); - return __res_vinit (resp, 1); - } - return 0; - } else if (preinit) { - if (!resp->retrans) - resp->retrans = RES_TIMEOUT; - if (!resp->retry) - resp->retry = 4; - resp->options = RES_DEFAULT; - if (!resp->id) - resp->id = res_randomid (); - return __res_vinit (resp, 1); - } else - return __res_ninit (resp); + return __res_vinit (&_res, 1); } -libc_hidden_def (__res_maybe_init) /* This needs to be after the use of _res in res_init, above. */ #undef _res @@ -129,16 +95,15 @@ __thread struct __res_state *__resp = &_res; extern __thread struct __res_state *__libc_resp __attribute__ ((alias ("__resp"))) attribute_hidden; +#include <shlib-compat.h> + /* We declare this with compat_symbol so that it's not visible at link time. Programs must use the accessor functions. */ #ifdef SHARED -# include <shlib-compat.h> compat_symbol (libc, _res, _res, GLIBC_2_0); #endif -#include <shlib-compat.h> - -#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2) +#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2) # undef res_init extern int __res_init_weak (void); weak_extern (__res_init_weak); diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c index 1635e6a035..213abeefad 100644 --- a/resolv/res_mkquery.c +++ b/resolv/res_mkquery.c @@ -1,3 +1,21 @@ +/* Creation of DNS query packets. + Copyright (C) 1995-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + /* * Copyright (c) 1985, 1993 * The Regents of the University of California. All rights reserved. @@ -64,204 +82,222 @@ * SOFTWARE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "$BINDId: res_mkquery.c,v 8.12 1999/10/13 16:39:40 vixie Exp $"; -#endif /* LIBC_SCCS and not lint */ - #include <sys/types.h> #include <sys/param.h> #include <netinet/in.h> #include <arpa/nameser.h> #include <netdb.h> -#include <resolv.h> -#include <stdio.h> +#include <resolv/resolv-internal.h> +#include <resolv/resolv_context.h> #include <string.h> #include <sys/time.h> +#include <shlib-compat.h> -/* Options. Leave them on. */ -/* #define DEBUG */ - -#ifdef _LIBC -# include <hp-timing.h> -# include <stdint.h> -# if HP_TIMING_AVAIL -# define RANDOM_BITS(Var) { uint64_t v64; HP_TIMING_NOW (v64); Var = v64; } -# endif +#include <hp-timing.h> +#include <stdint.h> +#if HP_TIMING_AVAIL +# define RANDOM_BITS(Var) { uint64_t v64; HP_TIMING_NOW (v64); Var = v64; } #endif -/* - * Form all types of queries. - * Returns the size of the result or -1. - */ int -res_nmkquery(res_state statp, - int op, /* opcode of query */ - const char *dname, /* domain name */ - int class, int type, /* class and type of query */ - const u_char *data, /* resource record data */ - int datalen, /* length of data */ - const u_char *newrr_in, /* new rr for modify or append */ - u_char *buf, /* buffer to put query */ - int buflen) /* size of buffer */ +__res_context_mkquery (struct resolv_context *ctx, int op, const char *dname, + int class, int type, const unsigned char *data, + unsigned char *buf, int buflen) { - HEADER *hp; - u_char *cp; - int n; - u_char *dnptrs[20], **dpp, **lastdnptr; - -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; res_nmkquery(%s, %s, %s, %s)\n", - _res_opcodes[op], dname, p_class(class), p_type(type)); -#endif - /* - * Initialize header fields. - */ - if ((buf == NULL) || (buflen < HFIXEDSZ)) - return (-1); - memset(buf, 0, HFIXEDSZ); - hp = (HEADER *) buf; - /* We randomize the IDs every time. The old code just - incremented by one after the initial randomization which - still predictable if the application does multiple - requests. */ - int randombits; - do - { + HEADER *hp; + unsigned char *cp; + int n; + unsigned char *dnptrs[20], **dpp, **lastdnptr; + + if (class < 0 || class > 65535 || type < 0 || type > 65535) + return -1; + + /* Initialize header fields. */ + if ((buf == NULL) || (buflen < HFIXEDSZ)) + return -1; + memset (buf, 0, HFIXEDSZ); + hp = (HEADER *) buf; + /* We randomize the IDs every time. The old code just incremented + by one after the initial randomization which still predictable if + the application does multiple requests. */ + int randombits; #ifdef RANDOM_BITS - RANDOM_BITS (randombits); + RANDOM_BITS (randombits); #else - struct timeval tv; - __gettimeofday (&tv, NULL); - randombits = (tv.tv_sec << 8) ^ tv.tv_usec; + struct timeval tv; + __gettimeofday (&tv, NULL); + randombits = (tv.tv_sec << 8) ^ tv.tv_usec; #endif - } - while ((randombits & 0xffff) == 0); - statp->id = (statp->id + randombits) & 0xffff; - hp->id = statp->id; - hp->opcode = op; - hp->rd = (statp->options & RES_RECURSE) != 0; - hp->rcode = NOERROR; - cp = buf + HFIXEDSZ; - buflen -= HFIXEDSZ; - dpp = dnptrs; - *dpp++ = buf; - *dpp++ = NULL; - lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; - /* - * perform opcode specific processing - */ - switch (op) { - case NS_NOTIFY_OP: - if ((buflen -= QFIXEDSZ + (data == NULL ? 0 : RRFIXEDSZ)) < 0) - return (-1); - goto compose; - - case QUERY: - if ((buflen -= QFIXEDSZ) < 0) - return (-1); - compose: - n = ns_name_compress(dname, cp, buflen, - (const u_char **) dnptrs, - (const u_char **) lastdnptr); - if (n < 0) - return (-1); - cp += n; - buflen -= n; - NS_PUT16 (type, cp); - NS_PUT16 (class, cp); - hp->qdcount = htons(1); - if (op == QUERY || data == NULL) - break; - /* - * Make an additional record for completion domain. - */ - n = ns_name_compress((char *)data, cp, buflen, - (const u_char **) dnptrs, - (const u_char **) lastdnptr); - if (__glibc_unlikely (n < 0)) - return (-1); - cp += n; - buflen -= n; - NS_PUT16 (T_NULL, cp); - NS_PUT16 (class, cp); - NS_PUT32 (0, cp); - NS_PUT16 (0, cp); - hp->arcount = htons(1); - break; - - case IQUERY: - /* - * Initialize answer section - */ - if (__glibc_unlikely (buflen < 1 + RRFIXEDSZ + datalen)) - return (-1); - *cp++ = '\0'; /* no domain name */ - NS_PUT16 (type, cp); - NS_PUT16 (class, cp); - NS_PUT32 (0, cp); - NS_PUT16 (datalen, cp); - if (datalen) { - memcpy(cp, data, datalen); - cp += datalen; - } - hp->ancount = htons(1); - break; - - default: - return (-1); - } - return (cp - buf); + + hp->id = randombits; + hp->opcode = op; + hp->rd = (ctx->resp->options & RES_RECURSE) != 0; + hp->rcode = NOERROR; + cp = buf + HFIXEDSZ; + buflen -= HFIXEDSZ; + dpp = dnptrs; + *dpp++ = buf; + *dpp++ = NULL; + lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; + + /* Perform opcode specific processing. */ + switch (op) + { + case NS_NOTIFY_OP: + if ((buflen -= QFIXEDSZ + (data == NULL ? 0 : RRFIXEDSZ)) < 0) + return -1; + goto compose; + + case QUERY: + if ((buflen -= QFIXEDSZ) < 0) + return -1; + compose: + n = ns_name_compress (dname, cp, buflen, + (const unsigned char **) dnptrs, + (const unsigned char **) lastdnptr); + if (n < 0) + return -1; + cp += n; + buflen -= n; + NS_PUT16 (type, cp); + NS_PUT16 (class, cp); + hp->qdcount = htons (1); + if (op == QUERY || data == NULL) + break; + + /* Make an additional record for completion domain. */ + n = ns_name_compress ((char *)data, cp, buflen, + (const unsigned char **) dnptrs, + (const unsigned char **) lastdnptr); + if (__glibc_unlikely (n < 0)) + return -1; + cp += n; + buflen -= n; + NS_PUT16 (T_NULL, cp); + NS_PUT16 (class, cp); + NS_PUT32 (0, cp); + NS_PUT16 (0, cp); + hp->arcount = htons (1); + break; + + default: + return -1; + } + return cp - buf; +} + +/* Common part of res_nmkquery and res_mkquery. */ +static int +context_mkquery_common (struct resolv_context *ctx, + int op, const char *dname, int class, int type, + const unsigned char *data, + unsigned char *buf, int buflen) +{ + if (ctx == NULL) + return -1; + int result = __res_context_mkquery + (ctx, op, dname, class, type, data, buf, buflen); + if (result >= 2) + memcpy (&ctx->resp->id, buf, 2); + __resolv_context_put (ctx); + return result; } -libresolv_hidden_def (res_nmkquery) +/* Form all types of queries. Returns the size of the result or -1 on + error. -/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */ -#ifndef T_OPT -#define T_OPT 41 -#endif + STATP points to an initialized resolver state. OP is the opcode of + the query. DNAME is the domain. CLASS and TYPE are the DNS query + class and type. DATA can be NULL; otherwise, it is a pointer to a + domain name which is included in the generated packet (if op == + NS_NOTIFY_OP). BUF must point to the out buffer of BUFLEN bytes. + DATALEN and NEWRR_IN are currently ignored. */ int -__res_nopt(res_state statp, - int n0, /* current offset in buffer */ - u_char *buf, /* buffer to put query */ - int buflen, /* size of buffer */ - int anslen) /* UDP answer buffer size */ +res_nmkquery (res_state statp, int op, const char *dname, + int class, int type, + const unsigned char *data, int datalen, + const unsigned char *newrr_in, + unsigned char *buf, int buflen) { - u_int16_t flags = 0; + return context_mkquery_common + (__resolv_context_get_override (statp), + op, dname, class, type, data, buf, buflen); +} -#ifdef DEBUG - if ((statp->options & RES_DEBUG) != 0U) - printf(";; res_nopt()\n"); -#endif +int +res_mkquery (int op, const char *dname, int class, int type, + const unsigned char *data, int datalen, + const unsigned char *newrr_in, + unsigned char *buf, int buflen) +{ + return context_mkquery_common + (__resolv_context_get_preinit (), + op, dname, class, type, data, buf, buflen); +} - HEADER *hp = (HEADER *) buf; - u_char *cp = buf + n0; - u_char *ep = buf + buflen; +/* Create an OPT resource record. Return the length of the final + packet, or -1 on error. - if ((ep - cp) < 1 + RRFIXEDSZ) - return -1; + STATP must be an initialized resolver state. N0 is the current + number of bytes of the packet (already written to BUF by the + aller). BUF is the packet being constructed. The array it + pointers to must be BUFLEN bytes long. ANSLEN is the advertised + EDNS buffer size (to be included in the OPT resource record). */ +int +__res_nopt (struct resolv_context *ctx, + int n0, unsigned char *buf, int buflen, int anslen) +{ + uint16_t flags = 0; + HEADER *hp = (HEADER *) buf; + unsigned char *cp = buf + n0; + unsigned char *ep = buf + buflen; - *cp++ = 0; /* "." */ + if ((ep - cp) < 1 + RRFIXEDSZ) + return -1; - NS_PUT16(T_OPT, cp); /* TYPE */ - NS_PUT16(MIN(anslen, 0xffff), cp); /* CLASS = UDP payload size */ - *cp++ = NOERROR; /* extended RCODE */ - *cp++ = 0; /* EDNS version */ + /* Add the root label. */ + *cp++ = 0; - if (statp->options & RES_USE_DNSSEC) { -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; res_opt()... ENDS0 DNSSEC\n"); -#endif - flags |= NS_OPT_DNSSEC_OK; - } + NS_PUT16 (T_OPT, cp); /* Record type. */ + + /* Lowering the advertised buffer size based on the actual + answer buffer size is desirable because the server will + minimize the reply to fit into the UDP packet (and A + non-minimal response might not fit the buffer). + + The RESOLV_EDNS_BUFFER_SIZE limit could still result in TCP + fallback and a non-minimal response which has to be + hard-truncated in the stub resolver, but this is price to + pay for avoiding fragmentation. (This issue does not + affect the nss_dns functions because they use the stub + resolver in such a way that it allocates a properly sized + response buffer.) */ + { + uint16_t buffer_size; + if (anslen < 512) + buffer_size = 512; + else if (anslen > RESOLV_EDNS_BUFFER_SIZE) + buffer_size = RESOLV_EDNS_BUFFER_SIZE; + else + buffer_size = anslen; + NS_PUT16 (buffer_size, cp); + } - NS_PUT16(flags, cp); - NS_PUT16(0, cp); /* RDLEN */ - hp->arcount = htons(ntohs(hp->arcount) + 1); + *cp++ = NOERROR; /* Extended RCODE. */ + *cp++ = 0; /* EDNS version. */ - return cp - buf; + if (ctx->resp->options & RES_USE_DNSSEC) + flags |= NS_OPT_DNSSEC_OK; + + NS_PUT16 (flags, cp); + NS_PUT16 (0, cp); /* RDATA length (no options are preent). */ + hp->arcount = htons (ntohs (hp->arcount) + 1); + + return cp - buf; } -libresolv_hidden_def (__res_nopt) + +#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_2) +# undef res_mkquery +weak_alias (__res_mkquery, res_mkquery); +#endif diff --git a/resolv/res_query.c b/resolv/res_query.c index 95470a93e9..ebbe5a6a4e 100644 --- a/resolv/res_query.c +++ b/resolv/res_query.c @@ -64,11 +64,6 @@ * SOFTWARE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "$BINDId: res_query.c,v 8.20 2000/02/29 05:39:12 vixie Exp $"; -#endif /* LIBC_SCCS and not lint */ - #include <assert.h> #include <sys/types.h> #include <sys/param.h> @@ -79,12 +74,12 @@ static const char rcsid[] = "$BINDId: res_query.c,v 8.20 2000/02/29 05:39:12 vix #include <errno.h> #include <netdb.h> #include <resolv.h> +#include <resolv/resolv-internal.h> +#include <resolv/resolv_context.h> #include <stdio.h> #include <stdlib.h> #include <string.h> - -/* Options. Leave them on. */ -/* #undef DEBUG */ +#include <shlib-compat.h> #if PACKETSZ > 65536 #define MAXPACKET PACKETSZ @@ -95,39 +90,33 @@ static const char rcsid[] = "$BINDId: res_query.c,v 8.20 2000/02/29 05:39:12 vix #define QUERYSIZE (HFIXEDSZ + QFIXEDSZ + MAXCDNAME + 1) static int -__libc_res_nquerydomain(res_state statp, const char *name, const char *domain, - int class, int type, u_char *answer, int anslen, - u_char **answerp, u_char **answerp2, int *nanswerp2, - int *resplen2, int *answerp2_malloced); - -/* - * Formulate a normal query, send, and await answer. - * Returned answer is placed in supplied buffer "answer". - * Perform preliminary check of answer, returning success only - * if no error is indicated and the answer count is nonzero. - * Return the size of the response on success, -1 on error. - * Error number is left in H_ERRNO. - * - * Caller must parse answer and determine whether it answers the question. - */ +__res_context_querydomain (struct resolv_context *, + const char *name, const char *domain, + int class, int type, unsigned char *answer, int anslen, + unsigned char **answerp, unsigned char **answerp2, int *nanswerp2, + int *resplen2, int *answerp2_malloced); + +/* Formulate a normal query, send, and await answer. Returned answer + is placed in supplied buffer ANSWER. Perform preliminary check of + answer, returning success only if no error is indicated and the + answer count is nonzero. Return the size of the response on + success, -1 on error. Error number is left in h_errno. + + Caller must parse answer and determine whether it answers the + question. */ int -__libc_res_nquery(res_state statp, - const char *name, /* domain name */ - int class, int type, /* class and type of query */ - u_char *answer, /* buffer to put answer */ - int anslen, /* size of answer buffer */ - u_char **answerp, /* if buffer needs to be enlarged */ - u_char **answerp2, - int *nanswerp2, - int *resplen2, - int *answerp2_malloced) +__res_context_query (struct resolv_context *ctx, const char *name, + int class, int type, + unsigned char *answer, int anslen, + unsigned char **answerp, unsigned char **answerp2, + int *nanswerp2, int *resplen2, int *answerp2_malloced) { + struct __res_state *statp = ctx->resp; HEADER *hp = (HEADER *) answer; HEADER *hp2; int n, use_malloc = 0; - u_int oflags = statp->_flags; - size_t bufsize = (type == T_UNSPEC ? 2 : 1) * QUERYSIZE; + size_t bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * QUERYSIZE; u_char *buf = alloca (bufsize); u_char *query1 = buf; int nquery1 = -1; @@ -137,21 +126,18 @@ __libc_res_nquery(res_state statp, again: hp->rcode = NOERROR; /* default */ -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; res_query(%s, %d, %d)\n", name, class, type); -#endif - - if (type == T_UNSPEC) + if (type == T_QUERY_A_AND_AAAA) { - n = res_nmkquery(statp, QUERY, name, class, T_A, NULL, 0, NULL, - query1, bufsize); + n = __res_context_mkquery (ctx, QUERY, name, class, T_A, NULL, + query1, bufsize); if (n > 0) { - if ((oflags & RES_F_EDNS0ERR) == 0 - && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) + if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) { - n = __res_nopt(statp, n, query1, bufsize, anslen / 2); + /* Use RESOLV_EDNS_BUFFER_SIZE because the receive + buffer can be reallocated. */ + n = __res_nopt (ctx, n, query1, bufsize, + RESOLV_EDNS_BUFFER_SIZE); if (n < 0) goto unspec_nomem; } @@ -167,13 +153,14 @@ __libc_res_nquery(res_state statp, } int nused = n + npad; query2 = buf + nused; - n = res_nmkquery(statp, QUERY, name, class, T_AAAA, NULL, 0, - NULL, query2, bufsize - nused); + n = __res_context_mkquery (ctx, QUERY, name, class, T_AAAA, + NULL, query2, bufsize - nused); if (n > 0 - && (oflags & RES_F_EDNS0ERR) == 0 && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) - n = __res_nopt(statp, n, query2, bufsize - nused - n, - anslen / 2); + /* Use RESOLV_EDNS_BUFFER_SIZE because the receive + buffer can be reallocated. */ + n = __res_nopt (ctx, n, query2, bufsize, + RESOLV_EDNS_BUFFER_SIZE); nquery2 = n; } @@ -181,21 +168,29 @@ __libc_res_nquery(res_state statp, } else { - n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL, - query1, bufsize); + n = __res_context_mkquery (ctx, QUERY, name, class, type, NULL, + query1, bufsize); if (n > 0 - && (oflags & RES_F_EDNS0ERR) == 0 && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) - n = __res_nopt(statp, n, query1, bufsize, anslen); + { + /* Use RESOLV_EDNS_BUFFER_SIZE if the receive buffer + can be reallocated. */ + size_t advertise; + if (answerp == NULL) + advertise = anslen; + else + advertise = RESOLV_EDNS_BUFFER_SIZE; + n = __res_nopt (ctx, n, query1, bufsize, advertise); + } nquery1 = n; } - if (__builtin_expect (n <= 0, 0) && !use_malloc) { + if (__glibc_unlikely (n <= 0) && !use_malloc) { /* Retry just in case res_nmkquery failed because of too short buffer. Shouldn't happen. */ - bufsize = (type == T_UNSPEC ? 2 : 1) * MAXPACKET; + bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * MAXPACKET; buf = malloc (bufsize); if (buf != NULL) { query1 = buf; @@ -204,42 +199,24 @@ __libc_res_nquery(res_state statp, } } if (__glibc_unlikely (n <= 0)) { - /* If the query choked with EDNS0, retry without EDNS0. */ - if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0 - && ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) { - statp->_flags |= RES_F_EDNS0ERR; -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; res_nquery: retry without EDNS0\n"); -#endif - goto again; - } -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; res_query: mkquery failed\n"); -#endif RES_SET_H_ERRNO(statp, NO_RECOVERY); if (use_malloc) free (buf); return (n); } assert (answerp == NULL || (void *) *answerp == (void *) answer); - n = __libc_res_nsend(statp, query1, nquery1, query2, nquery2, answer, - anslen, answerp, answerp2, nanswerp2, resplen2, - answerp2_malloced); + n = __res_context_send (ctx, query1, nquery1, query2, nquery2, answer, + anslen, answerp, answerp2, nanswerp2, resplen2, + answerp2_malloced); if (use_malloc) free (buf); if (n < 0) { -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; res_query: send error\n"); -#endif RES_SET_H_ERRNO(statp, TRY_AGAIN); return (n); } if (answerp != NULL) - /* __libc_res_nsend might have reallocated the buffer. */ + /* __res_context_send might have reallocated the buffer. */ hp = (HEADER *) *answerp; /* We simplify the following tests by assigning HP to HP2 or @@ -263,15 +240,6 @@ __libc_res_nquery(res_state statp, if ((hp->rcode != NOERROR || ntohs(hp->ancount) == 0) && (hp2->rcode != NOERROR || ntohs(hp2->ancount) == 0)) { -#ifdef DEBUG - if (statp->options & RES_DEBUG) { - printf(";; rcode = %d, ancount=%d\n", hp->rcode, - ntohs(hp->ancount)); - if (hp != hp2) - printf(";; rcode2 = %d, ancount2=%d\n", hp2->rcode, - ntohs(hp2->ancount)); - } -#endif switch (hp->rcode == NOERROR ? hp2->rcode : hp->rcode) { case NXDOMAIN: if ((hp->rcode == NOERROR && ntohs (hp->ancount) != 0) @@ -308,7 +276,24 @@ __libc_res_nquery(res_state statp, success: return (n); } -libresolv_hidden_def (__libc_res_nquery) +libresolv_hidden_def (__res_context_query) + +/* Common part of res_nquery and res_query. */ +static int +context_query_common (struct resolv_context *ctx, + const char *name, int class, int type, + unsigned char *answer, int anslen) +{ + if (ctx == NULL) + { + RES_SET_H_ERRNO (&_res, NETDB_INTERNAL); + return -1; + } + int result = __res_context_query (ctx, name, class, type, answer, anslen, + NULL, NULL, NULL, NULL, NULL); + __resolv_context_put (ctx); + return result; +} int res_nquery(res_state statp, @@ -317,30 +302,31 @@ res_nquery(res_state statp, u_char *answer, /* buffer to put answer */ int anslen) /* size of answer buffer */ { - return __libc_res_nquery(statp, name, class, type, answer, anslen, - NULL, NULL, NULL, NULL, NULL); + return context_query_common + (__resolv_context_get_override (statp), name, class, type, answer, anslen); } -libresolv_hidden_def (res_nquery) -/* - * Formulate a normal query, send, and retrieve answer in supplied buffer. - * Return the size of the response on success, -1 on error. - * If enabled, implement search rules until answer or unrecoverable failure - * is detected. Error code, if any, is left in H_ERRNO. - */ int -__libc_res_nsearch(res_state statp, - const char *name, /* domain name */ - int class, int type, /* class and type of query */ - u_char *answer, /* buffer to put answer */ - int anslen, /* size of answer */ - u_char **answerp, - u_char **answerp2, - int *nanswerp2, - int *resplen2, - int *answerp2_malloced) +res_query (const char *name, int class, int type, + unsigned char *answer, int anslen) { - const char *cp, * const *domain; + return context_query_common + (__resolv_context_get (), name, class, type, answer, anslen); +} + +/* Formulate a normal query, send, and retrieve answer in supplied + buffer. Return the size of the response on success, -1 on error. + If enabled, implement search rules until answer or unrecoverable + failure is detected. Error code, if any, is left in h_errno. */ +int +__res_context_search (struct resolv_context *ctx, + const char *name, int class, int type, + unsigned char *answer, int anslen, + unsigned char **answerp, unsigned char **answerp2, + int *nanswerp2, int *resplen2, int *answerp2_malloced) +{ + struct __res_state *statp = ctx->resp; + const char *cp; HEADER *hp = (HEADER *) answer; char tmp[NS_MAXDNAME]; u_int dots; @@ -360,16 +346,11 @@ __libc_res_nsearch(res_state statp, trailing_dot++; /* If there aren't any dots, it could be a user-level alias. */ - if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL) - return (__libc_res_nquery(statp, cp, class, type, answer, - anslen, answerp, answerp2, - nanswerp2, resplen2, answerp2_malloced)); - -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf("dots=%d, statp->ndots=%d, trailing_dot=%d, name=%s\n", - (int)dots,(int)statp->ndots,(int)trailing_dot,name); -#endif + if (!dots && (cp = __res_context_hostalias + (ctx, name, tmp, sizeof tmp))!= NULL) + return __res_context_query (ctx, cp, class, type, answer, + anslen, answerp, answerp2, + nanswerp2, resplen2, answerp2_malloced); /* * If there are enough dots in the name, let's just give it a @@ -378,10 +359,10 @@ __libc_res_nsearch(res_state statp, */ saved_herrno = -1; if (dots >= statp->ndots || trailing_dot) { - ret = __libc_res_nquerydomain(statp, name, NULL, class, type, - answer, anslen, answerp, - answerp2, nanswerp2, resplen2, - answerp2_malloced); + ret = __res_context_querydomain (ctx, name, NULL, class, type, + answer, anslen, answerp, + answerp2, nanswerp2, resplen2, + answerp2_malloced); if (ret > 0 || trailing_dot /* If the second response is valid then we use that. */ || (ret == 0 && resplen2 != NULL && *resplen2 > 0)) @@ -411,13 +392,14 @@ __libc_res_nsearch(res_state statp, (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) { int done = 0; - for (domain = (const char * const *)statp->dnsrch; - *domain && !done; - domain++) { - const char *dname = domain[0]; + for (size_t domain_index = 0; !done; ++domain_index) { + const char *dname = __resolv_context_search_list + (ctx, domain_index); + if (dname == NULL) + break; searched = 1; - /* __libc_res_nquerydoman concatenates name + /* __res_context_querydoman concatenates name with dname with a "." in between. If we pass it in dname the "." we got from the configured default search path, we'll end @@ -431,11 +413,10 @@ __libc_res_nsearch(res_state statp, if (dname[0] == '\0') root_on_list++; - ret = __libc_res_nquerydomain(statp, name, dname, - class, type, - answer, anslen, answerp, - answerp2, nanswerp2, - resplen2, answerp2_malloced); + ret = __res_context_querydomain + (ctx, name, dname, class, type, + answer, anslen, answerp, answerp2, nanswerp2, + resplen2, answerp2_malloced); if (ret > 0 || (ret == 0 && resplen2 != NULL && *resplen2 > 0)) return (ret); @@ -503,10 +484,10 @@ __libc_res_nsearch(res_state statp, */ if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0) && !(tried_as_is || root_on_list)) { - ret = __libc_res_nquerydomain(statp, name, NULL, class, type, - answer, anslen, answerp, - answerp2, nanswerp2, resplen2, - answerp2_malloced); + ret = __res_context_querydomain + (ctx, name, NULL, class, type, + answer, anslen, answerp, answerp2, nanswerp2, + resplen2, answerp2_malloced); if (ret > 0 || (ret == 0 && resplen2 != NULL && *resplen2 > 0)) return (ret); @@ -534,7 +515,24 @@ __libc_res_nsearch(res_state statp, RES_SET_H_ERRNO(statp, TRY_AGAIN); return (-1); } -libresolv_hidden_def (__libc_res_nsearch) +libresolv_hidden_def (__res_context_search) + +/* Common part of res_nsearch and res_search. */ +static int +context_search_common (struct resolv_context *ctx, + const char *name, int class, int type, + unsigned char *answer, int anslen) +{ + if (ctx == NULL) + { + RES_SET_H_ERRNO (&_res, NETDB_INTERNAL); + return -1; + } + int result = __res_context_search (ctx, name, class, type, answer, anslen, + NULL, NULL, NULL, NULL, NULL); + __resolv_context_put (ctx); + return result; +} int res_nsearch(res_state statp, @@ -543,36 +541,34 @@ res_nsearch(res_state statp, u_char *answer, /* buffer to put answer */ int anslen) /* size of answer */ { - return __libc_res_nsearch(statp, name, class, type, answer, - anslen, NULL, NULL, NULL, NULL, NULL); + return context_search_common + (__resolv_context_get_override (statp), name, class, type, answer, anslen); } -libresolv_hidden_def (res_nsearch) -/* - * Perform a call on res_query on the concatenation of name and domain. - */ +int +res_search (const char *name, int class, int type, + unsigned char *answer, int anslen) +{ + return context_search_common + (__resolv_context_get (), name, class, type, answer, anslen); +} + +/* Perform a call on res_query on the concatenation of name and + domain. */ static int -__libc_res_nquerydomain(res_state statp, - const char *name, - const char *domain, - int class, int type, /* class and type of query */ - u_char *answer, /* buffer to put answer */ - int anslen, /* size of answer */ - u_char **answerp, - u_char **answerp2, - int *nanswerp2, - int *resplen2, - int *answerp2_malloced) +__res_context_querydomain (struct resolv_context *ctx, + const char *name, const char *domain, + int class, int type, + unsigned char *answer, int anslen, + unsigned char **answerp, unsigned char **answerp2, + int *nanswerp2, int *resplen2, + int *answerp2_malloced) { + struct __res_state *statp = ctx->resp; char nbuf[MAXDNAME]; const char *longname = nbuf; size_t n, d; -#ifdef DEBUG - if (statp->options & RES_DEBUG) - printf(";; res_nquerydomain(%s, %s, %d, %d)\n", - name, domain?domain:"<Nil>", class, type); -#endif if (domain == NULL) { n = strlen(name); @@ -594,9 +590,28 @@ __libc_res_nquerydomain(res_state statp, } sprintf(nbuf, "%s.%s", name, domain); } - return (__libc_res_nquery(statp, longname, class, type, answer, - anslen, answerp, answerp2, nanswerp2, - resplen2, answerp2_malloced)); + return __res_context_query (ctx, longname, class, type, answer, + anslen, answerp, answerp2, nanswerp2, + resplen2, answerp2_malloced); +} + +/* Common part of res_nquerydomain and res_querydomain. */ +static int +context_querydomain_common (struct resolv_context *ctx, + const char *name, const char *domain, + int class, int type, + unsigned char *answer, int anslen) +{ + if (ctx == NULL) + { + RES_SET_H_ERRNO (&_res, NETDB_INTERNAL); + return -1; + } + int result = __res_context_querydomain (ctx, name, domain, class, type, + answer, anslen, + NULL, NULL, NULL, NULL, NULL); + __resolv_context_put (ctx); + return result; } int @@ -607,19 +622,28 @@ res_nquerydomain(res_state statp, u_char *answer, /* buffer to put answer */ int anslen) /* size of answer */ { - return __libc_res_nquerydomain(statp, name, domain, class, type, - answer, anslen, NULL, NULL, NULL, NULL, - NULL); + return context_querydomain_common + (__resolv_context_get_override (statp), + name, domain, class, type, answer, anslen); +} + +int +res_querydomain (const char *name, const char *domain, int class, int type, + unsigned char *answer, int anslen) +{ + return context_querydomain_common + (__resolv_context_get (), name, domain, class, type, answer, anslen); } -libresolv_hidden_def (res_nquerydomain) const char * -res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) { +__res_context_hostalias (struct resolv_context *ctx, + const char *name, char *dst, size_t siz) +{ char *file, *cp1, *cp2; char buf[BUFSIZ]; FILE *fp; - if (statp->options & RES_NOALIASES) + if (ctx->resp->options & RES_NOALIASES) return (NULL); file = getenv("HOSTALIASES"); if (file == NULL || (fp = fopen(file, "rce")) == NULL) @@ -649,4 +673,43 @@ res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) { fclose(fp); return (NULL); } -libresolv_hidden_def (res_hostalias) +libresolv_hidden_def (__res_context_hostalias) + +/* Common part of res_hostalias and hostalias. */ +static const char * +context_hostalias_common (struct resolv_context *ctx, + const char *name, char *dst, size_t siz) +{ + if (ctx == NULL) + { + RES_SET_H_ERRNO (&_res, NETDB_INTERNAL); + return NULL; + } + const char *result = __res_context_hostalias (ctx, name, dst, siz); + __resolv_context_put (ctx); + return result; +} + +const char * +res_hostalias (res_state statp, const char *name, char *dst, size_t siz) +{ + return context_hostalias_common + (__resolv_context_get_override (statp), name, dst, siz); +} + +const char * +hostalias (const char *name) +{ + static char abuf[MAXDNAME]; + return context_hostalias_common + (__resolv_context_get (), name, abuf, sizeof (abuf)); +} + +#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_2) +# undef res_query +# undef res_querydomain +# undef res_search +weak_alias (__res_query, res_query); +weak_alias (__res_querydomain, res_querydomain); +weak_alias (__res_search, res_search); +#endif diff --git a/resolv/res_randomid.c b/resolv/res_randomid.c new file mode 100644 index 0000000000..b96865c515 --- /dev/null +++ b/resolv/res_randomid.c @@ -0,0 +1,92 @@ +/* Legacy libresolv random number generator. + Copyright (C) 1995-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* + * Copyright (c) 1985, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1993 by Digital Equipment Corporation. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies, and that + * the name of Digital Equipment Corporation not be used in advertising or + * publicity pertaining to distribution of the document or software without + * specific, written prior permission. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL + * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT + * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +#include <resolv.h> +#include <unistd.h> + +unsigned int +res_randomid (void) { + return 0xffff & __getpid (); +} +libc_hidden_def (__res_randomid) diff --git a/resolv/res_send.c b/resolv/res_send.c index 25c19f12c3..947ebf5212 100644 --- a/resolv/res_send.c +++ b/resolv/res_send.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2016 Free Software Foundation, Inc. +/* Copyright (C) 2016-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -81,11 +81,6 @@ * SOFTWARE. */ -#if defined(LIBC_SCCS) && !defined(lint) -static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93"; -static const char rcsid[] = "$BINDId: res_send.c,v 8.38 2000/03/30 20:16:51 vixie Exp $"; -#endif /* LIBC_SCCS and not lint */ - /* * Send query to name server and wait for reply. */ @@ -106,14 +101,15 @@ static const char rcsid[] = "$BINDId: res_send.c,v 8.38 2000/03/30 20:16:51 vixi #include <errno.h> #include <fcntl.h> #include <netdb.h> -#include <resolv.h> +#include <resolv/resolv-internal.h> +#include <resolv/resolv_context.h> #include <signal.h> -#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <kernel-features.h> -#include <libc-internal.h> +#include <libc-diag.h> +#include <hp-timing.h> #if PACKETSZ > 65536 #define MAXPACKET PACKETSZ @@ -185,15 +181,11 @@ evNowTime(struct timespec *res) { } -/* Options. Leave them on. */ -/* #undef DEBUG */ -#include "res_debug.h" - #define EXT(res) ((res)->_u._ext) /* Forward. */ -static struct sockaddr *get_nsaddr (res_state, int); +static struct sockaddr *get_nsaddr (res_state, unsigned int); static int send_vc(res_state, const u_char *, int, const u_char *, int, u_char **, int *, int *, int, u_char **, @@ -203,11 +195,6 @@ static int send_dg(res_state, const u_char *, int, u_char **, int *, int *, int, int *, int *, u_char **, u_char **, int *, int *, int *); -#ifdef DEBUG -static void Aerror(const res_state, FILE *, const char *, int, - const struct sockaddr *); -static void Perror(const res_state, FILE *, const char *, int); -#endif static int sock_eq(struct sockaddr_in6 *, struct sockaddr_in6 *); /* Public. */ @@ -257,6 +244,12 @@ res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp) return (0); } +int +res_isourserver (const struct sockaddr_in *inp) +{ + return res_ourserver_p (&_res, (const struct sockaddr_in6 *) inp); +} + /* int * res_nameinquery(name, type, class, buf, eom) * look for (name,type,class) in the query section of packet (buf,eom) @@ -296,6 +289,62 @@ res_nameinquery(const char *name, int type, int class, } libresolv_hidden_def (res_nameinquery) +/* Returns a shift value for the name server index. Used to implement + RES_ROTATE. */ +static unsigned int +nameserver_offset (struct __res_state *statp) +{ + /* If we only have one name server or rotation is disabled, return + offset 0 (no rotation). */ + unsigned int nscount = statp->nscount; + if (nscount <= 1 || !(statp->options & RES_ROTATE)) + return 0; + + /* Global offset. The lowest bit indicates whether the offset has + been initialized with a random value. Use relaxed MO to access + global_offset because all we need is a sequence of roughly + sequential value. */ + static unsigned int global_offset; + unsigned int offset = atomic_fetch_add_relaxed (&global_offset, 2); + if ((offset & 1) == 0) + { + /* Initialization is required. */ +#if HP_TIMING_AVAIL + uint64_t ticks; + HP_TIMING_NOW (ticks); + offset = ticks; +#else + struct timeval tv; + __gettimeofday (&tv, NULL); + offset = ((tv.tv_sec << 8) ^ tv.tv_usec); +#endif + /* The lowest bit is the most random. Preserve it. */ + offset <<= 1; + + /* Store the new starting value. atomic_fetch_add_relaxed + returns the old value, so emulate that by storing the new + (incremented) value. Concurrent initialization with + different random values is harmless. */ + atomic_store_relaxed (&global_offset, (offset | 1) + 2); + } + + /* Remove the initialization bit. */ + offset >>= 1; + + /* Avoid the division in the most common cases. */ + switch (nscount) + { + case 2: + return offset & 1; + case 3: + return offset % 3; + case 4: + return offset & 3; + default: + return offset % nscount; + } +} + /* int * res_queriesmatch(buf1, eom1, buf2, eom2) * is there a 1:1 mapping of (name,type,class) @@ -352,12 +401,15 @@ res_queriesmatch(const u_char *buf1, const u_char *eom1, libresolv_hidden_def (res_queriesmatch) int -__libc_res_nsend(res_state statp, const u_char *buf, int buflen, - const u_char *buf2, int buflen2, - u_char *ans, int anssiz, u_char **ansp, u_char **ansp2, - int *nansp2, int *resplen2, int *ansp2_malloced) +__res_context_send (struct resolv_context *ctx, + const unsigned char *buf, int buflen, + const unsigned char *buf2, int buflen2, + unsigned char *ans, int anssiz, + unsigned char **ansp, unsigned char **ansp2, + int *nansp2, int *resplen2, int *ansp2_malloced) { - int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; + struct __res_state *statp = ctx->resp; + int gotsomewhere, terrno, try, v_circuit, resplen, n; if (statp->nscount == 0) { __set_errno (ESRCH); @@ -369,24 +421,6 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen, return (-1); } -#ifdef USE_HOOKS - if (__glibc_unlikely (statp->qhook || statp->rhook)) { - if (anssiz < MAXPACKET && ansp) { - /* Always allocate MAXPACKET, callers expect - this specific size. */ - u_char *buf = malloc (MAXPACKET); - if (buf == NULL) - return (-1); - memcpy (buf, ans, HFIXEDSZ); - *ansp = buf; - ans = buf; - anssiz = MAXPACKET; - } - } -#endif - - DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY), - (stdout, ";; res_send()\n"), buf, buflen); v_circuit = ((statp->options & RES_USEVC) || buflen > PACKETSZ || buflen2 > PACKETSZ); @@ -403,7 +437,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen, if (EXT(statp).nscount != statp->nscount) needclose++; else - for (ns = 0; ns < statp->nscount; ns++) { + for (unsigned int ns = 0; ns < statp->nscount; ns++) { if (statp->nsaddr_list[ns].sin_family != 0 && !sock_eq((struct sockaddr_in6 *) &statp->nsaddr_list[ns], @@ -423,7 +457,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen, * Maybe initialize our private copy of the ns_addr_list. */ if (EXT(statp).nscount == 0) { - for (ns = 0; ns < statp->nscount; ns++) { + for (unsigned int ns = 0; ns < statp->nscount; ns++) { EXT(statp).nssocks[ns] = -1; if (statp->nsaddr_list[ns].sin_family == 0) continue; @@ -437,91 +471,29 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen, '\0', sizeof (struct sockaddr_in6) - sizeof (struct sockaddr_in)); + else + return -1; } EXT(statp).nscount = statp->nscount; } - /* - * Some resolvers want to even out the load on their nameservers. - * Note that RES_BLAST overrides RES_ROTATE. - */ - if (__builtin_expect ((statp->options & RES_ROTATE) != 0, 0) && - (statp->options & RES_BLAST) == 0) { - struct sockaddr_in ina; - struct sockaddr_in6 *inp; - int lastns = statp->nscount - 1; - int fd; - - inp = EXT(statp).nsaddrs[0]; - ina = statp->nsaddr_list[0]; - fd = EXT(statp).nssocks[0]; - for (ns = 0; ns < lastns; ns++) { - EXT(statp).nsaddrs[ns] = EXT(statp).nsaddrs[ns + 1]; - statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1]; - EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1]; - } - EXT(statp).nsaddrs[lastns] = inp; - statp->nsaddr_list[lastns] = ina; - EXT(statp).nssocks[lastns] = fd; - } + /* Name server index offset. Used to implement + RES_ROTATE. */ + unsigned int ns_offset = nameserver_offset (statp); /* * Send request, RETRY times, or until successful. */ for (try = 0; try < statp->retry; try++) { - for (ns = 0; ns < statp->nscount; ns++) + for (unsigned ns_shift = 0; ns_shift < statp->nscount; ns_shift++) { -#ifdef DEBUG - char tmpbuf[40]; -#endif -#if defined USE_HOOKS || defined DEBUG - struct sockaddr *nsap = get_nsaddr (statp, ns); -#endif + /* The actual name server index. This implements + RES_ROTATE. */ + unsigned int ns = ns_shift + ns_offset; + if (ns >= statp->nscount) + ns -= statp->nscount; same_ns: -#ifdef USE_HOOKS - if (__glibc_unlikely (statp->qhook != NULL)) { - int done = 0, loops = 0; - - do { - res_sendhookact act; - - struct sockaddr_in *nsap4; - nsap4 = (struct sockaddr_in *) nsap; - act = (*statp->qhook)(&nsap4, &buf, &buflen, - ans, anssiz, &resplen); - nsap = (struct sockaddr_in6 *) nsap4; - switch (act) { - case res_goahead: - done = 1; - break; - case res_nextns: - __res_iclose(statp, false); - goto next_ns; - case res_done: - return (resplen); - case res_modified: - /* give the hook another try */ - if (++loops < 42) /*doug adams*/ - break; - /*FALLTHROUGH*/ - case res_error: - /*FALLTHROUGH*/ - default: - return (-1); - } - } while (!done); - } -#endif - - Dprint(statp->options & RES_DEBUG, - (stdout, ";; Querying server (# %d) address = %s\n", - ns + 1, inet_ntop(nsap->sa_family, - (nsap->sa_family == AF_INET6 - ? (void *) &((struct sockaddr_in6 *) nsap)->sin6_addr - : (void *) &((struct sockaddr_in *) nsap)->sin_addr), - tmpbuf, sizeof (tmpbuf)))); - if (__glibc_unlikely (v_circuit)) { /* Use VC; at most one attempt per server. */ try = statp->retry; @@ -551,22 +523,6 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen, resplen = n; - Dprint((statp->options & RES_DEBUG) || - ((statp->pfcode & RES_PRF_REPLY) && - (statp->pfcode & RES_PRF_HEAD1)), - (stdout, ";; got answer:\n")); - - DprintQ((statp->options & RES_DEBUG) || - (statp->pfcode & RES_PRF_REPLY), - (stdout, "%s", ""), - ans, (resplen > anssiz) ? anssiz : resplen); - if (buf2 != NULL) { - DprintQ((statp->options & RES_DEBUG) || - (statp->pfcode & RES_PRF_REPLY), - (stdout, "%s", ""), - *ansp2, (*resplen2 > *nansp2) ? *nansp2 : *resplen2); - } - /* * If we have temporarily opened a virtual circuit, * or if we haven't been asked to keep a socket open, @@ -576,38 +532,6 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen, (statp->options & RES_STAYOPEN) == 0) { __res_iclose(statp, false); } -#ifdef USE_HOOKS - if (__glibc_unlikely (statp->rhook)) { - int done = 0, loops = 0; - - do { - res_sendhookact act; - - act = (*statp->rhook)((struct sockaddr_in *) - nsap, buf, buflen, - ans, anssiz, &resplen); - switch (act) { - case res_goahead: - case res_done: - done = 1; - break; - case res_nextns: - __res_iclose(statp, false); - goto next_ns; - case res_modified: - /* give the hook another try */ - if (++loops < 42) /*doug adams*/ - break; - /*FALLTHROUGH*/ - case res_error: - /*FALLTHROUGH*/ - default: - return (-1); - } - } while (!done); - - } -#endif return (resplen); next_ns: ; } /*foreach ns*/ @@ -623,20 +547,44 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen, return (-1); } +/* Common part of res_nsend and res_send. */ +static int +context_send_common (struct resolv_context *ctx, + const unsigned char *buf, int buflen, + unsigned char *ans, int anssiz) +{ + if (ctx == NULL) + { + RES_SET_H_ERRNO (&_res, NETDB_INTERNAL); + return -1; + } + int result = __res_context_send (ctx, buf, buflen, NULL, 0, ans, anssiz, + NULL, NULL, NULL, NULL, NULL); + __resolv_context_put (ctx); + return result; +} + int -res_nsend(res_state statp, - const u_char *buf, int buflen, u_char *ans, int anssiz) +res_nsend (res_state statp, const unsigned char *buf, int buflen, + unsigned char *ans, int anssiz) { - return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz, - NULL, NULL, NULL, NULL, NULL); + return context_send_common + (__resolv_context_get_override (statp), buf, buflen, ans, anssiz); +} + +int +res_send (const unsigned char *buf, int buflen, unsigned char *ans, int anssiz) +{ + return context_send_common + (__resolv_context_get (), buf, buflen, ans, anssiz); } -libresolv_hidden_def (res_nsend) /* Private */ static struct sockaddr * -get_nsaddr (res_state statp, int n) +get_nsaddr (res_state statp, unsigned int n) { + assert (n < statp->nscount); if (statp->nsaddr_list[n].sin_family == 0 && EXT(statp).nsaddrs[n] != NULL) /* EXT(statp).nsaddrs[n] holds an address that is larger than @@ -649,6 +597,18 @@ get_nsaddr (res_state statp, int n) return (struct sockaddr *) (void *) &statp->nsaddr_list[n]; } +/* Close the resolver structure, assign zero to *RESPLEN2 if RESPLEN2 + is not NULL, and return zero. */ +static int +__attribute__ ((warn_unused_result)) +close_and_return_error (res_state statp, int *resplen2) +{ + __res_iclose(statp, false); + if (resplen2 != NULL) + *resplen2 = 0; + return 0; +} + /* The send_vc function is responsible for sending a DNS query over TCP to the nameserver numbered NS from the res_state STATP i.e. EXT(statp).nssocks[ns]. The function supports sending both IPv4 and @@ -657,7 +617,7 @@ get_nsaddr (res_state statp, int n) Please note that for TCP there is no way to disable sending both queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP and sends the queries serially and waits for the result after each - sent query. This implemetnation should be corrected to honour these + sent query. This implementation should be corrected to honour these options. Please also note that for TCP we send both queries over the same @@ -750,8 +710,6 @@ send_vc(res_state statp, u_short len2; u_char *cp; - if (resplen2 != NULL) - *resplen2 = 0; connreset = 0; same_ns: truncating = 0; @@ -773,10 +731,12 @@ send_vc(res_state statp, if (statp->_vcsock >= 0) __res_iclose(statp, false); - statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0); + statp->_vcsock = socket + (nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0); if (statp->_vcsock < 0) { *terrno = errno; - Perror(statp, stderr, "socket(vc)", errno); + if (resplen2 != NULL) + *resplen2 = 0; return (-1); } __set_errno (0); @@ -785,9 +745,7 @@ send_vc(res_state statp, ? sizeof (struct sockaddr_in) : sizeof (struct sockaddr_in6)) < 0) { *terrno = errno; - Aerror(statp, stderr, "connect/vc", errno, nsap); - __res_iclose(statp, false); - return (0); + return close_and_return_error (statp, resplen2); } statp->_flags |= RES_F_VC; } @@ -809,9 +767,7 @@ send_vc(res_state statp, } if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, niov)) != explen) { *terrno = errno; - Perror(statp, stderr, "write failed", errno); - __res_iclose(statp, false); - return (0); + return close_and_return_error (statp, resplen2); } /* * Receive length & response @@ -832,8 +788,6 @@ send_vc(res_state statp, } if (n <= 0) { *terrno = errno; - Perror(statp, stderr, "read failed", errno); - __res_iclose(statp, false); /* * A long running process might get its TCP * connection reset if the remote server was @@ -843,11 +797,13 @@ send_vc(res_state statp, * instead of failing. We only allow one reset * per query to prevent looping. */ - if (*terrno == ECONNRESET && !connreset) { - connreset = 1; - goto same_ns; - } - return (0); + if (*terrno == ECONNRESET && !connreset) + { + __res_iclose (statp, false); + connreset = 1; + goto same_ns; + } + return close_and_return_error (statp, resplen2); } int rlen = ntohs (rlen16); @@ -879,11 +835,11 @@ send_vc(res_state statp, /* Always allocate MAXPACKET, callers expect this specific size. */ u_char *newp = malloc (MAXPACKET); - if (newp == NULL) { - *terrno = ENOMEM; - __res_iclose(statp, false); - return (0); - } + if (newp == NULL) + { + *terrno = ENOMEM; + return close_and_return_error (statp, resplen2); + } *thisanssizp = MAXPACKET; *thisansp = newp; if (thisansp == ansp2) @@ -894,9 +850,6 @@ send_vc(res_state statp, read RLEN bytes instead. */ len = rlen; } else { - Dprint(statp->options & RES_DEBUG, - (stdout, ";; response truncated\n") - ); truncating = 1; len = *thisanssizp; } @@ -907,11 +860,8 @@ send_vc(res_state statp, /* * Undersized message. */ - Dprint(statp->options & RES_DEBUG, - (stdout, ";; undersized: %d\n", len)); *terrno = EMSGSIZE; - __res_iclose(statp, false); - return (0); + return close_and_return_error (statp, resplen2); } cp = *thisansp; @@ -921,9 +871,7 @@ send_vc(res_state statp, } if (__glibc_unlikely (n <= 0)) { *terrno = errno; - Perror(statp, stderr, "read(vc)", errno); - __res_iclose(statp, false); - return (0); + return close_and_return_error (statp, resplen2); } if (__glibc_unlikely (truncating)) { /* @@ -950,14 +898,8 @@ send_vc(res_state statp, * wait for the correct one. */ if ((recvresp1 || hp->id != anhp->id) - && (recvresp2 || hp2->id != anhp->id)) { - DprintQ((statp->options & RES_DEBUG) || - (statp->pfcode & RES_PRF_REPLY), - (stdout, ";; old answer (unexpected):\n"), - *thisansp, - (rlen > *thisanssizp) ? *thisanssizp: rlen); + && (recvresp2 || hp2->id != anhp->id)) goto read_len; - } /* Mark which reply we received. */ if (recvresp1 == 0 && hp->id == anhp->id) @@ -984,19 +926,20 @@ reopen (res_state statp, int *terrno, int ns) /* only try IPv6 if IPv6 NS and if not failed before */ if (nsap->sa_family == AF_INET6 && !statp->ipv6_unavail) { - EXT(statp).nssocks[ns] - = socket(PF_INET6, SOCK_DGRAM|SOCK_NONBLOCK, 0); + EXT(statp).nssocks[ns] = socket + (PF_INET6, + SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); if (EXT(statp).nssocks[ns] < 0) statp->ipv6_unavail = errno == EAFNOSUPPORT; slen = sizeof (struct sockaddr_in6); } else if (nsap->sa_family == AF_INET) { - EXT(statp).nssocks[ns] - = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, 0); + EXT(statp).nssocks[ns] = socket + (PF_INET, + SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); slen = sizeof (struct sockaddr_in); } if (EXT(statp).nssocks[ns] < 0) { *terrno = errno; - Perror(statp, stderr, "socket(dg)", errno); return (-1); } @@ -1011,8 +954,16 @@ reopen (res_state statp, int *terrno, int ns) * error message is received. We can thus detect * the absence of a nameserver without timing out. */ + /* With GCC 5.3 when compiling with -Os the compiler + emits a warning that slen may be used uninitialized, + but that is never true. Both slen and + EXT(statp).nssocks[ns] are initialized together or + the function return -1 before control flow reaches + the call to connect with slen. */ + DIAG_PUSH_NEEDS_COMMENT; + DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized"); if (connect(EXT(statp).nssocks[ns], nsap, slen) < 0) { - Aerror(statp, stderr, "connect(dg)", errno, nsap); + DIAG_POP_NEEDS_COMMENT; __res_iclose(statp, false); return (0); } @@ -1114,7 +1065,11 @@ send_dg(res_state statp, retry_reopen: retval = reopen (statp, terrno, ns); if (retval <= 0) - return retval; + { + if (resplen2 != NULL) + *resplen2 = 0; + return retval; + } retry: evNowTime(&now); evConsTime(&timeout, seconds, 0); @@ -1127,18 +1082,13 @@ send_dg(res_state statp, int recvresp2 = buf2 == NULL; pfd[0].fd = EXT(statp).nssocks[ns]; pfd[0].events = POLLOUT; - if (resplen2 != NULL) - *resplen2 = 0; wait: if (need_recompute) { recompute_resend: evNowTime(&now); if (evCmpTime(finish, now) <= 0) { poll_err_out: - Perror(statp, stderr, "poll", errno); - err_out: - __res_iclose(statp, false); - return (0); + return close_and_return_error (statp, resplen2); } evSubTime(&timeout, &finish, &now); need_recompute = 0; @@ -1154,7 +1104,6 @@ send_dg(res_state statp, need_recompute = 1; } if (n == 0) { - Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n")); if (resplen > 1 && (recvresp1 || (buf2 != NULL && recvresp2))) { /* There are quite a few broken name servers out @@ -1185,7 +1134,9 @@ send_dg(res_state statp, } *gotsomewhere = 1; - return (0); + if (resplen2 != NULL) + *resplen2 = 0; + return 0; } if (n < 0) { if (errno == EINTR) @@ -1203,25 +1154,27 @@ send_dg(res_state statp, if (have_sendmmsg >= 0 && nwritten == 0 && buf2 != NULL && !single_request) { - struct iovec iov[2]; - struct mmsghdr reqs[2]; - reqs[0].msg_hdr.msg_name = NULL; - reqs[0].msg_hdr.msg_namelen = 0; - reqs[0].msg_hdr.msg_iov = &iov[0]; - reqs[0].msg_hdr.msg_iovlen = 1; - iov[0].iov_base = (void *) buf; - iov[0].iov_len = buflen; - reqs[0].msg_hdr.msg_control = NULL; - reqs[0].msg_hdr.msg_controllen = 0; - - reqs[1].msg_hdr.msg_name = NULL; - reqs[1].msg_hdr.msg_namelen = 0; - reqs[1].msg_hdr.msg_iov = &iov[1]; - reqs[1].msg_hdr.msg_iovlen = 1; - iov[1].iov_base = (void *) buf2; - iov[1].iov_len = buflen2; - reqs[1].msg_hdr.msg_control = NULL; - reqs[1].msg_hdr.msg_controllen = 0; + struct iovec iov = + { .iov_base = (void *) buf, .iov_len = buflen }; + struct iovec iov2 = + { .iov_base = (void *) buf2, .iov_len = buflen2 }; + struct mmsghdr reqs[2] = + { + { + .msg_hdr = + { + .msg_iov = &iov, + .msg_iovlen = 1, + }, + }, + { + .msg_hdr = + { + .msg_iov = &iov2, + .msg_iovlen = 1, + } + }, + }; int ndg = __sendmmsg (pfd[0].fd, reqs, 2, MSG_NOSIGNAL); if (__glibc_likely (ndg == 2)) @@ -1252,8 +1205,7 @@ send_dg(res_state statp, #endif fail_sendmmsg: - Perror(statp, stderr, "sendmmsg", errno); - goto err_out; + return close_and_return_error (statp, resplen2); } } else @@ -1270,8 +1222,7 @@ send_dg(res_state statp, if (sr != (nwritten != 0 ? buflen2 : buflen)) { if (errno == EINTR || errno == EAGAIN) goto recompute_resend; - Perror(statp, stderr, "send", errno); - goto err_out; + return close_and_return_error (statp, resplen2); } just_one: if (nwritten != 0 || buf2 == NULL || single_request) @@ -1331,12 +1282,6 @@ send_dg(res_state statp, MSG_TRUNC which is only available on Linux. We can abstract out the Linux-specific feature in the future to detect truncation. */ - if (__glibc_unlikely (*thisanssizp < *thisresplenp)) { - Dprint(statp->options & RES_DEBUG, - (stdout, ";; response may be truncated (UDP)\n") - ); - } - HEADER *anhp = (HEADER *) *thisansp; socklen_t fromlen = sizeof(struct sockaddr_in6); assert (sizeof(from) <= fromlen); @@ -1348,19 +1293,15 @@ send_dg(res_state statp, need_recompute = 1; goto wait; } - Perror(statp, stderr, "recvfrom", errno); - goto err_out; + return close_and_return_error (statp, resplen2); } *gotsomewhere = 1; if (__glibc_unlikely (*thisresplenp < HFIXEDSZ)) { /* * Undersized message. */ - Dprint(statp->options & RES_DEBUG, - (stdout, ";; undersized: %d\n", - *thisresplenp)); *terrno = EMSGSIZE; - goto err_out; + return close_and_return_error (statp, resplen2); } if ((recvresp1 || hp->id != anhp->id) && (recvresp2 || hp2->id != anhp->id)) { @@ -1369,12 +1310,6 @@ send_dg(res_state statp, * XXX - potential security hazard could * be detected here. */ - DprintQ((statp->options & RES_DEBUG) || - (statp->pfcode & RES_PRF_REPLY), - (stdout, ";; old answer:\n"), - *thisansp, - (*thisresplenp > *thisanssizp) - ? *thisanssizp : *thisresplenp); goto wait; } if (!(statp->options & RES_INSECURE1) && @@ -1384,34 +1319,8 @@ send_dg(res_state statp, * XXX - potential security hazard could * be detected here. */ - DprintQ((statp->options & RES_DEBUG) || - (statp->pfcode & RES_PRF_REPLY), - (stdout, ";; not our server:\n"), - *thisansp, - (*thisresplenp > *thisanssizp) - ? *thisanssizp : *thisresplenp); goto wait; } -#ifdef RES_USE_EDNS0 - if (anhp->rcode == FORMERR - && (statp->options & RES_USE_EDNS0) != 0U) { - /* - * Do not retry if the server does not understand - * EDNS0. The case has to be captured here, as - * FORMERR packet do not carry query section, hence - * res_queriesmatch() returns 0. - */ - DprintQ(statp->options & RES_DEBUG, - (stdout, - "server rejected query with EDNS0:\n"), - *thisansp, - (*thisresplenp > *thisanssizp) - ? *thisanssizp : *thisresplenp); - /* record the error */ - statp->_flags |= RES_F_EDNS0ERR; - goto err_out; - } -#endif if (!(statp->options & RES_INSECURE2) && (recvresp1 || !res_queriesmatch(buf, buf + buflen, *thisansp, @@ -1426,23 +1335,11 @@ send_dg(res_state statp, * XXX - potential security hazard could * be detected here. */ - DprintQ((statp->options & RES_DEBUG) || - (statp->pfcode & RES_PRF_REPLY), - (stdout, ";; wrong query name:\n"), - *thisansp, - (*thisresplenp > *thisanssizp) - ? *thisanssizp : *thisresplenp); goto wait; } if (anhp->rcode == SERVFAIL || anhp->rcode == NOTIMP || anhp->rcode == REFUSED) { - DprintQ(statp->options & RES_DEBUG, - (stdout, "server rejected query:\n"), - *thisansp, - (*thisresplenp > *thisanssizp) - ? *thisanssizp : *thisresplenp); - next_ns: if (recvresp1 || (buf2 != NULL && recvresp2)) { *resplen2 = 0; @@ -1461,18 +1358,13 @@ send_dg(res_state statp, goto wait; } - __res_iclose(statp, false); /* don't retry if called from dig */ if (!statp->pfcode) - return (0); + return close_and_return_error (statp, resplen2); + __res_iclose(statp, false); } if (anhp->rcode == NOERROR && anhp->ancount == 0 && anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) { - DprintQ(statp->options & RES_DEBUG, - (stdout, "referred query:\n"), - *thisansp, - (*thisresplenp > *thisanssizp) - ? *thisanssizp : *thisresplenp); goto next_ns; } if (!(statp->options & RES_IGNTC) && anhp->tc) { @@ -1480,12 +1372,12 @@ send_dg(res_state statp, * To get the rest of answer, * use TCP with same server. */ - Dprint(statp->options & RES_DEBUG, - (stdout, ";; truncated answer\n")); *v_circuit = 1; __res_iclose(statp, false); // XXX if we have received one reply we could // XXX use it and not repeat it over TCP... + if (resplen2 != NULL) + *resplen2 = 0; return (1); } /* Mark which reply we received. */ @@ -1501,67 +1393,28 @@ send_dg(res_state statp, __res_iclose (statp, false); retval = reopen (statp, terrno, ns); if (retval <= 0) - return retval; + { + if (resplen2 != NULL) + *resplen2 = 0; + return retval; + } pfd[0].fd = EXT(statp).nssocks[ns]; } } goto wait; } - /* - * All is well, or the error is fatal. Signal that the - * next nameserver ought not be tried. - */ + /* All is well. We have received both responses (if + two responses were requested). */ return (resplen); - } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { - /* Something went wrong. We can stop trying. */ - goto err_out; - } + } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) + /* Something went wrong. We can stop trying. */ + return close_and_return_error (statp, resplen2); else { /* poll should not have returned > 0 in this case. */ abort (); } } -#ifdef DEBUG -static void -Aerror(const res_state statp, FILE *file, const char *string, int error, - const struct sockaddr *address) -{ - int save = errno; - - if ((statp->options & RES_DEBUG) != 0) { - char tmp[sizeof "xxxx.xxxx.xxxx.255.255.255.255"]; - - fprintf(file, "res_send: %s ([%s].%u): %s\n", - string, - (address->sa_family == AF_INET - ? inet_ntop(address->sa_family, - &((const struct sockaddr_in *) address)->sin_addr, - tmp, sizeof tmp) - : inet_ntop(address->sa_family, - &((const struct sockaddr_in6 *) address)->sin6_addr, - tmp, sizeof tmp)), - (address->sa_family == AF_INET - ? ntohs(((struct sockaddr_in *) address)->sin_port) - : address->sa_family == AF_INET6 - ? ntohs(((struct sockaddr_in6 *) address)->sin6_port) - : 0), - strerror(error)); - } - __set_errno (save); -} - -static void -Perror(const res_state statp, FILE *file, const char *string, int error) { - int save = errno; - - if ((statp->options & RES_DEBUG) != 0) - fprintf(file, "res_send: %s: %s\n", - string, strerror(error)); - __set_errno (save); -} -#endif - static int sock_eq(struct sockaddr_in6 *a1, struct sockaddr_in6 *a2) { if (a1->sin6_family == a2->sin6_family) { diff --git a/resolv/res_use_inet6.h b/resolv/res_use_inet6.h new file mode 100644 index 0000000000..dd5a31c54c --- /dev/null +++ b/resolv/res_use_inet6.h @@ -0,0 +1,49 @@ +/* Support functions for handling RES_USE_INET6 in getaddrinfo/nscd. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _RES_USE_INET6_H +#define _RES_USE_INET6_H + +#include <resolv/resolv_context.h> +#include <resolv/resolv-internal.h> + +/* Ensure that RES_USE_INET6 is disabled in *CTX. Return true if + __resolv_context_enable_inet6 below should enable RES_USE_INET6 + again. */ +static inline bool +__resolv_context_disable_inet6 (struct resolv_context *ctx) +{ + if (ctx != NULL && ctx->resp->options & DEPRECATED_RES_USE_INET6) + { + ctx->resp->options &= ~DEPRECATED_RES_USE_INET6; + return true; + } + else + return false; +} + +/* If ENABLE, re-enable RES_USE_INET6 in *CTX. To be paired with + __resolv_context_disable_inet6. */ +static inline void +__resolv_context_enable_inet6 (struct resolv_context *ctx, bool enable) +{ + if (ctx != NULL && enable) + ctx->resp->options |= DEPRECATED_RES_USE_INET6; +} + +#endif diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h new file mode 100644 index 0000000000..b8e447c726 --- /dev/null +++ b/resolv/resolv-internal.h @@ -0,0 +1,103 @@ +/* libresolv interfaces for internal use across glibc. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _RESOLV_INTERNAL_H +#define _RESOLV_INTERNAL_H 1 + +#include <resolv.h> +#include <stdbool.h> + +/* Resolver flags. Used for _flags in struct __res_state. */ +#define RES_F_VC 0x00000001 /* Socket is TCP. */ +#define RES_F_CONN 0x00000002 /* Socket is connected. */ +#define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors. */ + + +/* Internal version of RES_USE_INET6 which does not trigger a + deprecation warning. */ +#define DEPRECATED_RES_USE_INET6 0x00002000 + +static inline bool +res_use_inet6 (void) +{ + return _res.options & DEPRECATED_RES_USE_INET6; +} + +enum + { + /* The advertized EDNS buffer size. The value 1200 is derived + from the IPv6 minimum MTU (1280 bytes) minus some arbitrary + space for tunneling overhead. If the DNS server does not react + to ICMP Fragmentation Needed But DF Set messages, this should + avoid all UDP fragments on current networks. Avoiding UDP + fragments is desirable because it prevents fragmentation-based + spoofing attacks because the randomness in a DNS packet is + concentrated in the first fragment (with the headers) and does + not protect subsequent fragments. */ + RESOLV_EDNS_BUFFER_SIZE = 1200, + }; + +struct resolv_context; + +/* Internal function for implementing res_nmkquery and res_mkquery. + Also used by __res_context_query. */ +int __res_context_mkquery (struct resolv_context *, int op, const char *dname, + int class, int type, const unsigned char *data, + unsigned char *buf, int buflen) attribute_hidden; + +/* Main resolver query function for use within glibc. */ +int __res_context_search (struct resolv_context *, const char *, int, int, + unsigned char *, int, unsigned char **, + unsigned char **, int *, int *, int *); +libresolv_hidden_proto (__res_context_search) + +/* Main resolver query function for use within glibc. */ +int __res_context_query (struct resolv_context *, const char *, int, int, + unsigned char *, int, unsigned char **, + unsigned char **, int *, int *, int *); +libresolv_hidden_proto (__res_context_query) + +/* Internal function used to implement the query and search + functions. */ +int __res_context_send (struct resolv_context *, const unsigned char *, int, + const unsigned char *, int, unsigned char *, + int, unsigned char **, unsigned char **, + int *, int *, int *) attribute_hidden; + +/* Internal function similar to res_hostalias. */ +const char *__res_context_hostalias (struct resolv_context *, + const char *, char *, size_t); +libresolv_hidden_proto (__res_context_hostalias); + +/* Add an OPT record to a DNS query. */ +int __res_nopt (struct resolv_context *, int n0, + unsigned char *buf, int buflen, int anslen) attribute_hidden; + +/* Convert from presentation format (which usually means ASCII + printable) to network format (which is usually some kind of binary + format). The input is in the range [SRC, SRC + SRCLEN). The + output is written to DST (which has to be 4 or 16 bytes long, + depending on AF). Return 0 for invalid input, 1 for success, -1 + for an invalid address family. */ +int __inet_pton_length (int af, const char *src, size_t srclen, void *); +libc_hidden_proto (__inet_pton_length) + +/* Called as part of the thread shutdown sequence. */ +void __res_thread_freeres (void) attribute_hidden; + +#endif /* _RESOLV_INTERNAL_H */ diff --git a/resolv/resolv.h b/resolv/resolv.h index 53c3bba182..80a523e5e4 100644 --- a/resolv/resolv.h +++ b/resolv/resolv.h @@ -50,109 +50,30 @@ */ #ifndef _RESOLV_H_ +#define _RESOLV_H_ -/* These headers are needed for types used in the `struct res_state' - declaration. */ +#include <sys/cdefs.h> +#include <sys/param.h> #include <sys/types.h> +#include <stdio.h> #include <netinet/in.h> - -#ifndef __need_res_state -# define _RESOLV_H_ - -# include <sys/param.h> -# include <sys/cdefs.h> -# include <stdio.h> -# include <arpa/nameser.h> -#endif - -#ifndef __res_state_defined -# define __res_state_defined - -typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error } - res_sendhookact; - -typedef res_sendhookact (*res_send_qhook) (struct sockaddr_in * const *__ns, - const u_char **__query, - int *__querylen, - u_char *__ans, - int __anssiz, - int *__resplen); - -typedef res_sendhookact (*res_send_rhook) (const struct sockaddr_in *__ns, - const u_char *__query, - int __querylen, - u_char *__ans, - int __anssiz, - int *__resplen); +#include <arpa/nameser.h> +#include <bits/types/res_state.h> /* * Global defines and variables for resolver stub. */ -# define MAXNS 3 /* max # name servers we'll track */ -# define MAXDFLSRCH 3 /* # default domain levels to try */ -# define MAXDNSRCH 6 /* max # domains in search path */ -# define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */ +#define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */ -# define RES_TIMEOUT 5 /* min. seconds between retries */ -# define MAXRESOLVSORT 10 /* number of net to sort on */ -# define RES_MAXNDOTS 15 /* should reflect bit field size */ -# define RES_MAXRETRANS 30 /* only for resolv.conf/RES_OPTIONS */ -# define RES_MAXRETRY 5 /* only for resolv.conf/RES_OPTIONS */ -# define RES_DFLRETRY 2 /* Default #/tries. */ -# define RES_MAXTIME 65535 /* Infinity, in milliseconds. */ +#define RES_TIMEOUT 5 /* min. seconds between retries */ +#define RES_MAXNDOTS 15 /* should reflect bit field size */ +#define RES_MAXRETRANS 30 /* only for resolv.conf/RES_OPTIONS */ +#define RES_MAXRETRY 5 /* only for resolv.conf/RES_OPTIONS */ +#define RES_DFLRETRY 2 /* Default #/tries. */ +#define RES_MAXTIME 65535 /* Infinity, in milliseconds. */ -struct __res_state { - int retrans; /* retransmition time interval */ - int retry; /* number of times to retransmit */ - u_long options; /* option flags - see below. */ - int nscount; /* number of name servers */ - struct sockaddr_in - nsaddr_list[MAXNS]; /* address of name server */ -# define nsaddr nsaddr_list[0] /* for backward compatibility */ - u_short id; /* current message id */ - /* 2 byte hole here. */ - char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */ - char defdname[256]; /* default domain (deprecated) */ - u_long pfcode; /* RES_PRF_ flags - see below. */ - unsigned ndots:4; /* threshold for initial abs. query */ - unsigned nsort:4; /* number of elements in sort_list[] */ - unsigned ipv6_unavail:1; /* connecting to IPv6 server failed */ - unsigned unused:23; - struct { - struct in_addr addr; - u_int32_t mask; - } sort_list[MAXRESOLVSORT]; - /* 4 byte hole here on 64-bit architectures. */ - res_send_qhook qhook; /* query hook */ - res_send_rhook rhook; /* response hook */ - int res_h_errno; /* last one set for this context */ - int _vcsock; /* PRIVATE: for res_send VC i/o */ - u_int _flags; /* PRIVATE: see below */ - /* 4 byte hole here on 64-bit architectures. */ - union { - char pad[52]; /* On an i386 this means 512b total. */ - struct { - u_int16_t nscount; - u_int16_t nsmap[MAXNS]; - int nssocks[MAXNS]; - u_int16_t nscount6; - u_int16_t nsinit; - struct sockaddr_in6 *nsaddrs[MAXNS]; -#ifdef _LIBC - unsigned long long int initstamp - __attribute__((packed)); -#else - unsigned int _initstamp[2]; -#endif - } _ext; - } _u; -}; - -typedef struct __res_state *res_state; -# undef __need_res_state -#endif +#define nsaddr nsaddr_list[0] /* for backward compatibility */ -#ifdef _RESOLV_H_ /* * Revision information. This is the release date in YYYYMMDD format. * It can change every day so the right thing to do with it is use it @@ -180,23 +101,15 @@ struct res_sym { }; /* - * Resolver flags (used to be discrete per-module statics ints). - */ -#define RES_F_VC 0x00000001 /* socket is TCP */ -#define RES_F_CONN 0x00000002 /* socket is connected */ -#define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors */ - -/* res_findzonecut() options */ -#define RES_EXHAUSTIVE 0x00000001 /* always do all queries */ - -/* * Resolver options (keep these in synch with res_debug.c, please) */ #define RES_INIT 0x00000001 /* address initialized */ #define RES_DEBUG 0x00000002 /* print debug messages */ -#define RES_AAONLY 0x00000004 /* authoritative answers only (!IMPL)*/ +#define RES_AAONLY \ + __glibc_macro_warning ("RES_AAONLY is deprecated") 0x00000004 #define RES_USEVC 0x00000008 /* use virtual circuit */ -#define RES_PRIMARY 0x00000010 /* query primary server only (!IMPL) */ +#define RES_PRIMARY \ + __glibc_macro_warning ("RES_PRIMARY is deprecated") 0x00000010 #define RES_IGNTC 0x00000020 /* ignore trucation errors */ #define RES_RECURSE 0x00000040 /* recursion desired */ #define RES_DEFNAMES 0x00000080 /* use default domain name */ @@ -205,15 +118,15 @@ struct res_sym { #define RES_INSECURE1 0x00000400 /* type 1 security disabled */ #define RES_INSECURE2 0x00000800 /* type 2 security disabled */ #define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */ -#define RES_USE_INET6 0x00002000 /* use/map IPv6 in gethostbyname() */ +#define RES_USE_INET6 \ + __glibc_macro_warning ("RES_USE_INET6 is deprecated") 0x00002000 #define RES_ROTATE 0x00004000 /* rotate ns list after each query */ -#define RES_NOCHECKNAME 0x00008000 /* do not check names for sanity (!IMPL) */ -#define RES_KEEPTSIG 0x00010000 /* do not strip TSIG records */ -#define RES_BLAST 0x00020000 /* blast all recursive servers */ -#define RES_USEBSTRING 0x00040000 /* IPv6 reverse lookup with byte - strings */ -#define RES_NOIP6DOTINT 0x00080000 /* Do not use .ip6.int in IPv6 - reverse lookup */ +#define RES_NOCHECKNAME \ + __glibc_macro_warning ("RES_NOCHECKNAME is deprecated") 0x00008000 +#define RES_KEEPTSIG \ + __glibc_macro_warning ("RES_KEEPTSIG is deprecated") 0x00010000 +#define RES_BLAST \ + __glibc_macro_warning ("RES_BLAST is deprecated") 0x00020000 #define RES_USE_EDNS0 0x00100000 /* Use EDNS0. */ #define RES_SNGLKUP 0x00200000 /* one outstanding request at a time */ #define RES_SNGLKUPREOP 0x00400000 /* -"-, but open new socket for each @@ -221,8 +134,9 @@ struct res_sym { #define RES_USE_DNSSEC 0x00800000 /* use DNSSEC using OK bit in OPT */ #define RES_NOTLDQUERY 0x01000000 /* Do not look up unqualified name as a TLD. */ +#define RES_NORELOAD 0x02000000 /* No automatic configuration reload. */ -#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT) +#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH) /* * Resolver "pfcode" values. Used by dig. @@ -250,7 +164,6 @@ extern struct __res_state *__res_state(void) __attribute__ ((__const__)); __END_DECLS #define _res (*__res_state()) -#ifndef __BIND_NOSTATIC #define fp_nquery __fp_nquery #define fp_query __fp_query #define hostalias __hostalias @@ -265,22 +178,25 @@ __END_DECLS #define res_send __res_send __BEGIN_DECLS -void fp_nquery (const u_char *, int, FILE *) __THROW; -void fp_query (const u_char *, FILE *) __THROW; +void fp_nquery (const unsigned char *, int, FILE *) __THROW; +void fp_query (const unsigned char *, FILE *) __THROW; const char * hostalias (const char *) __THROW; -void p_query (const u_char *) __THROW; +void p_query (const unsigned char *) __THROW; void res_close (void) __THROW; int res_init (void) __THROW; int res_isourserver (const struct sockaddr_in *) __THROW; -int res_mkquery (int, const char *, int, int, const u_char *, - int, const u_char *, u_char *, int) __THROW; -int res_query (const char *, int, int, u_char *, int) __THROW; +int res_mkquery (int, const char *, int, int, + const unsigned char *, int, const unsigned char *, + unsigned char *, int) __THROW; +int res_query (const char *, int, int, unsigned char *, int) + __THROW; int res_querydomain (const char *, const char *, int, int, - u_char *, int) __THROW; -int res_search (const char *, int, int, u_char *, int) __THROW; -int res_send (const u_char *, int, u_char *, int) __THROW; + unsigned char *, int) __THROW; +int res_search (const char *, int, int, unsigned char *, int) + __THROW; +int res_send (const unsigned char *, int, unsigned char *, int) + __THROW; __END_DECLS -#endif #define b64_ntop __b64_ntop #define b64_pton __b64_pton @@ -297,8 +213,6 @@ __END_DECLS #define p_fqname __p_fqname #define p_fqnname __p_fqnname #define p_option __p_option -#define p_secstodate __p_secstodate -#define p_section __p_section #define p_time __p_time #define p_type __p_type #define p_rcode __p_rcode @@ -312,12 +226,10 @@ __END_DECLS #define res_nclose __res_nclose #define res_ninit __res_ninit #define res_nmkquery __res_nmkquery -#define res_npquery __res_npquery #define res_nquery __res_nquery #define res_nquerydomain __res_nquerydomain #define res_nsearch __res_nsearch #define res_nsend __res_nsend -#define res_nisourserver __res_nisourserver #define res_ownok __res_ownok #define res_queriesmatch __res_queriesmatch #define res_randomid __res_randomid @@ -332,58 +244,61 @@ int res_dnok (const char *) __THROW; int sym_ston (const struct res_sym *, const char *, int *) __THROW; const char * sym_ntos (const struct res_sym *, int, int *) __THROW; const char * sym_ntop (const struct res_sym *, int, int *) __THROW; -int b64_ntop (u_char const *, size_t, char *, size_t) __THROW; -int b64_pton (char const *, u_char *, size_t) __THROW; -int loc_aton (const char *__ascii, u_char *__binary) __THROW; -const char * loc_ntoa (const u_char *__binary, char *__ascii) __THROW; -int dn_skipname (const u_char *, const u_char *) __THROW; -void putlong (u_int32_t, u_char *) __THROW; -void putshort (u_int16_t, u_char *) __THROW; +int b64_ntop (const unsigned char *, size_t, char *, size_t) + __THROW; +int b64_pton (char const *, unsigned char *, size_t) __THROW; +int loc_aton (const char *__ascii, unsigned char *__binary) __THROW; +const char * loc_ntoa (const unsigned char *__binary, char *__ascii) __THROW; +int dn_skipname (const unsigned char *, const unsigned char *) + __THROW; +void putlong (uint32_t, unsigned char *) __THROW; +void putshort (uint16_t, unsigned char *) __THROW; const char * p_class (int) __THROW; -const char * p_time (u_int32_t) __THROW; +const char * p_time (uint32_t) __THROW; const char * p_type (int) __THROW; const char * p_rcode (int) __THROW; -const u_char * p_cdnname (const u_char *, const u_char *, int, FILE *) - __THROW; -const u_char * p_cdname (const u_char *, const u_char *, FILE *) __THROW; -const u_char * p_fqnname (const u_char *__cp, const u_char *__msg, - int, char *, int) __THROW; -const u_char * p_fqname (const u_char *, const u_char *, FILE *) __THROW; -const char * p_option (u_long __option) __THROW; -char * p_secstodate (u_long) __THROW; +const unsigned char * p_cdnname (const unsigned char *, + const unsigned char *, int, FILE *) __THROW; +const unsigned char * p_cdname (const unsigned char *, const unsigned char *, + FILE *) __THROW; +const unsigned char * p_fqnname (const unsigned char *__cp, + const unsigned char *__msg, + int, char *, int) __THROW; +const unsigned char * p_fqname (const unsigned char *, + const unsigned char *, FILE *) __THROW; +const char * p_option (unsigned long __option) __THROW; int dn_count_labels (const char *) __THROW; -int dn_comp (const char *, u_char *, int, u_char **, u_char **) - __THROW; -int dn_expand (const u_char *, const u_char *, const u_char *, - char *, int) __THROW; -u_int res_randomid (void) __THROW; +int dn_comp (const char *, unsigned char *, int, unsigned char **, + unsigned char **) __THROW; +int dn_expand (const unsigned char *, const unsigned char *, + const unsigned char *, char *, int) __THROW; +unsigned int res_randomid (void) __THROW; int res_nameinquery (const char *, int, int, - const u_char *, const u_char *) __THROW; -int res_queriesmatch (const u_char *, const u_char *, - const u_char *, const u_char *) __THROW; -const char * p_section (int __section, int __opcode) __THROW; + const unsigned char *, + const unsigned char *) __THROW; +int res_queriesmatch (const unsigned char *, + const unsigned char *, + const unsigned char *, + const unsigned char *) __THROW; /* Things involving a resolver context. */ int res_ninit (res_state) __THROW; -int res_nisourserver (const res_state, - const struct sockaddr_in *) __THROW; void fp_resstat (const res_state, FILE *) __THROW; -void res_npquery (const res_state, const u_char *, int, FILE *) - __THROW; const char * res_hostalias (const res_state, const char *, char *, size_t) __THROW; -int res_nquery (res_state, const char *, int, int, u_char *, int) - __THROW; -int res_nsearch (res_state, const char *, int, int, u_char *, int) - __THROW; +int res_nquery (res_state, const char *, int, int, + unsigned char *, int) __THROW; +int res_nsearch (res_state, const char *, int, int, + unsigned char *, int) __THROW; int res_nquerydomain (res_state, const char *, const char *, int, - int, u_char *, int) __THROW; + int, unsigned char *, int) __THROW; int res_nmkquery (res_state, int, const char *, int, int, - const u_char *, int, const u_char *, u_char *, - int) __THROW; -int res_nsend (res_state, const u_char *, int, u_char *, int) + const unsigned char *, int, + const unsigned char *, unsigned char *, int) __THROW; +int res_nsend (res_state, const unsigned char *, int, + unsigned char *, int) __THROW; void res_nclose (res_state) __THROW; + __END_DECLS -#endif #endif /* !_RESOLV_H_ */ diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c new file mode 100644 index 0000000000..2f0ffbc524 --- /dev/null +++ b/resolv/resolv_conf.c @@ -0,0 +1,700 @@ +/* Extended resolver state separate from struct __res_state. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <resolv_conf.h> + +#include <alloc_buffer.h> +#include <assert.h> +#include <libc-lock.h> +#include <resolv-internal.h> +#include <sys/stat.h> +#include <libc-symbols.h> + +/* _res._u._ext.__glibc_extension_index is used as an index into a + struct resolv_conf_array object. The intent of this construction + is to make reasonably sure that even if struct __res_state objects + are copied around and patched by applications, we can still detect + accesses to stale extended resolver state. The array elements are + either struct resolv_conf * pointers (if the LSB is cleared) or + free list entries (if the LSB is set). The free list is used to + speed up finding available entries in the array. */ +#define DYNARRAY_STRUCT resolv_conf_array +#define DYNARRAY_ELEMENT uintptr_t +#define DYNARRAY_PREFIX resolv_conf_array_ +#define DYNARRAY_INITIAL_SIZE 0 +#include <malloc/dynarray-skeleton.c> + +/* A magic constant for XORing the extension index + (_res._u._ext.__glibc_extension_index). This makes it less likely + that a valid index is created by accident. In particular, a zero + value leads to an invalid index. */ +#define INDEX_MAGIC 0x26a8fa5e48af8061ULL + +/* Global resolv.conf-related state. */ +struct resolv_conf_global +{ + /* struct __res_state objects contain the extension index + (_res._u._ext.__glibc_extension_index ^ INDEX_MAGIC), which + refers to an element of this array. When a struct resolv_conf + object (extended resolver state) is associated with a struct + __res_state object (legacy resolver state), its reference count + is increased and added to this array. Conversely, if the + extended state is detached from the basic state (during + reinitialization or deallocation), the index is decremented, and + the array element is overwritten with NULL. */ + struct resolv_conf_array array; + + /* Start of the free list in the array. Zero if the free list is + empty. Otherwise, free_list_start >> 1 is the first element of + the free list (and the free list entries all have their LSB set + and are shifted one to the left). */ + uintptr_t free_list_start; + + /* Cached current configuration object for /etc/resolv.conf. */ + struct resolv_conf *conf_current; + + /* These properties of /etc/resolv.conf are used to check if the + configuration needs reloading. */ + struct timespec conf_mtime; + struct timespec conf_ctime; + off64_t conf_size; + ino64_t conf_ino; +}; + +/* Lazily allocated storage for struct resolv_conf_global. */ +static struct resolv_conf_global *global; + +/* The lock synchronizes access to global and *global. It also + protects the __refcount member of struct resolv_conf. */ +__libc_lock_define_initialized (static, lock); + +/* Ensure that GLOBAL is allocated and lock it. Return NULL if + memory allocation failes. */ +static struct resolv_conf_global * +get_locked_global (void) +{ + __libc_lock_lock (lock); + /* Use relaxed MO through because of load outside the lock in + __resolv_conf_detach. */ + struct resolv_conf_global *global_copy = atomic_load_relaxed (&global); + if (global_copy == NULL) + { + global_copy = calloc (1, sizeof (*global)); + if (global_copy == NULL) + return NULL; + atomic_store_relaxed (&global, global_copy); + resolv_conf_array_init (&global_copy->array); + } + return global_copy; +} + +/* Relinquish the lock acquired by get_locked_global. */ +static void +put_locked_global (struct resolv_conf_global *global_copy) +{ + __libc_lock_unlock (lock); +} + +/* Decrement the reference counter. The caller must acquire the lock + around the function call. */ +static void +conf_decrement (struct resolv_conf *conf) +{ + assert (conf->__refcount > 0); + if (--conf->__refcount == 0) + free (conf); +} + +struct resolv_conf * +__resolv_conf_get_current (void) +{ + struct stat64 st; + if (stat64 (_PATH_RESCONF, &st) != 0) + { + switch (errno) + { + case EACCES: + case EISDIR: + case ELOOP: + case ENOENT: + case ENOTDIR: + case EPERM: + /* Ignore errors due to file system contents. */ + memset (&st, 0, sizeof (st)); + break; + default: + /* Other errors are fatal. */ + return NULL; + } + } + + struct resolv_conf_global *global_copy = get_locked_global (); + if (global_copy == NULL) + return NULL; + struct resolv_conf *conf; + if (global_copy->conf_current != NULL + && (global_copy->conf_mtime.tv_sec == st.st_mtim.tv_sec + && global_copy->conf_mtime.tv_nsec == st.st_mtim.tv_nsec + && global_copy->conf_ctime.tv_sec == st.st_ctim.tv_sec + && global_copy->conf_ctime.tv_nsec == st.st_ctim.tv_nsec + && global_copy->conf_ino == st.st_ino + && global_copy->conf_size == st.st_size)) + /* We can reuse the cached configuration object. */ + conf = global_copy->conf_current; + else + { + /* Parse configuration while holding the lock. This avoids + duplicate work. */ + conf = __resolv_conf_load (NULL); + if (conf != NULL) + { + if (global_copy->conf_current != NULL) + conf_decrement (global_copy->conf_current); + global_copy->conf_current = conf; /* Takes ownership. */ + + /* Update file modification stamps. The configuration we + read could be a newer version of the file, but this does + not matter because this will lead to an extraneous reload + later. */ + global_copy->conf_mtime = st.st_mtim; + global_copy->conf_ctime = st.st_ctim; + global_copy->conf_ino = st.st_ino; + global_copy->conf_size = st.st_size; + } + } + + if (conf != NULL) + { + /* Return an additional reference. */ + assert (conf->__refcount > 0); + ++conf->__refcount; + assert (conf->__refcount > 0); + } + put_locked_global (global_copy); + return conf; +} + +/* Internal implementation of __resolv_conf_get, without validation + against *RESP. */ +static struct resolv_conf * +resolv_conf_get_1 (const struct __res_state *resp) +{ + /* Not initialized, and therefore no assoicated context. */ + if (!(resp->options & RES_INIT)) + return NULL; + + struct resolv_conf_global *global_copy = get_locked_global (); + if (global_copy == NULL) + /* A memory allocation failure here means that no associated + contexts exists, so returning NULL is correct. */ + return NULL; + size_t index = resp->_u._ext.__glibc_extension_index ^ INDEX_MAGIC; + struct resolv_conf *conf = NULL; + if (index < resolv_conf_array_size (&global_copy->array)) + { + uintptr_t *slot = resolv_conf_array_at (&global_copy->array, index); + if (!(*slot & 1)) + { + conf = (struct resolv_conf *) *slot; + assert (conf->__refcount > 0); + ++conf->__refcount; + } + } + put_locked_global (global_copy); + return conf; +} + +/* Return true if both IPv4 addresses are equal. */ +static bool +same_address_v4 (const struct sockaddr_in *left, + const struct sockaddr_in *right) +{ + return left->sin_addr.s_addr == right->sin_addr.s_addr + && left->sin_port == right->sin_port; +} + +/* Return true if both IPv6 addresses are equal. This ignores the + flow label. */ +static bool +same_address_v6 (const struct sockaddr_in6 *left, + const struct sockaddr_in6 *right) +{ + return memcmp (&left->sin6_addr, &right->sin6_addr, + sizeof (left->sin6_addr)) == 0 + && left->sin6_port == right->sin6_port + && left->sin6_scope_id == right->sin6_scope_id; +} + +static bool +same_address (const struct sockaddr *left, const struct sockaddr *right) +{ + if (left->sa_family != right->sa_family) + return false; + switch (left->sa_family) + { + case AF_INET: + return same_address_v4 ((const struct sockaddr_in *) left, + (const struct sockaddr_in *) right); + case AF_INET6: + return same_address_v6 ((const struct sockaddr_in6 *) left, + (const struct sockaddr_in6 *) right); + } + return false; +} + +/* Check that *RESP and CONF match. Used by __resolv_conf_get. */ +static bool +resolv_conf_matches (const struct __res_state *resp, + const struct resolv_conf *conf) +{ + /* NB: Do not compare the options, retrans, retry, ndots. These can + be changed by applicaiton. */ + + /* Check that the name servers in *RESP have not been modified by + the application. */ + { + size_t nserv = conf->nameserver_list_size; + if (nserv > MAXNS) + nserv = MAXNS; + /* _ext.nscount is 0 until initialized by res_send.c. */ + if (resp->nscount != nserv + || (resp->_u._ext.nscount != 0 && resp->_u._ext.nscount != nserv)) + return false; + for (size_t i = 0; i < nserv; ++i) + { + if (resp->nsaddr_list[i].sin_family == 0) + { + if (resp->_u._ext.nsaddrs[i]->sin6_family != AF_INET6) + return false; + if (!same_address ((struct sockaddr *) resp->_u._ext.nsaddrs[i], + conf->nameserver_list[i])) + return false; + } + else if (resp->nsaddr_list[i].sin_family != AF_INET) + return false; + else if (!same_address ((struct sockaddr *) &resp->nsaddr_list[i], + conf->nameserver_list[i])) + return false; + } + } + + /* Check that the search list in *RESP has not been modified by the + application. */ + { + if (resp->dnsrch[0] == NULL) + { + /* Empty search list. No default domain name. */ + return conf->search_list_size == 0 && resp->defdname[0] == '\0'; + } + + if (resp->dnsrch[0] != resp->defdname) + /* If the search list is not empty, it must start with the + default domain name. */ + return false; + + size_t nsearch; + for (nsearch = 0; nsearch < MAXDNSRCH; ++nsearch) + if (resp->dnsrch[nsearch] == NULL) + break; + if (nsearch > MAXDNSRCH) + /* Search list is not null-terminated. */ + return false; + + size_t search_list_size = 0; + for (size_t i = 0; i < conf->search_list_size; ++i) + { + if (resp->dnsrch[i] != NULL) + { + search_list_size += strlen (resp->dnsrch[i]) + 1; + if (strcmp (resp->dnsrch[i], conf->search_list[i]) != 0) + return false; + } + else + { + /* resp->dnsrch is truncated if the number of elements + exceeds MAXDNSRCH, or if the combined storage space for + the search list exceeds what can be stored in + resp->defdname. */ + if (i == MAXDNSRCH || search_list_size > sizeof (resp->dnsrch)) + break; + /* Otherwise, a mismatch indicates a match failure. */ + return false; + } + } + } + + /* Check that the sort list has not been modified. */ + { + size_t nsort = conf->sort_list_size; + if (nsort > MAXRESOLVSORT) + nsort = MAXRESOLVSORT; + if (resp->nsort != nsort) + return false; + for (size_t i = 0; i < nsort; ++i) + if (resp->sort_list[i].addr.s_addr != conf->sort_list[i].addr.s_addr + || resp->sort_list[i].mask != conf->sort_list[i].mask) + return false; + } + + return true; +} + +struct resolv_conf * +__resolv_conf_get (struct __res_state *resp) +{ + struct resolv_conf *conf = resolv_conf_get_1 (resp); + if (conf == NULL) + return NULL; + if (resolv_conf_matches (resp, conf)) + return conf; + __resolv_conf_put (conf); + return NULL; +} + +void +__resolv_conf_put (struct resolv_conf *conf) +{ + if (conf == NULL) + return; + + __libc_lock_lock (lock); + conf_decrement (conf); + __libc_lock_unlock (lock); +} + +struct resolv_conf * +__resolv_conf_allocate (const struct resolv_conf *init) +{ + /* Allocate in decreasing order of alignment. */ + _Static_assert (__alignof__ (const char *const *) + <= __alignof__ (struct resolv_conf), "alignment"); + _Static_assert (__alignof__ (struct sockaddr_in6) + <= __alignof__ (const char *const *), "alignment"); + _Static_assert (__alignof__ (struct sockaddr_in) + == __alignof__ (struct sockaddr_in6), "alignment"); + _Static_assert (__alignof__ (struct resolv_sortlist_entry) + <= __alignof__ (struct sockaddr_in), "alignment"); + + /* Space needed by the nameserver addresses. */ + size_t address_space = 0; + for (size_t i = 0; i < init->nameserver_list_size; ++i) + if (init->nameserver_list[i]->sa_family == AF_INET) + address_space += sizeof (struct sockaddr_in); + else + { + assert (init->nameserver_list[i]->sa_family == AF_INET6); + address_space += sizeof (struct sockaddr_in6); + } + + /* Space needed by the search list strings. */ + size_t string_space = 0; + for (size_t i = 0; i < init->search_list_size; ++i) + string_space += strlen (init->search_list[i]) + 1; + + /* Allocate the buffer. */ + void *ptr; + struct alloc_buffer buffer = alloc_buffer_allocate + (sizeof (struct resolv_conf) + + init->nameserver_list_size * sizeof (init->nameserver_list[0]) + + address_space + + init->search_list_size * sizeof (init->search_list[0]) + + init->sort_list_size * sizeof (init->sort_list[0]) + + string_space, + &ptr); + struct resolv_conf *conf + = alloc_buffer_alloc (&buffer, struct resolv_conf); + if (conf == NULL) + /* Memory allocation failure. */ + return NULL; + assert (conf == ptr); + + /* Initialize the contents. */ + conf->__refcount = 1; + conf->retrans = init->retrans; + conf->retry = init->retry; + conf->options = init->options; + conf->ndots = init->ndots; + + /* Allocate the arrays with pointers. These must come first because + they have the highets alignment. */ + conf->nameserver_list_size = init->nameserver_list_size; + const struct sockaddr **nameserver_array = alloc_buffer_alloc_array + (&buffer, const struct sockaddr *, init->nameserver_list_size); + conf->nameserver_list = nameserver_array; + + conf->search_list_size = init->search_list_size; + const char **search_array = alloc_buffer_alloc_array + (&buffer, const char *, init->search_list_size); + conf->search_list = search_array; + + /* Fill the name server list array. */ + for (size_t i = 0; i < init->nameserver_list_size; ++i) + if (init->nameserver_list[i]->sa_family == AF_INET) + { + struct sockaddr_in *sa = alloc_buffer_alloc + (&buffer, struct sockaddr_in); + *sa = *(struct sockaddr_in *) init->nameserver_list[i]; + nameserver_array[i] = (struct sockaddr *) sa; + } + else + { + struct sockaddr_in6 *sa = alloc_buffer_alloc + (&buffer, struct sockaddr_in6); + *sa = *(struct sockaddr_in6 *) init->nameserver_list[i]; + nameserver_array[i] = (struct sockaddr *) sa; + } + + /* Allocate and fill the sort list array. */ + { + conf->sort_list_size = init->sort_list_size; + struct resolv_sortlist_entry *array = alloc_buffer_alloc_array + (&buffer, struct resolv_sortlist_entry, init->sort_list_size); + conf->sort_list = array; + for (size_t i = 0; i < init->sort_list_size; ++i) + array[i] = init->sort_list[i]; + } + + /* Fill the search list array. This must come last because the + strings are the least aligned part of the allocation. */ + { + for (size_t i = 0; i < init->search_list_size; ++i) + search_array[i] = alloc_buffer_copy_string + (&buffer, init->search_list[i]); + } + + assert (!alloc_buffer_has_failed (&buffer)); + return conf; +} + +/* Update *RESP from the extended state. */ +static __attribute__ ((nonnull (1, 2), warn_unused_result)) bool +update_from_conf (struct __res_state *resp, const struct resolv_conf *conf) +{ + resp->defdname[0] = '\0'; + resp->pfcode = 0; + resp->_vcsock = -1; + resp->_flags = 0; + resp->ipv6_unavail = false; + resp->__glibc_unused_qhook = NULL; + resp->__glibc_unused_rhook = NULL; + + resp->retrans = conf->retrans; + resp->retry = conf->retry; + resp->options = conf->options; + resp->ndots = conf->ndots; + + /* Copy the name server addresses. */ + { + resp->nscount = 0; + resp->_u._ext.nscount = 0; + size_t nserv = conf->nameserver_list_size; + if (nserv > MAXNS) + nserv = MAXNS; + for (size_t i = 0; i < nserv; i++) + { + if (conf->nameserver_list[i]->sa_family == AF_INET) + { + resp->nsaddr_list[i] + = *(struct sockaddr_in *)conf->nameserver_list[i]; + resp->_u._ext.nsaddrs[i] = NULL; + } + else + { + assert (conf->nameserver_list[i]->sa_family == AF_INET6); + resp->nsaddr_list[i].sin_family = 0; + /* Make a defensive copy of the name server address, in + case the application overwrites it. */ + struct sockaddr_in6 *sa = malloc (sizeof (*sa)); + if (sa == NULL) + { + for (size_t j = 0; j < i; ++j) + free (resp->_u._ext.nsaddrs[j]); + return false; + } + *sa = *(struct sockaddr_in6 *)conf->nameserver_list[i]; + resp->_u._ext.nsaddrs[i] = sa; + } + resp->_u._ext.nssocks[i] = -1; + } + resp->nscount = nserv; + /* Leave resp->_u._ext.nscount at 0. res_send.c handles this. */ + } + + /* Fill in the prefix of the search list. It is truncated either at + MAXDNSRCH, or if reps->defdname has insufficient space. */ + { + struct alloc_buffer buffer + = alloc_buffer_create (resp->defdname, sizeof (resp->defdname)); + size_t size = conf->search_list_size; + size_t i; + for (i = 0; i < size && i < MAXDNSRCH; ++i) + { + resp->dnsrch[i] = alloc_buffer_copy_string + (&buffer, conf->search_list[i]); + if (resp->dnsrch[i] == NULL) + /* No more space in resp->defdname. Truncate. */ + break; + } + resp->dnsrch[i] = NULL; + } + + /* Copy the sort list. */ + { + size_t nsort = conf->sort_list_size; + if (nsort > MAXRESOLVSORT) + nsort = MAXRESOLVSORT; + for (size_t i = 0; i < nsort; ++i) + { + resp->sort_list[i].addr = conf->sort_list[i].addr; + resp->sort_list[i].mask = conf->sort_list[i].mask; + } + resp->nsort = nsort; + } + + /* The overlapping parts of both configurations should agree after + initialization. */ + assert (resolv_conf_matches (resp, conf)); + return true; +} + +/* Decrement the configuration object at INDEX and free it if the + reference counter reaches 0. *GLOBAL_COPY must be locked and + remains so. */ +static void +decrement_at_index (struct resolv_conf_global *global_copy, size_t index) +{ + if (index < resolv_conf_array_size (&global_copy->array)) + { + /* Index found. */ + uintptr_t *slot = resolv_conf_array_at (&global_copy->array, index); + /* Check that the slot is not already part of the free list. */ + if (!(*slot & 1)) + { + struct resolv_conf *conf = (struct resolv_conf *) *slot; + conf_decrement (conf); + /* Put the slot onto the free list. */ + *slot = global_copy->free_list_start; + global_copy->free_list_start = (index << 1) | 1; + } + } +} + +bool +__resolv_conf_attach (struct __res_state *resp, struct resolv_conf *conf) +{ + assert (conf->__refcount > 0); + + struct resolv_conf_global *global_copy = get_locked_global (); + if (global_copy == NULL) + return false; + + /* Try to find an unused index in the array. */ + size_t index; + { + if (global_copy->free_list_start & 1) + { + /* Unlink from the free list. */ + index = global_copy->free_list_start >> 1; + uintptr_t *slot = resolv_conf_array_at (&global_copy->array, index); + global_copy->free_list_start = *slot; + assert (global_copy->free_list_start == 0 + || global_copy->free_list_start & 1); + /* Install the configuration pointer. */ + *slot = (uintptr_t) conf; + } + else + { + size_t size = resolv_conf_array_size (&global_copy->array); + /* No usable index found. Increase the array size. */ + resolv_conf_array_add (&global_copy->array, (uintptr_t) conf); + if (resolv_conf_array_has_failed (&global_copy->array)) + { + put_locked_global (global_copy); + __set_errno (ENOMEM); + return false; + } + /* The new array element was added at the end. */ + index = size; + } + } + + /* We have added a new reference to the object. */ + ++conf->__refcount; + assert (conf->__refcount > 0); + put_locked_global (global_copy); + + if (!update_from_conf (resp, conf)) + { + /* Drop the reference we acquired. Reacquire the lock. The + object has already been allocated, so it cannot be NULL this + time. */ + global_copy = get_locked_global (); + decrement_at_index (global_copy, index); + put_locked_global (global_copy); + return false; + } + resp->_u._ext.__glibc_extension_index = index ^ INDEX_MAGIC; + + return true; +} + +void +__resolv_conf_detach (struct __res_state *resp) +{ + if (atomic_load_relaxed (&global) == NULL) + /* Detach operation after a shutdown, or without any prior + attachment. We cannot free the data (and there might not be + anything to free anyway). */ + return; + + struct resolv_conf_global *global_copy = get_locked_global (); + size_t index = resp->_u._ext.__glibc_extension_index ^ INDEX_MAGIC; + decrement_at_index (global_copy, index); + + /* Clear the index field, so that accidental reuse is less + likely. */ + resp->_u._ext.__glibc_extension_index = 0; + + put_locked_global (global_copy); +} + +/* Deallocate the global data. */ +libc_freeres_fn (freeres) +{ + /* No locking because this function is supposed to be called when + the process has turned single-threaded. */ + if (global == NULL) + return; + + if (global->conf_current != NULL) + { + conf_decrement (global->conf_current); + global->conf_current = NULL; + } + + /* Note that this frees only the array itself. The pointed-to + configuration objects should have been deallocated by res_nclose + and per-thread cleanup functions. */ + resolv_conf_array_free (&global->array); + + free (global); + + /* Stop potential future __resolv_conf_detach calls from accessing + deallocated memory. */ + global = NULL; +} diff --git a/resolv/resolv_conf.h b/resolv/resolv_conf.h new file mode 100644 index 0000000000..e903a206da --- /dev/null +++ b/resolv/resolv_conf.h @@ -0,0 +1,103 @@ +/* Extended resolver state separate from struct __res_state. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef RESOLV_STATE_H +#define RESOLV_STATE_H + +#include <netinet/in.h> +#include <stdbool.h> +#include <stddef.h> + +/* This type corresponds to members of the _res.sort_list array. */ +struct resolv_sortlist_entry +{ + struct in_addr addr; + uint32_t mask; +}; + +/* Extended resolver state associated with res_state objects. Client + code can reach this state through a struct resolv_context + object. */ +struct resolv_conf +{ + /* Reference counter. The object is deallocated once it reaches + zero. For internal use within resolv_conf only. */ + size_t __refcount; + + /* List of IPv4 and IPv6 name server addresses. */ + const struct sockaddr **nameserver_list; + size_t nameserver_list_size; + + /* The domain names forming the search list. */ + const char *const *search_list; + size_t search_list_size; + + /* IPv4 address preference rules. */ + const struct resolv_sortlist_entry *sort_list; + size_t sort_list_size; + + /* _res.options has type unsigned long, but we can only use 32 bits + for portability across all architectures. */ + unsigned int options; + unsigned int retrans; /* Timeout. */ + unsigned int retry; /* Number of times to retry. */ + unsigned int ndots; /* Dots needed for initial non-search query. */ +}; + +/* The functions below are for use by the res_init resolv.conf parser + and the struct resolv_context facility. */ + +struct __res_state; + +/* Read /etc/resolv.conf and return a configuration object, or NULL if + /etc/resolv.conf cannot be read due to memory allocation errors. + If PREINIT is not NULL, some configuration values are taken from the + struct __res_state object. */ +struct resolv_conf *__resolv_conf_load (struct __res_state *preinit) + attribute_hidden __attribute__ ((warn_unused_result)); + +/* Return a configuration object for the current /etc/resolv.conf + settings, or NULL on failure. The object is cached. */ +struct resolv_conf *__resolv_conf_get_current (void) + attribute_hidden __attribute__ ((warn_unused_result)); + +/* Return the extended resolver state for *RESP, or NULL if it cannot + be determined. A call to this function must be paired with a call + to __resolv_conf_put. */ +struct resolv_conf *__resolv_conf_get (struct __res_state *) attribute_hidden; + +/* Converse of __resolv_conf_get. */ +void __resolv_conf_put (struct resolv_conf *) attribute_hidden; + +/* Allocate a new struct resolv_conf object and copy the + pre-configured values from *INIT. Return NULL on allocation + failure. The object must be deallocated using + __resolv_conf_put. */ +struct resolv_conf *__resolv_conf_allocate (const struct resolv_conf *init) + attribute_hidden __attribute__ ((nonnull (1), warn_unused_result)); + +/* Associate an existing extended resolver state with *RESP. Return + false on allocation failure. In addition, update *RESP with the + overlapping non-extended resolver state. */ +bool __resolv_conf_attach (struct __res_state *, struct resolv_conf *) + attribute_hidden; + +/* Detach the extended resolver state from *RESP. */ +void __resolv_conf_detach (struct __res_state *resp) attribute_hidden; + +#endif /* RESOLV_STATE_H */ diff --git a/resolv/resolv_context.c b/resolv/resolv_context.c new file mode 100644 index 0000000000..4bd79111f0 --- /dev/null +++ b/resolv/resolv_context.c @@ -0,0 +1,252 @@ +/* Temporary, thread-local resolver state. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <resolv_context.h> +#include <resolv_conf.h> +#include <resolv-internal.h> + +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <stdio.h> + +/* Currently active struct resolv_context object. This pointer forms + the start of a single-linked list, using the __next member of + struct resolv_context. This list serves two purposes: + + (a) A subsequent call to __resolv_context_get will only increment + the reference counter and will not allocate a new object. The + _res state freshness check is skipped in this case, too. + + (b) The per-thread cleanup function defined by the resolver calls + __resolv_context_freeres, which will deallocate all the context + objects. This avoids the need for cancellation handlers and + the complexity they bring, but it requires heap allocation of + the context object because the per-thread cleanup functions run + only after the stack has been fully unwound (and all on-stack + objects have been deallocated at this point). + + The TLS variable current is updated even in + __resolv_context_get_override, to support case (b) above. This does + not override the per-thread resolver state (as obtained by the + non-res_state function such as __resolv_context_get) in an + observable way because the wrapped context is only used to + implement the res_n* functions in the resolver, and those do not + call back into user code which could indirectly use the per-thread + resolver state. */ +static __thread struct resolv_context *current attribute_tls_model_ie; + +/* The resolv_conf handling will gives us a ctx->conf pointer even if + these fields do not match because a mis-match does not cause a loss + of state (_res objects can store the full information). This + function checks to ensure that there is a full patch, to prevent + overwriting a patched configuration. */ +static bool +replicated_configuration_matches (const struct resolv_context *ctx) +{ + return ctx->resp->options == ctx->conf->options + && ctx->resp->retrans == ctx->conf->retrans + && ctx->resp->retry == ctx->conf->retry + && ctx->resp->ndots == ctx->conf->ndots; +} + +/* Initialize *RESP if RES_INIT is not yet set in RESP->options, or if + res_init in some other thread requested re-initializing. */ +static __attribute__ ((warn_unused_result)) bool +maybe_init (struct resolv_context *ctx, bool preinit) +{ + struct __res_state *resp = ctx->resp; + if (resp->options & RES_INIT) + { + if (resp->options & RES_NORELOAD) + /* Configuration reloading was explicitly disabled. */ + return true; + + /* If there is no associated resolv_conf object despite the + initialization, something modified *ctx->resp. Do not + override those changes. */ + if (ctx->conf != NULL && replicated_configuration_matches (ctx)) + { + struct resolv_conf *current = __resolv_conf_get_current (); + if (current == NULL) + return false; + + /* Check if the configuration changed. */ + if (current != ctx->conf) + { + /* This call will detach the extended resolver state. */ + if (resp->nscount > 0) + __res_iclose (resp, true); + /* Reattach the current configuration. */ + if (__resolv_conf_attach (ctx->resp, current)) + { + __resolv_conf_put (ctx->conf); + /* ctx takes ownership, so we do not release current. */ + ctx->conf = current; + } + } + else + /* No change. Drop the reference count for current. */ + __resolv_conf_put (current); + } + return true; + } + + assert (ctx->conf == NULL); + if (preinit) + { + if (!resp->retrans) + resp->retrans = RES_TIMEOUT; + if (!resp->retry) + resp->retry = RES_DFLRETRY; + resp->options = RES_DEFAULT; + if (!resp->id) + resp->id = res_randomid (); + } + + if (__res_vinit (resp, preinit) < 0) + return false; + ctx->conf = __resolv_conf_get (ctx->resp); + return true; +} + +/* Allocate a new context object and initialize it. The object is put + on the current list. */ +static struct resolv_context * +context_alloc (struct __res_state *resp) +{ + struct resolv_context *ctx = malloc (sizeof (*ctx)); + if (ctx == NULL) + return NULL; + ctx->resp = resp; + ctx->conf = __resolv_conf_get (resp); + ctx->__refcount = 1; + ctx->__from_res = true; + ctx->__next = current; + current = ctx; + return ctx; +} + +/* Deallocate the context object and all the state within. */ +static void +context_free (struct resolv_context *ctx) +{ + int error_code = errno; + current = ctx->__next; + __resolv_conf_put (ctx->conf); + free (ctx); + __set_errno (error_code); +} + +/* Reuse the current context object. */ +static struct resolv_context * +context_reuse (void) +{ + /* A context object created by __resolv_context_get_override cannot + be reused. */ + assert (current->__from_res); + + ++current->__refcount; + + /* Check for reference counter wraparound. This can only happen if + the get/put functions are not properly paired. */ + assert (current->__refcount > 0); + + return current; +} + +/* Backing function for the __resolv_context_get family of + functions. */ +static struct resolv_context * +context_get (bool preinit) +{ + if (current != NULL) + return context_reuse (); + + struct resolv_context *ctx = context_alloc (&_res); + if (ctx == NULL) + return NULL; + if (!maybe_init (ctx, preinit)) + { + context_free (ctx); + return NULL; + } + return ctx; +} + +struct resolv_context * +__resolv_context_get (void) +{ + return context_get (false); +} +libc_hidden_def (__resolv_context_get) + +struct resolv_context * +__resolv_context_get_preinit (void) +{ + return context_get (true); +} +libc_hidden_def (__resolv_context_get_preinit) + +struct resolv_context * +__resolv_context_get_override (struct __res_state *resp) +{ + /* NB: As explained asbove, context_alloc will put the context on + the current list. */ + struct resolv_context *ctx = context_alloc (resp); + if (ctx == NULL) + return NULL; + + ctx->__from_res = false; + return ctx; +} +libc_hidden_def (__resolv_context_get_override) + +void +__resolv_context_put (struct resolv_context *ctx) +{ + if (ctx == NULL) + return; + + /* NB: Callers assume that this function preserves errno and + h_errno. */ + + assert (current == ctx); + assert (ctx->__refcount > 0); + + if (ctx->__from_res && --ctx->__refcount > 0) + /* Do not pop this context yet. */ + return; + + context_free (ctx); +} +libc_hidden_def (__resolv_context_put) + +void +__resolv_context_freeres (void) +{ + /* Deallocate the entire chain of context objects. */ + struct resolv_context *ctx = current; + current = NULL; + while (ctx != NULL) + { + struct resolv_context *next = ctx->__next; + context_free (ctx); + ctx = next; + } +} diff --git a/resolv/resolv_context.h b/resolv/resolv_context.h new file mode 100644 index 0000000000..c1dff76cb9 --- /dev/null +++ b/resolv/resolv_context.h @@ -0,0 +1,182 @@ +/* Temporary, thread-local resolver state. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* struct resolv_context objects are allocated on the heap, + initialized by __resolv_context_get (and its variants), and + destroyed by __resolv_context_put. + + A nested call to __resolv_context_get (after another call to + __resolv_context_get without a matching __resolv_context_put call, + on the same thread) returns the original pointer, instead of + allocating a new context. This prevents unexpected reloading of + the resolver configuration. Care is taken to keep the context in + sync with the thread-local _res object. (This does not happen with + __resolv_context_get_override, and __resolv_context_get_no_inet6 may + also interpose another context object if RES_USE_INET6 needs to be + disabled.) + + In contrast to struct __res_state, struct resolv_context is not + affected by ABI compatibility concerns. + + For the benefit of the res_n* functions, a struct __res_state + pointer is included in the context object, and a separate + initialization function is provided. */ + +#ifndef _RESOLV_CONTEXT_H +#define _RESOLV_CONTEXT_H + +#include <bits/types/res_state.h> +#include <resolv/resolv_conf.h> +#include <stdbool.h> +#include <stddef.h> + +/* Temporary resolver state. */ +struct resolv_context +{ + struct __res_state *resp; /* Backing resolver state. */ + + /* Extended resolver state. This is set to NULL if the + __resolv_context_get functions are unable to locate an associated + extended state. In this case, the configuration data in *resp + has to be used; otherwise, the data from *conf should be + preferred (because it is a superset). */ + struct resolv_conf *conf; + + /* The following fields are for internal use within the + resolv_context module. */ + size_t __refcount; /* Count of reusages by the get functions. */ + bool __from_res; /* True if created from _res. */ + + /* If RES_USE_INET6 was disabled at this level, this field points to + the previous context. */ + struct resolv_context *__next; +}; + +/* Return the current temporary resolver context, or NULL if there was + an error (indicated by errno). A call to this function must be + paired with a call to __resolv_context_put. */ +struct resolv_context *__resolv_context_get (void) + __attribute__ ((warn_unused_result)); +libc_hidden_proto (__resolv_context_get) + +/* Deallocate the temporary resolver context. Converse of + __resolv_context_get. Restore the RES_USE_INET6 flag if necessary. + Do nothing if CTX is NULL. */ +void __resolv_context_put (struct resolv_context *ctx); +libc_hidden_proto (__resolv_context_put) + +/* Like __resolv_context_get, but the _res structure can be partially + initialzed and those changes will not be overwritten. */ +struct resolv_context *__resolv_context_get_preinit (void) + __attribute__ ((warn_unused_result)); +libc_hidden_proto (__resolv_context_get_preinit) + +/* Wrap a struct __res_state object in a struct resolv_context object. + A call to this function must be paired with a call to + __resolv_context_put. */ +struct resolv_context *__resolv_context_get_override (struct __res_state *) + __attribute__ ((nonnull (1), warn_unused_result)); +libc_hidden_proto (__resolv_context_get_override) + +/* Return the search path entry at INDEX, or NULL if there are fewer + than INDEX entries. */ +static __attribute__ ((nonnull (1), unused)) const char * +__resolv_context_search_list (const struct resolv_context *ctx, size_t index) +{ + if (ctx->conf != NULL) + { + if (index < ctx->conf->search_list_size) + return ctx->conf->search_list[index]; + else + return NULL; + } + /* Fallback. ctx->resp->dnsrch is a NULL-terminated array. */ + for (size_t i = 0; ctx->resp->dnsrch[i] != NULL && i < MAXDNSRCH; ++i) + if (i == index) + return ctx->resp->dnsrch[i]; + return NULL; +} + +/* Return the number of name servers. */ +static __attribute__ ((nonnull (1), unused)) size_t +__resolv_context_nameserver_count (const struct resolv_context *ctx) +{ + if (ctx->conf != NULL) + return ctx->conf->nameserver_list_size; + else + return ctx->resp->nscount; +} + +/* Return a pointer to the socket address of the name server INDEX, or + NULL if the index is out of bounds. */ +static __attribute__ ((nonnull (1), unused)) const struct sockaddr * +__resolv_context_nameserver (const struct resolv_context *ctx, size_t index) +{ + if (ctx->conf != NULL) + { + if (index < ctx->conf->nameserver_list_size) + return ctx->conf->nameserver_list[index]; + } + else + if (index < ctx->resp->nscount) + { + if (ctx->resp->nsaddr_list[index].sin_family != 0) + return (const struct sockaddr *) &ctx->resp->nsaddr_list[index]; + else + return (const struct sockaddr *) &ctx->resp->_u._ext.nsaddrs[index]; + } + return NULL; +} + +/* Return the number of sort list entries. */ +static __attribute__ ((nonnull (1), unused)) size_t +__resolv_context_sort_count (const struct resolv_context *ctx) +{ + if (ctx->conf != NULL) + return ctx->conf->sort_list_size; + else + return ctx->resp->nsort; +} + +/* Return the sort list entry at INDEX. */ +static __attribute__ ((nonnull (1), unused)) struct resolv_sortlist_entry +__resolv_context_sort_entry (const struct resolv_context *ctx, size_t index) +{ + if (ctx->conf != NULL) + { + if (index < ctx->conf->sort_list_size) + return ctx->conf->sort_list[index]; + /* Fall through. */ + } + else if (index < ctx->resp->nsort) + return (struct resolv_sortlist_entry) + { + .addr = ctx->resp->sort_list[index].addr, + .mask = ctx->resp->sort_list[index].mask, + }; + + return (struct resolv_sortlist_entry) { .mask = 0, }; +} + +/* Called during thread shutdown to free the associated resolver + context (mostly in response to cancellation, otherwise the + __resolv_context_get/__resolv_context_put pairing will already have + deallocated the context object). */ +void __resolv_context_freeres (void) attribute_hidden; + +#endif /* _RESOLV_CONTEXT_H */ diff --git a/resolv/tst-bug18665-tcp.c b/resolv/tst-bug18665-tcp.c new file mode 100644 index 0000000000..52849fabb9 --- /dev/null +++ b/resolv/tst-bug18665-tcp.c @@ -0,0 +1,230 @@ +/* Test __libc_res_nsend buffer mismanagement, basic TCP coverage. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <support/check.h> +#include <support/check_nss.h> +#include <support/resolv_test.h> +#include <support/xthread.h> +#include <support/xmemstream.h> + +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + +static int initial_address_count = 1; +static int subsequent_address_count = 2000; +static int response_number = 0; + +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + TEST_VERIFY_EXIT (qname != NULL); + + /* If not using TCP, just force its use. */ + if (!ctx->tcp) + { + struct resolv_response_flags flags = {.tc = true}; + resolv_response_init (b, flags); + resolv_response_add_question (b, qname, qclass, qtype); + return; + } + + struct resolv_response_flags flags = {}; + resolv_response_init (b, flags); + resolv_response_add_question (b, qname, qclass, qtype); + + resolv_response_section (b, ns_s_an); + + /* The number of addresses (in the additional section) for the name + server record (in the authoritative section). */ + int address_count; + xpthread_mutex_lock (&lock); + ++response_number; + if (response_number == 1) + address_count = initial_address_count; + else if (response_number == 2) + { + address_count = 0; + resolv_response_drop (b); + resolv_response_close (b); + } + else + address_count = subsequent_address_count; + xpthread_mutex_unlock (&lock); + + /* Only add the address record to the answer section if we requested + any name server addresses. */ + if (address_count > 0) + { + resolv_response_open_record (b, qname, qclass, qtype, 0); + switch (qtype) + { + case T_A: + { + char ipv4[4] = {10, response_number >> 8, response_number, 0}; + ipv4[3] = 2 * ctx->tcp + 4 * ctx->server_index; + resolv_response_add_data (b, &ipv4, sizeof (ipv4)); + } + break; + case T_AAAA: + { + char ipv6[16] + = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, + response_number >> 8, response_number, 0, 0}; + ipv6[15] = 2 * ctx->tcp + 4 * ctx->server_index; + resolv_response_add_data (b, &ipv6, sizeof (ipv6)); + } + break; + default: + support_record_failure (); + printf ("error: unexpected QTYPE: %s/%u/%u\n", + qname, qclass, qtype); + } + resolv_response_close_record (b); + + /* Add the name server record. */ + resolv_response_section (b, ns_s_ns); + resolv_response_open_record (b, "example", C_IN, T_NS, 0); + resolv_response_add_name (b, "ns.example"); + resolv_response_close_record (b); + + /* Increase the response size with name server addresses. These + addresses are not copied out of nss_dns, and thus do not + trigger getaddrinfo retries with a larger buffer, making + testing more predictable. */ + resolv_response_section (b, ns_s_ar); + for (int i = 1; i <= address_count; ++i) + { + resolv_response_open_record (b, "ns.example", qclass, qtype, 0); + switch (qtype) + { + case T_A: + { + char ipv4[4] = {response_number, i >> 8, i, 0}; + ipv4[3] = 2 * ctx->tcp + 4 * ctx->server_index; + resolv_response_add_data (b, &ipv4, sizeof (ipv4)); + } + break; + case T_AAAA: + { + char ipv6[16] + = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, + response_number >> 8, response_number, + i >> 8, i, 0, 0}; + ipv6[15] = 2 * ctx->tcp + 4 * ctx->server_index; + resolv_response_add_data (b, &ipv6, sizeof (ipv6)); + } + break; + default: + support_record_failure (); + printf ("error: unexpected QTYPE: %s/%u/%u\n", + qname, qclass, qtype); + } + resolv_response_close_record (b); + } + } +} + +static char * +expected_result (unsigned port, unsigned response_number) +{ + struct xmemstream mem; + xopen_memstream (&mem); + /* We fail the second TCP query to the first server by closing the + connection immediately, without returning any data. This should + cause failover to the second server. */ + int server_index = 1; + fprintf (mem.out, "address: STREAM/TCP 10.%u.%u.%u %u\n", + (response_number >> 8) & 0xff, response_number & 0xff, + 2 + 4 * server_index, port); + fprintf (mem.out, "address: STREAM/TCP 2001:db8::%x:%x %u\n", + (response_number + 1) & 0xffff, + 2 + 4 * server_index, port); + xfclose_memstream (&mem); + return mem.buffer; +} + +static void +test_different_sizes (void) +{ + struct addrinfo hints = + { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP, + }; + struct addrinfo *ai; + char *expected; + int ret; + + /* This magic number produces a response size close to 2048 + bytes. */ + initial_address_count = 124; + response_number = 0; + + ret = getaddrinfo ("www.example", "80", &hints, &ai); + expected = expected_result (80, 3); + check_addrinfo ("www.example:80", ai, ret, expected); + if (ret == 0) + freeaddrinfo (ai); + free (expected); + + response_number = 0; + ret = getaddrinfo ("www123.example", "80", &hints, &ai); + if (ret == 0) + freeaddrinfo (ai); + + response_number = 0; + ret = getaddrinfo ("www1234.example", "80", &hints, &ai); + if (ret == 0) + freeaddrinfo (ai); + + response_number = 0; + ret = getaddrinfo ("www12345.example", "80", &hints, &ai); + if (ret == 0) + freeaddrinfo (ai); +} + +static int +do_test (void) +{ + struct resolv_test *obj = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response + }); + + test_different_sizes (); + + _res.options |= RES_SNGLKUP; + test_different_sizes (); + + _res.options |= RES_SNGLKUPREOP; + test_different_sizes (); + + resolv_test_end (obj); + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-bug18665.c b/resolv/tst-bug18665.c new file mode 100644 index 0000000000..dc911f0468 --- /dev/null +++ b/resolv/tst-bug18665.c @@ -0,0 +1,138 @@ +/* Test for __libc_res_nsend buffer mismanagent (bug 18665), UDP case. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> +#include <support/check.h> +#include <support/resolv_test.h> +#include <support/xthread.h> + +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + +static int initial_address_count; +static int response_count; + +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + TEST_VERIFY_EXIT (qname != NULL); + struct resolv_response_flags flags = {}; + resolv_response_init (b, flags); + resolv_response_add_question (b, qname, qclass, qtype); + + resolv_response_section (b, ns_s_an); + + /* Add many A/AAAA records to the second response. */ + int address_count; + xpthread_mutex_lock (&lock); + if (response_count == 0) + address_count = initial_address_count; + else + address_count = 2000; + ++response_count; + xpthread_mutex_unlock (&lock); + + for (int i = 0; i < address_count; ++i) + { + resolv_response_open_record (b, qname, qclass, qtype, 0); + switch (qtype) + { + case T_A: + { + char ipv4[4] = {10, i >> 8, i, 0}; + ipv4[3] = 2 * ctx->tcp + 4 * ctx->server_index; + resolv_response_add_data (b, &ipv4, sizeof (ipv4)); + } + break; + case T_AAAA: + { + char ipv6[16] + = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + i >> 8, i, 0}; + ipv6[15] = 2 * ctx->tcp + 4 * ctx->server_index; + resolv_response_add_data (b, &ipv6, sizeof (ipv6)); + } + break; + default: + support_record_failure (); + printf ("error: unexpected QTYPE: %s/%u/%u\n", + qname, qclass, qtype); + } + resolv_response_close_record (b); + } +} + +static void +test_different_sizes (void) +{ + struct addrinfo hints = { .ai_family = AF_UNSPEC, }; + struct addrinfo *ai; + int ret; + + /* This magic number produces a response size close to 2048 + bytes. */ + initial_address_count = 126; + response_count = 0; + + ret = getaddrinfo ("www.example", "80", &hints, &ai); + if (ret == 0) + freeaddrinfo (ai); + + response_count = 0; + ret = getaddrinfo ("www123.example", "80", &hints, &ai); + if (ret == 0) + freeaddrinfo (ai); + + response_count = 0; + ret = getaddrinfo ("www1234.example", "80", &hints, &ai); + if (ret == 0) + freeaddrinfo (ai); + + response_count = 0; + ret = getaddrinfo ("www12345.example", "80", &hints, &ai); + if (ret == 0) + freeaddrinfo (ai); +} + +static int +do_test (void) +{ + struct resolv_test *obj = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response + }); + + test_different_sizes (); + + _res.options |= RES_SNGLKUP; + test_different_sizes (); + + _res.options |= RES_SNGLKUPREOP; + test_different_sizes (); + + resolv_test_end (obj); + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-inet_pton.c b/resolv/tst-inet_pton.c new file mode 100644 index 0000000000..af12f38fa9 --- /dev/null +++ b/resolv/tst-inet_pton.c @@ -0,0 +1,492 @@ +/* Test inet_pton functions. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <arpa/inet.h> +#include <resolv/resolv-internal.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <support/check.h> +#include <support/next_to_fault.h> +#include <support/xunistd.h> +#include <unistd.h> + +struct test_case +{ + /* The input data. */ + const char *input; + + /* True if AF_INET parses successfully. */ + bool ipv4_ok; + + /* True if AF_INET6 parses successfully. */ + bool ipv6_ok; + + /* Expected result for AF_INET. */ + unsigned char ipv4_expected[4]; + + /* Expected result for AF_INET6. */ + unsigned char ipv6_expected[16]; +}; + +static void +check_result (const char *what, const struct test_case *t, int family, + void *result_buffer, int inet_ret) +{ + TEST_VERIFY_EXIT (inet_ret >= -1); + TEST_VERIFY_EXIT (inet_ret <= 1); + + int ok; + const unsigned char *expected; + size_t result_size; + switch (family) + { + case AF_INET: + ok = t->ipv4_ok; + expected = t->ipv4_expected; + result_size = 4; + break; + case AF_INET6: + ok = t->ipv6_ok; + expected = t->ipv6_expected; + result_size = 16; + break; + default: + FAIL_EXIT1 ("invalid address family %d", family); + } + + if (inet_ret != ok) + { + support_record_failure (); + printf ("error: %s return value mismatch for [[%s]], family %d\n" + " expected: %d\n" + " actual: %d\n", + what, t->input, family, ok, inet_ret); + return; + } + if (memcmp (result_buffer, expected, result_size) != 0) + { + support_record_failure (); + printf ("error: %s result mismatch for [[%s]], family %d\n", + what, t->input, family); + } +} + +static void +run_one_test (const struct test_case *t) +{ + size_t test_len = strlen (t->input); + + struct support_next_to_fault ntf_out4 = support_next_to_fault_allocate (4); + struct support_next_to_fault ntf_out6 = support_next_to_fault_allocate (16); + + /* inet_pton requires NUL termination. */ + { + struct support_next_to_fault ntf_in + = support_next_to_fault_allocate (test_len + 1); + memcpy (ntf_in.buffer, t->input, test_len + 1); + memset (ntf_out4.buffer, 0, 4); + check_result ("inet_pton", t, AF_INET, ntf_out4.buffer, + inet_pton (AF_INET, ntf_in.buffer, ntf_out4.buffer)); + memset (ntf_out6.buffer, 0, 16); + check_result ("inet_pton", t, AF_INET6, ntf_out6.buffer, + inet_pton (AF_INET6, ntf_in.buffer, ntf_out6.buffer)); + support_next_to_fault_free (&ntf_in); + } + + /* __inet_pton_length does not require NUL termination. */ + { + struct support_next_to_fault ntf_in + = support_next_to_fault_allocate (test_len); + memcpy (ntf_in.buffer, t->input, test_len); + memset (ntf_out4.buffer, 0, 4); + check_result ("__inet_pton_length", t, AF_INET, ntf_out4.buffer, + __inet_pton_length (AF_INET, ntf_in.buffer, ntf_in.length, + ntf_out4.buffer)); + memset (ntf_out6.buffer, 0, 16); + check_result ("__inet_pton_length", t, AF_INET6, ntf_out6.buffer, + __inet_pton_length (AF_INET6, ntf_in.buffer, ntf_in.length, + ntf_out6.buffer)); + support_next_to_fault_free (&ntf_in); + } + + support_next_to_fault_free (&ntf_out4); + support_next_to_fault_free (&ntf_out6); +} + +/* The test cases were manually crafted and the set enhanced with + American Fuzzy Lop. */ +const struct test_case test_cases[] = + { + {.input = ".:", }, + {.input = "0.0.0.0", + .ipv4_ok = true, + .ipv4_expected = {0, 0, 0, 0}, + }, + {.input = "0.:", }, + {.input = "00", }, + {.input = "0000000", }, + {.input = "00000000000000000", }, + {.input = "092.", }, + {.input = "10.0.301.2", }, + {.input = "127.0.0.1", + .ipv4_ok = true, + .ipv4_expected = {127, 0, 0, 1}, + }, + {.input = "19..", }, + {.input = "192.0.2.-1", }, + {.input = "192.0.2.01", }, + {.input = "192.0.2.1.", }, + {.input = "192.0.2.1192.", }, + {.input = "192.0.2.192.\377..", }, + {.input = "192.0.2.256", }, + {.input = "192.0.2.27", + .ipv4_ok = true, + .ipv4_expected = {192, 0, 2, 27}, + }, + {.input = "192.0.201.", }, + {.input = "192.0.261.", }, + {.input = "192.0.2\256", }, + {.input = "192.0.\262.", }, + {.input = "192.062.", }, + {.input = "192.092.\256", }, + {.input = "192.0\2562.", }, + {.input = "192.192.0.2661\031", }, + {.input = "192.192.00n2.1.", }, + {.input = "192.192.2.190.", }, + {.input = "192.255.255.2555", }, + {.input = "192.92.219\023.", }, + {.input = "192.\260.2.", }, + {.input = "1:1::1:1", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1 + }, + }, + {.input = "2", }, + {.input = "2.", }, + {.input = "2001:db8:00001::f", }, + {.input = "2001:db8:10000::f", }, + {.input = "2001:db8:1234:5678:abcd:ef01:2345:67", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x12, 0x34, 0x56, 0x78, + 0xab, 0xcd, 0xef, 0x1, 0x23, 0x45, 0x0, 0x67 + }, + }, + {.input = "2001:db8:1234:5678:abcd:ef01:2345:6789:1", }, + {.input = "2001:db8:1234:5678:abcd:ef01:2345::6789", }, + {.input = "2001:db8::0", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 + }, + }, + {.input = "2001:db8::00", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 + }, + }, + {.input = "2001:db8::1", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1 + }, + }, + {.input = "2001:db8::10", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10 + }, + }, + {.input = "2001:db8::19", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19 + }, + }, + {.input = "2001:db8::1::\012", }, + {.input = "2001:db8::1::2\012", }, + {.input = "2001:db8::2", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2 + }, + }, + {.input = "2001:db8::3", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3 + }, + }, + {.input = "2001:db8::4", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4 + }, + }, + {.input = "2001:db8::5", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5 + }, + }, + {.input = "2001:db8::6", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6 + }, + }, + {.input = "2001:db8::7", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7 + }, + }, + {.input = "2001:db8::8", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8 + }, + }, + {.input = "2001:db8::9", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9 + }, + }, + {.input = "2001:db8::A", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa + }, + }, + {.input = "2001:db8::B", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb + }, + }, + {.input = "2001:db8::C", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc + }, + }, + {.input = "2001:db8::D", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd + }, + }, + {.input = "2001:db8::E", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe + }, + }, + {.input = "2001:db8::F", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf + }, + }, + {.input = "2001:db8::a", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa + }, + }, + {.input = "2001:db8::b", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb + }, + }, + {.input = "2001:db8::c", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc + }, + }, + {.input = "2001:db8::d", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd + }, + }, + {.input = "2001:db8::e", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe + }, + }, + {.input = "2001:db8::f", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf + }, + }, + {.input = "2001:db8::ff", + .ipv6_ok = true, + .ipv6_expected = { + 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff + }, + }, + {.input = "2001:db8::ffff:2\012", }, + {.input = "22", }, + {.input = "2222@", }, + {.input = "255.255.255.255", + .ipv4_ok = true, + .ipv4_expected = {255, 255, 255, 255}, + }, + {.input = "255.255.255.255\001", }, + {.input = "255.255.255.25555", }, + {.input = "2:", }, + {.input = "2:a:8:EEEE::EEEE:F:EEE8:EEEE\034*:", }, + {.input = "2:ff:1:1:7:ff:1:1:7.", }, + {.input = "2f:0000000000000000000000000000000000000000000000000000000000" + "0000000000000000000000000000000000000000000000000000000000000000000000" + "0G01", + }, + {.input = "429495", }, + {.input = "5::5::", }, + {.input = "6.6.", }, + {.input = "992.", }, + {.input = "::", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 + }, + }, + {.input = "::00001", }, + {.input = "::1", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1 + }, + }, + {.input = "::10000", }, + {.input = "::1:1", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1 + }, + }, + {.input = "::ff:1:1:7.0.0.1", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff, + 0x0, 0x1, 0x0, 0x1, 0x7, 0x0, 0x0, 0x1 + }, + }, + {.input = "::ff:1:1:7:ff:1:1:7.", }, + {.input = "::ff:1:1:7ff:1:8:7.0.0.1", }, + {.input = "::ff:1:1:7ff:1:8f:1:1:71", }, + {.input = "::ffff:02fff:127.0.S1", }, + {.input = "::ffff:127.0.0.1", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x1 + }, + }, + {.input = "::ffff:1:7.0.0.1", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0xff, 0xff, 0x0, 0x1, 0x7, 0x0, 0x0, 0x1 + }, + }, + {.input = ":\272", }, + {.input = "A:f:ff:1:1:D:ff:1:1::7.", }, + {.input = "AAAAA.", }, + {.input = "D:::", }, + {.input = "DF8F", }, + {.input = "F::", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 + }, + }, + {.input = "F:A:8:EEEE:8:EEEE\034*:", }, + {.input = "F:a:8:EEEE:8:EEEE\034*:", }, + {.input = "F:ff:100:7ff:1:8:7.0.10.1", + .ipv6_ok = true, + .ipv6_expected = { + 0x0, 0xf, 0x0, 0xff, 0x1, 0x0, 0x7, 0xff, + 0x0, 0x1, 0x0, 0x8, 0x7, 0x0, 0xa, 0x1 + }, + }, + {.input = "d92.", }, + {.input = "ff:00000000000000000000000000000000000000000000000000000000000" + "00000000000000000000000000000000000000000000000000000000000000000001", + }, + {.input = "fff2:2::ff2:2:f7", + .ipv6_ok = true, + .ipv6_expected = { + 0xff, 0xf2, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0xf, 0xf2, 0x0, 0x2, 0x0, 0xf7 + }, + }, + {.input = "ffff:ff:ff:fff:ff:ff:ff:", }, + {.input = "\272:", }, + {NULL} + }; + +static int +do_test (void) +{ + for (size_t i = 0; test_cases[i].input != NULL; ++i) + run_one_test (test_cases + i); + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-leaks.c b/resolv/tst-leaks.c index b97c0648fd..5715f1ba34 100644 --- a/resolv/tst-leaks.c +++ b/resolv/tst-leaks.c @@ -1,5 +1,5 @@ /* Tests for res_query in libresolv - Copyright (C) 2003-2016 Free Software Foundation, Inc. + Copyright (C) 2003-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/resolv/tst-leaks2.c b/resolv/tst-leaks2.c index 3e9c4a2dc7..6a1fd6aa9c 100644 --- a/resolv/tst-leaks2.c +++ b/resolv/tst-leaks2.c @@ -1,5 +1,5 @@ /* Tests for res_init in libresolv - Copyright (C) 2004-2016 Free Software Foundation, Inc. + Copyright (C) 2004-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or diff --git a/resolv/tst-no-libidn2.c b/resolv/tst-no-libidn2.c new file mode 100644 index 0000000000..590696e3fa --- /dev/null +++ b/resolv/tst-no-libidn2.c @@ -0,0 +1,2 @@ +/* Compiled into an empty shared object. Used by + tst-resolv-ai_idn-nolibidn2 to disable libidn2. */ diff --git a/resolv/tst-ns_name.c b/resolv/tst-ns_name.c new file mode 100644 index 0000000000..970c3d6d15 --- /dev/null +++ b/resolv/tst-ns_name.c @@ -0,0 +1,438 @@ +/* Test ns_name-related functions. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* This test program processes the tst-ns_name.data file. */ + +#include <ctype.h> +#include <resolv.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <support/check.h> +#include <support/support.h> +#include <support/xstdio.h> + +/* A byte buffer and its length. */ +struct buffer +{ + unsigned char *data; + size_t length; +}; + +/* Convert a base64-encoded string to its binary representation. */ +static bool +base64_to_buffer (const char *base64, struct buffer *result) +{ + /* "-" denotes an empty input. */ + if (strcmp (base64, "-") == 0) + { + result->data = xmalloc (1); + result->length = 0; + return true; + } + + size_t size = strlen (base64); + unsigned char *data = xmalloc (size); + int ret = b64_pton (base64, data, size); + if (ret < 0 || ret > size) + return false; + result->data = xrealloc (data, ret); + result->length = ret; + return true; +} + +/* A test case for ns_name_unpack and ns_name_ntop. */ +struct test_case +{ + char *path; + size_t lineno; + struct buffer input; + size_t input_offset; + int unpack_result; + struct buffer unpack_output; + int ntop_result; + char *ntop_text; +}; + +/* Deallocate the buffers associated with the test case. */ +static void +free_test_case (struct test_case *t) +{ + free (t->path); + free (t->input.data); + free (t->unpack_output.data); + free (t->ntop_text); +} + +/* Extract the test case information from a test file line. */ +static bool +parse_test_case (const char *path, size_t lineno, const char *line, + struct test_case *result) +{ + memset (result, 0, sizeof (*result)); + result->path = xstrdup (path); + result->lineno = lineno; + result->ntop_result = -1; + char *input = NULL; + char *unpack_output = NULL; + int ret = sscanf (line, "%ms %zu %d %ms %d %ms", + &input, &result->input_offset, + &result->unpack_result, &unpack_output, + &result->ntop_result, &result->ntop_text); + if (ret < 3) + { + printf ("%s:%zu: error: missing input fields\n", path, lineno); + free (input); + return false; + } + if (!base64_to_buffer (input, &result->input)) + { + printf ("%s:%zu: error: malformed base64 input data\n", path, lineno); + free (input); + free (unpack_output); + free (result->ntop_text); + return false; + } + free (input); + + if (unpack_output == NULL) + result->unpack_output = (struct buffer) { NULL, 0 }; + else if (!base64_to_buffer (unpack_output, &result->unpack_output)) + { + printf ("%s:%zu: error: malformed base64 unpack data\n", path, lineno); + free (result->input.data); + free (unpack_output); + free (result->ntop_text); + return false; + } + free (unpack_output); + + /* At this point, all allocated buffers have been transferred to + *result. */ + + if (result->input_offset > result->input.length) + { + printf ("%s:%zu: error: input offset %zu exceeds buffer size %zu\n", + path, lineno, result->input_offset, result->input.length); + free_test_case (result); + return false; + } + if (result->unpack_result < -1) + { + printf ("%s:%zu: error: invalid unpack result %d\n", + path, lineno, result->unpack_result); + free_test_case (result); + return false; + } + if (result->ntop_result < -1) + { + printf ("%s:%zu: error: invalid ntop result %d\n", + path, lineno, result->ntop_result); + free_test_case (result); + return false; + } + + bool fields_consistent; + switch (ret) + { + case 3: + fields_consistent = result->unpack_result == -1; + break; + case 5: + fields_consistent = result->unpack_result != -1 + && result->ntop_result == -1; + break; + case 6: + fields_consistent = result->unpack_result != -1 + && result->ntop_result != -1; + break; + default: + fields_consistent = false; + } + if (!fields_consistent) + { + printf ("%s:%zu: error: wrong number of fields: %d\n", + path, lineno, ret); + free_test_case (result); + return false; + } + return true; +} + +/* Format the buffer as a hexadecimal string and write it to standard + output. */ +static void +print_hex (const char *label, struct buffer buffer) +{ + printf (" %s ", label); + unsigned char *p = buffer.data; + unsigned char *end = p + buffer.length; + while (p < end) + { + printf ("%02X", *p & 0xFF); + ++p; + } + putchar ('\n'); +} + +/* Run the test case specified in *T. */ +static void +run_test_case (struct test_case *t) +{ + /* Test ns_name_unpack. */ + unsigned char *unpacked = xmalloc (NS_MAXCDNAME); + int consumed = ns_name_unpack + (t->input.data, t->input.data + t->input.length, + t->input.data + t->input_offset, + unpacked, NS_MAXCDNAME); + if (consumed != t->unpack_result) + { + support_record_failure (); + printf ("%s:%zu: error: wrong result from ns_name_unpack\n" + " expected: %d\n" + " actual: %d\n", + t->path, t->lineno, t->unpack_result, consumed); + return; + } + if (consumed != -1) + { + if (memcmp (unpacked, t->unpack_output.data, + t->unpack_output.length) != 0) + { + support_record_failure (); + printf ("%s:%zu: error: wrong data from ns_name_unpack\n", + t->path, t->lineno); + print_hex ("expected:", t->unpack_output); + print_hex ("actual: ", + (struct buffer) { unpacked, t->unpack_output.length }); + return; + } + + /* Test ns_name_ntop. */ + char *text = xmalloc (NS_MAXDNAME); + int ret = ns_name_ntop (unpacked, text, NS_MAXDNAME); + if (ret != t->ntop_result) + { + support_record_failure (); + printf ("%s:%zu: error: wrong result from ns_name_top\n" + " expected: %d\n" + " actual: %d\n", + t->path, t->lineno, t->ntop_result, ret); + return; + } + if (ret != -1) + { + if (strcmp (text, t->ntop_text) != 0) + { + support_record_failure (); + printf ("%s:%zu: error: wrong data from ns_name_ntop\n", + t->path, t->lineno); + printf (" expected: \"%s\"\n", t->ntop_text); + printf (" actual: \"%s\"\n", text); + return; + } + + /* Test ns_name_pton. Unpacking does not check the + NS_MAXCDNAME limit, but packing does, so we need to + adjust the expected result. */ + int expected; + if (t->unpack_output.length > NS_MAXCDNAME) + expected = -1; + else if (strcmp (text, ".") == 0) + /* The root domain is fully qualified. */ + expected = 1; + else + /* The domain name is never fully qualified. */ + expected = 0; + unsigned char *repacked = xmalloc (NS_MAXCDNAME); + ret = ns_name_pton (text, repacked, NS_MAXCDNAME); + if (ret != expected) + { + support_record_failure (); + printf ("%s:%zu: error: wrong result from ns_name_pton\n" + " expected: %d\n" + " actual: %d\n", + t->path, t->lineno, expected, ret); + return; + } + if (ret >= 0 + && memcmp (repacked, unpacked, t->unpack_output.length) != 0) + { + support_record_failure (); + printf ("%s:%zu: error: wrong data from ns_name_pton\n", + t->path, t->lineno); + print_hex ("expected:", t->unpack_output); + print_hex ("actual: ", + (struct buffer) { repacked, t->unpack_output.length }); + return; + } + + /* Test ns_name_compress, no compression case. */ + if (t->unpack_output.length > NS_MAXCDNAME) + expected = -1; + else + expected = t->unpack_output.length; + memset (repacked, '$', NS_MAXCDNAME); + { + enum { ptr_count = 5 }; + const unsigned char *dnptrs[ptr_count] = { repacked, }; + ret = ns_name_compress (text, repacked, NS_MAXCDNAME, + dnptrs, dnptrs + ptr_count); + if (ret != expected) + { + support_record_failure (); + printf ("%s:%zu: error: wrong result from ns_name_compress\n" + " expected: %d\n" + " actual: %d\n", + t->path, t->lineno, expected, ret); + return; + } + if (ret < 0) + { + TEST_VERIFY (dnptrs[0] == repacked); + TEST_VERIFY (dnptrs[1] == NULL); + } + else + { + if (memcmp (repacked, unpacked, t->unpack_output.length) != 0) + { + support_record_failure (); + printf ("%s:%zu: error: wrong data from ns_name_compress\n", + t->path, t->lineno); + print_hex ("expected:", t->unpack_output); + print_hex ("actual: ", (struct buffer) { repacked, ret }); + return; + } + TEST_VERIFY (dnptrs[0] == repacked); + if (unpacked[0] == '\0') + /* The root domain is not a compression target. */ + TEST_VERIFY (dnptrs[1] == NULL); + else + { + TEST_VERIFY (dnptrs[1] == repacked); + TEST_VERIFY (dnptrs[2] == NULL); + } + } + } + + /* Test ns_name_compress, full compression case. Skip this + test for invalid names and the root domain. */ + if (expected >= 0 && unpacked[0] != '\0') + { + /* The destination buffer needs additional room for the + offset, the initial name, and the compression + reference. */ + enum { name_offset = 259 }; + size_t target_offset = name_offset + t->unpack_output.length; + size_t repacked_size = target_offset + 2; + repacked = xrealloc (repacked, repacked_size); + memset (repacked, '@', repacked_size); + memcpy (repacked + name_offset, + t->unpack_output.data, t->unpack_output.length); + enum { ptr_count = 5 }; + const unsigned char *dnptrs[ptr_count] + = { repacked, repacked + name_offset, }; + ret = ns_name_compress + (text, repacked + target_offset, NS_MAXCDNAME, + dnptrs, dnptrs + ptr_count); + if (ret != 2) + { + support_record_failure (); + printf ("%s:%zu: error: wrong result from ns_name_compress" + " (2)\n" + " expected: 2\n" + " actual: %d\n", + t->path, t->lineno, ret); + return; + } + if (memcmp (repacked + target_offset, "\xc1\x03", 2) != 0) + { + support_record_failure (); + printf ("%s:%zu: error: wrong data from ns_name_compress" + " (2)\n" + " expected: C103\n", + t->path, t->lineno); + print_hex ("actual: ", + (struct buffer) { repacked + target_offset, ret }); + return; + } + TEST_VERIFY (dnptrs[0] == repacked); + TEST_VERIFY (dnptrs[1] == repacked + name_offset); + TEST_VERIFY (dnptrs[2] == NULL); + } + + free (repacked); + } + free (text); + } + free (unpacked); +} + +/* Open the file at PATH, parse the test cases contained in it, and + run them. */ +static void +run_test_file (const char *path) +{ + FILE *fp = xfopen (path, "re"); + char *line = NULL; + size_t line_allocated = 0; + size_t lineno = 0; + + while (true) + { + ssize_t ret = getline (&line, &line_allocated, fp); + if (ret < 0) + { + if (ferror (fp)) + { + printf ("%s: error reading file: %m\n", path); + exit (1); + } + TEST_VERIFY (feof (fp)); + break; + } + + ++lineno; + char *p = line; + while (isspace (*p)) + ++p; + if (*p == '\0' || *p == '#') + continue; + + struct test_case test_case; + if (!parse_test_case (path, lineno, line, &test_case)) + { + support_record_failure (); + continue; + } + run_test_case (&test_case); + free_test_case (&test_case); + } + free (line); + xfclose (fp); +} + +static int +do_test (void) +{ + run_test_file ("tst-ns_name.data"); + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-ns_name.data b/resolv/tst-ns_name.data new file mode 100644 index 0000000000..890a89a976 --- /dev/null +++ b/resolv/tst-ns_name.data @@ -0,0 +1,548 @@ +# Test input for ns_name_unpack and ns_name_ntop. +# Copyright (C) 2017-2018 Free Software Foundation, Inc. +# This file is part of the GNU C Library. +# +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <http://www.gnu.org/licenses/>. + +# This file contains test input and expected output for the +# ns_name_unpack and ns_name_ntop functions. Empty lines and comments +# (lines starting with #) are ignored. Test data lines have the +# following format: +# +# INPUT INPUT-OFFSET UNPACK-RESULT UNPACK-OUTPUT NTOP-RESULT NTOP-OUTPUT +# +# INPUT, UNPACK-OUTPUT are base64-encoded binary blobs. INPUT-OFFSET, +# UNPACK-RESULT, NTOP-RESULT are signed integers. NTOP-OUTPUT is an +# ASCII string (without spaces). If UNPACK-RESULT or NTOP-RESULT are +# -1, the fields after that are missing (-1 is an error code, so the +# output buffer is undefined). + +# First some manually-crafted test cases. + +# bytes-1 +AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgEvATABMQEyATMBNAE1ATYBNwE4ATkBOgE7ATwBPQE+AT8BQAFBAUIBQwFEAUUBRgFHAUgBSQFKAUsBTAFNAU4BTwFQAVEBUgFTAVQBVQFWAVcBWAFZAVoBWwFcAV0BXgFfAWABYQFiAWMBZAFlAWYBZwFoAWkBagFrAWwBbQFuAW8BcAFxAXIBcwF0AXUBdgF3AXgBeQF6AXsBfAF9AX4BfwGAAYEBggGDAYQBhQGGAYcBiAGJAYoBiwGMAY0BjgGPAZABkQGSAZMBlAGVAZYBlwGYAZkBmgGbAZwBnQGeAZ8BoAGhAaIBowGkAaUBpgGnAagBqQGqAasBrAGtAa4BrwGwAbEBsgGzAbQBtQG2AbcBuAG5AboBuwG8Ab0BvgG/AcABwQHCAcMBxAHFAcYBxwHIAckBygHLAcwBzQHOAc8B0AHRAdIB0wHUAdUB1gHXAdgB2QHaAdsB3AHdAd4B3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QH+Af8A 0 -1 +# bytes-1a +AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgEvATABMQEyATMBNAE1ATYBNwE4ATkBOgE7ATwBPQE+AT8A 0 129 AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgEvATABMQEyATMBNAE1ATYBNwE4ATkBOgE7ATwBPQE+AT8A 233 \000.\001.\002.\003.\004.\005.\006.\007.\008.\009.\010.\011.\012.\013.\014.\015.\016.\017.\018.\019.\020.\021.\022.\023.\024.\025.\026.\027.\028.\029.\030.\031.\032.!.\".#.\$.%.&.'.\(.\).*.+.,.-.\../.0.1.2.3.4.5.6.7.8.9.:.\;.<.=.>.? +# bytes-1b +AUABQQFCAUMBRAFFAUYBRwFIAUkBSgFLAUwBTQFOAU8BUAFRAVIBUwFUAVUBVgFXAVgBWQFaAVsBXAFdAV4BXwFgAWEBYgFjAWQBZQFmAWcBaAFpAWoBawFsAW0BbgFvAXABcQFyAXMBdAF1AXYBdwF4AXkBegF7AXwBfQF+AX8A 0 129 AUABQQFCAUMBRAFFAUYBRwFIAUkBSgFLAUwBTQFOAU8BUAFRAVIBUwFUAVUBVgFXAVgBWQFaAVsBXAFdAV4BXwFgAWEBYgFjAWQBZQFmAWcBaAFpAWoBawFsAW0BbgFvAXABcQFyAXMBdAF1AXYBdwF4AXkBegF7AXwBfQF+AX8A 133 \@.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.[.\\.].^._.`.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.{.|.}.~.\127 +# bytes-1c +AYABgQGCAYMBhAGFAYYBhwGIAYkBigGLAYwBjQGOAY8BkAGRAZIBkwGUAZUBlgGXAZgBmQGaAZsBnAGdAZ4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8A 0 129 AYABgQGCAYMBhAGFAYYBhwGIAYkBigGLAYwBjQGOAY8BkAGRAZIBkwGUAZUBlgGXAZgBmQGaAZsBnAGdAZ4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8A 320 \128.\129.\130.\131.\132.\133.\134.\135.\136.\137.\138.\139.\140.\141.\142.\143.\144.\145.\146.\147.\148.\149.\150.\151.\152.\153.\154.\155.\156.\157.\158.\159.\160.\161.\162.\163.\164.\165.\166.\167.\168.\169.\170.\171.\172.\173.\174.\175.\176.\177.\178.\179.\180.\181.\182.\183.\184.\185.\186.\187.\188.\189.\190.\191 +# bytes-1d +AcABwQHCAcMBxAHFAcYBxwHIAckBygHLAcwBzQHOAc8B0AHRAdIB0wHUAdUB1gHXAdgB2QHaAdsB3AHdAd4B3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QH+Af8A 0 129 AcABwQHCAcMBxAHFAcYBxwHIAckBygHLAcwBzQHOAc8B0AHRAdIB0wHUAdUB1gHXAdgB2QHaAdsB3AHdAd4B3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QH+Af8A 320 \192.\193.\194.\195.\196.\197.\198.\199.\200.\201.\202.\203.\204.\205.\206.\207.\208.\209.\210.\211.\212.\213.\214.\215.\216.\217.\218.\219.\220.\221.\222.\223.\224.\225.\226.\227.\228.\229.\230.\231.\232.\233.\234.\235.\236.\237.\238.\239.\240.\241.\242.\243.\244.\245.\246.\247.\248.\249.\250.\251.\252.\253.\254.\255 +# bytes-4 +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaWwRcXV5fBGBhYmMEZGVmZwRoaWprBGxtbm8EcHFycwR0dXZ3BHh5ensEfH1+fwSAgYKDBISFhocEiImKiwSMjY6PBJCRkpMElJWWlwSYmZqbBJydnp8EoKGiowSkpaanBKipqqsErK2urwSwsbKzBLS1trcEuLm6uwS8vb6/BMDBwsMExMXGxwTIycrLBMzNzs8E0NHS0wTU1dbXBNjZ2tsE3N3e3wTg4eLjBOTl5ucE6Onq6wTs7e7vBPDx8vME9PX29wT4+fr7BPz9/v8A 0 -1 +# bytes-4a +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 185 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +# bytes-4b +BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8A 0 81 BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8A 85 \@ABC.DEFG.HIJK.LMNO.PQRS.TUVW.XYZ[.\\]^_.`abc.defg.hijk.lmno.pqrs.tuvw.xyz{.|}~\127 +# bytes-4c +BICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUlZaXBJiZmpsEnJ2enwSgoaKjBKSlpqcEqKmqqwSsra6vBLCxsrMEtLW2twS4ubq7BLy9vr8A 0 81 BICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUlZaXBJiZmpsEnJ2enwSgoaKjBKSlpqcEqKmqqwSsra6vBLCxsrMEtLW2twS4ubq7BLy9vr8A 272 \128\129\130\131.\132\133\134\135.\136\137\138\139.\140\141\142\143.\144\145\146\147.\148\149\150\151.\152\153\154\155.\156\157\158\159.\160\161\162\163.\164\165\166\167.\168\169\170\171.\172\173\174\175.\176\177\178\179.\180\181\182\183.\184\185\186\187.\188\189\190\191 +# bytes-4d +BMDBwsMExMXGxwTIycrLBMzNzs8E0NHS0wTU1dbXBNjZ2tsE3N3e3wTg4eLjBOTl5ucE6Onq6wTs7e7vBPDx8vME9PX29wT4+fr7BPz9/v8A 0 81 BMDBwsMExMXGxwTIycrLBMzNzs8E0NHS0wTU1dbXBNjZ2tsE3N3e3wTg4eLjBOTl5ucE6Onq6wTs7e7vBPDx8vME9PX29wT4+fr7BPz9/v8A 272 \192\193\194\195.\196\197\198\199.\200\201\202\203.\204\205\206\207.\208\209\210\211.\212\213\214\215.\216\217\218\219.\220\221\222\223.\224\225\226\227.\228\229\230\231.\232\233\234\235.\236\237\238\239.\240\241\242\243.\244\245\246\247.\248\249\250\251.\252\253\254\255 +# bytes-63 +PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0/fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8P72+v8DBwsPExcbHyMnKy8zNzs/Q0dLT1NXW19jZ2tvc3d7f4OHi4+Tl5ufo6err7O3u7/Dx8vP09fb3+Pn6+wT8/f7/AA== 0 -1 +# bytes-63a +PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9PgE/AA== 0 67 PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9PgE/AA== 171 \000\001\002\003\004\005\006\007\008\009\010\011\012\013\014\015\016\017\018\019\020\021\022\023\024\025\026\027\028\029\030\031\032!\"#\$%&'\(\)*+,-\./0123456789:\;<=>.? +# bytes-63b +P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fgF/AA== 0 67 P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fgF/AA== 71 \@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.\127 +# bytes-63c +P4CBgoOEhYaHiImKi4yNjo+QkZKTlJWWl5iZmpucnZ6foKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vgG/AA== 0 67 P4CBgoOEhYaHiImKi4yNjo+QkZKTlJWWl5iZmpucnZ6foKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vgG/AA== 258 \128\129\130\131\132\133\134\135\136\137\138\139\140\141\142\143\144\145\146\147\148\149\150\151\152\153\154\155\156\157\158\159\160\161\162\163\164\165\166\167\168\169\170\171\172\173\174\175\176\177\178\179\180\181\182\183\184\185\186\187\188\189\190.\191 +# bytes-63d +P8DBwsPExcbHyMnKy8zNzs/Q0dLT1NXW19jZ2tvc3d7f4OHi4+Tl5ufo6err7O3u7/Dx8vP09fb3+Pn6+/z9/gH/AA== 0 67 P8DBwsPExcbHyMnKy8zNzs/Q0dLT1NXW19jZ2tvc3d7f4OHi4+Tl5ufo6err7O3u7/Dx8vP09fb3+Pn6+/z9/gH/AA== 258 \192\193\194\195\196\197\198\199\200\201\202\203\204\205\206\207\208\209\210\211\212\213\214\215\216\217\218\219\220\221\222\223\224\225\226\227\228\229\230\231\232\233\234\235\236\237\238\239\240\241\242\243\244\245\246\247\248\249\250\251\252\253\254.\255 +# compression-loop +wAA= 0 -1 +# compression-loop-2 +wALAAA== 0 -1 +# empty +- 0 -1 +# root +AA== 0 1 AA== 2 . +# truncated-compression +wA== 0 -1 +# www +A3d3dwA= 0 5 A3d3dwA= 4 www +# www-truncated +A3d3dw== 0 -1 +# www-truncated-2 +A3d3 0 -1 +# www.example.com +5jrGq8kVxMt3ZS3RA3d3dwdleGFtcGxlA2NvbQA= 12 17 A3d3dwdleGFtcGxlA2NvbQA= 16 www.example.com +# www.example.com-answer +5jrGq8kVxMt3ZS3RA3d3dwdleGFtcGxlA2NvbQAAAQABwAw= 33 2 A3d3dwdleGFtcGxlA2NvbQA= 16 www.example.com +# www.example.com-answer-truncated +5jrGq8kVxMt3ZS3RA3d3dwdleGFtcGxlA2NvbQAAAQABwA== 33 -1 +# www.example.com-truncated +5jrGq8kVxMt3ZS3RA3d3dwdleGFtcGw= 12 -1 +# www1.example.com-answer +5jrGq8kVxMt3ZS3RA3d3dwdleGFtcGxlA2NvbQAAAQABBHd3dzHAEA== 33 7 BHd3dzEHZXhhbXBsZQNjb20A 17 www1.example.com + +# Then test cases derived from the above by American Fuzzy Lop (AFL). +BAABAgMEBAUGBwQICQoLAAwN 0 16 BAABAgMEBAUGBwQICQoLAA== 51 \000\001\002\003.\004\005\006\007.\008\009\010\011 +PwABAgMEBQYHCAmztLUAABYXGBmInAoLDA0ODyQRNDU2NwE5Ojs8PT4/PwkKCwwNDg8kSwoLDA0ODyQpKSkpKSkpPT4/VTAxMjM0NDY3AYeLjCspCSkpKSkpKSkpKSkpZCcoKSorLC0uPD0+Pz9AQUJDREVGLzAxMjM0NDY3AYoEAKytrq8= 0 -1 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2ADwBAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2ADwBAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAA 618 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000<\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\000\001X+66666vvvvvv\@\@\@\000\000 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AA8BAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AA8BAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAA 621 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\015\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\000\001X+66666vvvvvv\@\@\@\000\000 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjbJNjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAAAQAb 0 -1 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NskAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NskAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAA 624 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.6\201\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\000\001X+66666vvvvvv\@\@\@\000\000 +BAABAgMEBAUGBwQICQoLBBINDg8QAAAAEwQUFRYXBBgZGhsEHB0eNjY2AAA2NjY2Njw2ATYYNkUAAAIQ//9/TExMTExMTExMTExMTExMTExMTExMTENMTBMTExNqEykTlhMTEyYLAAEUFAAABjY2NjYAAAE2NhwAAAABAAABBDb/fwAAAzY2NgX//wU2NgD7SDYkNjk5OTk5OTk5OTk5OTk5OTk5OTk5PTY0pDY2NjY2NiQAAAE2Nn82cXZ2dnZ2dnZ20Coq0DPQ0P/QM9DQ//9//9AAAAHSu9DRkNAABgAA/xQUAAAGfzYkNjY0Nks2AAQeVTb/AAABNn////8= 0 -1 +BAABAgMEBAUGBwQICQoLBBINDg8EAAAQAAQUFRYXBBgZGhsEHB0eNjY2AAA2NjY2Njw2ATYYNkUAAAIQ//9/TExMTExMTExMTExMTExMTExMTExMTENMTBMTExNqEykTlhMTEyYLAAEUFAAABjY2NjYAAAE2NhwAAAABAAABBDb/fwAAAzY2NgX//wU2NgD7SDYkNjk5OTk5OTk5OTk5OTk5OTk5OTk5PTY0pDY2NjY2NiQAAAE2Nn82cXZ2dnZ2dnZ20Coq0DPQ0P/QM9DQ//9//9AAAAHSu9DRkNAABgAA/xQUAAAGfzYkNjY0Nks2AAQeVTb/AAABNn////8= 0 -1 +AgIhIiMEJCUkAScBKAEpASoBKwEsAS0BLgExATgBOQE6IDsBASoBKwEsAS0BLgE3ATgBOQE6IDsBPAE9AT4BPw0BDgEPARABEQESARMBFAEBDgEPARABEQESARMBFCEhISEhISEhISEhISEhIX4hISEhISEhISEhARcFGAEZARoBGwEcAR0BASYBJwEoASkBKjwBPQE+AT8NAQ4BDwEQAREBEgETARQBFwUYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBAAACQCsBLAEtAS4BJwEoAUgBKgErASwBLQEuATsBPAE9AT4BPwA= 0 242 AgIhIiMEJCUkAScBKAEpASoBKwEsAS0BLgExATgBOQE6IDsBASoBKwEsAS0BLgE3ATgBOQE6IDsBPAE9AT4BPw0BDgEPARABEQESARMBFAEBDgEPARABEQESARMBFCEhISEhISEhISEhISEhIX4hISEhISEhISEhARcFGAEZARoBGwEcAR0BASYBJwEoASkBKjwBPQE+AT8NAQ4BDwEQAREBEgETARQBFwUYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBAAACQCsBLAEtAS4BJwEoAUgBKgErASwBLQEuATsBPAE9AT4BPwA= 607 \002!.#\004\$%\$\001'\001\(\001\)\001*\001+\001,\001-\001\.\0011\0018\0019\001:\032\;\001\001*.+.,.-.\..7.8.9.:.\;\001<\001=\001>\001?\013\001\014\001\015\001\016\001\017\001\018\001\019\001\020\001\001\014\001\015\001\016\001.\001\018\001\019\001\020!!!!!!!!!!!.!!!~!!!!!!!!!!\001\023\005\024\001\025\001\026\001\027\001\028\001\029\001\001&\001'.\(.\).*.\001=\001>\001?\013\001\014\001\015\001\016\001\017\001\018\001\019\001\020\001\023\005\024\001\025\001\026\001\027\001\028\001\029\001\030\001\031\001\032\001!\001\"\001#\001\$\001%\001&\001'\001\(\001\000\000.\@+.,.-.\..'.\(.H.*.+.,.-.\..\;.<.=.>.? +wMAAAcDAwMDAQAA2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2iTY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAUYUwB82Nn7s7OzsEBQUDDY2NgAAATY2NjZYNjYyNk02NlEAEQEANjYABf//BUU2OTY2NiU9PT09NgAAAfI//3Y2AAABNjY0NgAAAYA2PRAA+/v7+/v7+/v///8= 16 -1 +AwAAJ8AAISEhISEhISEhISEhISEhfiEhISEhISEhISG7u5CjAA== 0 -1 +AhIAAlBINQAAATU1FTo/SEhIAwMDAwMFRTY5NgA2JT09PQEfNjY8NjYkFTY0NjYyNjY2NjYADDY2QksAAAEBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgD//gABNjY2PDY2JBUAfg== 68 -1 +AQQBAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAFdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4ASEhISEhISEhISEhISEhIX4hISEhISEhISEhuQG6AbsBvAG9Ab4BvwHAAdwBwgHDAcQBxQHGAQ0BDgEPARABEQESARMBFAEVARYBFwEYARkBGiEhuQG6AbsBvAG9Ab4BvwHAAdwBwgHDAcQBxQHGAQ3xDQEPARABEQESARMBFAEVARYBFwEYARkBGgEbARwBXQEeAZ8BoAGhAaIBowGkAaUBpgGnAagBqQGqAasBrAGtAa4BrwGwAbEBsgGzAbQBtQG2AbcBuAEhISEBqgGrAawBrQGuAa8BsAGxASEhISEhISEhISEhISEhISEhISEhIX4hISEhISEhISEhEhISEhISEhISAAABEhISEhISEhICAgICAgICAgICAgICIssBzAHNAc4BzwHQAdEB0gHTAdQB1QHWASPHAcgByf9/AAABzAHNAc4BzwHQAdEB0gHTg9QB1QHWARISEhISEhISEhISEhISEhIREhISEhISEhISEgAAAH8SAAABEhISEhISEhICAgICAgICAgICAgICIssBzAHNAc4BzwHQAdEB0gHTAdQB1QHWASMELyTrJwQIKSsrACw= 0 -1 +AQA= 0 -1 +AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHcAd0V3gHfAeAB4QHiAc8B0AHRAdIB0wHUAdUB1gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QD+ 0 -1 +AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHcAd0B3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9Af4B/wA= 0 -1 +BOgDAwgINjY2NjY2NjY2NjY2NjY2NjY2NgAAASY2NjY2NjZAAAAANjY2NjY2NgAAAAE2NjY2NjY2NjY2Ng82NjY2NjY2NjYhNis2RhQ2Nv9///82NjY2NjY2NjY2Nlc2QDY2NjYAAAE2NiM2NjY2NoE2NjY2Np5CPAAhNhM2NjY2NjY2Np42PAAYNhM2NjY2NjY2NgA2NjY2NjY2NjY2NvA2tzY2NjY2NjY2NjY2NjY2NjY2NjY2Njk2NjYxNjY2NjY2Nv9/NjY2NhY2NjY2NgAAATY2NjY2NjaeNjwAGDY2NjY2NjY2FDYAgAAANgAAATY2NjY2NjY2NjYBNgAAATY2 0 255 BOgDAwgINjY2NjY2NjY2NjY2NjY2NjY2NgAAASY2NjY2NjZAAAAANjY2NjY2NgAAAAE2NjY2NjY2NjY2Ng82NjY2NjY2NjYhNis2RhQ2Nv9///82NjY2NjY2NjY2Nlc2QDY2NjYAAAE2NiM2NjY2NoE2NjY2Np5CPAAhNhM2NjY2NjY2Np42PAAYNhM2NjY2NjY2NgA2NjY2NjY2NjY2NvA2tzY2NjY2NjY2NjY2NjY2NjY2NjY2Njk2NjYxNjY2NjY2Nv9/NjY2NhY2NjY2NgAAATY2NjY2NjaeNjwAGDY2NjY2NjY2FDYAgAAANgAAATY2NjY2NjY2NjYBNgAA 412 \232\003\003\008.66666666.6666666666\000\000\001&666666\@\000\000\0006666666\000\000\000\00166666666666\0156666666.6!6+6F\02066\255\127\255\25566666666666W6\@6666\000\000\00166#66666\12966666\158B<\000!6.66666666\1586<\000\0246\0196666.666\00066666666666\2406\183666666666666666666666966616666666\255\1276.66\02266666\000\000\0016666666\1586<\000\02466666666\0206\000\128\000\0006\000\000\0016666666666\0016\000 +AhIAAlBIAABISEhIUz4AAAE1FTU1LTU1LTW2NTU1NQAAATU1FTo/SEhISEhISEhISEhISEhISEhISEhISAABAABISCZIUw== 68 -1 +AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgE3ATgBOQE6ATsBPAE9AT4BPwA= 0 113 AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgE3ATgBOQE6ATsBPAE9AT4BPwA= 217 \000.\001.\002.\003.\004.\005.\006.\007.\008.\009.\010.\011.\012.\013.\014.\015.\016.\017.\018.\019.\020.\021.\022.\023.\024.\025.\026.\027.\028.\029.\030.\031.\032.!.\".#.\$.%.&.'.\(.\).*.+.,.-.\..7.8.9.:.\;.<.=.>.? +BOgAAAEDAwgINjY2NgAAAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2NDZYBAX//wU2NjY0NgAAAQAAAYA2NhY2Njbn0NDQ0NDQ0NA2NjY2NjY2NjY2NgAAAAEENjY2NjY2NjY2NjY2NgAAAAEAG0tsS0tLS0tLSwE2vh9GFDY2NjYAADY2JDY2NDY2NjY2NjY2NjY2NjY2NjY2JDY2f3Z2dnZ2dnZ2dnZ2dnZ2dkE2ATYeBAX//wU2NjY0NgAACQAAAYA2NhY2NjbQ0NDQ0NDQ0NAz0NDQ0NDQ0NDQ0NCQ0AAUFAAAARQUNjY2NjY2Nlg2NjY2TSE2UQARAQAAATY2 0 255 BOgAAAEDAwgINjY2NgAAAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2NDZYBAX//wU2NjY0NgAAAQAAAYA2NhY2Njbn0NDQ0NDQ0NA2NjY2NjY2NjY2NgAAAAEENjY2NjY2NjY2NjY2NgAAAAEAG0tsS0tLS0tLSwE2vh9GFDY2NjYAADY2JDY2NDY2NjY2NjY2NjY2NjY2NjY2JDY2f3Z2dnZ2dnZ2dnZ2dnZ2dkE2ATYeBAX//wU2NjY0NgAACQAAAYA2NhY2NjbQ0NDQ0NDQ0NAz0NDQ0NDQ0NDQ0NCQ0AAUFAAAARQUNjY2NjY2Nlg2NjY2TSE2UQARAQAA 572 \232\000\000\001.\003\008\008.666\000\000\000\192\0316\128\00066\$\021666\0216\000\004666666666646X\004\005\255\255\00566646\000\000\001\000\000\001\12866.666\231\208\208\208\208\208\208\208\2086666666666.\000\000\000\001\0046666666666666\000\000\000\001\000\027KlKKKKKKK\0016\190\031F\0206666\000\00066\$664666.6666666666666\$66\127vvvvvvvvvvvvvvvA6\0016\030\004\005\255\255\00566646\000\000\009\000\000\001\128.6\022666\208\208\208\208\208\208\208\208\2083\208\208\208\208\208\208\208\208\208\208\208\144\208\000\020\020\000\000\001\020\0206666666X6666M!6Q\000\017.\000 +AQABAwEJAQoYARkBGmwbARwHGgEeAc0BAAAB0AAAA+gB0w== 0 -1 +AUABQwFEAUUBRgFPAVABUQFSAVMBVAFVAVYBVwFYAVkBWgFbAVwBXwFgAWEBYgFjAWQBZQFmAWcBaAFpAWoBawFsAW0BbgFvAXABcQFyAXMBdAF1AXYBdwF4AXkBegF7AXwBfQF+AX8A 0 105 AUABQwFEAUUBRgFPAVABUQFSAVMBVAFVAVYBVwFYAVkBWgFbAVwBXwFgAWEBYgFjAWQBZQFmAWcBaAFpAWoBawFsAW0BbgFvAXABcQFyAXMBdAF1AXYBdwF4AXkBegF7AXwBfQF+AX8A 109 \@.C.D.E.F.O.P.Q.R.S.T.U.V.W.X.Y.Z.[.\\._.`.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.{.|.}.~.\127 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAA 618 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\1276X+66666vvvvvvvv\255\011\000 +AYABnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+ 0 -1 +BOgAAAEDAwgINjY2NgAAAMAfNjZkAAAAAAEAFPY2HjY2NDYMAAEABAEAAAE2NgAAATb7IPvz+/sAAAFCRDYkDzI0NjY2NjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTY2FTYABDk2NgAAATY2NjY2Nhw0NlgAIDY2/zY+NjY2NjYAADYAAPs2DAEAAAH0wB82NjY2 0 146 BOgAAAEDAwgINjY2NgAAAMAfNjZkAAAAAAEAFPY2HjY2NDYMAAEABAEAAAE2NgAAATb7IPvz+/sAAAFCRDYkDzI0NjY2NjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTY2FTYABDk2NgAAATY2NjY2Nhw0NlgAIDY2/zY+NjY2NjYAADYAAPs2DAEAAAH0NjY0NgwAAQAEAQAAATY2AAABNvsg+/P7+wAAAUJENiQPMjQ2NjY2NjY2NgAQNjY2WDY2NjY2NjY2AAABAAE2NjZFNjYVNgAEOTY2AAABNjY2NjY2HDQ2WAAgNjb/Nj42NjY2NgAANgAA+zYMAQAA 607 \232\000\000\001.\003\008\008.666\000\000\000\192\03166d\000\000\000\000\001\000\020\2466\0306646\012\000\001\000\004\001\000\000\00166\000\000\0016\251\032\251\243\251\251\000\000\001BD6\$\015.466666666\000\016666X66666666\000\000\001\000\001666E66\0216\000\004966\000\000\001666666.46X\000\03266\2556>66666\000\0006\000\000\2516\012\001\000\000\001\244.646\012\000\001\000\004\001\000\000\00166\000\000\0016\251\032\251\243\251\251\000\000\001BD6\$\0152466666666\000\016666X666666.6\000\000\001\000\001666E66\0216\000\004966\000\000\001666666\02846X\000\03266\2556>66666\000\0006\000\000\2516\012\001\000 +AcAB3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QH+ 0 -1 +BOgAAAENAwgINjY2NgAAAMAfNjY2NjY2NgAQNjY2WDY2NjY2NjY2APP2FgE2NjZFNjYVNgAENjY2NjY2NjY2NjQ2WDY2NjY2NiUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlNjY2NjY2NjYAAAABBB82NgAAATY2NiQVNjQ2NjY2NjY2NjY2NjY2NgAAAAEENgAAATY2NjY2NgAAATY2NjY2NjY2AAAAAQQ2NjY2NjY2NjY2NjY2AAAAAQAbS2xLS0tLS0tLATa+HQABNjY2AFA2NiQgNjQ2NjY2NlE2NjY2NjY2NjY2Nho2Nn92dnZ2dpZ2dnZ2dkE2AQAAAQAAARY2 0 255 BOgAAAENAwgINjY2NgAAAMAfNjY2NjY2NgAQNjY2WDY2NjY2NjY2APP2FgE2NjZFNjYVNgAENjY2NjY2NjY2NjQ2WDY2NjY2NiUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlNjY2NjY2NjYAAAABBB82NgAAATY2NiQVNjQ2NjY2NjY2NjY2NjY2NgAAAAEENgAAATY2NjY2NgAAATY2NjY2NjY2AAAAAQQ2NjY2NjY2NjY2NjY2AAAAAQAbS2xLS0tLS0tLATa+HQABNjY2AFA2NiQgNjQ2NjY2NlE2NjY2NjY2NjY2Nho2Nn92dnZ2dpZ2dnZ2dkE2AQAAAQAA 460 \232\000\000\001.\003\008\0086666\000\000\000\192\0316.66666\000\016666X66666666\000\243\246\022\001666E66\0216\000\004666666666646X666666%.%%%%%%%%%%%%%%%%%%%%%%%%66666666\000\000\000\001\004.66\000\000\001666\$\0216466666666666666\000\000\000\001\004.\000\000\001666666\000\000\00166666666\000\000\000\001\0046666666666666\000\000\000\001\000\027KlKKKKKKK\001.\190\029\000\001666\000P66\$\0326466666Q66666666666\02666\127vvvvv\150vvvvvA6\001\000\000\001\000 +BAABAgMEERITBBQVFhceHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaWwRcXV5fBGBhYmMEZGVmZwRoaWprBGxtbm8EcHFycwR0dXZ3BHh5ensEfH1+fwSAgYKDBISFhocEiImKiwSMjY6PBJCRkpMElJWWlwSYmZqbBJydnp8EoKGiowQ= 0 -1 +BOgAAAEDAwgIFjY2NgAAAMAfNjY2NjYkFTY0NjY2NjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTY2FTYABDY2NjY2NjY2NjY0Nlg2NjY2NjY2NgAAATY2NgAAAADAHzY2NjY2JAkJCf9/CQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkVNjQ2NjY2NjY2NjY2NjY2NgAAAAEENjY2NjY2NjY2NjY2NgAAAAEAG0tsS0tLS0tLSwE2vh9GFDY2NjYAADY2JDY2NDY2NjY2NjY2NjY2NjY2NiQ2Nn92dnZ2dnZ2dnZ2dnZ2dnZBNgE2HgQAQP82NjY2NDYAAAEAAAGA 0 255 BOgAAAEDAwgIFjY2NgAAAMAfNjY2NjYkFTY0NjY2NjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTY2FTYABDY2NjY2NjY2NjY0Nlg2NjY2NjY2NgAAATY2NgAAAADAHzY2NjY2JAkJCf9/CQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkVNjQ2NjY2NjY2NjY2NjY2NgAAAAEENjY2NjY2NjY2NjY2NgAAAAEAG0tsS0tLS0tLSwE2vh9GFDY2NjYAADY2JDY2NDY2NjY2NjY2NjY2NjY2NiQ2Nn92dnZ2dnZ2dnZ2dnZ2dnZBNgE2HgQAQP82NjY2NDYAAAEA 526 \232\000\000\001.\003\008\008.666\000\000\000\192\03166666\$\0216466666.66\000\016666X66666666\000\000\001\000\001666E66\0216\000\004666666666646X66666666\000\000.6.6\000\000\000\000\192\03166666\$\009\009\009\255\127\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\021646666666.666666\000\000\000\001\0046666666666666\000\000\000\001\000\027KlKKKKKKK\0016\190\031F\0206666\000\00066\$.64666666666666666\$66\127vvvvvvvvvvvvvvvA6\0016\030\004\000\@\255666646\000\000\001 +AQABBwEIAQkBCgELAQwBZAEOAegB6QHqAesB7AHtAe4B7wHwAfEB8gHzAfQB9QH2AfcB+AH5AfoB+wH8Af0B/gH/AA== 0 67 AQABBwEIAQkBCgELAQwBZAEOAegB6QHqAesB7AHtAe4B7wHwAfEB8gHzAfQB9QH2AfcB+AH5AfoB+wH8Af0B/gH/AA== 162 \000.\007.\008.\009.\010.\011.\012.d.\014.\232.\233.\234.\235.\236.\237.\238.\239.\240.\241.\242.\243.\244.\245.\246.\247.\248.\249.\250.\251.\252.\253.\254.\255 +AQAB3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QFAAP8A 0 67 AQAB3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QFAAA== 163 \000.\223.\224.\225.\226.\227.\228.\229.\230.\231.\232.\233.\234.\235.\236.\237.\238.\239.\240.\241.\242.\243.\244.\245.\246.\247.\248.\249.\250.\251.\252.\253.\@ +AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGAEVFhcEGDoaGwQLHR4fDTUpIhkEJDoaGwQUIx4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CAjsA 0 255 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGAEVFhcEGDoaGwQLHR4fDTUpIhkEJDoaGwQUIx4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CAjsA 781 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\004\008\002\002\002\002.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\001\021\022\023\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$.\026\027\004\020#\030\031&5\)\"\025\004\$\$\000\000\002\000\@\002\016\"\002\016\@\002\016\"\002\016\"\002\016\@\002\016\"\002\016\031\004\032\)\"#\004\$\$\000\000\002\000\@\002\016\"\002.\@\002\016\"\002\016\"\006\004\008\002\@\002\002\002\254.\002\; +YcAAAcDAwA3AAQAQFBQMNjY2AAABNjY2Hlg2NjY2PzY2UQARAQA2NktLS0sBFrsfRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PAFLATa+H0YUwB82Nn7s7OwAAAEB7OHsFAD/ADY0NjYyNjY2NjY9PT0BNjY2AAAAAQA2NDY2MjInNhgYGBgYGBgYGBgYGBgYGBgYGBgYGBg2NgAQNjYAEDY2AAABQAAAAQAAAUsBNr4fRgEAHzY2fuzs7AAAAQHs4ewUNrY2NgAdNjQ2NjZBNj42NjY2NjY2TtDQ0JDQABQUFBS2NjU2Njo2WDY2NjYAAAHQ0DPQ0NDQ0NDQ0ND///8BABAUFAw2NjYAAAE2Ng== 16 255 NjYAAAE2NjYeWDY2NjY/NjZRABEBADY2S0tLSwEWux9GFDY2NjYAADY2WDZ2PDY2NjY2AAABAAE2NjY8AUsBNr4fRhTAHzY2fuzs7AAAAQHs4ewUAP8ANjQ2NjI2NjY2Nj09PQE2NjYAAAABADY0NjYyMic2GBgYGBgYGBgYGBgYGBgYGBgYGBgYGDY2ABA2NgAQNjYAAAFAAAABAAABSwE2vh9GAQAfNjZ+7OzsAAABAezh7BQ2tjY2AB02NDY2NkE2PjY2NjY2NjZO0NDQkNAAFBQUFLY2NTY2OjZYNjY2NgAAAdDQM9DQ0NDQ0NDQ0P///wEAEBQUDDY2NgAA 660 6\000\000\001666\030X6666?66Q\000\017\001\00066KKKK\001\022\187\031F\0206666\000\00066X6v<66666\000\000\001\000.6.6<\001K\0016\190\031F\020\192\03166~\236\236\236\000\000\001\001\236\225\236\020\000\255\0006466266666===\001666\000\000\000\001\000646.22'6\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\02466\000\01666\000\01666\000\000\001\@\000\000\001\000\000\001K\0016\190\031F\001\000.66~\236\236\236\000\000\001\001\236\225\236\0206\18266\000\02964666A6>666.666N\208\208\208\144\208\000\020\020\020\020\1826566:6X6666\000\000\001\208\2083\208\208\208\208\208\208\208\208\208\255\255\255\001\000\016\020\020\012666\000 +PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0/fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8P70= 0 -1 +AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIPAgKAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISJBISAEASEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhICAgICAgICAgICAgICIiMELyTrJwQIKSorACw= 2 239 AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDwICgAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEiQSEgBAEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISAgICAgICAgICAgICAiIjBC8k6ycECCkqKwA= 786 \002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002\128\002\002\002\002\002\002\002\002\002\002\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018.\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\$\018.\000\@\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018.\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018.\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\002\002\002.\002\002.\002\002.\002\002.\"#./\$\235'.\008\)*+ +PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9PgE/ 0 -1 +AQAh5ifGs8kVxMsAAAHRAAABdwdle2FtcGxlA2NvbQAAGgABBHd3dzHAEA== 0 -1 +P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fgF/ 0 -1 +wMAAAcDgwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0s2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BHzY2PDY2JBU2NDY2MjY2NjY2AAw2NktLAAABARa+H0YUNjY2NgAANjZYNnY8NjY2NjYAAP4AATY2Njw2NiQVNgSzNqI2NjY2NgX//wVFNjk2PjYlPT09ATY2NgAAAAEANjQ2NjI2NjY2NgAQNjZLS0tAAAABSwE2vh9GFMAfNi5+7Ozs7AAAAezs7BQ2NjY2AAAAAAE2NjQ2NjZBNj42NjY2NjY2TtDQ0JDQABQUFBQ2NjU2NkM2WDY2NjZNNjZRABEBAA== 16 2 NjY2NgAQNjZLSzY2WDZ2PDY2NjY2AAABAAE2NjY8NjYkFTYEszaiNjY2NjYF//8FRTY5Nj42JT09PQEfNjY8NjYkFTY0NjYyNjY2NjYADDY2S0sAAAEBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAA/gABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Ln7s7OzsAAAB7OzsFDY2NjYAAAAAATY2NDY2NkE2PjY2NjY2NjZO0NDQkNAAFBQUFDY2NTY2QzZYNjY2Nk02NlEAEQEA 523 666\000\01666KK66X6v<66666\000\000\001\000\001666<66\$\0216\004\1796\16266666\005\255\255\005E696>6%.==\001\03166<66\$\0216466266666\000\01266KK\000\000\001\001\022\190\031F\0206666\000\00066X6v<66666\000\000\254\000\001666.66\$\0216\004\1796\16266666\005\255\255\005E696>6%===\001666\000\000\000\001\0006466266666\000\01666KKK\@\000\000\001K\001.\190\031F\020\192\0316\.~\236\236\236\236\000\000\001\236\236\236\0206666\000\000\000\000\001664666A6>6666666N\208\208\208\144\208\000\020\020.\02066566C6X6666M66Q\000\017\001 +P4CBgoOEhYaHiImKi4yNjo+QkZKTlJWWl5iZmpucnZ6foKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vgG/ 0 -1 +P8DBwsPExcbHyMnKy8zNzs/Q0dLT1NXW19jZ2tvc3d7f4OHi4+Tl5ufo6err7O3u7/Dx8vP09fb3+Pn6+/z9/gH/ 0 -1 +A3c= 0 -1 +5jrGq8kVxMt3ZS3RA3d3dwdl 12 -1 +BAALBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9 64 -1 +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0rBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0= 32 -1 +BAAEBQYHBAgJCgsEDA0ODwQQFBUWFysELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PQ== 16 -1 +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 8 73 BgcECAkKCwQMDQ4PBBAREhMEFBUWFwQYGRobBBwdHh8EICEiIwQkJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/AA== 159 \007\004\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +hAA= 0 -1 +JAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2Nw== 0 -1 +FAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCsELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PQ== 0 -1 +DAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 DAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 224 \000\001\002\003\004\004\005\006\007\004\008\009.\011\004\012\013\014\015\004\016\017\018.\004\020\021\022\023\004\024\025\026\027\004\028\029\030\031\004\032!\".\004\$%&'\004\(\)*+\004,-\./\0040123\0044567\00489:\;\004<=>? +BgABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BgABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 221 \000\001\002\003\004\004.\006\007\004\008\009.\011\004\012\013\014\015\004\016\017\018.\004\020\021\022\023\004\024\025\026\027\004\028\029\030\031\004\032!\".\004\$%&'\004\(\)*+\004,-\./\0040123\0044567\00489:\;\004<=>? +BQABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BQABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 188 \000\001\002\003\004.\005\006\007\004.\009\010\011\004\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +BEABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BEABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 183 \@\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +BABBAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BABBAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 182 \000A\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +BAAhAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAAhAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 182 \000!\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +BAABIgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABIgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 183 \000\001\"\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +BAABAgMUBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXGwQcHR4fBCAhIiMEJCUmJwQoKSo= 0 -1 +BAABAgMMBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMMBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 209 \000\001\002\003.\004\005\006\007\004\008\009\010\011\004\012\013.\015\004\016\017\018\019\004\020\021\022\023\004\024\025.\027\004\028\029\030\031\004\032!\"#\004\$%&'\004\(\)*+\004,-\./.0123.4567.89:\;.<=>? +BAABAgMA 0 6 BAABAgMA 17 \000\001\002\003 +BAABAgMEAAgJCg== 0 -1 +BAABAgMEBAUGBwYICQoLBAwNDg8EEAQYGRobBBwdHh8EICEiIwQrBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwA= 0 -1 +BAABAgMEBAUGBwQIKQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQIKQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 183 \000\001\002\003.\004\005\006\007.\008\)\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +BAABAgMEBAUGBwQICQoLFAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQICQoLFAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 209 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015\004\016\017\018\019\004\020\021\022\023\004\024\025\026\027\004.\029\030\031\004\032!\"#\004\$%&'\004\(\)*+\004,-\./\0040123.4567.89:\;.<=>? +BAABAgMEBAUGBwQICQoLBAwNDg8AEA== 0 21 BAABAgMEBAUGBwQICQoLBAwNDg8A 68 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015 +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBRgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBRgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 200 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027\004.\029\030\031\004\032!\"#\004\$%&'\004\(\)*+\004,-\./\0040123.4567.89:\;.<=>? +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGjsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGjsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 183 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\;.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgIaIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgIaIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 187 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\162#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjJA== 0 -1 +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjAA== 0 46 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjAA== 145 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"# +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgJCUmJw== 0 -1 +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwAsLQ== 0 56 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwA= 158 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+ +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBA== 0 -1 +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vADA= 0 61 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vAA== 164 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./ +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMA 0 66 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMA 169 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123 +BAABAgMEBAUGBwQICQoLBAwNDg8EEAQYGRobBBwdHh8EICEiIwQkJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwY8PQ== 0 -1 +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8B 0 -1 +BAAEBQYHBAgJCgsEDA0ODwQQERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwA= 6 71 BAgJCgsEDA0ODwQQERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwA= 151 \008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 3 78 AgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 176 \003\004.\005\006\007\004.\009\010\011\004\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +NAABAgMEBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9 0 -1 +HAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9 0 -1 +CAABAgMEBAUGBwQICQoLBAwNDg8EEAQYGRobBBwdHh8EICEiIwQrBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwA= 0 -1 +AgABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 AgABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 185 \000\001.\003\004.\005\006\007\004.\009\010\011\004\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +BAABAgM0ERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0= 0 -1 +AQABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 AQABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 182 \000.\002.\004\004\005.\007\004\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +BAABAgMmBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMmBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 227 \000\001\002\003.\004\005\006\007\004\008\009\010\011\004\012\013\014\015\004\016\017\018\019\004\020\021\022\023\004\024\025\026\027\004\028\029\030\031\004\032!\".\004\$%&'\004\(\)*+\004,-\./\0040123\0044567\00489:\;\004<=>? +BAQYGRobBBwdHh8EICEiIwQkJSYnBCgpKisELC0uHB0eHwQgISIjBCQlJicEKCkqKwQsLS45BDAxBCAhIiMEJAAB 0 -1 +BAABAgMEDA0ODwQQERITBBQVFhcEGBkaGwQcLx4fBCAhIiMEJCUmJwQoKyorBA== 0 -1 +BAABAiAEBAUGBwQICQoLBAxkAA8EEBEeHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDxvPj8A 0 66 BAABAiAEBAUGBwQICQoLBAxkAA8EEBEeHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDxvPj8A 131 \000\001\002\032.\004\005\006\007.\008\009\010\011.\012d\000\015.\016\017\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<o>? +BAAkdXV1dR0pELsELC0uPBgZGhsEHgkJ2gEBAmQEBAeAABogBCkJCdonBBQVPUAEGBkaGwQpGgAEKAkJ2gQWJRfaGxITBAEVFgBAGCQwGwT5HClHuwQsLS48GBkaGwQpCQnKARKKBJ2dnZ2dnZ2dnRgsLUAEGCwtLgA= 2 -1 +BAABAgMEBEAADQ4PBBAREhMEFBUWFwQYGRobBAQgISIjBA8lJicczx4fBCAhIiMEJCUmLwQwMS8EMDEyMww0NTQ3BDg5GwQmJ/UnNjcEODkyMww0NzY3BDg5GwQmJ/UnNjcEODk6OwQ6OwQ8PT4/AA== 0 112 BAABAgMEBEAADQ4PBBAREhMEFBUWFwQYGRobBAQgISIjBA8lJicczx4fBCAhIiMEJCUmLwQwMS8EMDEyMww0NTQ3BDg5GwQmJ/UnNjcEODkyMww0NzY3BDg5GwQmJ/UnNjcEODk6OwQ6OwQ8PT4/AA== 261 \000\001\002\003.\004\@\000\013.\015\004\016\017\018\019\004\020\021\022\023\004\024\025.\027\004\004\032!\"#\004\015%&'\028\207\030\031\004\032!\"#\004\$%&/.01/\004.123\0124547\00489\027\004&'\245'67\0048923\0124767\00489\027\004&'\245'67\00489:\;\004:\;.<=>? +BAABAgMEBAUiIwQkJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEOAYHBAgJCoAEDA0ODwQQERITBBQFFhcEGBkaGwQcHR4fBKAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwA= 0 110 BAABAgMEBAUiIwQkJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEOAYHBAgJCoAEDA0ODwQQERITBBQFFhcEGBkaGwQcHR4fBKAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwA= 222 \000\001\002\003.\004\005\"#.\$%&'.\(\)*+.,-\./.0123.4567.8\006\007\004.\009\010\128\004\012\013\014\015.\016\017\018\019.\020\005\022\023.\024\025\026\027.\028\029\030\031.\160!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +BCorBCwtLjL79Pv7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+3sEPD0VFhcEGBka0yYMHR4mBCAhIiO0ELS0trTFtLS0tLS09rS0tCsELC0uLQAEAAB/AAA= 4 82 LC0uMvv0+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7ewQ8PRUWFwQYGRrTJgwdHiYEICEiI7QQtLS2tMW0tLS0tLT2tLS0KwQsLS4tAAQAAH8AAA== 270 -\.2\251\244\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251{\004<=\021\022\023\004\024\025\026\211&\012\029.&\004\032!\"#\180\016\180\180\182\180\197\180\180\180\180\180\180\246\180\180\180+\004,-\.-\000.\000\000\127\000 +BAABAh0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dAwQEBQYHBAgJCgsEDP0NDwQQERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJwQoKTY3BDg4OjsEPD0+PwA= 0 98 BAABAh0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dAwQEBQYHBAgJCgsEDP0NDwQQERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJwQoKTY3BDg4OjsEPD0+PwA= 321 \000\001\002\029.\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029.\003\004\004\005\006\007\004\008\009\010\011\004\012\253\013\015\004\016\017\018\019\004\020\021\022\023\004\024\025.\027\004\028\029\030\031\004\032!\"#\004\$%&'\004\(\)67\00488:\;.<=>? +BAABAgMEBAUGBwQAAAEABAwNDhQEEBESEwQUNBYXBAcH5wYHogcHBw0HBwcHBwcAEAcHBwcigDUzNjcEODk6OwQ8UT4/AA== 0 70 BAABAgMEBAUGBwQAAAEABAwNDhQEEBESEwQUNBYXBAcH5wYHogcHBw0HBwcHBwcAEAcHBwcigDUzNjcEODk6OwQ8UT4/AA== 200 \000\001\002\003.\004\005\006\007.\000\000\001\000.\012\013\014\020.\016\017\018\019.\0204\022\023.\007\007\231\006.\162\007\007\007\013\007\007.\007\007\007\000\016\007\007.\007\"\1285367.89:\;.<Q>? +DQ4EAAHlDQQEBQYBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBBAgJAA4PAwAAGRobBCchHB0eHwQgISIjBCQlJiciIwQkJSYnBCj+3vH+/u7+/v7+BCQlJichIiME/h7//t7+3/7+/v7+/v7+/v7+BAg/AA== 0 118 DQ4EAAHlDQQEBQYBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBBAgJAA4PAwAAGRobBCchHB0eHwQgISIjBCQlJiciIwQkJSYnBCj+3vH+/u7+/v7+BCQlJichIiME/h7//t7+3/7+/v7+/v7+/v7+BAg/AA== 354 \014\004\000\001\229\013\004\004\005\006\001\001\001.\001.\001.\001.\001.\001.\001.\001.\001.\001.\001.\001.\001.\004.\009\000\014\015\003\000\000\025.\027\004'!\028\029\030\031\004\032!\"#\004\$%&'\"#\004\$%&'\004.\254\222\241\254\254\238\254\254\254\254\004\$%&'!\"#\004\254\030\255\254\222\254\223\254\254\254\254\254\254\254\254\254\254\254\004\008? +BAAIAgMEBwQsLS4vBC0xCAkKCwQMDQ4PfxA3BDgEAAgCAwQHBDwtLjIzBDQ1NggJCgsEDA0OD38QNwQ/OTotLkYELTEyNggJCgsEDA0OD38QNwQ4BAAIAgMEBwQsLS4vBC0xMjMENDU2CAkKCwQ5OjsEPEg+Pw== 0 -1 +BAABAgMEBAUGBwLrCQoFBgcD6wkKCwQMDQ7//xAREhMEFBUWFwQYGRob 0 -1 +BAAP/wAXBBgZGhsEHB0eHwQOIZgAIvQJ//8WGRcXFxcXFxcXFxwlF/oXICEiEAxAABcXFxcXFxcXFxcX/xcXFxccJQxAABcXFxcXFxcX 0 -1 +DAAB/AMEBAUGBwQICQoLAwxADg8EEBESEwQkJSYnBCgpKisELC1ADg8EBgcECAxADg8TBBQiIwQkJSY5OjsEPD0+ 0 -1 +BH8PEhMEIn4EABD/BCEiIwQkJSYADg8EBEwSEwQiIwQADf8EAXUjBA0ABCIjBAAQ/wQhIiNVDQ4PBgQPEhMEFCMk+gAA+i4AAAADQAAAAC4uLi4uLi5PLi4uLi4uLi4jAAACAAAO 0 101 BH8PEhMEIn4EABD/BCEiIwQkJSYADg8EBEwSEwQiIwQADf8EAXUjBA0ABCIjBAAQ/wQhIiNVDQ4PBgQPEhMEFCMk+gAA+i4AAAADQAAAAC4uLi4uLi5PLi4uLi4uLi4jAAACAAA= 289 \127\015\018\019.\"~\004\000.\255\004!\"#\004\$%&\000\014\015\004\004L\018.\004\"#\004\000\013\255\004\001u#\004\013\000\004\"#\004\000.\255\004!\"#U\013\014\015\006\004\015\018\019\004\020.\$\250\000\000\250\.\000\000\000\003\@\000\000\000\.\.\.\.\.\.\.O\.\.\.\.\.\.\.\.#\000\000\002\000 +BAAYGRoCAgICAgICAgICAgIC 0 -1 +BBwBAhwBBQYAABAACgsEDA0OFwMUBAUGAAAQAAoLBAwNDicEKD8qKwQsMjMENA== 0 -1 +BAABAvsEBDQmNjcEAEA6O6GhoZ2hoaGhoakhoaGhoaEEPD0FHQcECAkKCwB/DQ4uBBAREhMEFBUWFwQYGAACAAAdHh8EICljAAAAADEySwQ0NTY3BABAOjsEPD1APwQ8PT4= 0 -1 +BP9/AgMEBAUGBwQICQoLBAwNDg8EEBESEwQEGRobBBwdHh8EICEkJSYnMzMzMzMzMzMzMzMzMysELC0uLwQwMTIzBDQ1NjcEODktOwQ8PT4/AA== 0 -1 +DQ4PBAgICgtADA0ODwQICQoLAAD//w8EBF4GBwwABF4GBwwNBg8EBBMEBv8ICQoDQAQTBgcEDwQICdsLQAwzBDRONjcEOA== 12 -1 +BAABAgMEBDAxMjMENCwtLi8EBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgAAIAAHF2hHyEiIwQkJTEnBCgpKisELC0uLwQwMTIzBDQsLS4vBDAxMjMENDU2NwQ4OTpkNjcEODk6OwQ8PQ== 0 -1 +A+cBAgMEBCkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKQcECAkKISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OVc7BDw9PgA= 0 -1 +BAABAhERAwQEBQYHBCEJCAghCQgICAgJCAgI7REICAAICAgICAiICAgICAgICAgICAgICAoLBAwNDg8EBhESEx0UFRYXfyX/JwQoKSorBCwtLi8EMDEyMwQ0NTw9Pg== 0 -1 +BAABAgMEBQUG5gMI5ycLBAwNDg8EyxG6EykRHQEBAQEBAQEBAQEBAQEBAQEBAQEBAQF/auUs 0 -1 +CgsjFSQlJicEKCkqKwQsNDQAEDcUFRYX/wAAABsEHB0bBBwdHh8EICEiIxUkAAAbFhcEMTIzBDQAEBsEHB0eHwQgMwQ0NQ== 0 -1 +BAABAgMEBAUGBwQI7AoLBAwNDicEEBESEwQUFRYXBAYZGhsEHB0eIgQgISIjAj4/AA== 0 49 BAABAgMEBAUGBwQI7AoLBAwNDicEEBESEwQUFRYXBAYZGhsEHB0eIgQgISIjAj4/AA== 143 \000\001\002\003.\004\005\006\007.\008\236\010\011.\012\013\014'.\016\017\018\019.\020\021\022\023.\006\025\026\027.\028\029\030\".\032!\"#.>? +BBABAgMsLS4A/zA0MvoAAPo2NwQ4PD03PwAEJwQoKR0eHwQg//8aGwABHR4fBCA2IiMEJCUmJwQoKQACEu4rLS4vBDCysn8ENDU2NwQ4ORUWFwQgISIjBCSyBDQ1NjcEODkVFhcGGBkaGwQwMDAwMCoqKioqKioqKiogKioqKioqKioqKioqKioqJSYnBCgpHR4fBCD///+APT5BAA== 0 -1 +BBABggMEBAUG6wQICQoLBAxuBBQtLiBQMwQzNTY5BDgeOTsEUFEENDUpNwQ4ADkEMDFQKhcELC0uIAQwMVAzBAQzNTY0NQ== 0 -1 +GQABAgMEBAUGBAIWCwQL8Q8EChESEwYUFRYXpQIDBAQFBgQIFgsEC/EPBAoREhMGFBYXpRgZGhvuHB0dHh7iPQ0ODwQQERITBhQV+gAAdHB0dOICBBwdQIAAKwQsLS6jvzA= 0 -1 +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEDh0eHwQgISIjBAICAgICAgICAgICAgICAgICAgICAgICAjsEPD0= 0 -1 +BAABAgMEBAX0BgQICf9/BAwNEg8EEBESEwQUFRYXBBgZGhsEFB0eHwQgKSIjBCQk6ycECCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAX0BgQICf9/BAwNEg8EEBESEwQUFRYXBBgZGhsEFB0eHwQgKSIjBCQk6ycECCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 192 \000\001\002\003.\004\005\244\006.\008\009\255\127.\012\013\018\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\020\029\030\031.\032\)\"#.\$\$\235'.\008\)*+.,-\./.0123.4567.89:\;.<=>? +BAABAGQEBAUGBwQICQouLwQwMTIzBDQAgAAASzk6OwQ8PT4EGBkaGwQcHR4fBCAhIyMKJCUmJwQoKSo4BCYtLi8EMDEyMuI0NTYEJi0uLwQwMTIzBDQAAAABAAA6OwQ8PT4/BDcEODk6Oys8PT4/BA== 0 -1 +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESKQQUFRYXBBgZGigEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESKQQUFRYXBBgZGigEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 181 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\).\020\021\022\023.\024\025\026\(.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +BAABAgICAgICAgICLhwEMDEyMwICAgICAgQUFRYXAgICAgICAgICAgICAgICAgICAgICAgICAgICAi4cBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgICAgICAgICLhwEMDEyMwICAgICAgQUFRYXAgICAgICAgICAgICAgICAgICAgICAgICAgICAi4cBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 191 \000\001\002\002.\002\002.\002\002.\.\028.0123.\002\002.\002\002.\020\021\022\023.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\.\028.0123.4567.89:\;.<=>? +BAABAgMEBAUGBwQICQoLBAwNDgICAgICAicEKCkqKwQsLS4vBDACAgICAgICAgICAicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQICQoLBAwNDgICAgICAicEKCkqKwQsLS4vBDACAgICAgICAgICAicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 168 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\002.\002\002.\002'.\(\)*+.,-\./.0\002\002\002.\002\002.\002\002.\002'.\(\)*+.,-\./.0123.4567.89:\;.<=>? +BAAYDQ4PBBAREhMBjAMEBAUGDQ4PBBAREhMEFBUWEwQUFRYXBBgZGhsEkx0eHxobBJMdDB8EICEiIwQ2NDUEkx0eDg8EEBESEwQEGBkaGwSTHQ== 0 -1 +ZAENAWQBDQAA/w== 1 7 AQ0BZAENAA== 12 \013.d.\013 +BAQIIwoLDwQQEeQcPx4fBCAhIiMEJCUmJx8FIAQoKSorBCwhLi8EMB0yD6cQEcscPx4fBCA+IiMEJCUmJx8EFd4oKSorFCcEGSkqKwQsLTcEODk6OwQ8BwQYBxobBBwdHg/HEBES 3 -1 +wAADJRoVHignKiuALC1AAAAABCBNLn////97fwAcPj+A 0 -1 +BAARAgMEBAUGBwQICQrvAwgJCsAEDBcEGAQMDQ4PBBAdHh8EICEiIwQkJSYnBCgpKisELC0uLwQwMQAAEQIDBAQFBgcECAkK7wP/BDQ1NjcEODk6OwQ8PT4/ 0 -1 +BAABAgMEBAAGBwQICQoLBAwNDg8EEBESKAQUFRYXBBgZGhsEHB0eHwQgISIrBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwQ4OTo7BDw9AEAA 0 81 BAABAgMEBAAGBwQICQoLBAwNDg8EEBESKAQUFRYXBBgZGhsEHB0eHwQgISIrBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwQ4OTo7BDw9AEAA 185 \000\001\002\003.\004\000\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\(.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"+.,-\./.0123.4567.89:\;.<=>?.89:\;.<=\000\@ +BAABAgMEBAUGBwQICQoPDwQQFBUWFwQYGRobAQEBAQEBAQEBBBwdHh8EICEiIwQkJSYnBCgpKisELC0uL////38zBDQ1NjcEPBA+P0A= 0 -1 +BA8EAgAsAID/////MjMEMjU2NwMEFgUEBf//9BEAHALNBAb/f0AA6iAEICEiIwQkJSYn+vr6+vr6BPYGACQICQoQAiADvQABEgMEBAUEBQYHBEAA6iAEICEiIwQkJSYn+vr6+vr6+vr6+vr0BBIdLC0u9gQwMSgMBwRkAAAgBEQAIAQgISI= 0 -1 +BAABAgMEBAUGBwQICQoLBBobBBwdHh8EICEiIwQkJSYnBCgpKisELDEyMwQ0NTY3BAACOjsEPHI+OwQ8PT4/AA== 0 64 BAABAgMEBAUGBwQICQoLBBobBBwdHh8EICEiIwQkJSYnBCgpKisELDEyMwQ0NTY3BAACOjsEPHI+OwQ8PT4/AA== 147 \000\001\002\003.\004\005\006\007.\008\009\010\011.\026\027\004\028.\030\031\004\032!\"#\004\$%&'\004\(\)*+\004,123\0044567\004\000.:\;.<r>\;.<=>? +wAABAgMEERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJ/snKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwA= 0 -1 +BB4fBAQcKSkpKSkpKSkpKSkpKSkpKRMpKSkpBCAhDyMEJCUmJwQ= 0 -1 +AgAAAhAiAhAiFvQAzwACECICECIW9ADpFvQW9ADpA/QAzw== 0 33 AgAAAhAiAhAiFvQAzwACECICECIW9ADpFvQW9ADpA/QA 108 \000\000.\016\".\016\".\244\000\207\000\002\016\"\002\016\"\022\244\000\233\022\244\022\244\000\233\003\244 +BAABFwMEBAUWFwQYGRobBBwdHh8EICEiIwQkJSYnBCgpKisELDsuLwQgISIjBCQlJicEKCkqKwQsOy4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABFwMEBAUWFwQYGRobBBwdHh8EICEiIwQkJSYnBCgpKisELDsuLwQgISIjBCQlJicEKCkqKwQsOy4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 147 \000\001\023\003.\004\005\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,\;\./.\032!\"#.\$%&'.\(\)*+.,\;\./.0123.4567.89:\;.<=>? +BAABAQEBAQEBAQEBAQoL9gwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJieuDCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAQEBAQEBAQEBAQoL9gwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJieuDCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 214 \000\001\001\001.\001.\001.\001.\001.\011\246\012\013\014\015\004\016\017\018.\004\020\021\022\023\004\024\025\026\027\004\028\029\030\031\004\032!\".\004\$%&'\174\012\)*+\004,-\./\0040123\0044567\00489:\;\004<=>? +BBgZKhsEHIAAHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMgICAgICAgIC 0 -1 +PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0/fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8P70= 64 -1 +PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0Afg== 0 129 PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0A 235 \000\001\002\003\004\005\006\007\008\009\010\011\012\013\014\015\016\017\018\019\020\021\022\023\024\025\026\027\028\029\030\031\032!\"#\$%&'\(\)*+,-\./0123456789:\;<=>.?\@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|} +PwAhIiMFJSZZKAPoKzQtLi0wMTIzSTU2Nzg5OjsSPT4/PwECy8vLy+fnntTn5wQBBgcILy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL38jBSUmWSgD6Cs0LS4tMDEyMzRGR0hJSktMTYODgwUGBwgJCgsMDQ4PEBETFEAADw== 0 -1 +wACQkAQAJiYmJiYmJiYmJiYi 0 -1 +AgBAAhAiAhAiFvQAzwACECICECIW9ADpFvQW9ADpA/QAzw== 0 33 AgBAAhAiAhAiFvQAzwACECICECIW9ADpFvQW9ADpA/QA 106 \000\@.\016\".\016\".\244\000\207\000\002\016\"\002\016\"\022\244\000\233\022\244\022\244\000\233\003\244 +AgAAAgEiAhAiFusCzwACECICZCIW9A/pFvQW9ADpAwACASICECIW6wLPAAIQDQJkIhb0D+kW9Bb0AOkDJQA= 0 62 AgAAAgEiAhAiFusCzwACECICZCIW9A/pFvQW9ADpAwACASICECIW6wLPAAIQDQJkIhb0D+kW9Bb0AOkDJQA= 200 \000\000.\001\".\016\".\235\002\207\000\002\016\"\002d\"\022\244\015\233\022\244\022\244\000\233\003\000.\001\".\016\".\235\002\207\000\002\016\013\002d\"\022\244\015\233\022\244\022\244\000\233\003% +AgABAQEBAQEBAQIBAQEBAQEBAQEBAQ== 0 -1 +AgACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgL0 0 -1 +AgAAAhAiAQEBCQEBAQACENQBAQEBAQEBAQEBAWQBAAEBAgEBAQEBKSkp 0 -1 +AgABAQEBAQEBAQEBAQECAQACAAACECIBAQEBAQEBAQEBAQEBAQE= 0 -1 +AgAAAhAiAgAAAhAiAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQIBVwEBAQEBAQEBAQECAVcBAQEBAQEBAQEBAQECAVcBAQEBAQEBFAE= 0 -1 +BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwTgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8A 0 81 BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwTgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8A 88 \@ABC.DEFG.HIJK.LMNO.PQRS.TUVW.XYZ[.\\]^_.\224abc.defg.hijk.lmno.pqrs.tuvw.xyz{.|}~\127 +BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawBsbQ== 0 56 BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawA= 57 \@ABC.DEFG.HIJK.LMNO.PQRS.TUVW.XYZ[.\\]^_.`abc.defg.hijk +BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fj8A 0 81 BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fj8A 82 \@ABC.DEFG.HIJK.LMNO.PQRS.TUVW.XYZ[.\\]^_.`abc.defg.hijk.lmno.pqrs.tuvw.xyz{.|}~? +PwABAgMEBQYHCAmztLUAABYXGBmInAoLDA0ODyQRNDU2NwE5Ojs8PT4/PwkKCwwNDg8kSwoLDA0ODyQpKSkpKSkpPT4/VTAxMjM0NDY3AYeLjKqObB0eHyB9KSkpKSkpKWQnKCkqKykJKSkpKSkpKSkpKSlkJygpKissLS48PT4/P0BBQkNERUYvMDEyMzQ0NjcBigQArK2urw== 0 -1 +PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyTsJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNLVVZXWFlaW1xdXl9gYWJjZGVmZ2hpMDAwMDEwMDAwMDAwME0wMDAwMDAwMDAwMDAwMDAwMGprbG1ub3BxcnN0dXZ3eHl6ewh9P35/gIGCg4SFhoeIiYo7PD0+Pz9AQUJLTE1OT1BRUouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqMgpaanqKmqq6ytrq+wsbKztLW2t7i5uru8P70= 0 -1 +KCgoKCgoKDkQgAQwQDJDxsbGyP9EKsbG1sbGxsbGxsbGyP8qxkAqKioqKioqKMbGzcbG1v8qKsbG1sbGxsbGxsbGyP8qKkAqKioqKioqQSoqACgTExMTExMTExMTExMTExMTExMTExMTExMTExMTKioMKioqKir/ACroAyoq 0 -1 +BAwDAwMDA+gCAwMDAwMDAwMDAwP6A+gCAwMDAwMDAwMDAwP6AAA= 0 38 BAwDAwMDA+gCAwMDAwMDAwMDAwP6A+gCAwMDAwMDAwMDAwP6AAA= 121 \012\003\003\003.\003\232\002.\003\003\003.\003\003\003.\003\003\250.\232\002\003.\003\003\003.\003\003\003.\003\250\000 +BAABAh0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dAwQEBQYHBAgJCgsEDP0NDwQQERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJwQoKTY3BDg4OjsEPD0+P8A= 0 -1 +//8FDgMEBwQsLS4nBC0AEwIQAAcAAH/fMjMENDU2CAkKTy4gAB8ANgQsLS4vBAcAAH/fMjMENDU2CCAAHwA2BCwtLi8eBC4gAB8ANgQsIAAfAC4vBH8QHgQ/OTpPLiCVlZWVlZWVlZWVlZWVlZWVlZWV 5 -1 +FgAAEAAnBCgpKisELC0uEdkuEQYDBCEJCAghCQgICBgJCAgIAwIICAAICAgIAAkICCEJCAgIGAgICO0RCAgACAYIFAgICIYICAgICO0RCAgACAYIFAgPBAYREhMdag== 0 -1 +BA8ICAgEBAUG6wQICQoLBAxuJSY2BBAAAAAEFC0uIFAzBDM1NjkEOB45OwRQUgQ0NSk3BDgAOQQ1NjkEOB45OwRQUQQ0NSk3BDA0UCoX 0 -1 +PwABFwMEenp6enp6enp6enp6enp6enp6enp6enp6enp6enp6IyQlJicoKSorLC0uLzAxMjM0ACAzODk6Ozw4Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaAVxdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0Afg== 0 129 PwABFwMEenp6enp6enp6enp6enp6enp6enp6enp6enp6enp6IyQlJicoKSorLC0uLzAxMjM0ACAzODk6Ozw4Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaAVxdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0A 159 \000\001\023\003\004zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz#\$%&'\(\)*+,-\./01234\000\032389:\;<8>.?\@ABCDEFGHIJKLMNOPQRSTUVWXYZ\001\\]^_`abcdefghijklmnopqrstuvwxyz{|} +PwDuAQMEBQYHCAl8fHx8fHx8fHx8fHx8fHx8fHx8fHx8ICEiIyQlJjU2Nzg5Ojs8ICEiIyQlJjU2Nzg5Ojs8PT4/P0BBQkNEVHx8fHx8fHx8fHx8fHx8fHx8fHx8fCAhVVZXWFlaW1xdXl9gABBjZGVwcXJzdHV2QAAAAHt8fQB+ 0 128 PwDuAQMEBQYHCAl8fHx8fHx8fHx8fHx8fHx8fHx8fHx8ICEiIyQlJjU2Nzg5Ojs8ICEiIyQlJjU2Nzg5Ojs8PT4/P0BBQkNEVHx8fHx8fHx8fHx8fHx8fHx8fHx8fCAhVVZXWFlaW1xdXl9gABBjZGVwcXJzdHV2QAAAAHt8fQA= 190 \000\238\001\003\004\005\006\007\008\009||||||||||||||||||||||\032!\"#\$%&56789:\;<\032!\"#\$%&56789:\;<=.??\@ABCDT|||||||||||||||||||||\032!UVWXYZ[\\]^_`\000\016cdepqrstuv\@\000\000\000{|} +wACQmAQA 0 -1 +ARABIQEiAYABJAElASYBJwEoASkBKgEaARsBHAEdAR4BHwEgASEBIgGAASQBJQEmAScBKAEpASsBLAEtAS4BNwE4 0 -1 +AQABAwEEAQUBBgEnASgBKQEqASkBKgErASwBLQEuATcBOAE5AToBOwE8AT0BKwEsAS0BLgE3ATgBOQE6ATsBPAE9 0 -1 +A98BAgMEBCkpKCkpKSkpKSkpKSkpBikmKSkrKSkpICkpKSkpKQEnBCgpKSkpKSkpKSkGKSYpJDMENA== 0 -1 +A2QBAgMEBCkpKSkpKSkpKSkpKSkpKQQEKSkpKSkpKSkpKSkpKSkpKSkMKSkpKSkpKSkpKSkpKSkpKCkHBAgJCiFAKSkpKSkpKSkpKSkpKQcEKSkpKSkpKSkpKTcEODlXOwQ= 0 -1 +BBABAgMsLS4A/yoqMgUAAH82NwQ1NjcEODwVFhcGGBkaG/0vEQYYIgQoKQACEu4rLS4vBDCysioqKiAqKio2MC4wKioqKioEIEciIwQkCCYnKQoCEu4rLS4vBDCysgRFKQACEu4rAwAAfyoqICoCEu4rLS4BADCysioqKiAqKioqJSoqKioqKioqEiolJicEPCk= 0 -1 +AUABRQFGAU8BUAFRAVIBUwFUAVUBVgFXAVgBWQFaAVsBXAFfAWABYQFiAWMBZAFlAWYBZwFoAWkBagFrAWwBbQFuAW8BcAFxAXIBcwF0AXUBdgF3AXgBeQF6AXsBfAF9AX4BfwA= 64 37 AW4BbwFwAXEBcgFzAXQBdQF2AXcBeAF5AXoBewF8AX0BfgF/AA== 39 n.o.p.q.r.s.t.u.v.w.x.y.z.{.|.}.~.\127 +BAAEBQYHBAgJCgsEDA0ODwQQERITBBQVFhcEGBkaGwQcHSEiIwQkJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChoqMEpKWmpwSoqao= 32 -1 +BAAEBQYHBAgJCgsEDA0kJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChoqMEpKWmpwSoqao= 8 -1 +BAABAgMEBAUGBwQICQocHR4fBCAhIiMEJCUsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaWwRcXV5fBGBhYmMEZGVmZwRoaWprBGxtHh8EICEiIwQkJSYnBCgpKisELC0uLwSAgYKDBISFhocEiImKiwSMjY6PBJCRkpMElJWWlwSYmZqbBJydnp8EoKGiowSkpaanBKipqqsErK2urwSwsbI= 0 -1 +BAAEBQYHBAgJCgsEDA0kJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEgAA6OwQ8PT4/BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgNTY3BDg5OjsEPD0+PwRAQUJDBERFRkcEdHV2dwR4eXp7BHx9fn8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChoqMEpKWmpwSoqao= 8 -1 +BAAEBQYHBAgJCgsEDA0kJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT5fBGBhYGMEZGVmZwRoaWprBGxtbm8EcHFycwR0dVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8EgIGCgwSEhYaHBIiJiosEjJGOjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChoqMEpKWmpwSoqao= 8 -1 +BOgCAwMD+gPoAgMDAwMDAwMDAwMD+gAMAwMDAwPoF+gCAwMDAwMDA+ICAwP6AAADAwMDAwMDAwMDA/oD6AIDAwMDAwMDAw== 0 -1 +BOj6A+gCAwMDAwMDAwMDAwP6AAwDAwMDA+gX6AIDAwMDAwMD4gIDA/oAAAMDAwMDAwMDAwMD+gToAgMDA/oD6AIDAwMDAwMDAwMDA/oADAMDAwMD6BfoAgMDAwMDAwPiAgMD+gAAAwMDAwMDAwMDAwP6A+gCAwMDAwMDAwMSAwP6A+gCAwM= 0 -1 +BOj6A+gCAwMDAwAMAwMDAwPoF+gCAwMDAwMDA+LwAwP6AAADAQMDA/oD6AIDAwPoF+gCAwMDAwMDA+LwAwMDAwMD+gMDAwMDAwMDAwMD+gAMAwMDAwPoF+gCAwMDAwMDA+LwAwP6AAADAwMDAwMDAwMDA/oD6AIDAwMDAwMDAwMDAw== 0 -1 +BOgDAwgICAgICAgICAgICAgICAgICAgBCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICHQICAgICAEICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIdAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI 0 -1 +BOgCFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFQMDAwMDAwMJ+gPoAgPwAgM= 0 -1 +GxsbGxsAGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsVGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbAxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGyYbGxsbGxsbGxsbGxsbGxsbGxsb 27 -1 +BOgCAwMD+gPoAgMDAwMADAMDAwMD6BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAE6AQDAwP6A+gC 0 -1 +BOgCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC 0 -1 +BOgDAwgIDAgICAjvCAgICAgIAgjCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCAMLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwuXCwsLCwsLCwsLCwsLCwsLCwsLCwsK6wsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCssLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCqMLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwggICAEICAgIf3QICAgICAEICAfwCAgICAgIB+8IEwgIgAgICB8ICAgICBgICAgICAgSCAgICAgICAgICAgICAgfJoAICAgICAgICACAAAAF/+kFCH8ICAgICAgICAgICHQICAgICJwIwqrCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwtLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCpcLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsIICAgBCAgICH90CAgICAgBCAgH8AgICAgICAfvCAgICIAICAgfCAgICAgYCAgICAgIEggICAgICAgICAgICAgH8AgICAgIAQgIB/AICAgICAgICAgICAjwCAgIHwgICAgIGAgICAgICBIICAgICAgICCAACAgICAgICAgICAjeCAgICAgICAgICAgICAgFHyYICAgICAgICAgAgAAABf/pCFpaWlpaWlp6WlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWggICAgBCAgH8AgICAgICAgICAgICPAICAgfCAgICAgYCAgICAgIEggICAgICAgICAgICAgICAgICAgICN4ICAgICAgICAgICAgICAUfJggICAgICAgICACAAAAF/+kIWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpahoaGhoaGhoaGkIaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGf4aGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaTlpaWlpaWlpaWlpaWlpaWlpaWlpaWggICAEICAfwCAgI///CwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwgAACAgH8AgICP//AAAICAgI+QcICAgICAUICAgICAgICAgICAgICAgICAgICAgICAgICAgI//8AAAgICAgICAgICAgIBQgICAgICAgICAgICAkICAgICAgICAgICAgIDA== 0 -1 +BOgDAwgIFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcCFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXAAADFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFwgI 0 -1 +BOg6OjoIOjo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Mzo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo= 0 -1 +BOgDAwQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAgQEBAQEBA== 0 -1 +BOgDAwgINjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjaeNjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Np42NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY= 0 -1 +AQABAQECAQcBCAEJAQoBCwEMAQECAQsBDAENAQ4BDwEQAREBEgETARQBFQEWARkBGgEbARwBHQEeAR8BIAEjASQBJQEmAScBKAEpASoBKwEsAS0BLgE3ATgBOQE6ATsBPAE9AT4BPw0BDgEPARABEQESARMBFAEXBRgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgE3ATgBOQE6ATsBPAE9AT4BPwA= 0 185 AQABAQECAQcBCAEJAQoBCwEMAQECAQsBDAENAQ4BDwEQAREBEgETARQBFQEWARkBGgEbARwBHQEeAR8BIAEjASQBJQEmAScBKAEpASoBKwEsAS0BLgE3ATgBOQE6ATsBPAE9AT4BPw0BDgEPARABEQESARMBFAEXBRgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgE3ATgBOQE6ATsBPAE9AT4BPwA= 387 \000.\001.\002.\007.\008.\009.\010.\011.\012.\001.\001\011.\012.\013.\014.\015.\016.\017.\018.\019.\020.\021.\022.\025.\026.\027.\028.\029.\030.\031.\032.#.\$.%.&.'.\(.\).*.+.,.-.\..7.8.9.:.\;.<.=.>.?.\001\014\001\015\001\016\001\017\001\018\001\019\001.\001\023\005\024\001\025\001\026\001\027\001\028\001\029\001\030\001\031\001\032.!.\".#.\$.%.&.'.\(.\).*.+.,.-.\..7.8.9.:.\;.<.=.>.? +AQABAQECAQMBBAEFAQYBJwEoASkBKgEpASoBAQIBOQE6ATsBKwEsAS0BLgE3ATgBOQE6ATsBLQEuATcBOAE5AToBOwE8AQ== 0 -1 +BAABAgMEAAAEAAQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BEBBQkMEREUwRwRISUtLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnaGiAAA= 0 241 BAABAgMEAAAEAAQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BEBBQkMEREUwRwRISUtLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnaGiAA== 438 \000\001\002\003.\000\000\004\000.\008\009\010\011.\012\013\014\015.\016\017\018\019.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?.\@ABC.DE0G.HIKK.LMNO.PQRS.TUVW.XYZ[.\\]^_.89:\027.<=>?.\@ABC.DE0G.HIKK.LMNO.PQRS.TUVW.XYZ[.\\]^_.`abc.defg.hijk.lm\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.\128\129\130\131.\132\133\134\135.\136\137\138\139.\140\141\142\143.\144\145\146\147.\148\149\150\151.\152\153\154\155.\156\157\161\162 +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFRkcESElKSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EYGFiYwRkZWZnBGhpamsEbG0eHwQgISIjBCQlJicEKCkqKwQsLS4vBICBgoME+oWGhwSIOwQ8PQ== 0 -1 +BAABAgMEBAgJCgsEDA0gISIjMDEyMwQ0NTY3BDg5OjsEPD0iIwQkJSYnBD8pKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/BEBFRkcESElKSwRMTUNPBFBRUlsEVFVWVwRYWVpbBFxNXl8EYGFiYwRkZWZnBGhpamsEbG0eHwQgISIjBCQlJicEKCkqKwQsLScvBICBgoME+oWGhwSIiYqLBDQ1NjcEODk9Pj8E 0 -1 +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmBwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFRkcESElKSwRMTU5PBFBRUlMEVFVWVwRYWVpbBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUOwQ8PQ== 0 -1 +AgAAAhBiAgAAAhAiAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQIBVwEBAQEBAQEBAQECAVcBAQEBAQEBAQEBAQECAVcBAQEBAQEBFAE= 0 -1 +AykpKSkpKSkpKQQEKSkpKSkpKSkpKSkpKSkpDCkMKSkuKSkpKSkpKSkpKSkpKCkG9QgJCiFAKSkpKSn/KSkpKSkAAAEpKQcEKSkpKSkpKSkpKSkpKSkpKQwpKSkpKSkpKSkpKTsEQAApKSkpKCkG9QgJCiFAKSkpKSn/KSkpKSkpKQcEKSkpKSkyKSkpKbckODlXOwRAAD4pBwQgHCkpKSkA 0 162 AykpKSkpKSkpKQQEKSkpKSkpKSkpKSkpKSkpDCkMKSkuKSkpKSkpKSkpKSkpKCkG9QgJCiFAKSkpKSn/KSkpKSkAAAEpKQcEKSkpKSkpKSkpKSkpKSkpKQwpKSkpKSkpKSkpKTsEQAApKSkpKCkG9QgJCiFAKSkpKSn/KSkpKSkpKQcEKSkpKSkyKSkpKbckODlXOwRAAD4pBwQgHCkpKSkA 365 \)\)\).\)\)\)\)\)\004\004\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\012\)\012\)\)\.\)\)\)\)\)\)\)\)\)\)\)\)\(.\006\245\008\009\010!\@\)\)\)\)\)\255\)\)\)\)\)\000\000\001\)\)\007\004\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\).\)\)\)\)\)\)\)\)\)\)\)\;.\@\000\)\).\)\(\)\006\245\008\009\010!\@\)\)\)\)\)\255\)\)\)\)\)\)\)\007\004\)\)\)\)\)2\)\)\)\)\183\$89W\;.\@\000>\).\004\032\028\)\)\)\) +AgAAAhBiAQEBAQIQYgIiAQEBAQEBAQEBAQEBAQECAVcBAQEBAQEBAQEBAgFXAQEBAQEBAQEBAQEBAgFXAUEBAQEBAQECAVcBAQE= 0 -1 +AgBAAhAiAhBAAhAiAhATBAEVFhcEGBkaGwQUHR4fBCApIiMEJCTrJwQIKSorBAgJ/38EDA0SDwQQERITBBQVFhcEGBkaGwQUHR4fBCAp 0 -1 +AgAAAhBiAgAAAhAiAQEBAgFXAhBiAgAAAhABAQEBAQIBVwEBAQEBAQIQYgIAAAIQIgEBAQEBAQIBVwEBAgFXAQEBAQIBVwFBAQEBAQEBAgFXAQ== 0 -1 +AgBAAhAiAhBAAhAiAhAMDRIPBBAIEhMEARUWFwQYGRobBBQdHh8EICkiIwQkJAAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBgZGhsEFB0eHwQgKSIjBCQk6ycECCkAAAE= 0 108 AgBAAhAiAhBAAhAiAhAMDRIPBBAIEhMEARUWFwQYGRobBBQdHh8EICkiIwQkJAAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBgZGhsEFB0eHwQgKSIjBCQk6ycECCkA 344 \000\@.\016\".\016\@.\016\".\016\012.\018\015\004\016\008\018\019\004\001\021\022\023\004.\025\026\027\004\020\029\030\031\004\032\)\"#\004\$\$\000\000\002\000\@\002\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\025\026\027\004\020\029\030\031\004\032\)\"#\004\$\$\235'\004\008\) +AgAfBCApJOsnBAgpKisELC0uLwQwQAIQIgIQQAIQIgIQIgYECAAAAQn/fwQMDRIPBBAIEhMEARUWFwQYGRobBBQdHh8EICkiIwQkJOsnBAgpKisELC0xMjMENDU2IgYECAn/fwQMDRIPBBAREhMEFBEWFwQYGRobBBQdHh8EICkiIwQvJOsnBAgpKisELC0uLwQwMTIzBDRCNjcEODk6OwQ8 0 -1 +AgBAAhAiAhBAAhAiAhAiAhAiBgQICR0eHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGBksLS6KBDAxMjMENDU2IgYECAn/fwQMDRIPBBAREhMEFBUQAAQYGRobBBQdHh8EICkiIwQkJOsnBAgpKisELC0uLwQwMTIzBDRCNjcEOHk6OwQ86ycECCkAAAEsLS4vBDAGBAgJ/38EDBAREhMEFBUQ 0 -1 +AgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBgZGhsEFB0eHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgJ/38EAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBgZGhsEFB0eHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGBkagAQUHR4fBCApIiMEJCTrJwQIKQAAAQw= 0 191 AgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBgZGhsEFB0eHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgJ/38EAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBgZGhsEFB0eHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGBkagAQUHR4fBCApIiMEJCTrJwQIKQA= 603 \000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\025\026\027\004\020\029\030\031\004\032\)\"#\004\$\$\000\000\002\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\025\026\027\004\020\029\030\031\004\032\)\"#\004\$\$\000\000\002\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\025\026\128\004\020\029\030\031\004\032\)\"#\004\$\$\235'\004\008\) +AgAAAgBAAhAiAhBAAhAdHh8NNSkiGQQkJAAA/wBAAhAiAhBAAhAiAhAiBgQQIgIQQAIQIgIQHwQgKSIjBAQkAAACAEACEAACEEACECICBBAIEhMEARUWFwQYOhobBBQdHh8mNSkiGQQkJAAAAgBAAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQAAAIAQAIQIgIQQAIQIgIQIgYECAJAAgIC/gICOwA= 0 -1 +BAABAwMEAwjnJwsEDA0OHwTpASMBAQEBAQEBAADm 0 29 BAABAwMEAwjnJwsEDA0OHwTpASMBAQEBAQEBAAA= 88 \000\001\003\003.\003\008\231'.\004\012\013\014\031\004\233\001#\001\001.\001.\001.\000 +BAAAAQABAgMEBQAAAQU= 0 12 BAAAAQABAgMEBQAA 35 \000\000\001\000.\002.\004\005\000 +AQAcqAT1BQbmAwgAAAEEDA0ODwQAABHm/LkzKREyAQDo+w== 0 32 AQAcqAT1BQbmAwgAAAEEDA0ODwQAABHm/LkzKREyAQA= 110 \000.\168\004\245\005\006\230\003\008\000\000\001\004\012\013\014\015\004\000\000\017\230\252\1853\)\0172\001 +AgICAgICAgICAgICAgIAAAF/ 0 16 AgICAgICAgICAgICAgIAAA== 45 \002\002.\002\002.\002\002.\002\002.\002\000 +BBwcHAwcHBwcHBwc9KgMAQEBQBwcHBwcAcsRfX19fX76EwAAARw= 0 35 BBwcHAwcHBwcHBwc9KgMAQEBQBwcHBwcAcsRfX19fX76EwA= 113 \028\028\028\012.\028\028\028\028\028\028\244\168\012\001\001\001\@\028\028\028\028\028\001\203\017}}}}~\250\019 +BEAfPj4+HFBRUlMEVAAAASYmJiYmJiYmJiYmrSYVJiZnBGhpP2sAAABhYmMfZGUmJhgmJiYmJjImJiYmJiYmJiYmJiYmJiYmJiatJhUmJiZmZwRoaT9rACYmJiYmJq0mJiYmJmZnBGhpQAAAAQA= 0 108 BEAfPj4+HFBRUlMEVAAAASYmJiYmJiYmJiYmrSYVJiZnBGhpP2sAAABhYmMfZGUmJhgmJiYmJjImJiYmJiYmJiYmJiYmJiYmJiatJhUmJiZmZwRoaT9rACYmJiYmJq0mJiYmJmZnBGhpQAAA 172 \@\031>>.\028PQRS\004T\000\000\001&&&&&&&&&&&\173&\021&&g\004hi?k\000\000\000abc\031de&&\024&&&&&2&&&&&&&&&&&&.&&&&&\173&\021&&&fg\004hi?k\000&&&&&&\173&&&&&fg\004hi\@\000 +BOgD6wcINjY2NjY2MzY2NjY2NgD2ABA2UDY2NjY2NjY2NjY2NjY2JDY2NjYAAP//AAA2AAABNgAQNlg2NjaHNjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjYAgAAAKDY2zjY2Np42NjY2Njb/////6DY2QzY2NjYgAQA2 0 125 BOgD6wcINjY2NjY2MzY2NjY2NgD2ABA2UDY2NjY2NjY2NjY2NjY2JDY2NjYAAP//AAA2AAABNgAQNlg2NjaHNjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjYAgAAAKDY2zjY2Np42NjY2Njb/////6DY2QzY2NjYgAQA= 225 \232\003\235\007.66666636.6666\000\246\000\0166P66666666666666\$6666\000\000\255\255\000\0006\000\000\0016\000\0166X666\135666666.6666666666666666666666\000\128\000\000\(66\206666\158666666\255\255\255\255\23266C6666\032\001 +BCYmJiYmNjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2EhISEhISEhISEhISEhISEhISEhISEhISEhI2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Nhw2njY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2HTY2NjZINjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjaeNjY2NjY2NjY2NjY2NjY2NjY2NjY2NiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmNjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Ng== 0 -1 +BOgAAAEDAwgINjY2NgAAAMAfNjY2NjYkFTY0NjY2NjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTY2FTYABDY2NjY2NjY2NjY0Nlg2NjY2NjY2NgAAATY2NgAAAADAHzY2NjY2JBU2NDY2NjY2NjY2NjY2NjY2AAAAAQQ2NjY2NjY2NjY2NjY2AAAAAQAbS2xLS0tLS0tLATa+H0YUNjY2NgAANjYkNjY0NjY2NjY2NjY2NjY2NjY2NjYkNjZ/dnZ2dnZ2dnZ2dnZ2dnZ2QTYBNh4EAED/NjY2NjQ2AAABAAABgDY2FjY2NtDQ0NDQ0NDQ0DPQ0NDQ0NDQ0NDQ0JDQABQUFBQ2NjY2NjY2WDY2NjZNNjZRABEBAAABNiU9PT09NgBAAAGANj0QAPv7+/v7+/v7+/sg+/v7+0JEAAABNjYyNjY= 0 -1 +BOgDAwgINjZWNhU2NgE2NjY2NjY2NjY2NjY2UjY2AzY2NjY2NjY2NjYlNkk2NjY2NjY2NjY2NiIiIiIiIkAiNugDNjY2NjY2NjY2NjZDNjY2NpiYmDY2NjYiICIiIiIiIiIiIiIiIiJJNjY2NjY2NjY2NjYiIiIiIiJAIjboAzYiIiIiIiIiIiIiIiI2NjY2NjY2NjZkNjY2NjY2NjZNNgAAATY2NjYCAAQANjY2NgAQAIAAADY= 0 180 BOgDAwgINjZWNhU2NgE2NjY2NjY2NjY2NjY2UjY2AzY2NjY2NjY2NjYlNkk2NjY2NjY2NjY2NiIiIiIiIkAiNugDNjY2NjY2NjY2NjZDNjY2NpiYmDY2NjYiICIiIiIiIiIiIiIiIiJJNjY2NjY2NjY2NjYiIiIiIiJAIjboAzYiIiIiIiIiIiIiIiI2NjY2NjY2NjZkNjY2NjY2NjZNNgAAATY2NjYCAAQANjY2NgAQAIAA 299 \232\003\003\008.66V6\02166\001.666666666666R66\0036666666666%6I66666666666\"\"\"\"\"\"\@\"6\232\003666.6666666C6666\152\152\1526666\"\032\"\"\"\"\"\"\"\"\"\"\"\"\"I66666666666\"\"\"\"\"\"\@\".\232\0036\"\"\"\"\"\"\"\"\"\"\"\"666666666d66666666M6\000\000\0016666\002\000\004\0006666\000\016\000\128 +BOgAATY2NjY2fwA2NjY2NjY2NjY2NjY2NjY2NjY2Njb/ADY2NjY2NjY2NjY5NjY2AAAAgFQ2NjY2NjY2NjY2UzY2NjY2tzY2NjY2NjY2NjY2NjY2NjY2NjY2NgAAATY2O0o2NjY2NjY2NjY2NjY2NjYAEDY2OTY2NgAAAIBUNjY2NjY2NjY2NjY2NjY2/zY2NlU2NjY2NjY2NjY2NjY2Nis2NgABAACA/zY2NjY2NjY2NjY2Np42NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2IjY2NjY2IDY2NjY2NjY2NjY2NjY2NjY2IjY2NjY2IDY2NjY2NjY2NjY2IzY2NjY2NjY2NjY2NjZINjY2NjYTDAwMDAwMDAwMDAYMDAwMDAwMDAwMDAwMDDY2NjY2JTY2NjY2NjY2NjY2Np42NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY= 0 -1 +BOgAAAABAAgINjY2NgAAAMAQNjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTY2FTY2NjY2NjQ2WDY2NjY2NjY2AAABNjY2AAD/8cAfNjY2NjYkFTYUNjY2NjY2NjY2NgAAAAEENjY2NjY2NjY2NjY2NgAAAAEAG0tsS0tLS0tLSwE2vh9GFAAAATYAADY2JDY2NDY2NjY2NjY2NnZ2dnZ2QTYBNh4EAED/NjY2NjQ2AAABAAABgDY2FjY2NtDQ0NDQ0NDQ0DPQ0NDQ0NDQ0EDQ0JDQABQUFBQ2NjY2NjY2WDY2NjZNNjZRABEBAAABNjY2RTY5NjY2JT09PT02ADY0NgAAAYA2PRAA+/v7+/v7+w== 0 -1 +BOgDCAg2NjY2AAAAwB82NjY2NiQVNjQ2NjY2NjY2NgAQNgAAATY2NjY2NjY2AAABAAE2NjZFNjYVNgAENjY2NjY2JzY2NjQ2WDY2NjY2NjY2AAABNjY2AAAAAMAfNjY2NjYkFTY0NjY2NjY2NjY2NjY2NjYAAAABBDY2NjY2NjY2NjY2NjYAAAABABtLbEtLS0tLS0sBAAABRhQ2gDY2AAA2NiQ2NjQ2NjY2NjY2NjY2NjY2NjY2NiQ2Nn92dnZ2dnZ2dnZ2dnZ2dnZBNgE2HgQAQP82NjY2NDYAAAEAAAGANhkWNjY20NDQ0NDQ0NDQM9DQ0NDQ0NDQ0NDQkNAAFBQUFDY2NjY2NjZYNjY2Nk02NlEAEQEAAAEjNjZFNjk2NjYlPT09VDYAQP82NjY2NDYAAAGANj0QAPv7+/v7+/v7+/sg+/v7+0JEAAABNgsLCwsLCwsLCwsLCwsLCws= 0 -1 +wMAAAcDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Nn7s7OzsEBQUDDY2NgAAATY2NjZYNjY2Nk02NlEAEQEANjYABf//BUU2OTY2NiU9PT09NgAAAfI//3Y2AAABNjY0NgAAAYA2PRAA+/v7+/v7+/v///8= 16 -1 +BOgAAGQB4ggISTY2NgAEQMAAAAAAATY2NjY6JDY2NgAQNjZKWDYgNjY2AAA2NjY2Njw2ATYYNkUAAAIQ//9/TExMTExMTExMTExMTExMTExMTExMTENMTBMTExMTEykTExMTEyYLAAEUFAAABjY2NjYAAAE2NhwAAAABAAABBDY2NtAAAzY2NgX//wU2NgD7SDYkNjk5OTk5OTk5OTk5OTk5OTk5OTk5PTY0NjY2NjY2NiQAAAE2Nn82cXZ2dnZ2dnZ20Coq0DPQ0P/QM9DQ//9//9AAAAHSu9DRkNAABgAA/xQUAAAGfzYkNjY0Nks2AAQeVTb/Nn////82TENMTBMTExMTEykTExMTEyYTACATNjYmfwLuAaMYAAABgDY2SlggIDY2NiQAAAE2Nn82cXZ2dnZ2dnZ20Co2Pk4ABQABADcyNjY= 0 -1 +BOgAAGQB4ggISTY2NgBEQMAAAADOzs7Ozs6wzs7O//9/TExMTExMTExMTExMTExMTExMTExMTENMTBMTEwAAARMTEy0T1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NQcExMTJgsAARQeAAAGNzY2WAAAATY2HAAAAAEAAAEENhY20AADNjY2Bf//BTY2APtIACQ2OTk5OTk5OTk5OTk5OTk5OTk5OTk9NjQ2NjY2NjY2GwAAATY2fzZxdnZ2dnZ2dnbQKirQM9DQ/9Az0ND//3//0AAA5tK70NGQ0AAGAAD/FBQAEAB/NiQ2NjQ2SzY0NjY2NjY2NiRVNv82f+4BoxgAAAGANjZKVSAgNjY2JAAAATY1fzZxdnZ2dnZ2dnbQKjY+TeYFACEANzI2OTk9NjQ2NjY2NjY2GwAAATY2fzZxdnZ2dnZ2dnY= 0 -1 +AgACAgICAgACAgICAgLXAgICAgICAuEBAgICAgICAgICAgICAgICAgICAgICAgICAgICAAL0 0 52 AgACAgICAgACAgICAgLXAgICAgICAuEBAgICAgICAgICAgICAgICAgICAgICAgICAgICAA== 153 \000\002.\002\002.\000\002.\002\002.\002\215.\002\002.\002\002.\225\001.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002 +AgwAAhAiAgAAAhAiAQECAVcBAQEBAQEBAQEBAgFXAQEBAQEBAQEBAQEBAgFXAQEBAQA= 0 50 AgwAAhAiAgAAAhAiAQECAVcBAQEBAQEBAQEBAgFXAQEBAQEBAQEBAQEBAgFXAQEBAQA= 120 \012\000.\016\".\000\000.\016\".\001.\001W.\001.\001.\001.\001.\001.\001W.\001.\001.\001.\001.\001.\001.\001W.\001.\001 +AgAAAhAiAgAAAhAiAQECAVcBAQEBAQEBAQEBAgFXAQEBAQEBARQBAQEBAQIBAQEBAQEBAQIBSgEBAQEBAQEBAQEBAQEBAgFXAVcBAQEBAQEBAQEBAQEAAAEC 0 87 AgAAAhAiAgAAAhAiAQECAVcBAQEBAQEBAQEBAgFXAQEBAQEBARQBAQEBAQIBAQEBAQEBAQIBSgEBAQEBAQEBAQEBAQEBAgFXAVcBAQEBAQEBAQEBAQEA 208 \000\000.\016\".\000\000.\016\".\001.\001W.\001.\001.\001.\001.\001.\001W.\001.\001.\001.\020.\001.\001.\002.\001.\001.\001.\001.\001J.\001.\001.\001.\001.\001.\001.\001.\001W.W.\001.\001.\001.\001.\001.\001 +BAAEBQYHBAgJCg4PBBAREhMEFBUWFwQYGRobBBwdHh8EICEiIwQkJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/GEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChoi0EpKWmpwSoqaqrBKytrq8EsLGyswS0tba3BLi5ursEvL3BwgAA 8 225 CQoODwQQERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PxhAQUJDBERFRkcESElKSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EYGFiYwRkZWZnBGhpamsEbG1ubwRwcXJzBHR1dncEeHl6ewR8fX5/BICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUlZaXBJiZmpsEnJ2enwSgoaItBKSlpqcEqKmqqwSsra6vBLCxsrMEtLW2twS4ubq7BLy9wcIA 520 \010\014\015\004\016\017\018\019\004.\021\022\023\004\024\025\026\027\004\028\029\030\031\004\032!\"#\004\$.&'\004\(\)*+\004,-\./\0040123\0044567\00489:\;\004<=>?\024\@ABC.DEFG.HIJK.LMNO.PQRS.TUVW.XYZ[.\\]^_.`abc.defg.hijk.lmno.pqrs.tuvw.xyz{.|}~\127.\128\129\130\131.\132\133\134\135.\136\137\138\139.\140\141\142\143.\144\145\146\147.\148\149\150\151.\152\153\154\155.\156\157\158\159.\160\161\162-.\164\165\166\167.\168\169\170\171.\172\173\174\175.\176\177\178\179.\180\181\182\183.\184\185\186\187.\188\189\193\194 +AgAAAhBiAgAAAhAiAQECEGICAQIBVwEBAhBiAgAAAhAiAVcBAgFXAQECAVcBAQEBAgFXAAAB 0 52 AgAAAhBiAgAAAhAiAQECEGICAQIBVwEBAhBiAgAAAhAiAVcBAgFXAQECAVcBAQEBAgFXAA== 116 \000\000.\016b.\000\000.\016\".\001.\016b.\001\002.W.\001.\016b.\000\000.\016\".W.\002.W.\001.\001W.\001.\001.\001W +AgAfBCApIiMEJAgpKisELC0uLwQwQAIQIgIQQAIQIgIQIgYECAAAAQn/fwQMDRIPBBAIEhMEiRUWFwQYGRobBBQdHh8EICkiIwQkJOsnBAgpKisELC0uLwQwMTIzBDQ1NiIGBAgJ/38EDA0SDwQQERITBBQRFhcEGBkaGwQUHR4fBCApIiMELyTrJwQIKSorACw= 0 145 AgAfBCApIiMEJAgpKisELC0uLwQwQAIQIgIQQAIQIgIQIgYECAAAAQn/fwQMDRIPBBAIEhMEiRUWFwQYGRobBBQdHh8EICkiIwQkJOsnBAgpKisELC0uLwQwMTIzBDQ1NiIGBAgJ/38EDA0SDwQQERITBBQRFhcEGBkaGwQUHR4fBCApIiMELyTrJwQIKSorAA== 432 \000\031.\032\)\"#.\$\008\)*.\004,-\./\0040\@\002\016\"\002\016\@\002\016\"\002\016\"\006\004\008\000\000\001\009\255\127\004\012\013\018\015\004\016\008\018\019\004\137\021\022.\004\024\025\026\027\004\020\029\030\031\004\032\)\"#\004\$\$\235'\004\008\).+\004,-\./\0040123\004456\"\006\004\008\009\255\127\004\012\013\018\015\004\016\017\018\019\004\020\017\022\023\004\024\025\026\027.\020\029\030\031.\032\)\"#./\$\235'.\008\)*+ +AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgIQIgYECAn/fwQMDRIPBBAIEhMEARUWFwQYFB0eHyY1KSIZBCQkAAACDkACECICEEACECICECICEEACECICEB8EICkiIwQkJAAAAgBAAhAiAhBAAhAiAhAAAA== 0 202 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgIQIgYECAn/fwQMDRIPBBAIEhMEARUWFwQYFB0eHyY1KSIZBCQkAAACDkACECICEEACECICECICEEACECICEB8EICkiIwQkJAAAAgBAAhAiAhBAAhAiAhAAAA== 593 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\020\029\030\031&5\)\"\025\004\$\$\000\000\002\014\@\002\016\"\002.\@\002\016\"\002\016\"\002\016\@\002\016\"\002\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\".\016\@.\016\".\016\000 +AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CADsA 0 232 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CAA== 664 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\128\000\000\0005\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\004\008\002\002\002\002.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\020\029\030\031&5\)\"\025\004\$\$\000\000\002\000\@.\016\".\016\@.\016\".\016\".\016\@.\016\".\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\002\@\002\002.\254\002 +AgAAAhBiAgAAAhAiAQECAVcBAQIBVwIQYgIAAAIQYgIAAAIQIgEBAgFXAQECAVcCEGICAAACEAECAAACEGICAAACECIBAQIBVwEBAgFXAhBiAgAAAhBiAgAAAhAiAQECAVcBAQIBVwIQYgIAAAIQAQIBVwAAAQ== 0 116 AgAAAhBiAgAAAhAiAQECAVcBAQIBVwIQYgIAAAIQYgIAAAIQIgEBAgFXAQECAVcCEGICAAACEAECAAACEGICAAACECIBAQIBVwEBAgFXAhBiAgAAAhBiAgAAAhAiAQECAVcBAQIBVwIQYgIAAAIQAQIBVwA= 278 \000\000.\016b.\000\000.\016\".\001.\001W.\001.\001W.\016b.\000\000.\016b.\000\000.\016\".\001.\001W.\001.\001W.\016b.\000\000.\016\001.\000\000.\016b.\000\000.\016\".\001.\001W.\001.\001W.\016b.\000\000.\016b.\000\000.\016\".\001.\001W.\001.\001W.\016b.\000\000.\016\001.\001W +AQAfBCApIiMEJCTrJ3//BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBf//KwQsLS4vBAAAAQAAAQ== 0 177 AQAfBCApIiMEJCTrJ3//BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBf//KwQsLS4vBAAAAQAA 598 \000.\004\032\)\"#\004\$\$\235'\127\255\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\255\255+.,-\./.\000\000\001\000 +AgAABgYGBgYcBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBAYGBgYGBgYGBgYGBgQGBgYGBgYGBgYGBgYGBgYGBkAGBgYQBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGZAYGBgYGBgYGsgYGBgYGBgYGBgYGBgYFBgYGBgYGBgYGBgYGGgYGBgYGBgYGBgYGBhMGBgYGBgAgBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgboIR4fBCApIiMELyTrJwQIKSorACw= 0 241 AgAABgYGBgYcBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBAYGBgYGBgYGBgYGBgQGBgYGBgYGBgYGBgYGBgYGBkAGBgYQBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGZAYGBgYGBgYGsgYGBgYGBgYGBgYGBgYFBgYGBgYGBgYGBgYGGgYGBgYGBgYGBgYGBhMGBgYGBgAgBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgboIR4fBCApIiMELyTrJwQIKSorAA== 821 \000\000.\006\006\006\006\028\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\004\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\@.\006\006\016\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006d\006\006\006.\006\006\006\006\178\006.\006\006\006\006\006\006.\006\006\006\006\005\006.\006\006\006\006\006\006.\006\006\006\026\006\006.\006\006\006\006\006\006.\006\006\019\006\006\006.\006\000\032\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\232!\030\031.\032\)\"#./\$\235'.\008\)*+ +AgAfBCApIiMEJCTrJwQIKSqrBCwtLi8EMEECAB8EBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcGBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcOBwcHBwczMzMaOzMzMzMzMzMzMzMzMwcHBwcHBwcHBwcHBwcHBwcHBw4HBwcHBwcHIQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHFwcHBwcHBwcHBwcHBwIQIgcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcHBwcHBwcHAhAiAhAiBi4vAAABBDAx+X8EDA0SDxAiAhAiBi4vBDAxKjMENDU2IgYECAn5fwQMDRIPBCozBAcHBwcHBwcHBwcHBwcHBwcQERITBBQREkAAARYXMzMzMzMzMzMRMzMzMzMzM/9/EwQUERYXBBgkGhsEFB0CECIGBAgJ+X8EDCcSDwQQERITBEAAFhbogAAAGwQUHQAQMwQ0MX/+//8ICQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHDgcHBwcHBwchBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcHBwcHBwcHBwcHfwAEJDQdAhAiAhBAAhAiAhAiEkAAARYXBBgZGhsEFB0gHwAzMzM= 0 -1 +AgQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAQQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBOUDBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBATlAwQEBAQEBAQEBAQEBAQAAA== 0 165 AgQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAQQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBOUDBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBATlAwQEBAQEBAQEBAQEBAQA 554 \004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\000\000.\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\229\003\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\229.\004\004\004.\004\004\004\004.\004\004\004\004 +AgICAgICAgICAgICAgICAg8CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIiMELyTrJwQIKSorACw= 2 119 AgICAgICAgICAgICAgIPAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiIjBC8k6ycECCkqKwA= 337 \002\002.\002\002.\002\002.\002\002.\002\015.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\"#./\$\235'.\008\)*+ +BAABAgMEAAAEAAQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BEBBQkMEREV/RwRISUtLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbR42BCAhIiMEJCUmJwQoKSorBCwtLi8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChogAA 0 246 BAABAgMEAAAEAAQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BEBBQkMEREV/RwRISUtLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbR42BCAhIiMEJCUmJwQoKSorBCwtLi8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChogAA 455 \000\001\002\003.\000\000\004\000.\008\009\010\011.\012\013\014\015.\016\017\018\019.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?.\@ABC.DE0G.HIKK.LMNO.PQRS.TUVW.XYZ[.\\]^_.89:\027.<=>?.\@ABC.DE\127G.HIKK.LMNO.PQRS.TUVW.XYZ[.\\]^_.`abc.defg.hijk.lm\0306.\032!\"#.\$%&'.\(\)*+.,-\./.\128\129\130\131.\132\133\134\135.\136\137\138\139.\140\141\142\143.\144\145\146\147.\148\149\150\151.\152\153\154\155.\156\157\158\159.\160\161\162\000 +BAABAgMEAAAEAAQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BEBBQkMEREUwRwRISUtLBExNTk8EUFFSUwRUVVZXBEJZWlsEXF1eXwRgNTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BJSVlpcEmJmamwScnaGiAAA= 0 241 BAABAgMEAAAEAAQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BEBBQkMEREUwRwRISUtLBExNTk8EUFFSUwRUVVZXBEJZWlsEXF1eXwRgNTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BJSVlpcEmJmamwScnaGiAA== 370 \000\001\002\003.\000\000\004\000.\008\009\010\011.\012\013\014\015.\016\017\018\019.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?.\@ABC.DE0G.HIKK.LMNO.PQRS.TUVW.XYZ[.\\]^_.89:\027.<=>?.\@ABC.DE0G.HIKK.LMNO.PQRS.TUVW.BYZ[.\\]^_.`567.89:\;.<=>?.\@ABC.DE0G.HIKK.LMNO.PQRS.TUVW.XYZ[.\\]^_.89:\027.<=>?.\148\149\150\151.\152\153\154\155.\156\157\161\162 +EMDAwMDANjYAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAA= 0 146 EMDAwMDANjYAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAA= 475 \192\192\192\192\19266\000\003\003\003\003\003\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\000 +AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFQACAEACECICEEACECICECICEEACEBYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQWAAIAQAIQIgIQQAIQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CADs= 0 253 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFQACAEACECICEEACECICECICEEACEBYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQWAAIAQAIQIgIQQAIQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CAA== 715 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\000.\000\@.\016\".\016\@.\016\".\016\".\016\@.\016\022.\004\024:\026\027\004\011\128\000\000\0005\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\004\008\002\002\002\002.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\020\029\030\031&5\)\"\025\004\$\$\022\000\002\000\@.\016\".\016\@.\016\".\016\".\016\@.\016\".\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\002\@\002\002.\254\002 +AgAfBCApIiMEJCTrJwQIKSqrBCwtLi8EMEECAB8EBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwYHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBw4HBwcHBzMzMxo7MzMzMzMzMzMzMzMzBwcHBwcHBwcHBwcHBwcHBwcHDgcHBwcHBwchBwcHBwcHBwcHBwcF//8FBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcHBwcHBwcHAhAiBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBxcHBwcHBwMHBwcHBwcCECICECIGLi8AAAEEMDH5fwQMDRIPECICECIGLi8EMDEqMwQ0NTYiBgQICfl/BAwNEg8EKjMEBwcHBwcHB8XFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBgcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHDgcHBwcHMzMzGjszMzMzMzMzMzMzMzMHBwcHBwcHBwcHBwcHBwcHBwcOBwcHBwcHByEHBwcHBwcHBwcHBwX//wUHBwcHBwcHBwcHBwcHBwcHBxcHBwcHBwcHBwcHBwcCECIHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHFwcHBwcHAwcHBwcHBwIQIgIQIgYuLwAAAQQwMfl/BAwNEg8QIgIQIgYuLwQwMSozBDQ1NiIGBAgJ+X8EDA0SDwQqMwQHBwcHBwcHxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFBwcHBwcHBwcHEBESEwQUERJAAAEWFzMzMzMzMzMzETMzMzMzMzP/fxMEFBEWFwQYJBobBBQdAhAiBgQICfl/BAwnEg8EEBESEwRAABYW6IAAABsEFB0AEDMENDF//v//CAkHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBw4HBwcHBwcHIQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHFwcHBwcHBwcHBwfFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcUHBwcH 0 -1 +BB8BAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pl8EYGFgYwRkZWZnBGhpamsEbG1ubwRwcXJzBHR1VlcEWFlaWwRcXV5fBGBhYmMEZGVmZwRoaWprBGxtbm8EcHFycwR0dXZ3BHh5ensEfH1+fwSAgYKDBISFhocAAAGK 8 163 BgcECAkKCwQMDQ4PBBAREhMEFBUWFwQYGRobBBwdHh8EICEiIwQkJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT5fBGBhYGMEZGVmZwRoaWprBGxtbm8EcHFycwR0dVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8EgIGCgwSEhYaHAA== 277 \007\004\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>_.`a`c.defg.hijk.lmno.pqrs.tuVW.XYZ[.\\]^_.`abc.defg.hijk.lmno.pqrs.tuvw.xyz{.|}~\127.\128\129\130\131.\132\133\134\135 +AhI1AAABNTUVOj9ISEhISEhISEhISEhISAMDAwMDAwMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDCAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzYAPRAA+/v7+/v7+wMDAwMDAwMDAwMDAwAAAQMDAwMDAwMDAwMDAwADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMOAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzYAAAGA 68 -1 +AhIAAlBINQAAATU1FTo/SEhISEhIAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMFRTY5Nj42JT09PQEfNjY8NjYkFTY0NjYyNjY2NjYADDY2S0sAAAEBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAA/gABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2Mh02NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Ln7s7OzsAAAB7OzsFDY2NjYAAAAAATY2NDY2NkE2PjY2NjY2NjZO0NDQkNAAFBQUFDY2NTY2QzZYNjY2Nk02NlEAEQEANjY07Ozs7AAA 68 -1 +BCAhIiMEJCUmJwQoKSorBCwtLi8EMDEFGAEfASABIQEiASMBJAEnASgBKQEqASsBLAEtAS4BNwE4ATkBOiA7ATwBPQE+AT8NAQ4BDwEQAREBEgETARQBFwUYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBKQEqASsBLAEtAS4BJwEoAUgBKgErASwBLQEuATsBPAE9AT4BPwA= 0 161 BCAhIiMEJCUmJwQoKSorBCwtLi8EMDEFGAEfASABIQEiASMBJAEnASgBKQEqASsBLAEtAS4BNwE4ATkBOiA7ATwBPQE+AT8NAQ4BDwEQAREBEgETARQBFwUYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBKQEqASsBLAEtAS4BJwEoAUgBKgErASwBLQEuATsBPAE9AT4BPwA= 293 \032!\"#.\$%&'.\(\)*+.,-\./.01\005\024.\031.\032.!.\".#.\$.'.\(.\).*.+.,.-.\..7.8.9.:.\;\001<\001=\001>\001?\013\001\014\001\015\001\016\001\017\001\018\001\019\001\020\001\023\005\024\001\025\001\026.\027.\028.\029.\030.\031.\032.!.\".#.\$.%.&.'.\(.\).*.+.,.-.\..'.\(.H.*.+.,.-.\..\;.<.=.>.? +AX8CAAAA 0 6 AX8CAAAA 14 \127.\000\000 +AgIAAAEC 0 4 AgIAAA== 9 \002\000 +AQAAZA== 0 3 AQAA 5 \000 +AQWhQEBAQAAAAQ== 1 7 BaFAQEBAAA== 13 \161\@\@\@\@ +JB4kJDUkJCQkJCQkJCQCNCQC/yQkJCQkJAAAASQkJAAkHgcAgAA= 0 38 JB4kJDUkJCQkJCQkJCQCNCQC/yQkJCQkJAAAASQkJAAkHgcAgAA= 95 \030\$\$5\$\$\$\$\$\$\$\$\$\0024\$\002\255\$\$\$\$\$\$\000\000\001\$\$\$\000\$\030\007\000\128 +AQABAwEiAQUBBgEHAQgBCQEKAQsBDAENAQ4BDwESARMBFAEVARYBFwEYARkBGgEbARwBHRABEQESARMBFAEVARYBFwEYARkBGgEbARwBHQEeAZ8BoAGhAaIBowGkAaUBpgGnAagBqQGqAasBrAGtAa4BrwGwAbEBsgGzAbQBtQG2AbcBuAG5AboBuwG8Ab0BvgG/AcABwQHCAcMBxAHFAcYBxwHIAckBygHLAcwBzQHOAc8B0AHRAdIB0wHUAdUB1gHXAdgB2QHaAdsB3AHdAd4B3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QH+Af8A 0 -1 +AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHcAd0V3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9AP4= 0 253 AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHcAd0V3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9AA== 660 \000.\001.\002.\003.\004.\005.\006.\007.\008.\009.\010.\011.\012.\013.\014.\015.\016.\017.\018.\019.\020.\021.\022.\023.\024.\025.\026.\027.\028.\029.\030.\159.\160.\161.\162.\163.\164.\165.\166.\167.\168.\169.\170.\171.\172.\173.\174.\175.\176.\177.\178.\179.\180.\181.\182.\183.\184.\185.\186.\187.\188.\189.\190.\191.\192.\193.\194.\195.\196.\197.\198.\199.\200.\201.\202.\203.\204.\205.\206.\207.\208.\209.\210.\211.\212.\213.\214.\215.\216.\217.\218.\219.\220.\221.\222\001\223\001\224\001\225\001\226\001\227\001\228\001\229\001\230\001\231\001\232.\233.\234.\235.\236.\237.\238.\239.\240.\241.\242.\243.\244.\245.\246.\247.\248.\249.\250.\251.\252.\253 +AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHUAd0B3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9AQEA/wA= 0 255 AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHUAd0B3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9AQEA 635 \000.\001.\002.\003.\004.\005.\006.\007.\008.\009.\010.\011.\012.\013.\014.\015.\016.\017.\018.\019.\020.\021.\022.\023.\024.\025.\026.\027.\028.\029.\030.\159.\160.\161.\162.\163.\164.\165.\166.\167.\168.\169.\170.\171.\172.\173.\174.\175.\176.\177.\178.\179.\180.\181.\182.\183.\184.\185.\186.\187.\188.\189.\190.\191.\192.\193.\194.\195.\196.\197.\198.\199.\200.\201.\202.\203.\204.\205.\206.\207.\208.\209.\210.\211.\212.\213.\214.\215.\216.\217.\218.\219.\212.\221.\222.\223.\224.\225.\226.\227.\228.\229.\230.\231.\232.\233.\234.\235.\236.\237.\238.\239.\240.\241.\242.\243.\244.\245.\246.\247.\248.\249.\250.\251.\252.\253.\001 +AgAADABAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsmCx0eHw01KSIZBCQkAAD/AEACEBgCEEACECICECIGBBAiAhBAAgIQIgYECAICAgICECICEEACECICECIGBAgJIgICAhAiAhBAAhAiAhAiBgQICf9/BAwNIA8EEAgSEwQBFRYXBBgBFRYXBBg6GhsECx0eEA01KSIZBCQ6NSkiGQQkJAAAAgBAAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQOAAIAQAIQIgIQQAIQIgIQIgYECAJAAgIC/gICOwA= 0 239 AgAADABAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsmCx0eHw01KSIZBCQkAAD/AEACEBgCEEACECICECIGBBAiAhBAAgIQIgYECAICAgICECICEEACECICECIGBAgJIgICAhAiAhBAAhAiAhAiBgQICf9/BAwNIA8EEAgSEwQBFRYXBBgBFRYXBBg6GhsECx0eEA01KSIZBCQ6NSkiGQQkJAAAAgBAAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQOAAIAQAIQIgIQQAIQIgIQIgYECAJAAgIC/gICOwA= 793 \000\000.\000\@\002\016\"\002\016\@\002\016\"\002.\"\006\004\008\009\255\127\004\012\013\018\015\004\016\008\018.\004\001\021\022\023\004\024:\026\027&\011\029\030\031\0135\)\".\004\$\$\000\000\255\000\@\002\016\024\002\016\@\002\016\"\002\016\"\006\004\016\"\002.\@\002\002\016\"\006\004\008\002\002\002\002\002\016\"\002.\@\002\016\"\002\016\"\006\004\008\009\"\002\002\002\016.\002\016\@\002\016\"\002\016\"\006\004\008\009\255\127\004\012\013\032\015\004\016\008\018\019\004\001\021\022\023\004\024\001\021.\023\004\024:\026\027\004\011\029\030\016\0135\)\"\025\004\$:5\)\".\004\$\$\000\000\002\000\@\002\016\"\002\016\@\002\016\"\002\016\"\002\016\@\002\016.\002\016\031\004\032\)\"#\004\$\$\014\000\002\000\@\002\016\"\002\016\@\002\016\"\002\016\"\006\004\008\002\@\002.\002\254.\002\; +BOgDAwgINjY2NjY2NjY2PAA3NhM2NjY2NjY2Nkk2NjY2NjZAAAAANjk2NjY2NgAAAAFANjY2NjY2NjY2Ng82NjY8ADc2EzY2NjY2NjY2ADY2NjY2NjY2NjY28Da3NjY2NjbwNrc2NjY2NjY8ADc2EzY2NjY2NjY2NjY2NvA2tzY2NjYaAAE2NiM2NjY2NoE2NjY2NqVCPAAhNhM2NjY2NjY2Np42O/oYNhM2MjY2NjY2NgA2NjYAAAHwNrc2NjY2NjY2NjY2NjY2NjY2NjY2NjY5NjY2MTY2NjY2Njb/fzY2AAE2NjZ/PjZUnjY8ABg2NjY2Nj5SNhQ+AICAADYAAAE2 0 255 BOgDAwgINjY2NjY2NjY2PAA3NhM2NjY2NjY2Nkk2NjY2NjZAAAAANjk2NjY2NgAAAAFANjY2NjY2NjY2Ng82NjY8ADc2EzY2NjY2NjY2ADY2NjY2NjY2NjY28Da3NjY2NjbwNrc2NjY2NjY8ADc2EzY2NjY2NjY2NjY2NvA2tzY2NjYaAAE2NiM2NjY2NoE2NjY2NqVCPAAhNhM2NjY2NjY2Np42O/oYNhM2MjY2NjY2NgA2NjYAAAHwNrc2NjY2NjY2NjY2NjY2NjY2NjY2NjY5NjY2MTY2NjY2Njb/fzY2AAE2NjZ/PjZUnjY8ABg2NjY2Nj5SNhQ+AICAADYA 419 \232\003\003\008.66666666.<\00076\01966666666I666666\@\000\000\0006966666\000\000\000\001\@6666666666\015666<\00076.66666666\0006666666666.\2406\18366666\2406\183666666<\00076\019666666666666\2406\1836666\026\000\00166#66666\1296.666\165B<\000!6\01966666666\1586\;\250\0246\01962666666\000666\000\000\001\2406\18366666666666.666666666966616666666\255\12766\000\001666\127>6T\1586<\000\02466666>R6\020>\000\128\128\0006 +BOgDAwgINjY2NjY2NjY2NjYAAH//NgAAf/8XAjZ/UV5eIAAXFxcXFxcXFxcXFwI2fzZeAAABXiAAATYAAEVkNgAANjY2NjY2NgABQDY2NjYyNjYjQzb/fxN1Njb8NjaeQjwAIVkTNjY2Nfs2NjaeNFnkGDITNjY2Njb/HDf/fzY2NgAAAf///382VzY2NgA2NjY2NjY2NjY2NjY2AAAANjb/////NgAAAFw2f////zY2NjE2NjY2//82/382NjYAAAH///9/ZAABNjY2NjY2Np5eXl4RATYAAEVkNgAANjY2NjY2NgABQDY2NgABNg== 0 236 BOgDAwgINjY2NjY2NjY2NjYAAH//NgAAf/8XAjZ/UV5eIAAXFxcXFxcXFxcXFwI2fzZeAAABXiAAATYAAEVkNgAANjY2NjY2NgABQDY2NjYyNjYjQzb/fxN1Njb8NjaeQjwAIVkTNjY2Nfs2NjaeNFnkGDITNjY2Njb/HDf/fzY2NgAAAf///382VzY2NgA2NjY2NjY2NjY2NjY2AAAANjb/////NgAAAFw2f////zY2NjE2NjY2//82/382NjYAAAH///9/ZAABNjY2NjY2Np5eXl4RATYAAEVkNgAANjY2NjY2NgABQDY2NgA= 544 \232\003\003\008.66666666.66\000\000\127\2556\000\000\127\255\023\0026\127Q^^\032\000\023\023\023\023\023\023\023\023\023\023\023\0026\1276^\000\000\001^\032\000\0016\000\000Ed6\000\000666.666\000\001\@6666266#C6\255\127\019u66\25266\158B<\000!Y\0196665\251666\1584Y\228\0242\01966666\255\028.\255\127666\000\000\001\255\255\255\1276W666\0006666666666666\000\000\00066\255\255\255\2556\000\000\000\\6\127\255\255\25566616.66\255\2556\255\127666\000\000\001\255\255\255\127d\000\0016666666\158^^^\017\0016\000\000Ed6\000\0006666666\000\001\@666 +AykpKSkpKSkpKQQEKSkpKSkpKSkpKSkpKSkpDAAAASkMKSkuKSkpKSkpKSkpKSkpKCkG9QgJfyFAKSkpKSn/KSkpKSkAAAEpKQcEKSkpKSkpKSkpKSkpKSkpKQwpKSkpKSkpKSkpKSkpKQwpDCkpLikpKSkpKSkpKSkpKSkpKSkpKTsEQAIpKSkpKCkG9QgJCiFAKSkpKSn/KSkpKUUpKQcEKSkpKSkyKSkpKbckODlXOwRAAD4pBwQgKSkpKQAAEAA= 0 191 AykpKSkpKSkpKQQEKSkpKSkpKSkpKSkpKSkpDAAAASkMKSkuKSkpKSkpKSkpKSkpKCkG9QgJfyFAKSkpKSn/KSkpKSkAAAEpKQcEKSkpKSkpKSkpKSkpKSkpKQwpKSkpKSkpKSkpKSkpKQwpDCkpLikpKSkpKSkpKSkpKSkpKSkpKTsEQAIpKSkpKCkG9QgJCiFAKSkpKSn/KSkpKUUpKQcEKSkpKSkyKSkpKbckODlXOwRAAD4pBwQgKSkpKQA= 441 \)\)\).\)\)\)\)\)\004\004\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\012\000\000\001\)\012\)\)\.\)\)\)\)\)\)\)\)\)\).\)\(\)\006\245\008\009\127!\@\)\)\)\)\)\255\)\)\)\)\)\000\000\001\)\)\007\004\)\)\)\)\)\)\)\)\)\)\)\)\).\)\)\012\)\)\)\)\)\)\)\)\)\)\)\)\)\)\012\)\012\)\)\.\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\).\004\@\002\)\)\)\)\(\)\006\245\008\009\010!\@\)\)\)\)\)\255\)\)\)\)E\)\)\007\004\)\)\)\)\)2\)\)\)\)\183\$89W\;\004\@\000>\)\007\004\032\)\)\)\) +BAABFwMBBRYXBBgZGhsEHB0eAAAAACIjBCQlJicEKCkqKwQsOy4vBCAhIiMEJCUmJwQoKSorBCw7Li8EBAQFFhcEGBkaGwQcHR4AAAAAIiMEJCUmJwQoKSorBCw7Li8EICEiIwQkJSYnBCgpKisELDsuLwQwMTIzBDQ1NjcEODk6OwQ8PT5BAA== 0 136 BAABFwMBBRYXBBgZGhsEHB0eAAAAACIjBCQlJicEKCkqKwQsOy4vBCAhIiMEJCUmJwQoKSorBCw7Li8EBAQFFhcEGBkaGwQcHR4AAAAAIiMEJCUmJwQoKSorBCw7Li8EICEiIwQkJSYnBCgpKisELDsuLwQwMTIzBDQ1NjcEODk6OwQ8PT5BAA== 309 \000\001\023\003.\005.\023\004\024\025\026\027\004\028\029\030\000\000\000\000\"#\004\$%&'\004.\)*+\004,\;\./\004\032!\"#\004\$%&'\004\(\)*+\004,\;\./\004\004\004\005\022\023\004\024\025\026\027\004.\029\030\000\000\000\000\"#\004\$%&'\004\(\)*+\004,\;\./\004\032!\"#.\$%&'.\(\)*+.,\;\./.0123.4567.89:\;.<=>A +PwDuAQMEBQYHCAl8fHx8fHx8fHx8fHx8fHx8fHx8fHx8ICEiIyQlJjU2Nzg5Ojs8ICEiIyQlJjU2Nzg5Ojs8PT4/P0BBQkNEVHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8ICEiIyQlJjU2Nzg5Ojs8ICEiIyQlJjU2Nzg5Ojs8PT4/P0BBQkNEVCEiIyQlJjU2Nzg5Ojs8ICEiIyQlJiAhVVZXWFlaW1xdXl9gABBjZGVwcXJzdHV2QAAAfA== 0 188 PwDuAQMEBQYHCAl8fHx8fHx8fHx8fHx8fHx8fHx8fHx8ICEiIyQlJjU2Nzg5Ojs8ICEiIyQlJjU2Nzg5Ojs8PT4/P0BBQkNEVHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8ICEiIyQlJjU2Nzg5Ojs8ICEiIyQlJjU2Nzg5Ojs8PT4/P0BBQkNEVCEiIyQlJjU2Nzg5Ojs8ICEiIyQlJiAhVVZXWFlaW1xdXl9gABBjZGVwcXJzdHV2QAA= 261 \000\238\001\003\004\005\006\007\008\009||||||||||||||||||||||\032!\"#\$%&56789:\;<\032!\"#\$%&56789:\;<=.??\@ABCDT||||||||||||||||||||||||||\032!\"#\$%&56789:\;<\032!\"#\$%&56789:.<=>??\@ABCDT!\"#\$%&56789:\;<\032!\"#\$%&\032!UVWXYZ[\\]^_`\000\016cdepqrstuv\@ +PwDuKSkpKSkpKSkpRikpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpIikpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKRYpKSlyc3R1dkAAAAB7 0 149 PwDuKSkpKSkpKSkpRikpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpIikpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKRYpKSlyc3R1dkAAAAA= 297 \000\238\)\)\)\)\)\)\)\)\)F\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\".\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\).\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\022\)\)\)rstuv\@\000\000 +PwDuHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHQAAAR0dHR0dHR0dHR0dHR0+HR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHQAAAR0dHR0dHR0dHR0dHR0+HR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0UHR0dHR0dHR0dHR0BAwAAAQT9BQcICXx8fHx8fHx8AAABAHx8fHx8IAB8 0 245 PwDuHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHQAAAR0dHR0dHR0dHR0dHR0+HR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHQAAAR0dHR0dHR0dHR0dHR0+HR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0UHR0dHR0dHR0dHR0BAwAAAQT9BQcICXx8fHx8fHx8AAABAHx8fHx8IAA= 910 \000\238\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\000\000\001\029\029\029\029\029\029\029\029\029\029\029\029\029>\029\029\029\029\029\029\029\029\029\029.\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029.\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\000\000\001\029\029\029.\029\029\029\029\029\029\029\029\029>\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029.\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029.\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\020\029\029\029\029\029\029\029\029\029\029.\001\003\000\000\001\004\253\005\007\008\009||||||||\000\000\001\000|||||\032 +AQAAAAEgAAAA8Q8iAhAiAAABDkQICf9/BAAAAAEQCGNjL39jY2NjeHhvY2NjRwEVFjcEGDpaFwQLgAD//3//IgIAAAEQABCAAP//f/8iAhAAEBCb9BYfBENBh6AA+vr6FNkEAAQIZP8zAA== 100 6 BAhk/zMA 11 \008d\2553 +AgAAAgAAAAEiAg== 0 7 AgAAAgAAAA== 18 \000\000.\000\000 +AgAAAgBAAhAiAhBAAhAiAhAiBgQIDf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaIiMEBCQAAAIAQAIQAAIfQAIQIgIQIgYECAIChgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEAIECIiAEACECICECIGBAgCQAICAv4CAA== 0 250 AgAAAgBAAhAiAhBAAhAiAhAiBgQIDf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaIiMEBCQAAAIAQAIQAAIfQAIQIgIQIgYECAIChgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEAIECIiAEACECICECIGBAgCQAICAv4CAA== 754 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\013\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\128\000\000\0005\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\"#\004\004\$\000\000\002\000\@\002\016\000\002\031\@\002\016\".\016\".\004\008\002\002\134\002.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\020\029\030\031&5\)\"\025\004\$\$\016\"\002\016\".\016\@.\016\".\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\"\"\000\@\002\016\".\016\".\004\008\002\@\002\002.\254\002 +AQABAwEiAQcBCAEJAQoBCwEMAQ0BDgEPARIBEwEUARUBFgEXARgBGQEaARsBHAEdEAERARIBEwEUARUBFgEXAX0BGQEaARsBHAEdAR4BnwGgAaEBAAA= 0 86 AQABAwEiAQcBCAEJAQoBCwEMAQ0BDgEPARIBEwEUARUBFgEXARgBGQEaARsBHAEdEAERARIBEwEUARUBFgEXAX0BGQEaARsBHAEdAR4BnwGgAaEBAAA= 230 \000.\003.\".\007.\008.\009.\010.\011.\012.\013.\014.\015.\018.\019.\020.\021.\022.\023.\024.\025.\026.\027.\028.\029.\001\017\001\018\001\019\001\020\001\021\001\022\001\023\001}.\025.\026.\027.\028.\029.\030.\159.\160.\161.\000 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sNNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAARU2ClA2NtDO09DQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dgAA//92dnb/CwAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sNNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAARU2ClA2NtDO09DQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dgAA//92dnb/CwAA 633 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0136\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\001\0216\010P66\208\206\211\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\1276X+66666v\000\000\255\255vvv\255\011\000 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQsNjYAAdDQkAAAFBQUFDY2gH82WCs2NjY2NnZ2dnZ2dnZ2/wsAAAEAGw== 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQsNjYAAdDQkAAAFBQUFDY2gH82WCs2NjY2NnZ2dnZ2dnZ2/wsAAAEA 615 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020,66\000\001\208\208\144\000\000\020\020\020\02066\128\1276X+66666vvvvvvvv\255\011\000\000\001 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QAAAAAAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QAAAAAAA 625 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\000\001X+66666vvvvvv\@\000\000\000\000 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEAAAAAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEAAAAAA 623 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\000\001X+66666vvvvvv\@\@\000\000\000 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAA 621 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\000\001X+66666vvvvvv\@\@\@\000\000 +BAABAgMEBAUGBwQICQoLBBINDg8EEBESEwQUFRYXBBgZGhsEHB0eNjY2AAA2NjY2Njw2ATYYNkUAAAIQ//9/TExMTExMTExMTExMTExMTExMTExMTENMTBMTExNqEykTlhMTEyYLAAEUFAAABjY2NjYAAAE2NhwAAAABAAABBDb/fwAAAzY2NgX//wU2NgD7SDYkNjk5OTk5OTk5OTk5OTk5OTk5OTk5PTY0pDY2NjY2NiQAAAE2Nn82cXZ2dnZ2dnZ20Coq0DPQ0P/QM9DQ//9//9AAAAHSu9DRkNAABgAA/xQUAAAGfzYkNjY0Nks2AAQeVTb/AAABNn////8= 0 -1 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAQAAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAQAAA 619 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\000\001X+66666vvvvvv\@\@\@\@\000 +ISEhISEhISEhISEhISEhISEhISEAA+gAISEhISEhISEhISEhISEhGiEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhISEhIYAhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhIRAhISEhISEhISEhISEhISEhISEhISEhISEhIYAhISEhISEpcnN0dXZAAA== 33 205 ISEhISEhGiEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhISEhIYAhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhIRAhISEhISEhISEhISEhISEhISEhISEhISEhIYAhISEhISEpcnN0dXZAAA== 218 !!!!!\026!!!!!!!!!!!C!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!!!!!!!~!!!!!!!!!!!.!\128!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!C!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!~!!!!!!!!!!\016!!!!!!.!!!!!!!!!!!!!!!!!!!\128!!!!!!\)rstuv\@ +AQABAQEAAAEBBBswGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbBhsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsVGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGyobGxsbGxsbGxsbGxsbGxsbGxsbzs7Ozs7Ozs7Ozs4bGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsmGxsbGhsbGxsbNRsbGxsbGxsbGw== 0 7 AQABAQEAAA== 15 \000.\001.\000 +AQABAQECAQMbGwAAARsbGxsbGzobGyAbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbG2kbGxsbFRsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGwMbGxsbGxsbGxsbGxsbGxsbGxsbGxsiGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxvfGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsmGxsbGxsbGxsbGxsbGxsbGxsbGw== 0 -1 +AQABAQECAQMBBAEFAQYBB+sIAQkBCgELxwwBDQEOAQEXJwEoAT42JT09PTYfNjY8NjYkFTY0NjYyAAABNjY2NjYADDY2S0sAAAEBFr4fRhQ2NjY2AAA2Nlg2iTw2HDY2NgAA/gABRDY2TjY2JBA2BLM2ojY2NjY2Bf8AG0Q2OTZNNiU9PT0BNlM2AAAAAQA2NDY2MjY2NjYyJjY2NjYAEDY2S0tLQAAAAUsBNr4fRhTDHzbAQDYufuzs7OwAAAHs7OwUNjY2NgAAAH//NjY0NjY2QTYAAAE+NjY2NjY2Nk7W0NCQ0AAUFBQUGjY1UzZDNlh/NjY2TTY2UQARAQA= 0 -1 +AQABAQECAQMBBAEFAAABBwEIAQkBCgELAQwBDQEOAQ8BECABIQEiASMBJAElASYBJwEoAAw2NktLAAABARa+/kYkFTY0NjYyNjY2NjYADDY2S0sAAAEBFr7+RhQ2NjY2AAA2Nlg0djw2NjY2NgAA/t4BNjY2PDY2MxU2AbM2ojY2NjY2Bf82NjYAEDY2S0tLQAAAAUt//74fRhTANjQ2NiQ2NjY2NgAQNjZLAAABfvPs7OwAAAHs7OwUNjY2NgAAAAABNjY0NjY2QTY+NjY2NjY2Nk7Q1NCQ0AAUFBQUNjY1NjZDNlg2NjY2TTY2UQARAQA= 0 13 AQABAQECAQMBBAEFAA== 30 \000.\001.\002.\003.\004.\005 +AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8CAgICAgICAoAAAgICAAABAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC 0 42 AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8CAgICAgICAoAA 107 \000.\001.\002.\003.\004.\005.\006.\007.\008.\009.\010.\011.\012.\013.\014.\015.\002\002.\002\002.\002\128 +BOgAAAEDAwgINjY2NgAAAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2NDZYBAX//wU2NjY0NgAANjYWNjY259DQ0NDQ0NDQNjY2ABtLbEtLS0tLS0sBNr4fRhQ2NjY2AAA2NiQ2NjQ2NjY2NjY2NjY2NjY2NjY2NiQ2Nn92dnZ2dnZ2doF2dnZ2dnZBNgE2HgQF//8FNjY2NDYAAAkAAAGANjYWNjY20NDQ0NDQ0NDQf9DQ0NDQ0NDQ0NDQkNAAFBQAAAEUFDY2NjY2NjZYNjY2Nk0hNlEAEQEAAAE2Ng== 0 -1 +BOgAAAEDAwgINjY2AAABNgAAAMAAAADAHzaAADY2JBU2NjYVNgAENjw2NjY2NjY2BAX//+fQ0NDQ0NDQ0DY4NjY2NjY2NjY2AAAAAQQ2NjY2NjY2NjY2NjY2AAAAAQAbS2xLS0tLS0tLATa+H0YUNjY2NgAANjYgNjY0NjY2NjY2NjY0NjY2NjY2NvoAAPp/dnZ2dnZ2dnZ2dnZ2dnaAQTYBNh4EBf//BTY20NDQ0NDQ0NB2dnZ2dnZ2dnZ2QTYB0NDQ0DPQ0NDQ0ND///+A0JDQABQUAAAaNk0hNlEAEQEAAAE2Ng== 0 -1 +BOgAAAEDAwgINjY2NeYAAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2NDZYBAH//wU2NjY0NgAAAQDoAYA2NhY2Njbn0NDQ0DY2NjY2Fk//AAAAAAABABtLbEtLS0tLSwAAAQQ2NjQ2NjY2Nic2NjY2NjY2NgABAAA2Nn92dnZ2dnZ2dnZ2dnZ2dnZBNgE2HgQF//8FNjY2NDYAADY2NjY2Fk//AAAAAAABABtLbEtLS0sJAAABgDY2FjY2NtDQ0NDQ0NDQ0DPQw9DQ0NDQ0NDQ0JDQABQUAAABFBQ2NjY2NjY2aTY2NjZNITZAABEBAAABNjY= 0 88 BOgAAAEDAwgINjY2NeYAAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2NDZYBAH//wU2NjY0NgAAAQDoAYA2NhY2Njbn0NDQ0DY2NjY2Fk//AAAAAAABAA== 217 \232\000\000\001.\003\008\008.665\230\000\000\192\0316\128\00066\$\021666\0216\000\004666666666646X\004\001\255\255\00566646\000\000\001\000\232\001\12866.666\231\208\208\208\20866666\022O\255\000\000\000\000\000\001 +BOgAAAEDAwgINjY2AAABAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2NDZYBAX//wU2NjY0NgAAAQAAAYA2NhY2Njbn0NDQ0NDQ0NA2NjY2NjY2NjY2NgAAAAEENjY2NjY2NjY2NjY2NgAAAAEAG0tsS0tLS0tLSwE2vh9GFDY2NjY2AAAAAQQ2NjY2NjY2NjY2NjY2NjY2NjY2JDY2f3Z2dnZ2dnZ2dnZ2dnZ2dkE2ATYeBAX//wU2NjY0NgAACQAAAYA2NhY2NjbQ0NDQ0NDQ0NAz0NDQ0NDQ0NDQ0NCQ0AAUFAAAARQUNjY2NjY2Nlg2NjY2TSE2UQARAQAAATY2 0 255 BOgAAAEDAwgINjY2AAABAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2NDZYBAX//wU2NjY0NgAAAQAAAYA2NhY2Njbn0NDQ0NDQ0NA2NjY2NjY2NjY2NgAAAAEENjY2NjY2NjY2NjY2NgAAAAEAG0tsS0tLS0tLSwE2vh9GFDY2NjY2AAAAAQQ2NjY2NjY2NjY2NjY2NjY2NjY2JDY2f3Z2dnZ2dnZ2dnZ2dnZ2dkE2ATYeBAX//wU2NjY0NgAACQAAAYA2NhY2NjbQ0NDQ0NDQ0NAz0NDQ0NDQ0NDQ0NCQ0AAUFAAAARQUNjY2NjY2Nlg2NjY2TSE2UQARAQAA 583 \232\000\000\001.\003\008\008.66\000\000\001\000\192\0316\128\00066\$\021666\0216\000\004666666666646X\004\005\255\255\00566646\000\000\001\000\000\001\12866.666\231\208\208\208\208\208\208\208\2086666666666.\000\000\000\001\0046666666666666\000\000\000\001\000\027KlKKKKKKK\0016\190\031F\02066666\000\000\000\001\00466666.6666666666666\$66\127vvvvvvvvvvvvvvvA6\0016\030\004\005\255\255\00566646\000\000\009\000\000\001\128.6\022666\208\208\208\208\208\208\208\208\2083\208\208\208\208\208\208\208\208\208\208\208\144\208\000\020\020\000\000\001\020\0206666666X6666M!6Q\000\017.\000 +BOgAAGQAAAA2AAAAwB82gAA2NoAANjYkFTY2NhU2IAQ2NjY2NjY2NjY2NDYAAAFYBAX//wA2NjY0Nu//NTY2AAAAAQQ2NjY2////fzY0NiMAG0tsS2RLS0tLSwEAAAE2vh9GFDY2NjYAAAE2dnZ2dnZ2dnZ2dgAAAUE+ATYeBAX//wU2NjY0NgAACQAAaWlpaWlpaWlpaWnzaWlpaWn/f2lpaWlpaWlYNjY2Nk0hHVEAEQEAAAE2Ng== 0 6 BOgAAGQA 14 \232\000\000d +BOgAAAEDAwgINjY2NgAAAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2PSIjBCQlJicEPykqFQQsLS4uBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEVGRwRISUpLBExNQ08EUFFSWwRUVVZXBFhZWlsEXE1eXwRgYWJjBGRlZmcEaGlqawRsbR4fBCAhIiMEJCUmJwQoKSorBCwtJy8EgIGCgwT6hYaHBIiJiosENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwQ= 0 -1 +AAABBOgAAEFAA+gYAAA2TgD/8sAQAAAAATAkAAABAAE2AwAAdj52ATT/YTk5GVQ5Ad42QCL7/zA= 0 1 AA== 2 . +wMAAAcDgwMDANjY2NgAAGsAfNjY8NjYkFTo0NjYyNjY2NjYAEDY2S0s2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2NiU9PT0BHzY2FDY2NjYAADY2WDZ2PDY2NjY2AAD+AAE2NjY8NjYkFTYEszaiNjY2NjYF//8FRTY5Nj42JT09PQEAAAABADY0NjYyNjY2NjYAEDY2S0tLQABAAUsBNr4fRhQ2////fyQVNgTAHzYufuwp7OwAAAHs7OwUNjY2NgAAAAAAAAE0NjYAAAE+NjY2NjY2Nk7Q0NCQ0AsUFBQUNjY1NjZDNlg2NjY2TTY2UQD//wVFNjk2PjYlPT09AR82NhQ2NjY2AAA2Nlg2djw2NjY2NgAA/gABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NjY2Bf//BUU2OTY+NiU9PT0BAAAAAQA2gAAAADY2NjY2ABA2NktLS0AAAAFLATa+H0YUNv///38kFTYEwB82Ln7s7OzsAAAB7OzsFDY2NhEBAA== 16 2 NjY2NgAQNjZLSzY2WDZ2PDY2NjY2AAABAAE2NjY8NjYkFTYEszaiNjY2JT09PQEfNjYUNjY2NgA= 98 666\000\01666KK66X6v<66666\000\000\001\000\001666<66\$\0216\004\1796\162666%===\001\03166\0206666 +wMgAAcDgwMDANjY2NgAAGsAfNmY8NjY2QzZYNjY2NjY2NjYAAAE2S0s2NgFK4za+H0YUwB82Ln7s7OzsAAAB7BDsFDY2NjYAAAAAAf//NDZKNjZBNj42NjY2gDY2TtDQQTY+NjY2NjY2Nk7Q4tCQ0AAUFP////81NjZDNlg2Nhc2TTY2UQARAQA= 39 -1 +wMAAAcDgwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0s2OFg2djw2NjY2NgAAAQABNjY2PDY2QDY1NjZDNgAAAVhAADY2TTY2UQARAQA= 16 -1 +wMAAAcDgwMDANjY2NgAAGsAfNjY8NjY2cjY2NjY2ABA2NktLS0AAAAFLATYAAAEUwB82Ln7s7OzsAAAB7OzsFDY2NjYAAAAAATY2NDY2NkE2PjY2NjY2NjZOHzY2PDY2JBU2NDY2MjY2NjY2AAw2NktLAAABARa+H0YUNjY2NgAANjZYNnY8NjY2NjYAAP4AATY2Njw2NiQVNgSzNjY2cjY2NjY2ABA2NktLS0AAAAFLATYAAAEUwB82Ln7s7OzsAAAB7OzsFDY2NjYAAAAAATY2NDY2NkE2PjY2NjY2NjZO0NDQkNAAFBQUFDY2NTY2QzZYNjY2Nk02NlEAEQEA 16 -1 +wKoAAcDgwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0s2Nlg2djw2NjY2NkAAAQABNjY2PAAAARU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BHzY2PDY2JBU2AAABMjY2NjY2AAw2NktLAAABARa+AAABNjY2NgAANjZYNnY8NjY2NjYAAP4AATY2Njw2NiQVJgSzNqI2NjY2NgX//wVFNjk2PjYlPT09ATY2NgAAAAEANjQ2NjI2NjY2NgAQNjZLgABAAAABSwE2vh9GFMAfNi5+7Ozs7AAAAezs7BQ2NjY2AAAAAAE2NjQ2NjZBNj42NjY2NjY2TtDQ0JDQABQUFBQ2NjU2NkM2WDY2NjZNQDZRABEBAA== 16 2 NjY2NgAQNjZLSzY2WDZ2PDY2NjY2QAABAAE2NjY8AAABFTYEszaiNjY2NjYF//8FRTY5Nj42JT09PQEfNjY8NjYkFTYAAAEyNjY2NjYADDY2S0sAAAEBFr4AAAE2NjY2AAA2Nlg2djw2NjY2NgAA/gABNjY2PDY2JBUmBLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NkuAAEAAAAFLATa+H0YUwB82Ln7s7OzsAAAB7OzsFDY2NjYAAAAAATY2NDY2NkE2PjY2NjY2NjZO0NDQkNAAFBQUFDY2NTY2QzZYNjY2Nk1ANlEAEQEA 548 666\000\01666KK66X6v<66666\@\000\001\000\001666<\000\000\001\0216\004\1796\16266666\005\255\255\005E696>6%.==\001\03166<66\$\0216\000\000\001266666\000\01266KK\000\000\001\001\022\190\000\000\0016666\000\00066X6v<66666\000\000\254\000\001666.66\$\021&\004\1796\16266666\005\255\255\005E696>6%===\001666\000\000\000\001\0006466266666\000\01666K\128\000\@\000\000\001K\001.\190\031F\020\192\0316\.~\236\236\236\236\000\000\001\236\236\236\0206666\000\000\000\000\001664666A6>6666666N\208\208\208\144\208\000\020\020.\02066566C6X6666M\@6Q\000\017\001 +P8DBwsPExcbHyMnKy8zNzs/Q0dLT1NXe3+AbGxsbGxsbGxsbGxsbGxsbGxsbGyMbGxsbGxsbGxsbGxsbGxsbGxsbGxsbFRsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGwMbGxsbGxsbGxsbGxsbGxvW19jZ2tvc3d7f4BsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsVGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbAxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGyYbGxsbGxsbGxsbGxsbGxsbGxsb 0 -1 +wMAAAcDAf////zY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjZLS0tLSwEWAZ8BoAGhAaIBowGkAaUBpgGxAagBqQGqAasBrAGtAa4BrwGwAbEBsgGzAbQBtQG2AbcBuAG5AboBuwG8Ab0BvgG/AcABwQHCAcMBxAHFAcYBxwHIAckBygHLAcwBzQHOAc8B0AHRAdIB0wHUAdUB1gHXAdgB2QHaAdsB3AHdFd4B3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QD+ 16 2 NjY2NktLS0tLARYBnwGgAaEBogGjAaQBpQGmAbEBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHcAd0V3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9AA== 588 666KKKKK\001\022\001\159\001\160\001\161\001\162\001\163\001\164\001\165\001\166\001\177\001\168\001\169\001\170\001\171\001\172\001\173\001\174\001\175\001\176\001\177\001\178\001\179\001\180.\181.\182.\183.\184.\185.\186.\187.\188.\189.\190.\191.\192.\193.\194.\195.\196.\197.\198.\199.\200.\201.\202.\203.\204.\205.\206.\207.\208.\209.\210.\211.\212.\213.\214.\215.\216.\217.\218.\219.\220.\221.\222\001\223\001\224\001\225\001\226\001\227\001\228\001\229\001\230\001\231\001\232.\233.\234.\235.\236.\237.\238.\239.\240.\241.\242.\243.\244.\245.\246.\247.\248.\249.\250.\251.\252.\253 +BA8EAgAsAID/////MjMEMjU2NwMEFgUEBf//9BEAHP/NBAb/f0AA6iAEICEiIwQkJTon+vr6+vr6BPYGACQICQoQAgAAAQABEgMEBAUEBQYHBEAA6iDkHyEiIwQkJSYn+vr6+vr6+vr6+vr0BBIdLC0u9gQwMSgMBwRkAAAgBEQAIAQgISI= 0 -1 +BGQEAgAsAP//8/QQHALNBAb/9P+AFgAEBf//9AAQHALNBAb/9POAIAAiI/r6BgX2BgAkAAABCGQKEAIgBDYl+vr6fwAAAAAEIAAiI/r6BgX2BgAkAAABCGQKEAIgBDYlJif5+/rZ+voE9gYAJAhkChACIAO9AAESGQQEBQQFAwb/fwB/AAAELS72p6enp6enp6enp6enp6cgBJKSkqlxkiAhIg== 0 -1 +BA8EAgAsAID/////LzMEMjU2NwMEFgUEBf//9BEAHALNBAb/f0AA6iAEICEiIwQkJSYn+vr6+gYHBEAA6iAEICEiIwQkJSYn+vr6+vr6+vr6fwABAAAdLC0u9gQwMSgMBwRkAAAgBBwAIAQgISI= 0 -1 +BA8EAgAsAID/////MjMEMjU2NwMEJAUAAAH/9BD+HALNBAb/f0AA6iAEICEiIwQkJSYn+voX+vr6BPYGIwQkJSYnABDa+vr6+vr6AAAAgBIdLC0u9gQwMSgMBwRkAAAgBEQAIAQgISI= 0 99 BA8EAgAsAID/////MjMEMjU2NwMEJAUAAAH/9BD+HALNBAb/f0AA6iAEICEiIwQkJSYn+voX+vr6BPYGIwQkJSYnABDa+vr6+vr6AAAAgBIdLC0u9gQwMSgMBwRkAAAgBEQA 306 \015\004\002\000.\000\128\255\255\255\25523\0042567\003\004\$\005\000\000\001\255\244\016\254\028\002\205\004\006\255\127\@\000\234\032\004\032!\"#\004\$%&.\250\250\023\250\250\250\004\246\006#\004\$%&'\000\016\218\250\250\250\250\250\250\000\000\000\128\018\029,-\.\246\00401\(\012.\004d\000\000\032\004D +73//AO4D9YDuBPOA/0QgIAogChk= 8 -1 +BA8EAgAsAARAAOogBAIhIiMEJCUmJ/r6+vr6+vr68QT2AQAAAQkKEAIgA70AARIDBAQFBOjMBwRAAOogBAIhIiMEJCUmJ/r6+gAAAfr6+vr6+vr69AT5HSw9LvYEMC8AAAAAAQAAIAZEACAEICEi 0 -1 +BAABAgMEBAUGBwQICQocHR4fBCAhIiMEJCUsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaMgRcXV5fBGBhYmMEZGVmZwRoaWprBGxtHh8EICEiIwQkJSYnBCgpKgAAAS0uLwSAgYKDBISFhocEiImKiwSMi46PBJCRkpMElJWWlwSYmZqbBJydnp8EoKGiggSkpaanBKipqqsErK2urwSwsbI= 0 126 BAABAgMEBAUGBwQICQocHR4fBCAhIiMEJCUsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaMgRcXV5fBGBhYmMEZGVmZwRoaWprBGxtHh8EICEiIwQkJSYnBCgpKgAA 207 \000\001\002\003.\004\005\006\007.\008\009\010\028.\030\031\004\032!\"#\004\$%,-\./\0040123\0044567\00489:\;.<=>?.\@ABC.DEFG.HIJK.LMNO.PQRS.TUVW.XYZ2.\\]^_.`abc.defg.hijk.lm\030\031.\032!\"#.\$%&'.\(\)*\000 +BAABAgL8BAUGBwQICQoAAAEfBCAhIjMEJCUsLS4vBDAxMjMENDU2NwQ4OTo7BDw9BFRVVmYEWFlaWwRcAAACBGBhYmMMZGVmZwRoAAABaWprBGxtHh8EICEiIwQkJSYnBCgpKisELC0uLwSYs5qbBISdhocEiImKiwSMjY6PBJCRkpMElJWWlwSYs5qbBJydnp8EoKGiowSkpab//6jLqqsErK2urwSwsbI= 0 -1 +Ig== 0 -1 +AAABAAAEBAUGBwQICQocHR4fBCAhIiMEJCUsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaWwRcXV5fBGBhYmMEZGVmZwRoaWprBGxtHh8EICEiIwQkJSYnBCgpKisELC0uLwSAgYKDBISFhocEiImBiwSMjY6PBJCRkpMElJWWlwSYmZqbBKOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8WL0= 0 1 AA== 2 . +BAAcAgMEBAUGBwQICQocHR4fBCAhIiMEJDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 -1 +ACA= 2 -1 +BOgCFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFQUVFRUVFRUVFRUVFRUVFRUVFRQVFRUVFRUVFQAAARUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRU5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5FRUVFRUVFRUVFRU3FRUDAwMDAwMDAAABCfoD6AID8AID 0 -1 +BOgCFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFfQVFRUVFRQV+RUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRU2FRUVFRUVBQUFBQUFBRUVFS0VFX//FRUVFRUVFRUVFQX//wUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRX6FBUVFRUVFRUVFRUAAAEVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFREVFRUVBQUVFRUVFRUVFRUVFRUVFRUVFRUVFfoUFRUVFRUVFRUVFQAAARUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVERUVFRUFBQUFBQUFBQUFBQUFBQUFBQUFBQQsLS4vBAAAAQAAAQ== 0 -1 +BOgCFRUVFRUVFRUVFQAAAS8AAAEEMDH5fwQMDRIPECICECIGLi8EMDEqMwQ0NTYiBgQICfl+/AwNEg8EKjMEBwcHBwcHB8XFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFhcXFxcXFxcXFxcXFxcXFxcXFxcXFxQAAAAHFyMXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFwMXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxQcHBwcHBykHBwcHBwcHBwcHBwcHBwcIBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBgcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHDgcHBwcHMzMzGjszMzMzMzMzMzMzMzMHBwcHBwcHBwcHBwcHBxYHBwcOBwcHBwcHByEHBwcHBwcHBwcHBwX//wUHBwcHBwcHBwcHBwcHBwcHBxcHBwcHBwcHBwcHBwcCECIHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHFwcHBwcHAwcHBwcHBwIQIgIQIgYuLwAAAQQwMfl/BAwNEg8QIgIQIgYuLwQwMQMzBDQ1NiIGBAgJ+X8EDA0SDwQqMwQHBwcHBwcHxcXlxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcU3CCkqqwQsLS4vBDBBAgAAAQAfBAcHBwcHBwcHB+wGBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBweHBwcHBwcHBwcHBwcHBwcHBwcHcnJycnJycnJycnJycnJycnJycnJycldycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycgcHBwczMzMaOzMzMzMzMzMzMzMzMwcHBwcHBxYHBwcHBwcHBwcHBw4HBwcHBwcHIQcHBwcHBwcHBwcHBf//BQcHBwcHBwcHBwcHBwcHBwcHFwcHBwcHAAAAZAcHBwIQIgcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcDBwcHBwcHAhAiAhAiBi4vAAABBDAx+X8EDA0SDxAiAhAiBi4vBDAxKjMENDU2IgYECAn5fvwMDRIPBCozBAcHBwcHBwfFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcUAAAABxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFBwcHBwcHKQcHBwcHBwcHBwcHBwcHBwgHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcGBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcOBwcHBwczMzMaOzMzMzMzMzMzMzMzMwcHBwcHBwcHBwcHBwcHFgcHBw4HBwcHBwcHIQcHBwcHBwcHBwcHBf//BQcHBwcHBwcHBwcBBwcHIgcHFwcHBwcHBwcHBwcHBwIQIgcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHDQcXBwcHBwcDBwcHBwcHAhAiAhAiBi4vAAABBDAx+X8EDA0SDxAiAhAiBi4vBDAxAzMENDU2IgYECAn5fwQMDRIPBCozBAcHBwcHBwfFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxebFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXF//9//8XFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcUHBwcHBwcHBwcHB3JycnJycnJychYXMzMzMzMzMzMRMzMzMzMzM/9/EwQUERYXBBgkGhsEFB0CECIGBAgJ+X8EDCcSDwQQERITBEAAFhbogAAAGwQUHQAaMwQ0MX/+//8ICQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHDgcHBwcHBwchBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBygHBwcHIAAHBwcHBwcHBwcHBwcXBwcHBwcHBwcHB8XFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcW3xcXFxcXFxcXFxcXFxcXFxcXFxcXFxQcHBwc= 0 -1 +BBwcHAwcHBwcHBw+9KgLAQEBQBwcHBwcwsI2Nv////82NjY2NjY2AAAAAQAjZyw2AAQ2NjY2Ngk2NjY2NIBYNgAQAcw2NjY0/zZLaUtLATa+dnZ2dh9GNjY2NjY2NjYAAAABABtn6gABbEsxS0tpS0sBNr52dnZ2H0Y1ADY2NgAANjYkNjY0LRAAATY2NjYZNjZPNjY2RzYkNk/pEIAAdnZ2dnZ2dv8LAED/NjY2NgAAAQABAAABAAEAgAAAATY2CjYJNjY2NjSAWDYAEAHMNjY2NP82S2lLSwE2vnZ2dnYfRjY2NjY2NjY2AAAAAQAbZ+oAAWxLMUtLaUtLATa+dnZ2dh9GNQA2NjYAADY2JDY2NC0QAAE2NjY2GTY2TzY2Nkc2JDZP6RCAAHZ2dnZ2dnY2AAHQ0JAABf//BRQ/NoABAAABWCs2NjY2//92VHaRdkBAQAAAAAAAAQAjZyw2AAQ2NjY2Ngk2NjYyNIAAAQAb 0 -1 +AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfAhBAAgQgKRcjBAQkAAACAEACEAACEEACECICECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGBQdHh8mNSkiGQQkJAAAAg5AAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQAAAIAQAIQIgIQQAIQIgIQAAA= 0 206 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfAhBAAgQgKRcjBAQkAAACAEACEAACEEACECICECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGBQdHh8mNSkiGQQkJAAAAg5AAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQAAAIAQAIQIgIQQAIQIgIQAAA= 626 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\016\@.\004\032.\023#\004\004\$\000\000\002\000\@\002\016\000\002\016\@\002\016\"\002\016\"\002\016\"\006\004\008\009\255\127\004\012\013\018\015\004\016\008\018\019.\001\021\022\023.\024\020\029\030.&5\)\"\025\004\$\$\000\000\002\014\@\002\016\"\002\016\@\002\016\"\002\016\"\002\016\@\002\016\".\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\".\016\@.\016\".\016\000 +AgAAAuZAAhAiAhBAAhAiAhAiBgQICf9/BAwNAAABEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBAAABQAAAEACECQB8kACECIC8iEGBBAiAhBAAhAiAhAff////yMEByQAAAIAAAABQO0PAAIQQAIQDwIQImAQIh4ECAn/AR8mNSkiGQQkJAAAgiJAZBAiAhAAAAEigBACEAIQIgAAAgBAAhAAAA== 0 64 AgAAAuZAAhAiAhBAAhAiAhAiBgQICf9/BAwNAAABEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBAAABQAAAA== 202 \000\000.\230\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\000\000\001\018\015\004\016\008\018\019\004.\021.\023\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\000\000\005\000\000 +BICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUBJiZmpsEnJ2enwSgoaKjBKSlpqcEqKmqq1RVVldYWZWWlwSYmZqbBJydnp8EoKGiowSkpaanBKipqqtUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0Afg== 0 -1 +EgEABIAQABABAIOKAAAB6mtsAaurqwHqa2xtbauri6ChoqMAAAABPVxNP0ABAAEsBf//BQABT20AHgFo6OpzbG2rq6uJb3BxZBZ+ 0 -1 +AQAAAIMFhIWGhweaiYqLBIyNjo7ykKcAgP//hpaDBISFhocEATY2NjY0hiABADY2NiMAgAAAAAABNjY2NjY2NjZ+AAAAAAAhHxtn6gABbEt2AAAAQBgzNjYAADY2JDY2NP9/ATY2NjY2FTYVTzYAQDY2JACAAAyAGQB2dnZ0dn//Yv8AAAE2NjY0Nt3d3d3d3d0AAAHd3cfd3d3d3d3diosEpI0AIAEAAQB4AAABNjYK3d3d3d3d3d3d3d3d3f3H3cft3d3d3d3diisEpI2PBJCnAID//4aWgwSEhYaHBIiOjwAAAbMgABYWFhYWFgAAARY2fXZ2dgAAAQAb 0 3 AQAA 5 \000 +BICBgoMEhIWGhwSHiYqLBIyNjo8EkJGSkwQAAAGXBJiZmpsEnJ02AAAAAAsBZxU2AAQ2GjYAAQltbW1tbW1tbW1tbW1tbTY2NjY0gFg2ABABNjY2l5sEnJ02AAAAAAABZxU2AAQ2GjY2NgSYmZqbBJydNgAAAAAAAWcVNgA2NP82NjY2AAAA3gM/NjY2NjY2NjY2NjY2AAAAAQAbZ+oACmxLS0tLaUtLATa+dnaSdh9GFAA2AAABNjT/fzY2NjY2NhVDNk82ABAAACQ2Nv//gAB2dmX///9//wsAAAEiQP82NjYAAAFnFTY0NgHQ0NAz0NDi0NC9EAAA+y0UFAB2AAHQ0JAAABQUZAAAAIABAAABWCs2NjY2NnZ2dnZ2dkABAAAAAAEAGw== 0 41 BICBgoMEhIWGhwSHiYqLBIyNjo8EkJGSkwQAAAGXBJiZmpsEnJ02AAA= 133 \128\129\130\131.\132\133\134\135.\135\137\138\139.\140\141\142\143.\144\145\146\147.\000\000\001\151.\152\153\154\155.\156\1576\000 +BICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUlZaXBJiZmpsEnJ02AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADe/3//NjY2NjY2NjYVNjY2NjYAAAABABtqampqbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2BAAVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/LDY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY3gAEAAAFYKzY2NjY2dnZ2dnZ2QAAAAAAAAQAb 237 1 AA== 2 . +BGQDAwgINjZWNhU2NgE2NjY2NjY2NjYlNkk2NjY2NjY2NjY2NiIiIiIiLyIiIi8EMBQyMwQ0NTY3BDg5LTsEPD0+PwA= 0 -1 +AAEAAQ== 0 1 AA== 2 . +BOgDAwgINjZWNhU2NgE2NjY2NjY2NjY2NjY2UjY2AzY2NjY2NjY2NjYlNkk2NjY2NjY2NjY2NiIiIjYAAEVkNgAANjY2NjY2NgABQDY2NjYyNjYjQzb/fxN1Njb8NjaeQjwAIVkTNjY2Nfs2NjaeNFnkGDITNjY2NjbvHDf/fzY2NgAAAf///382VzY2NgA2NjY2NjY2NjY2NjY2BQAANjb/////NgAAAFw2f////zY2NjE2NjY2//82/382NjYAAAH///9/ZAABNjY2NjY2Np5eXl4RATYAAEVkNgAANjY2NjY2NgABQDY2NgABNg== 0 236 BOgDAwgINjZWNhU2NgE2NjY2NjY2NjY2NjY2UjY2AzY2NjY2NjY2NjYlNkk2NjY2NjY2NjY2NiIiIjYAAEVkNgAANjY2NjY2NgABQDY2NjYyNjYjQzb/fxN1Njb8NjaeQjwAIVkTNjY2Nfs2NjaeNFnkGDITNjY2NjbvHDf/fzY2NgAAAf///382VzY2NgA2NjY2NjY2NjY2NjY2BQAANjb/////NgAAAFw2f////zY2NjE2NjY2//82/382NjYAAAH///9/ZAABNjY2NjY2Np5eXl4RATYAAEVkNgAANjY2NjY2NgABQDY2NgA= 460 \232\003\003\008.66V6\02166\001.666666666666R66\0036666666666%6I66666666666\"\"\"6\000\000Ed6\000\000666.666\000\001\@6666266#C6\255\127\019u66\25266\158B<\000!Y\0196665\251666\1584Y\228\0242\01966666\239\028.\255\127666\000\000\001\255\255\255\1276W666\0006666666666666\005\000\00066\255\255\255\2556\000\000\000\\6\127\255\255\25566616.66\255\2556\255\127666\000\000\001\255\255\255\127d\000\0016666666\158^^^\017\0016\000\000Ed6\000\0006666666\000\001\@666 +ATY= 0 -1 +BOgDAwgINjZWAAABNgE2NjY2NjY2NjY2NjY2UjY2AzY2NjY2NjY2NjYlNkk2NjY2Ni02PTY2NiIiIjYAAEVkNgAANjY2NjY2NgABQDY2NjYyNjYjQzb/fxN1Njb8NjaeQgAAATwAIVkTNjY2Nfs2NjaeNFnkGDITNjY2Izb/HDf/f1Q2NgAAAQAAF4AA/382VzY2NgA2NjY2NjY2NjY2NjY2AAAANmT/////FgAAAQAANjb/////NgAAAFw2f////zY2NjE2NjY2//82//9/ZAABNjY2NjY2Np5eXl4RATYAADY2NjY2NjY2NlI2NgM2NjY2NjY2NjY2JTZJNjY2NjYAAAE2NjYiIiI2AABFZDYAADY2NjY2NjYAAUA2NjY2MjY2I0M2/38TdTY2/DY2nkIAAAE8ACFZEzY2NjX7NjY2njRZ5BgyEzY2NjY2/xw3/382NjYAAAEAAAGAAP9/Nlc2NjYANjY2NjY2NjY2NjY2NgAAADY2/////wAAAAEAADY2/////zYAAABcNn////82NjYxNjY2NjY2NgABQDY2NgABNg== 0 -1 +BAFXAAIEAg== 2 -1 +BOgDAwgINjZWNhU2NgE2NjY2NjY2NjY2NjY2UjY2EzY2NjY2NjY2NjYlNkk2NjY2NjY2NjY2NiIiIiIiIkAiNugDNjY2NjY2NjY2NjZDNjY2NpiYmDY2NjYiICIiIiIiIiIiIiIiIiJJNjY2NjY2NjY2NjYiIiIiIiJAIjboAzYiIiIiIiIiIiIiIiI2NjY2JzY2NjZkZAAANjY2NjY2NjY2NjYiIiIiIiJAIjboAzYiIiIiIiIiIiIiIgA2NjY2TV8EYGFiYwRkZWZnBGhpamsEbG0eNgQgISIjBCQlJicEKCkqKwQsLS4vBICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUlZaXBJiZmpsEnJ2enwSgoaIAAA== 0 -1 +7I2NjY2NjY2NjY2NjQACjY2NjY2NjY2NjY2NjY2NjY2NAAKNjY2NjY2NjY6NjY2NjY2NjY2Nm42NjY2NjY2NjY2NjWyNjY2NjY2kjY2NjY2NjY2NjTY2NjY2PQAAATY2RDY2U1I2NgAAAQM2NjY2Nvc2dnbQKjYQTfgFACEANzI2OekAABA2NjY2EABxGwAAATY2AAABAHZ2dnZ29g== 0 -1 +BOgAATY2NjY2fwDiNjY2NjY2NjY2NgAAATY2NjY2NjYmNjb/ADY2NjY2AwAAAQT9BQcICXx8fHx8fHx8AAABAHx8fHx8IAB8 0 61 BOgAATY2NjY2fwDiNjY2NjY2NjY2NgAAATY2NjY2NjYmNjb/ADY2NjY2AwAAAQT9BQcICXx8fHx8fHx8AA== 123 \232\000\0016.666\127\000\2266666666666\000\000\0016666666&66\255\00066666\003\000\000\001\004\253\005\007\008\009|||||||| +wMAAAcDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNgAQwMAAAcDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABPjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Nn7s7OzsEBQUDDY2NgAAATY2NjZYNjY2Nk02NlEAEQEANjYABf//BUU2OTY2NiU9PT09NgAAAV8//3Y2AAABNjY0NgAAAYA2PRAANjYAAAABADY0NjYyNjY2NjYAEDY2S0tLQAAAAUsBNr4fRhTAHzY2fuzs7OwQFBQMNjY2AAABNjY2Nlg2NjY2TTY2UQARAQA2NgAF//8FRTY5NjY2JT09PT02AAABXz//djYAAAE2NjQ2AAABgDY9EAD7+/v76fv7+////w== 16 -1 +wMAAAcDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUX/gDY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Nn7s7OzsEBQUDDY2NgAAATY2NjZYNjYkNk02f/8AEQEANjYABf//BUU2OTY2NiU9PT09NgAAAfI//3Y2AAgBNjY0NgAAAYA2PRAA+/v7+/v7+/v///8= 16 -1 +BAABAgMEBAUGBwQICQoLBBINDg8EEBESEwQUFRYXBBgZGhsEHB0eNjY2AAA2NjY2Njw2ATYYNkUAAAIQ//9/TExMTExMTExMTExMTExMTExMTExMTENMTBMTExNqEykTlhMTEyYLAAEUFAAABjY2NjYAAAE2NhwAAAABAAABBDb/fwAAAzYAAQX//wU2NgD7SDYkNjk5OTk5OTk5OTk5OTk5OTk5OTk5PTY0pjY2NjY2NiQAAAE2Nn82cXZ2dnZ2dnZ20Coq0DPQ0P/QM9DQ//9//9AAAAHSu9DRkNAABgAA/xQUAAAGfzYkNjY0Nks2AAQeVTb/AAABNn////8= 0 -1 +xcXFxcXFxcXFxcXFxcXFxcXFxcXFxRDAwExMaExMTExMHzY7TTY2JBU2NDY2MjY2NjY2AxA2NktLS0tLwDY2NjYAABrAHzY2MzYQAN4HBzc2ATY2AxA2NktLS0tLwDY2NjYAABrAHzY2NjY2NjYWvh8AAAFGFDA2NjYAADY2WDZ2PDY2NjY2ADY2NjY2NjYAAAE2NjY2NgMQNjZLS0tLS8A2NjY2AAAawB82NjY2NgCAAAA2NjYuLi4uLi4uLi4hLi4uLi4uLi4uLi4uLi4uNjY2NjY2NjY2ozY2NjZENiU2njY2NjY2NjY2NjY2NjY2FzY2NgAA 197 48 Li4uLi4uLi4uLjY2NjY2NjY2NqM2NjY2RDYlNp42NjY2NjY2NjY2NjY2Nhc2NjYA 65 \.\.\.\.\.\.\.\.\.666666666\1636666D6%6\15866666666666666\023666 +ASY= 0 -1 +AAEAIA== 0 1 AA== 2 . +BBABggMEBAAABBABggMEBAUG6wQICQoLBAxuBBQtLiBQMwQzNVEENDUpNwQ4ADkEMDFQKhcELC0uIAQwMVAzBAQzNTY0NQ== 0 -1 +AAAAGxsfGxv51ED/ACBk/vYbGxsbGxsbWRsbBQAbGxwbEAAAAAEb/QEAgACYAAEbGxsbGxtAG9EbJhsbAAAAGwMbJhsbAAAABwAg0rBpaWlpaWlpaWlpaWJpaWlpaQAAAAAAAQAAHSmJGw== 27 -1 +AACrq6r/7Q== 0 1 AA== 2 . +BAABAgLgAeEBgADjAeQB6QHqAesB8wH0AfUB9gH3AfgB+QH6AfsB/AEaAv4= 0 -1 +/38AAAEAAAHj/CGaygAEAAA= 0 -1 +BAABAgICAgICAgICLhwEMDEzAiMEABD/BCEiI1UNDg8GBA81/QQUIyT6AAD6LgAAAANAAAAALi4uLi4uLk8uLi4uLi4uLiMAAAIAAA4= 0 -1 +BAABAgICAgICAgICLhwEMDEyMwICAgICAgQUFRYXAgICAgICAnWAAAAABCIjBACQ/wQhIiNVDQ4PBgQPCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoSEwQUIyT6AAD6LgAAAANAAAAALi4uLi48Lk8uLi4uLi4uLiMAAAIAAA4= 0 40 BAABAgICAgICAgICLhwEMDEyMwICAgICAgQUFRYXAgICAgICAnWAAA== 106 \000\001\002\002.\002\002.\002\002.\.\028.0123.\002\002.\002\002.\020\021\022\023.\002\002.\002\002.u\128 +BAABAgICAgICAgICLhwEMDEyMwIGBgYGBgYkBgICAgICBBQVFhcCAgICAgICdSMEDQAEIgAAARD/BCEiI1UNDg8GBA8SEwQDIyT6AAD6LgAAAANAAAAALi4uLi4uLk8uLi4uLi4uLiMAAAIAAA4= 0 77 BAABAgICAgICAgICLhwEMDEyMwIGBgYGBgYkBgICAgICBBQVFhcCAgICAgICdSMEDQAEIgAAARD/BCEiI1UNDg8GBA8SEwQDIyT6AAA= 228 \000\001\002\002.\002\002.\002\002.\.\028.0123.\006\006.\006\006\006\$\006\002.\002\002.\004\020.\022\023\002\002\002\002\002\002\002u#\004\013\000\004\"\000\000\001\016\255.!\"#U.\014\015\006\004\015\018\019\004\003#\$\250\000 +d3gXBf//BUcQp0CAAAABfx4= 2 -1 +ZAABAgICAgICZS3RA3d3dwdleGFtcIhlA2NvbQAAAQABwAw= 0 -1 +Af8= 0 -1 +BAABAgICAgICAgICLhwEMDEyMwICAgICAgICAgICAgICAgICAgICAgICAgICLhwEMDEyMwQ0NXYBdwF4AXkBegF7AXwBfQF+ATZuAW8BcAFxAXIBcwF0AXUBdgF3Af8BeQF6AXsBfAF9AX4BfwA= 0 110 BAABAgICAgICAgICLhwEMDEyMwICAgICAgICAgICAgICAgICAgICAgICAgICLhwEMDEyMwQ0NXYBdwF4AXkBegF7AXwBfQF+ATZuAW8BcAFxAXIBcwF0AXUBdgF3Af8BeQF6AXsBfAF9AX4BfwA= 228 \000\001\002\002.\002\002.\002\002.\.\028.0123.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\..\0040123\00445v\001w\001x\001y\001z\001{\001|\001}\001~\0016n.o.p.q.r.s.t.u.v.w.\255.y.z.{.|.}.~.\127 +BAABAAABAwgINjY2NgAAAMAfNjZkAAAAAAEAFPY2HjY2NPoAAPoABAEAAAE2NgAAATb7IPvz+/sAAAFCAAABRDYkDzI0NjY2NjY2NjYAAAABNlg2Nv9/NjY2NgAAAQA2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2/zY+NjY2NjYAADYA/wA2DAEAAQH0wB82NjY2 0 -1 +ABAAFwMfExQVFhcYGRobHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4BPw== 0 1 AA== 2 . +hBABAgMAAAERCf//hBABAgMsARAAAAFkCQsADwAQANRMAACEMAECAwAAAAABHQEBKUIK 0 -1 +AAFAAGQpCgo= 0 1 AA== 2 . +BBABAAABf/8BCQEBAQACENQBAQEBAQEBAQEBAWQBAAEBAgEBAQEBKSkp 0 -1 +BBABAgMsLUcBCQEBAQACENQBAQEBAQEBAQEBAWQBAAEBAgEkAQEBKSkp 0 -1 +BBABAgMsLS4A/zA0MvoAAPo2NwQ4PD03PwAEJwRZWVlZWVlZWVlZGwABHR4fBCA2IiMEJCUmJwQoKQACEu4rLS4v9y+ysn8ENDU2NwQ4ORUWFwQgISIjBCSyBDQ1Nh0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHQAAAR0dHR0dHR0dHR0dHR0+HR0dHR0dHR0dDx0dHR0dHR0dHR0dHR0FHR0dHR0dHR0dHR0dHR0dFR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0UHR0dHR0dHR0dHQAAAR0BAwAAAQT9BQcICXy0BDB8fHx8AAABAHx8fHx8IAB8 0 222 BBABAgMsLS4A/zA0MvoAAPo2NwQ4PD03PwAEJwRZWVlZWVlZWVlZGwABHR4fBCA2IiMEJCUmJwQoKQACEu4rLS4v9y+ysn8ENDU2NwQ4ORUWFwQgISIjBCSyBDQ1Nh0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHQAAAR0dHR0dHR0dHR0dHR0+HR0dHR0dHR0dDx0dHR0dHR0dHR0dHR0FHR0dHR0dHR0dHR0dHR0dFR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0UHR0dHR0dHR0dHQAAAR0BAwAA 709 \016\001\002\003.-\.\000\255042\250\000\000\25067\0048<=7?\000\004'\004YYYYYYYYYY\027\000\001\029\030\031\004\0326\"#.\$%&'.\(\)\000\002.\238+-\./\247/\178\178\127\0044567\00489.\022\023\004\032!\"#\004\$\178\004456\029\029\029\029\029\029\029.\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\000\000\001\029\029\029\029\029\029\029\029\029\029.\029\029>\029\029\029\029\029\029\029\029\029\015\029\029\029\029\029\029\029\029\029\029\029\029\029\005\029\029.\029\029\029\029\029\029\029\029\029\029\029\029\021\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029.\029\029\029\029\029\029\029\029\029\029\029\020\029\029\029\029\029\029\029\029\029\029\000\000\001\029\001\003\000 +4BABAgMsLTw9Nz8ABCcWFwQYGRobBBwdHh8EICEiIwA= 0 -1 +BAABAgMEBAUGBwQICQoLBAwNDgICAgICAicEKCkqqwQsLS4vBDACAi0uLwQwAgICAgICEAICAgICBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/AA== 0 -1 +BAABAgMEBAUGBwQICQoLBAwNDgICAgICAicEKCkqKwQsLS4vBDACAgICAgICAgABADY2JzY2NjQ2WDY2NoAAAAA2AAABNjY2AAAAAMAfNjY2NjYkFTY0NjY2NjY2NjY2NjY2NjYAAAABBDY2NjY2NjY2NjY2NjYAAAABABtLbEtLS0tLS0sBAAABRhQ2gDY2NjY2NjY2NjY2NjY2NjY2NiQ2Nn92dnZ2dnZ2dnZ2dnZ2AXZBNgE2HgQAQP82NjY2NDYAAAEAAAGANhkWNjY20NDQ0NDQ0NDQM9DQ0NDQ0NDQ0NDQkNAAFBQUFDY2NjY2NjZYNjY2Nk02NlEAEQEAAAEjNjZFNjk2NjYlPT09VDYAQP82NjY2NDYAAAGANj0QAPsAAAH7AAAAZPv7+/sg+/v7+0JEAAABNgsLCwsLCwsLCwsLCwsLCwuYCwsLCwsLCwsLCws= 0 -1 +AQLAAA== 0 -1 +BAABAgMEBAUGBwQEDA2ADwQQBBgZGhsEHB0hIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFRkcESElKSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EYGFiYwRkZWZnBGhpamsEbG1ubwRwcXJzBHR1dncEeHl6ewR8fX5/BICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUlZaXBJiZmpsEnJ2enwSgoaKjBKSlpqcAAAGqqwSsra6vBLCxsrME 0 195 BAABAgMEBAUGBwQEDA2ADwQQBBgZGhsEHB0hIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFRkcESElKSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EYGFiYwRkZWZnBGhpamsEbG1ubwRwcXJzBHR1dncEeHl6ewR8fX5/BICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUlZaXBJiZmpsEnJ2enwSgoaKjBKSlpqcA 415 \000\001\002\003.\004\005\006\007.\004\012\013\128.\004\016\004\024\025\026\027\004\028\029!\"#\004\$.&'\004\(\)*+\004,-\./\0040123\0044567\00489:\;\004<=>?\004\@ABC.DEFG.HIJK.LMNO.PQRS.TUVW.XYZ[.\\]^_.`abc.defg.hijk.lmno.pqrs.tuvw.xyz{.|}~\127.\128\129\130\131.\132\133\134\135.\136\137\138\139.\140\141\142\143.\144\145\146\147.\148\149\150\151.\152\153\154\155.\156\157\158\159.\160\161\162\163.\164\165\166\167 +GxsAAAEbGxsbGxsbGxsbAxsbGxsbGxsbGxsYIBsbGxsbGxs2GxsbGxsbGxsbCxsbGxsbGxsbGxsbFRsbGxsbGxubGxs3GxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsUGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx8DGxsbGxsbAAEbGxsbGxsAAAHqGxsa+gAbGxsbGxsbGxsXGxsbGxsbG4AbGxsbGxsbGxsbGxsbGxsbGxsbGxv7GxsbGxsbGxsbGxsbGxsbGxsbGxs0G/waGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbJh8bGxsEGxsbGxsbGzEbGxsbAPoAAPo= 155 -1 +BBgfKgAA 0 6 BBgfKgAA 14 \024\031*\000 +wMAAAAABAcDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2MzYAEDY2S0tLABBQNktLS0tLATY2/+I2Nlg2djw2NjYAAAE2KQAAAf+ANjY2PDY2MRU2BLMF9AAB//8FRTYAEDY2S0tLQAAAAUsQNr4fRhTAHzY2fuwAAAHsrOwQAAABJBQMNjYAABAANjY2LVg2NjY2NiQVNjQ2NjI2NkMzNgAQNjZLS0s2JUU2HzM2ABA2NktLS0tLARu+H0YUNgABgDY9ARa+H0YUNjYQAPv7+/v7+/v7//8b 16 1 AA== 2 . +wMAAAcDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Nn7s7OzsEBQUDDY2NgAAATY2NjZYNjY2Nk02NlEAEQEANjYABf//BUU2OTY2NiU9PT09NgAAAfJAFXaANj0QAPv7+/v7+/v7//// 16 -1 +wMAAAcDAwMDANjY2NgAAGtgfNjY8NjYkFTY0NgAAAGQ2NjYAEDY2S0tLS0sBFr4fADaiNjY2NjYF//8FRTY5Nj42JT09PQE2NjYAAAABADY0NncyNjY2NjYAEDY2S0tLQAAAAUsBNr4fRhTAHzY2QOzs7OwQFBQMNjYQAAABNjY2Nlg2NjY2TTY2UQARAQA2NgAF//8FRTY5NjYqJT09PT02AAAB8j//djYAAAE2NjQ2AAABgDY9EAD7+/v7+/v7+////w== 16 -1 +wMAAAcDAwMA2JBU2NDY2MjY2NjY2ABA2NjY2NjYAADY2WDZ2PDY2NjZLS0tLSwEWvh9GFDZFNjYAADY2WDZ2PDY2NjY2AAABAAE2NjY8NjYkFTYEszaiNjY9NjYF//8FRTY5Nj42JT09PQE2NjYAAAABADY0NjYyNjY2NjYAECc2S0tLQAAAAUsBNr4fRhTAHzY2fuzs7OwQFDY2Nlg2JDY2TTY2UQARAQA2NgAF//8FRTY5NjY2JT09PT02AAAB8j//djYAAAE2NjQ2AAABgDY9EAAAAAH7+/v7+/v7+////w== 16 -1 +wMAAAcDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ogAENgAQAAD/BWM2OTY+NCU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YQwB82Nn7s7OzsEBQUDDY2NgAAATY2NjZYNjY2Nk02NlEAEQEANjb4Bf//BUU2OTY2NiVEPT09NgAAAfI//3Y2AAABNjY0NgAAAYA2PRAA+/v7+/oAAPr///8= 16 2 NjY2NgAQNjZLS0tLSwEWvh9GFDY2NjYAADY2WDZ2PDY2NjY2AAABAAE2NjY8NjYkFTYEszaiAAQ2ABAAAA== 127 666\000\01666KKKKK\001\022\190\031F\0206666\000\00066X6v<66666\000\000\001\000\001666<66\$\0216\004\1796\162\000.6\000\016\000 +wMDzAMDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Nn7s7Ow9PT09NgAAAewQFBQMNjY2AAABNjY2Nlg2NjY2TTY2UQARAQA2NgAF//8FRTY5NjY2JT09PT02AAAB8j//djYAAAE2GjQ2AAABgDY9EAD7+/v7+/v7+/9k/w== 16 -1 +wMAAAcDAwMDANjY2NgA2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2BLM2ojY2Bf//BUU4OTY+NiU9PT0BNjY2AAAAAQAuNDY2YjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Nn7s7OzsEBQUDDY2NgAAATQ2NjZYNjY2Nk02NlEAEQEANugDBf//BUU2OTY2NiU9PT09NgAAAfI//3ZCAAABNjY0NjY2NgAAAYA2PRAA+/v7+/v7+/v/ABA= 16 -1 +wMAAAcDAwMDANjYEHB0eHwQgISIjBCQlJicAKCkqKwQsLS4vBAkJCQkJCQkJCQkJAAABCQkJCQkJCQkJCQkJCTAxMjP+MzU2NwQ4OTo7BDw9 16 11 BCAhIiMEJCUmJwA= 15 \032!\"#.\$%&' +AX8= 0 -1 +AQ== 1 -1 +wMAAAcDAwMDANjY2NgAbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbwxsbGxsbGxsbGxsbGxsbGxsCGxsbGxsbGxsbGxsbGxsbGxsVGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxkbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbAxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGyYbEBsbGxsbGxsbGxsbGxsbGxsb 16 -1 +wMAAAQAAAcYEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYX6hcZGhsEHB0eBwcHBwcHBwcHB/cHBwcHBwcHBwcfBCAhIvIAASMEJCUmEAQoKSorBCwtLi8AMA== 16 53 CgsEDA0ODwQQERITBBQVFhfqFxkaGwQcHR4HBwcHBwcHBwcH9wcHBwcHBwcHBx8EICEi8gA= 188 \011\004\012\013\014\015\004\016\017\018.\004\020\021\022\023\234\023\025\026\027\004\028\029\030\007\007\007\007\007.\007\007\007\007\247\007\007.\007\007\007\007\007\007\031.\032!\"\242 +AgAfBCApIiMEJCTrJwQIKSqrBCwtLi8EMEECAB8EBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwYHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBw4HBwcHBzMzMxo7MzMzMzMzMzMzMzMzBwcHBwcHBwcHBwcHBwcHBwcHDgcHBwcHBwchBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcHBwcHBwcHAhAiBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBxcHBwcHBwcHBwcHBwcCECICECIGLi8AAAEEMDH5fwQMDRIPECICECIGLi8EMDEqMwQ0NTYiBgQICfl/BAwNEg8EKjMEBwcHBwcHBwcHBwcHBwcHBxAREhMEFBESQAABFhczMzMzMzMzMxEzMzMzMzMz/38TBBQRFhcEGCQaGwQUHQIQIgYECAn5fwQMJxIPBBAREhMEQAAWFuiAAAAbBBQdABAzBDQxf/7//wgJBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcOBwcHBwcHByEHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBxcHBwcHBwcHBwcHBwcHBwd/AAQkNB0CECICEEACECICECISQAABFhcEGBkaGwQUHSAfADMzMw== 0 -1 +AAEAEP8AAQD3 0 1 AA== 2 . +AegDCAg2HzY2AAAAwB82NjY2NiQVNjQ2NjY2NjY2NgAQNgAAATY2NjY2NjY2AAABAAE2NjZFNjYVNgAENjY2NjY2JzY2NjQ2WDY2NjY2NjY2AAABNjY2AAAAAMAfNjbj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+M2NjYkFTY0NjY2NjY2NjY2NjY2NjYAAAABBDY2NjY2NjY2NjY2NjYAAAABABtLbEtLS0tLS0sBAAABRhQ2gDY2AAA2NiQ2NjQ2NjY2NjY2NjY2NjY2NjY2NiQ2Nn92dnZ2dnZ2dnZ2dnZ2dnZBNgE2HgQAQP82NjY2NDYAAAEAAAGANhkWNjY20NDQ0NDQ0NDQM9DQ0NDQ0NDQ0NDQkNAAFBQUFDY2NjY2NjZYNjY2Nk02NlEAEQEAAAEjNjZFNjk2NjYlPT09VDYAQP82NjY2NDYAAAGANj0QAPv7+/v7+/v7+/sg+/v7+0JEAAABNgsLCwsLCwsLCwsLCwsLCws= 0 -1 +Bf//BcDAwMDANjY2NgAAVwECAVcBAQIBVwEBAQECAVcAAA== 16 17 AQIBVwEBAgFXAQEBAQIBVwA= 34 \002.W.\001.\001W.\001.\001.\001W +BAABAgMEBAUGBwSICQoLBAwA//wNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIj538lRicEKCkqKwQsLS4vBDAxMjMENDU2PgQ4OTo7BDwQPj8A 0 -1 +BAABAgMEBAUSEwQUFRYXBBgZGhsEHB0eOQQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw8Pj8A 0 66 BAABAgMEBAUSEwQUFRYXBBgZGhsEHB0eOQQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw8Pj8A 131 \000\001\002\003.\004\005\018\019.\020\021\022\023.\024\025\026\027.\028\029\0309.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<<>? +NwAAAAABAQQdIh8EICEiI/8QJSYnBCgpA+j4LBvrGx0eHwQgISKGBKQlJicEKP8qKwAAG4aGhgAQhoaGhoaGhoaGIh8EIICGhoY4PT5SAA== 0 -1 +AAABAgMEBAXrBgQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 1 AA== 2 . +AAEBAgMEBAUGBwQICQoLBAwNBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEAgKSIjBAQkAAACAEACAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgIQIgYECAn/fwQMDRIPBBAIEhMEARUWFwQYOhobBBQdHh8mNSkiGQQkJAAAAg5AAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQAAAIAQAIQIgIQQAIQIgIQAAA= 0 1 AA== 2 . +BAABAAABBAUGDQYECAn/fwAAARIPEBAJCgsEfwAAABMEByAACQoLBGQNEgkQEAgSEwQBFRYXBBg6Gv9/Hx0eHw01KSIZBCQkAAD/AEACECICEEACECLzDyIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAJkAAIQQAL+AgAQywIQIgYECAn/fyQkAAAAAAECDkACQCIAAAECEEACJiIBBCQkAAACAEACECJTENQCECICEAAA 0 -1 +5f8AAgAAAAEEBAX/ZAAICQoL5AwNBgQIgAAAAA38DgQQCBIZBCQcAAAAAUACEP9kAAgJECLtECL/D///AhBAAhAiAhAtBCApIiPpEgAAAAABAAIAQAAAAQJkAAIQCAAAEAAFACkJ/wL/fxcKGOoAAToa/wIcJ/R6enp6enp6enp6enp6enp6enp6enp6AAECA+gAAIACECICEAAA 0 -1 +A9YBAgMmAAABBwQIGQoACwQMCxQMDQ4AAAAA 0 -1 +lJWWogwA6P8A 0 -1 +wMAAAQBkn8CiNjY2NgAAGsAfNjY8yQAhEAACCSICAgIQIgIQQAA= 16 2 AhAiAhBAAA== 14 \016\".\016\@ +3g== 0 -1 +AQ== 0 -1 +AgAAAhBiAgAAAhAiAQECAVcBAQIBVwIQYgIAAAIQAQIBVwEBAhBiAgAAAhAiAVcBAgFXAQECAVcBAQEBAgFXAAAB 0 64 AgAAAhBiAgAAAhAiAQECAVcBAQIBVwIQYgIAAAIQAQIBVwEBAhBiAgAAAhAiAVcBAgFXAQECAVcBAQEBAgFXAA== 146 \000\000.\016b.\000\000.\016\".\001.\001W.\001.\001W.\016b.\000\000.\016\001.\001W.\001.\016b.\000\000.\016\".W.\002.W.\001.\001W.\001.\001.\001W +AQABAwEJAQoYARkBGmwbARwHGgEeAc0BAAAB0AAAA+gB01NTAZ8= 0 -1 +wMAAAcD/AMAbAgICAgICAgIAAgICAgABAAA= 16 7 AgACAgICAA== 18 \000\002.\002\002 +BOgAAAEDAwgINjY2NgAAAMAfNjZkAAAAAAEAFPY2HjY2NDYMAAEABAEAAAE2NgAAATb7IAAAAfsAAAFCRDYkDzI0NjY2NjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTY2FTYABDk2NgAAATY2NjY2Nhw0NlgAIDY2/zY+NjY2NjYAADYAAPs2DAEAAAH0ATY2Njw2NiQVNgSzNqI2NjY2NgX//wVFNjk2PjYlPT09ATY2NgAAAAEANjQ2NjI2NjY2NgAQNjZLS0tAAAABSwE2vh9GFMAfNi5+7Ozs7AAAAezs7BQ2NjY2AAAAAAE2NjQ2GTZBNj42LTY2NjY2TtDQ0ID///8UFBQ2NjU2NkM2WDY2NjZNNjZRABEBAA== 0 -1 +BDY2KwAAAMAfNjZkAAAAAAAAFHY2HjY2NDYMAAEABAEAAAE2NgAAATb7IPvz+/sAAUsBNr4fRhTAHzYufuzs7OwAAAHs7OwUNgABQkQ2JA8yNDY2NjY2NjY2ABA2Nj1YNjY2NjY2NjYAAAEAATY2NkU2EzY2HDQ2WAAgNjb/Nj42NjY2NgAANgAA+zYMAQAA8PMBNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AOj/AAAyNDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Ln7s7OzsAAAB7OzsFDY2NjYAAAAg+/P7+wAAAUJENiQPMjQ2NjY2SDY2AAE2NjQ2NjZRQzZYNjY2Nk02NlEAEQEA 0 6 BDY2KwAA 8 66+\000 +BOgANvsE+/vZ+wAAAX////8AMjQ2DjY2NjY2NgAAAID//wEAWCD7T1ZYEzY2NjY2NjYAAAEAATY2NkU2NhU21dXn1dXVINXV1dXV1dXV1dXV1RDV1dXL1dXV1dUABDk2NgAAAv///4c2PjY2NlY2AAAfRhTAHwAAA+g2PDY2fuzs7OwVAAAAADY2UQAR9gA= 0 11 BOgANvsE+/vZ+wA= 31 \232\0006\251.\251\251\217\251 +BOgAAAEDAwgINjYxNgD/5MApIPvz+wAAAQFCRDYkHjY2NDYMAAE2NjY2NjYAEDY2Nlj7IPvz+/sAAAFCRDYkDzI0NjY2NjY2NjYAEDY2Nlg2EzY2NjY2NgAcAQABNjY2RTY2FTYABDk2NgAAATY2NjY2Nhw0NlgAIDY2/zY+NjY2NugDADYAAPs2DAEAAAH0ATY2NjwpNiQVNgSzG6I2NjY2NgX//wVFNjk2PjYlPT09ATY2NgAAAAEANjQ2NjI2NjYfNjZkAAAAAAEAFPY2HjY2NDYMAAEABAEAAAE2NgAAAezs7BQ2NjY2AAAAAAE2NjY2QzZYNjY2Nk02NlEAEQEA 0 202 BOgAAAEDAwgINjYxNgD/5MApIPvz+wAAAQFCRDYkHjY2NDYMAAE2NjY2NjYAEDY2Nlj7IPvz+/sAAAFCRDYkDzI0NjY2NjY2NjYAEDY2Nlg2EzY2NjY2NgAcAQABNjY2RTY2FTYABDk2NgAAATY2NjY2Nhw0NlgAIDY2/zY+NjY2NugDADYAAPs2DAEAAAH0ATY2NjwpNiQVNgSzG6I2NjY2NgX//wVFNjk2PjYlPT09ATY2NgAAAAEANjQ2NjI2NjYfNjZkAAAAAA== 455 \232\000\000\001.\003\008\008.616\000\255\228\192\)\032\251\243\251\000\000\001\001BD6\$\0306646\012\000\001666666\000\016666X\251\032\251\243\251\251\000\000\001BD6\$\015.466666666\000\016666X6\019666666\000\028\001\000\001666E66\0216\000\004966\000\000\001666666.46X\000\03266\2556>6666\232\003\0006\000\000\2516\012\001\000\000\001\244.6.6<\)6\$\0216\004\179\027\16266666\005\255\255\005E696>6%===\001666\000\000\000\001\00064662666\03166d\000\000\000 +BOgAAAEDAwgINjY2NgAAAMAfNjZkAAAAAAE2vh9GFMAfNi5+7AAAAezs7AAAAezs7BQ2NgEAFAEAJA8yNDY2NjY2NjY2ABA2NjZYNvQBNjY2PDY2JBU2BLM2ojY2NgAAATY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Ln7s7OzsAAAB7OzsFDY2NjYAAAAAATY2NDY2NkE2PjY2NjY2NjZO0DZRABEBAA== 0 120 BOgAAAEDAwgINjY2NgAAAMAfNjZkAAAAAAE2vh9GFMAfNi5+7AAAAezs7AAAAezs7BQ2NgEAFAEAJA8yNDY2NjY2NjY2ABA2NjZYNvQBNjY2PDY2JBU2BLM2ojY2NgAAATY2Bf//BUU2OTY+NiU9PT0BNjY2AAAA 302 \232\000\000\001.\003\008\008.666\000\000\000\192\03166d\000\000\000\000\0016\190\031F\020\192\0316\.~\236\000\000\001\236\236\236\000\000\001\236\236\236\02066\001\000\020\001\000\$\01524666.6666\000\016666X6\244\001666<66\$\0216\004\1796\162666\000\000\00166\005\255\255\005E696>6%===\001666\000\000 +BOgAAAEDAwgINjY2NgAAAAEfNjZkAAAAAAEAFPY2HjY2NDYMAAEABAEAAAE2NgAAATb7IPvz+/t/AAFCRDYkDzI0NjY2NjY2NjYAEFY2Nlg2NjY2NjY2NgAAAQABWTY2RQAAATYABDk2NgAAATY2NjY2Nhw0NlgAIDY2/zY+NjY2NjYAADYAAPs2DAEAAAH0ATYVNjw2NiQVNgSzNqI2NjY2NgX//wVFNjk2PktLQAAAAUsBNr4fRhTAHzYufuzs7OwAAAHs7OwUNjY2NgAAAAABNjY0NjY2QTY+NjY2NjY2Nk7Q0NCQ0AAUFBQUNjY1NjZDNlg2NjY2TSE2UQARAQA= 0 -1 +BOgAAAEDAwgINjY2NgAAAMAfNjZkAAAAAAABAAEAFPY2HjY2NDYMAAEABAEAAPM2NgAAIzb7IPvz+/sAAAFCRDYkDzI0NjY2NjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTa1FTYABDk2NgAAATY2NjY2Nhw0JlgAIDY2/zY+NjY2NjYAADYAAPs2DAEAAAH0ATY2Njw2NiQVNgSzNqI2NjY2NgX//wVFNjk2PjYlPT09ATY2NgAAAAEANjQ2NjI2NjY2NgAQNjZLS0tAAAABSwE2vh9GFMAeNi5+7Ozs7AAAgADs7BQ2NjY2AAAAAAE2NjQ2NjZBNj42NjY2NjY2TtDQ0JDQABQUFBQ2NjU2NkM2WDY2NjZNNDZRABEBAA== 0 -1 +BOgAAAEDAwgINjY2NgAA6R8fNjZkAAAAAAEAFPY2HjY2NDYMAAEABAEAAAE2NgAAATb7IPvz+wEBAAFCRDYkDzI0NjY2NjYAATYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTYyFTYABDk2NgAAATY2NjY2Nhw0NlgAIDY2/w0NDQ0NDQ0NDQ0NNj42NgAAAQAANgAA+zYMAQAAAfQBNjY2PDY2JBU2BLM2ogX//wVFNjk2MjYlPT09ATY2MgAAAAEANjQ2NjI2NjY2NgAQNjZLS0tAAN8AAAEASwE2vh9GFMAfNi5+7Ozs7AAAAezs7BQ2NjY2AAAAAAE2NjQ2NjJBNj42NjY2NjY2TtDQ0JDQABQUFBTOUTU2NkM2WDY2NjZNNjZRABEBAA== 0 -1 +AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAjyEgQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACFyICECIGBBAiAhBAAoAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGAEVFhcEGDoaGwQL/x4fDTUpIhljJDoaGwQUIx4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIvIQIgIQQAIQIgAQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgAAAECAv4CAjsA 0 255 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAjyEgQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACFyICECIGBBAiAhBAAoAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGAEVFhcEGDoaGwQL/x4fDTUpIhljJDoaGwQUIx4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIvIQIgIQQAIQIgAQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgAAAECAv4CAjsA 780 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\242\018\004\001\021\022.\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\023\".\016\".\004\016\"\002\016\@.\128\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\004\008\002\002\002\002.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\001\021\022\023\004\024:\026\027\004\011\255\030\031\0135\)\"\025c\$.\026\027\004\020#\030\031&5\)\"\025\004\$\$\000\000\002\000\@\002\016\"\002\016\@\002\016\"\242\016\"\002\016\@\002\016\"\000\016\031\004\032\)\"#\004\$\$\000\000\002\000\@\002\016\"\002.\@\002\016\"\002\016\"\006\004\008\000\000\001\002\002\254.\002\; +AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/GgwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGAEVFhcEGDoaGwQLHR4fDTUpIhkEJDoaGwQUIx4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIgIQIgIQJQIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CAjsA 0 255 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/GgwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGAEVFhcEGDoaGwQLHR4fDTUpIhkEJDoaGwQUIx4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIgIQIgIQJQIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CAjsA 780 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\026.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\004\008\002\002\002\002.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\001\021\022\023\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$.\026\027\004\020#\030\031&5\)\"\025\004\$\$\000\000\002\000\@\002\016\"\002\016\@\002\016\"\002\016\"\002\016%\002\016\"\002\016\031\004\032\)\"#\004\$\$\000\000\002\000\@\002\016\"\002.\@\002\016\"\002\016\"\006\004\008\002\@\002\002\002\254.\002\; +AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw3oAwAABCQkAAD/AEACECICEEACECICECIGBBAiAkACEAACEEACECICECIGBAgCAgICAhAiAiY1KSIZBCQkBgQICf9/BAwNEg8EEAgSEwQBFRYXBBgBFRYXBBg6GhsECx0eHw01KSIZBCQ6GhsEFCMAAAEMHyY1KSIZBCQkGwACAEACECHtEEACECICECICEEACECICEB8EIBwiIwQkJAAAAgBAAhAiAhBAAhAiAhAiBgQIAkACAgL+AgI7AA== 0 -1 +DGQAAADKBhgi////fxA33d3d3QECAA0B+/HWEAA43iABAQyAEM/V3d3d8d3d3d3d3d3/AN3d3d3dyADGA+gAIvgP8gbz9A3z9PX2ECIB7SIB7AX43d3d3egD/wDd3d3d3cjd3d3/AAD19hAiAefTAARFAPgB6UD7BCUB/AUjIf8= 16 -1 +rgGvAbABsQGyAbMBtAG1AbYBtwEBtgG3AbgBuboBuQG6AbsBvAG9Ab4= 0 -1 +6AU2 3 -1 +BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxAwMDAwMDAwMDAwMDAwMCAwMDAwMDAwMDAwMDCAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzYAPRAA+/v7+/v7+wMDAwMDAwMDAwMDAwAAAQMDAwMDAwMDAwMDAwADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAQMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMOAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzYAAAGA 3 -1 +IBJDAQAQAAAAOj9IWUhISGVIAwMA//8AACBIAwMAAAHsSDD//wAAAwMDAwMAf9z//wAAAQMDAQMDAwMLAwMDAAEDAwMDAwQDAAA= 68 5 AwMEAwA= 13 \003\004\003 +BOiACwBA/78AABA2NjYyZxVHAOY1NDYfNkg2NP82NgABNjY2NGcVRwDmNTQYHzY2NjT/NjY2NgAA/wADNjY2H8LCwkYUAFA2NgAAgH0AAAfzATY+BFCCwkYUADYAAAGANjYkNv9//wB/NjY2NjYUAAABNjZPNjYYPgQ5NjbQztDQ0NDQ0Mcz0NDi0NDQAAAA+xAN+TY2BwEBAIkAABQUFBQ2NoAHAH8A6AE2WCs2NjYZNnZ2knZ2dnZ2gAsAAAEAGw== 0 -1 +BOgA8r8fNFI2wsK+wsLCBABSUBYAAQAAFBuQAAAA7DUmNgAEAAA2EAABAAAUG5AAAAA2AAAA3gAAgOXQ0NDQM9DQAAABAAAAAeZ/NjY2NjZ2dn92dgE2dn92dgE2Jgr//QFQNsLCwsLCwh80f////8JQNsLCwsLCwh80Nk3CwsLCwsLCwsLCADY2+gAA+nZ2AAABSwE0vjYAAACA5dDQ0NAy/+EB0NAAAAEAAAAB5n82NjY2NjZ2f3Z2ATZ2CgAQAAE2NgDo/4Dl0NDQ0DPQ0AAAAQAAAABAztDQ0M12dv/2AAC5ubm5ubm5ubm5ubm5ubkBAUZUADY2ADI2JDY2NJAAAQAA 0 38 BOgA8r8fNFI2wsK+wsLCBABSUBYAAQAAFBuQAAAA7DUmNgAEAAA= 118 \232\000\242\191.4R6\194\194\190\194\194\194\004\000RP\022\000\001\000\000\020\027\144\000\000\000\2365&6\000\004\000 +BOgAAMAfNjY2wsJCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADe4TU2NjY2NjY2NjY2NjYAAAABABtn6gABbEsAAAFLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQAAUAADPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2AHZ2dnZ2dnb/CwAAAQAb 0 93 BOgAAMAfNjY2wsJCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADe4TU2NjY2NjY2NjY2NjYAAAABABtn6gABbEsA 216 \232\000\000\192.666\194\194B\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.66\00966664\128X6\000\016\00166664\2556666\000\000\000\222\2255666666666666\000\000\000\001\000\027g\234\000\001lK +BOgAAMAfNjY2wvoAAPrCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0NjY2AAAA3gM2NjY2NjY2NjY2NjY2AAAAAQAbZ+oAAWxLS0tLaUtLATa+dnZ2dh9GFAA2NjYAADY2JDY2NP9/NjY2NjY2FTY2TzY2NjY2JDY2//+AAHZ2dnZ2dnb/CwBA/zY2NjY2NgA0NgAAAQABAIAAAAE2NgpQNjbQztDQ0NDQ0NAz0NDi0NDQAABA+xAUFDY2AAHQ0JAAABQUFBQ2NoABAH82WCs2NjY2NnZ2dnZ2dnZ2/wsAAAEAGw== 0 -1 +Z+oAASAAS0tLaUtLATa+AAAE6AAAwB82NjbCwsLCwsLCwsLCn8LCwsLCwjY2JBU2NDY2NjY2NjYAAAABABtnFTYABDY2NjY2CTY2NjY0gFg2ABABNl82NjT/NjY2NgABAN4DNjY2NjY2NjY2Njb6AAD6AP8AG2fqAAEgAEtLS2lLSwE2vnZ2dnYfRhQANjY2ACA2NiQ2NjT/fzY2NjY2NhU2Nk82NjY2NiQ2Nv//gAB2dnZ2dnb//3//QP+Dg4ODgzY2NjY0NgAAAQABAIAAAAE2NgpQNjYAAAHQNP9/NjY2NjY2FdA2WCs2NjY2NnZ2dnZ2anZ2/wsAAAEAGw== 27 -1 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngn/fzY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NlI2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngn/fzY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NlI2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAA 624 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\009\255\127664\128X6\000\016\00166664\2556666\000\000\000\222\003666666666R.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\1276X+66666vvvvvvvv\255\011\000 +BOgAAMBgYGBgYGBgYGBgYGBgYGBgYJ/Cs8LCwsLqNh0VNiE2NkI2NkM2AAAAEOkaZxU2AAQ2NlY2Ngk2lpaWlpaWlpaWlpaWlpaWHTY2IIBYNvQAAQAtATYiNn8AAAA2Nh02NjSAWDgALQE2NjZ/AOQANjY1///13gM2NjYFAGQAAwAAATY2NjZnFTYABDY2VjY2ZAD/f+//f4w2NjY2//82NjZQACAAHBwYHBwcHBwcHBwcAQB//xwcHBwcARAbZ+rwAWxLS3Z2djY2NP8QNjY2NjY2FTY2T3Z2dv8LAEAeNhQgf////xtn6vABbEtLdnZ2NjY0/xA2AdDQkAAAARTSFEAAAAABABs= 0 -1 +AAAAAQH/Hwb/AB7pAAAAAAAAAABAHyUlJSVWVlZfAP9/ADR3NjYjFBg2VTY29xQYNlU2NvdWVlZWVlYAAAFWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVl8A/wAAEiKA//8C////AATnVwAAxxUAAAAB//++hhAEiDsEOD0= 9 1 AA== 2 . +ATYkNjb/NiQgAF9fgF9XX184X71fX19fAF9fKysrfwBfAAABAHtfAwAAXwADAwMAAgMD/zYkIABfX19fAAABX19fOV+9X182NjYAAAEVaQAABgQ8PQ== 0 44 ATYkNjb/NiQgAF9fgF9XX184X71fX19fAF9fKysrfwBfAAABAHtfAwAAXwA= 86 6.66\2556\$\032\000__\128_W__8_\189____\000__+++\127\000_\000\000\001\000{_.\000\000_ +AOgAAMAfNjY2wsLCwsLCwuTiwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZwAAARU2AAQ2NjYAAAE2Ngk2NjY2NIBYNgAQAT02NjY0/zY2NjYAAADeAzY2NjY2NjY2NjYTNjbCwsLk4sKfwsLZwsLCNjYkFTY0NjY2NjY2NgAAABcAGwAAAQE2AAABNv+AhocEiDsEPD0= 0 1 AA== 2 . +8A== 1 -1 +BCorBCwtLjL79Pv7/BX7+/v7+/v7+/v7+/v7+/v7+wcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcBBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwYHBwcHBwcHBwcHB9EHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBw4HBwcHBzMzMxo7MzMzMzMzMzMzMzMzBwcHBwcHBwcHBwcHBwcHBwcHDgcHBwcHBwchBwcHBwcHBwcHBwcF//8FBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcHBwcHBwcHAhAiBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHAAEEMDH5fwQMDRIAECICECIGLi8EMDEqMwQ0NTYiBgQICfl/BAwNEgB/KjMEBwcHBwcHB8XFxcXFxcXFx8XFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFAAABxcXFxcXFxcXFxcXFxcXFxQAAAcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFvcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwMHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBgcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHDgcHKgcHMzMzGjszMzMzMzMzMzMzMzMHBwcHBwcHBwcHBwcHBwcHAAABBwcOBwcHBwcHxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcUHBwcHBwcHBwcHBwcCECIHBwcHBwcHBwcHBwcHBwcHBwcHBwcHAAABBwcHFwcHBwcHAwcHBwcHBwIQIgIQIgYuLwAAAQQwMfl/BAwNEg8QIgIQIgYuLwQwMSozBDQ1NiIGBAgJ+X8EDA0SDwQqMwQHBwcHBwcHxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFscXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxbfFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxeHFxcXFxcXFxcXFxcXFxcXFxcXFxcXNxcXFxcXFxcXFxcXFxcXFxcXFxcXF28XFxcXFxcXFxcXFxcXFxcXVxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxQHFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxdTFxcXFxQcHBwcHBwcHBxAREhMEFBESQAABFjEzMzMzMzMzMxEzMzMzMzMz/38TBBQRFhcEGCQaGwQUHQIQIgYECAn5fwQMJxIPBBAREhMEQAAWFuiAAAAbBBQdABAzBDQxf/7//wgJBwcHBwcHBwcHBwcHBwcGBwcHBwcHBwcHBwcHBwcOB08HBwcHByEHBwcHBwcHBwcHBwcHBwcHBwcHCQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBxcHBwcHBwcHBwcHxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxfv7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7xcXFxcXFAMXFxcXFxcXFxQAAAcXFxcXFxcXFxcXFxcUHBwcH 15 -1 +AAABASIAwA4= 0 1 AA== 2 . +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2NjY2NjY0Ejc2NjYAAADeAzYAAAE2NjY2NjY2NjbeAzYAAAE2NjY2NiQ2NjT/fzY2NjY2NhU2Nk82NjY2NiQ2Nv//gAB2dnZ2dnZ2/wsAQP82NjY2NDYAAAEAAQCAAAABNjYLUDY20M7Q0NDQ0NDQM9DQ4tDQ/38AAAABFBQ2NgAB0NCQAAAUFBQUNjaAAQB/NlgrNjY2NjZ2dnZ2dnZ2dv8LAAABABs= 0 148 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2NjY2NjY0Ejc2NjYAAADeAzYAAAE2NjY2NjY2NjbeAzYAAAE2NjY2NiQ2NjT/fzY2NjY2NhU2Nk82NjY2NiQ2Nv//gAB2dnZ2dnZ2/wsAQP82NjY2NDYAAAEAAQCAAA== 340 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\0046666666664\0187666\000\000\000\222\0036\000\000\001666666666\222\0036\000\000\001666.6\$664\255\127666666\02166O66666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATYmNjY0/zY2NjYAAADeCDY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATYmNjY0/zY2NjYAAADeCDY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAA 618 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\0016&664\2556666\000\000\000\222\0086666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\1276X+66666vvvvvvvv\255\011\000 +NjYAAAF2ZAAAFwtAAAABgn//AAABA0SAgAABCALLFTZXLNDGAAAU/wABAAIAAAAAgAAAAQkiHBU2V0XQ0JAAABQD6DZPrQAAAQCAAAAAAAEBAAIcFTZXRdDQkAAAFKP/AAAAo5Ojo6O+o56jo6Ojo6Ojo6Ojo6Ojo6MAAAGjdtB/AAAUAAAnNjVA3gABNv8AAzb/AAABdnZ2dnb/CwD8AQAb 54 -1 +ARERERERES42wsLCwuKfwsLCwsLCNjYkFTYiNjY2NjZ2Ngk2NjY2NIBYNg4QATYF//8F/zYXNjYAAACAAzY2VjY2SjY2NjY2ADYAAAABABsAECcAARw2NjYnpxknJycAAABAAOUBHDY2NgAAAQAAEjY0/382NjZNFzYVNhZPNgABAACA//////8F/zYXNjYRAPLeAzY2NjY2NjY2JCw2//+AAHYAABABNgX//wX/Nhc2NhEA8t4DNjY2NjY2djPQ0OLQ0NAAAAD7EBQUHTblgNDQkAAQKBQUGw== 0 -1 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAqATY2NjY0/zY2NjYAAADeAzZPNjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAqATY2NjY0/zY2NjYAAADeAzZPNjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAA 615 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000*\00166664\2556666\000\000\000\222\0036O66666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\1276X+66666vvvvvvvv\255\011\000 +BOhtAG0AAAA= 0 6 BOhtAG0A 11 \232m\000m +MzY238LYnwCAf8LCbzY2th82bzY2thU2NDYANiQlJicEKAAAAAHpARA2NwQ4OAE7BD49Pj8A 4 -1 +BOgAAMAfNjY2wsJAwsLCwsLCwp/CNjY2NjYAAIABABtnFTYABDY2NjY2CTY2NjY0gGA2ABABNjY2NmcxNgAENjYjNjYnBCgpNjcEODg6OwQ8PT4/AA== 0 -1 +BOgAEACf1MLCwsLCNgABABtnFTYABjY2NjY2CTY2NjY0gFhZADg4OTsEPD0+PwA= 0 -1 +ZAGU0g== 0 -1 +AAEp 1 -1 +//9/A4o= 5 -1 +//8FDgMEBwQsLS4nBC0AEwIQAAcAAH/fMjMEAAABCAkKTy4gAB8ANgQsLS4vBAcAAH/fMjMENDU2CCAAHwA2BCwtLi8eBC4gAB8ANgQsIAAfAC4vBH8QHgQ/OTpPLiCVlZWVlZWVlZWVlZWVBwcHBwcHBwcHBwYHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBw4HBwcHBzMzMxo7MzMzMzMzMzMzMzMzBwcHBwcHBwcHBwcHBxgHBwcHDgcHBwcHBwchBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcHBwcHBwcHAhAiBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBxcHBwcHBw0HBwcHBwcCECICECIGLi8AAAEEMDH5fwQMDRIPECICECIGLi8EMDEqMwQ0NTYiBgQICfl/BAz/EQ8EKjMEBwcHBwcHBwcHBwcHBwcHBxAREhMEFBESQAABFhczMzMzMzMzMxEzMzMzMzMz/38TBBQRFhcEGCQaGwQUHQIQIgYECAn5fwQMJxIPBBAREhMEQAAWFuiAAAAbBBQdABAzBDQxf/7/FAgJBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcOBzMzMwcHBwcHBwcHBwcHBwcHBwcHBw4HBwcHBwcHIQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHFwcHBwcHBwcHBwcHBwIQIgcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcNBwcHBwcHAhAiAhAiBi4vAAABBDAx+X8EDA0SDxAiAhAiBi4vBDAxKjMENDU2IgYECAn5hgQMDRIPBCozBAcHBwcHBwcHBwcHBwcHBwcQERITBBQREkAAARYXMzMzMzMzMzMRMzMzMzMzM/9/EwQUERYXBBgkGhsEFB0CECIGBAgJ+X8EDCcSBwcHBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcHBwcHBwcHBwcHfwAEJDQdAhAiAhBAAhAiAhAiEkAAARYXBBgZGhsEFB0gHwAzMzM= 5 -1 +BA8ICAgEBAUG6wQICQoLBAxuJSY2BBAAAAAEFC0uIFAzBDM1NjkEOB45OwQAAAE0NSk3BDgAOQQrNjkEOH////9QUQQ0KQIQIgYEECICEEACAhAiBgQIAgICAgIQIgIQQAIQIgIQIgYECAkiAgICkCICEEACECICECIGBAgJ/37hDA0gDwQQDRITBAEVFhcEGAEVFhcEGDoaGwQLHR4Q8TQpIhkEJDo1KSIZBCQkAAACAEAQQAIQIgIEECICEEACAhAiBgQIAgICAgIQIgIQQAIQIgIQIgYECAkiAgICECICBBAiAhBAAgIQIgYECAICAgICECICEEACECICECIGBAgJIgICApAiAhBAAhAiAhAiBgQICf9+4QwNIA8EEA0SEwQBFRYXBBgBFRYXBBg6GhsECx0eApAiAhBAAhAiAhAiBgQICf9+4QwNIA8EEA0SEwQBFRYXBBgBFRYXBBg6GhsECx0d/PEkJAAAAgBAEEACECICECIGBAgCHQICAv4QIgYECAJAAgIC/gICOwIQIgIQQAIQIgIQIgIQQAIQIgIQBAQgKSIjBCQkDgACAEACECICEEACECICEAAAASIGBAgCQAICAv4CAjsA 0 -1 +BAABAgMEERITBBQVFhceHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaWwRcXV5fBGBhYmMEZGVmZwRoaWprBGxtbm8EcHFycwR0dXZ3BHh5ensEfH1+fwSAgYKDBISFhocEiImKiwSMjY6PBJCRkpMElJWWlwSYmZqbBJydnp8EoKGiowSkpaanBKipqqsErK2urwSwsbKzBA== 0 -1 +BAABAgMEBAUGBwQAAAEABAwNDhQEEBESEwQUNBYXBAcH5wYHogcHByoHBwcHBwcHDQcHBwcHBwAQBwcHByKANTM2NwQ4OTo7BDxRPj8A 0 78 BAABAgMEBAUGBwQAAAEABAwNDhQEEBESEwQUNBYXBAcH5wYHogcHByoHBwcHBwcHDQcHBwcHBwAQBwcHByKANTM2NwQ4OTo7BDxRPj8A 226 \000\001\002\003.\004\005\006\007.\000\000\001\000.\012\013\014\020.\016\017\018\019.\0204\022\023.\007\007\231\006.\162\007\007\007*\007\007.\007\007\007\007\013\007\007.\007\007\007\000\016\007\007.\007\"\1285367.89:\;.<Q>? +BAAJCgsEGA0ODwQQERIEBAUGDQ4PBBAREhMEFBUWEwQUFRYXBBgZGhsEkx0eHxobBJMdDB8EICEiIwQ2NDUEkx0eDg8EEBESEwQEGBkaGwSTHQ== 0 -1 +BAAEBQYHBAgJCgsEDA0kJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEgAA6OwQ8PT4/BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgNTY3BDg5OjsEPD0+PwRAQUJDBERFRkcEdHV2dwR4eXp7BHx9fn8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChoqMEpKWmpwSoqaqrBKytrq8EsLGyswQ= 8 -1 +BAAEBQYHBAgJCgsEDA0ODwQQBBgZGhsEHB0hIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+XwRgYWBjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHVWVwRYWVpbBFxdXl8EYGFiYwRkZWZnBGhpamsEbG1ubwRwcXJzBHR1dncEeHl6ewR8fX5/BICBgoMEhIWGhwSIiYqLBIyRjo8EkJGSkwSUlZaXBJiZmpsEnJ2enwSgoaKjBKSlpqcEqKmqqwSsra6vBLCxsrME 8 -1 +AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgIQIgYECAn/fwQMDRIPBBAIEhMEARUWFwQYOhobBCY1KSIZBCQkAAACDkACECICEEACECICECICEEACECICEB8EICkiIwQkJAAAAgBAAhAiAhBAAhAiAhAAAA== 0 202 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgIQIgYECAn/fwQMDRIPBBAIEhMEARUWFwQYOhobBCY1KSIZBCQkAAACDkACECICEEACECICECICEEACECICEB8EICkiIwQkJAAAAgBAAhAiAhBAAhAiAhAAAA== 590 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004&5\)\"\025\004\$\$\000\000\002\014\@\002\016\"\002.\@\002\016\"\002\016\"\002\016\@\002\016\"\002\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\".\016\@.\016\".\016\000 +5h3eAgMEBAUGByQrCS0QAADy/38AzSoAAAFkLi8BLC0uL4AAAAEwMf///4ABQH8AQAAAAQAAY2QAZS8BLC1AZQAAAWVmZwQAAAFwZQBleARkZWZn6AP0//xwAAABYGRlAAAA5RAQAAABAQAAAAHw7uzs/+x/AEBlAPABgoMWEAD//w== 8 8 BgckKwktEAA= 17 \007\$+\009-\016 +BB8BAAAAAAEEBCEGBwAAAQQICQQhBgQICQoT2xMVAAABFhAoKRsuLwQwE9sTFQAAARYXBBgZMCsCAwQhPw== 8 6 BAQhBgcA 14 \004!\006\007 +BB8BAgMEBAUGCwQMDQ4PBAgIAQgICAgICAgICAcECAkKCwQMDQ4PBAgIAQgICAgICAgICAgICAgJCAgICAgICAgICAgICAgICAh0B/AICAgBCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAj/fwAACAgAAAAACHQAAAH/AAgICAg= 8 122 BgsEDA0ODwQICAEICAgICAgICAgHBAgJCgsEDA0ODwQICAEICAgICAgICAgICAgICQgICAgICAgICAgICAgICAgIdAfwCAgIAQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI/38AAAgIAAAAAAh0AAAB/wA= 427 \011\004\012\013\014\015.\008\008\001\008.\008\008\008\008\008\008\008\007.\008\009\010\011.\012\013\014\015.\008\008\001\008.\008\008\008\008\008\008\008\008.\008\008\009\008\008\008\008\008.\008\008\008\008\008\008\008\008.\008\008t\007\240\008\008\008.\008.\008\008\008\008\008\008\008\008.\008\008\008\008\008\008\008\008.\008\008\008\008\008\008\008\008.\008\008\008\255\127\000\000\008.\000\000\000\000\008t\000\000.\255 +AgAAAgBAAhAiAhBAAhAiAhAiBgQIDf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaIiMEBCQAAAIAQAIQAAIfQAIQIgIQIgYECAIChgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEAIECIiAEACECICECIGBAgCQAICAv4CADsA 0 250 AgAAAgBAAhAiAhBAAhAiAhAiBgQIDf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaIiMEBCQAAAIAQAIQAAIfQAIQIgIQIgYECAIChgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEAIECIiAEACECICECIGBAgCQAICAv4CAA== 754 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\013\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\128\000\000\0005\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\"#\004\004\$\000\000\002\000\@\002\016\000\002\031\@\002\016\".\016\".\004\008\002\002\134\002.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\020\029\030\031&5\)\"\025\004\$\$\016\"\002\016\".\016\@.\016\".\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\"\"\000\@\002\016\".\016\".\004\008\002\@\002\002.\254\002 +ISEhISEhISEhISEhISEhISEhISEAA+gAISEhISEhISEhISEhISEhGiEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhISEhIYAhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhIRAhISEhISEhISEhISEhISEhISEhISEhISEhIYAhISEhISEpcnN0dXZAAAAAew== 33 205 ISEhISEhGiEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhISEhIYAhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhIRAhISEhISEhISEhISEhISEhISEhISEhISEhIYAhISEhISEpcnN0dXZAAA== 218 !!!!!\026!!!!!!!!!!!C!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!!!!!!!~!!!!!!!!!!!.!\128!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!C!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!~!!!!!!!!!!\016!!!!!!.!!!!!!!!!!!!!!!!!!!\128!!!!!!\)rstuv\@ +AUABQwFEAUUBRgFPAVABUQFSAVMBVAFVAVYBVwFYAVkPWgFbAVwBXwFgAWEBYgFjAWQBZQFmAWcBaAFpAWoBawFsAW0BbgFvAXABcQFyAXMBdAF1AXYBdwF4AXkBegF7AXwBfQF+NjY2NjYAAAABBB82NgAAATY2NiQVNjQ2NjY2NjY2NjY2NjY2NgAAAAEENgAAATY2NjY2NgAAATY2NjY2NjY2AAAAAQQ2NjY2NjY2NjY2NjY2AAAANjY2NjY2NjYAAAABBDY2NjY2NjY2NjY2NiQgNjQ2NjY2NlE2NjY2NjY2NjY2Nho2Nn92dnZ2dpZ2dnb//0E2AQAAAQAAARY2 0 -1 +BwEBQwBkAQABRgFPAVABUQFSAesBVAFVAVYBbAFYAVkBWgFbF1wBAAABXwFgAVQBYgFrAWQBZQFmAWcBaAFpAWoBawdsAV0BbfxvAVs2NgBQNjYkZDY0NiQAZjZRNjY2Nv9aAVsBWwFfAQBQtDY2NjY2/1o2ZjZRNrdENjYAAAQ2NjY2MP9aAAEENgAAATY22jY2PwAABDY2AAAAAQQ2Gf4BNkc2Nr5LS0tLAAABSwE2vh0AATY2NuxQNjYkZDY0JCQ2ZjZRNks2AAABNmRaAVsbXAFfAWAAYQFiAWP/////AAABAWYBNgEAAAEAAAEWNg== 0 -1 +AUABQvZEAUUBRgFPAVABUQFSAVMBVAFVAVYBVwFLS0tLS0tLATa+HQDxNRc2AFgBWWH/AXMXdAF1AZEBdwF4AXkBegF7AXwBZwFo7GkBagFrAWwAAAFuAW8BcAF/AXIBcwEAAAH1kAF3AXgBeQF6AXsBfAAAAQF9AX42NjY2AAABAAEEHzY2AAABNjY2JBVdXV1dXV1dXV02NDY2NjY2NjY2NjY2NjY2AAAAAAABAQQ2AAABNjY2NjY2AAABAAABNjY2NjY2NjYAAAABGjY2NjY2NjY2NjY2NjYAAAEPHh4eHh4eHh4eHh4eHh4A5B4eAAAAAQAbS2xLS0tLS0tLATa+HQDxNRc2AFA2NiQsNjQ2GzY2NlE2NjY2NjY2NjY2Af/pAAABFjY= 0 -1 +AAAAAQIAAAGgACABgAGDDKABJQ== 0 1 AA== 2 . +AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgIQIgYECAn/fwQMDRIPBBAIEhMEARUWFwQYOhobBBQdHh8mNSkiGQQkJAAAAg5AAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQAAAIAQAIQIgIQQAIQIgIQAAA= 0 206 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgIQIgYECAn/fwQMDRIPBBAIEhMEARUWFwQYOhobBBQdHh8mNSkiGQQkJAAAAg5AAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQAAAIAQAIQIgIQQAIQIgIQAAA= 588 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\020\029\030\031&5\)\"\025\004\$\$\000\000\002\014\@.\016\".\016\@.\016\".\016\".\016\@.\016\".\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\".\016\@.\016\".\016\000 +AgAABgYGBgYcBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgQGBgYGBgYGBgYGBgYEBgYGBgYGBgYGBgYGBAYGBgYGBgYGBgYGBgYGBgYGQAYG/xAGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgZkBgYGBgYGBgayBgYGBgYGBgYGBgYGBgUGBgYGBgYGBgYGBgYaBgYGBgYGBgYGBgYGEwYGBgYGACAGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBughHh8EICkiIwQvJOsnBAgpKisALA== 0 255 AgAABgYGBgYcBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgQGBgYGBgYGBgYGBgYEBgYGBgYGBgYGBgYGBAYGBgYGBgYGBgYGBgYGBgYGQAYG/xAGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgZkBgYGBgYGBgayBgYGBgYGBgYGBgYGBgUGBgYGBgYGBgYGBgYaBgYGBgYGBgYGBgYGEwYGBgYGACAGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBughHh8EICkiIwQvJOsnBAgpKisA 871 \000\000.\006\006\006\006\028\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\004\006\006\006\006.\006\006\006\006\006\006.\004\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\@.\006\255\016\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006d\006\006\006.\006\006\006\006\178\006.\006\006\006\006\006\006.\006\006\006\006\005\006.\006\006\006\006\006\006.\006\006\006\026\006\006.\006\006\006\006\006\006.\006\006\019\006\006\006.\006\000\032\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\232!\030\031.\032\)\"#./\$\235'.\008\)*+ +BAABAgMEERITBBQVFtckHwQgISMjBCQlJicEKCkqKwQsLS4vBIAAMjMENDU2NwQ4/4A7BDw9Pj8EQEFCJwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaWwRcXV5fBDcEMzk6OwQ6WgQ8PT4/AA== 0 -1 +BAAB7gMEERITBBQVFhceHwQgIQgjBCQlJgQUFRYXBBgZGhsPHB0eHwQgIQAAAQ== 0 -1 +AABAAP//ERPyvwJEGB4bBBETNgQUFRPyvwJEGB4fGwQdEzYEKBUWFx4eHwQvHxgekwABDBsAASIjXl5eXl5eXl5eXl5eXl5eXiQ= 0 1 AA== 2 . +LS4vBDAxMjMENDUAAAE2NwAEAAECAwTyERMEFBUWFx4fBCAhMiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NQAAATY3BDg5OjsEPD0+PwRAQUJDBDlFRkcESEn//4AATU5PBFBRUlAEVFVWVwRYWVpbBFxdXl8EYGFiYwRkRmZnamsEbG1ubwRwcXJzBHR1dndpeHl6ewR8fX5/BICBgoMEhIWGEBAQEBAQEBAQEP///38QEBAQEBAQEBCA/xAQEBAQEBAQEBAQEAAAARAQEBAQAAToBAMDgAAAAfoD6AI= 44 -1 +BAABAgMEERITBBQVFhceHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaWwRcXWRfBGBhYmMEZGVmZwRoaWprfwSAgYKDBISFhhAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAE6AQDAwP6A+gC 0 -1 +FA== 0 -1 +AQABAwEiAQcBCAEJAQoBCwEMAZ/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQATZxU2AAQ2Ni42Ngk2NjY2NIBYNgAQATY2NhM0/yI2NjYAAADeAzY2NjY2AAAAAQAbZ+oAAYNLS0tLaUtLATa+kHZ2dh9GFAA2NjYAADYDNjY2NjY2NjY2NjY2NgAAAAEAG2fqAAFsS0tLS2lLSwE2vnZ2dnYfRhQANjY2AAA2NiQ2NjT/fzbsNjY2NhU2NgAAATY2NiQ2Nv//gAB2dnZ2dnZ2/wsANiQ2NjT/fzbCwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NhM0/zY2NjYAAADeAzY2NjYwNjY2NjY2NjYAAAABABtnNjY2Ngk2NjY2NIBYNgAQATZANhM0/zY2NjYAAADeAzY2Njb/NjY2NjYAAAE2NjYAAAABABtn6gABbEtLS0tpS0sBNr6QdnZ2H0YUADY2NgAANgM2NoD///82NjY2NjY2AAAAAQAbZ+oAAWxLS0tLaUtLATkAAAG+dnZ2dh9GFAA2NjYAADY2JDY2NP9/NjY2NjY2FTY2AAABNjY2JDY2//+AAHZ2dnZ2dnb/NjY2AAQ2AAAAAQAbZxU2AAQAAAE2NjY2Ngk2NjY2NIBYNgAQATY2NhM0/zY2NjYAAADeAzY2NjYwNjY2NjY2NjYAAAABABtnNjYhNjYVNjZPNjY2NjYkNjb/34AAbXZ2dnZ2dv8L0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0bnR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0QJA6DY2NjY0NgAAAQABAIAAAAE2NgpQNjbQsSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKQEAGw== 0 -1 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sNNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAARU2ClA2NtDO09DQ0NDQ0DPQ0OLQ0AAgAAD7EBQUNjYAAdDQkAAAFBQUFMLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NgAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sNNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAARU2ClA2NtDO09DQ0NDQ0DPQ0OLQ0AAgAAD7EBQUNjYAAdDQkAAAFBQUFMLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NgAA 655 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0136\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\001\0216\010P66\208\206\211\208\208\208\208\208\208.\208\208\226\208\208\000\032\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\020\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466\000 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AMXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxfr6+vr6xcUAAAEAG2cVNgAENjY2NjYJNjY2NjSAWDYAEAE2NjY2NP82NjY2AAAA3gM2Nrw2NjY2NjY2NjY2AAD8AAAbZ+oAAWxLS0tLaUtLDTa+dnZ2dh9GFAA2NjYAADY2JFE2NP9/NjY2NjY2FTY2TzY2NjY2JDY2//+AAHZ2dnZ2dnb/CwBA/zY2NjY0NgAAAQABAIAAAAEVNgpQNjbQztPQ3NDQ0NAz0NDi0NDQAAAA+xAUFDYAAAPo0JAAABQUFBQ2Ns0BAH82WCs2NjY2NnYAAP//dnZ2/wsAAAEAGw== 0 -1 +BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjYdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugHWEbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHUAd0B3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9AQEA/wA= 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjYdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugHWEbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHUAd0B3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9AQEA 717 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\009666\029\001\030\001\159\001\160\001\161\001\162\001\163\001\164\001\165\001\166\001\167\001\168\001\169\001\170\001\171\001\172\001\173.\174.\175.\176.\177.\178.\179.\180.\181.\182.\183.\184.\185.\186.\214.\188\001\189\001\190\001\191\001\192\001\193\001\194\001\195\001\196.\197.\198.\199.\200.\201.\202.\203.\204.\205.\206.\207.\208.\209.\210.\211.\212.\213.\214.\215.\216.\217.\218.\219.\212.\221.\222.\223.\224.\225.\226.\227.\228.\229.\230.\231.\232.\233.\234.\235.\236.\237.\238.\239.\240.\241.\242.\243.\244.\245.\246.\247.\248.\249.\250.\251.\252.\253.\001 +BOgAAMAfNjY2wsLCwsLCwsLCwp8EMDEFGAEfASABIQEiASMBJAEnASgBKQEqASsBLAEtAS4BNwE4ATkBOiA7ATwBPQE+AT8NAQ4A/gEQAREAAH//ARQBFwUYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBKQEqASvALMLCwsLCwsLCwp8EMDEFGAEfASABIQEiASMBJAEnASgBKQEqASsBLAEtAS4BNwE4ATkBOiA7ATwBPQE+AT8NAQ4A/gEQAREAAH//ARQBFwUYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBKQEqASvALAEtAS4BJwEoAUgBKgErASwBLQEuATsBLQEuAScBKAFIASoBKwEsAS0BLgE7ATwBPQE+AT8A 0 -1 +BAABAgMEAAABBwQICQoLBBINDg8EEBESEwQUFRYXBBgZGhsEHB0eNjY2AAA2NjY2Njw2ATYYNkUAAAIQ//9/TExMTExMTExMTExMTExMTExMTExMTENMbxMTExNqEykTlhMTEyYLAAEUFAAABjY2NjYAUwE2NhwAAAABAAABBDb/fwAAAzY2NgX//wU2NgD7SDYkNjk5OTk5OTk5OTk5OTk5OTk5OTk5PTY0pDY2NjY2NiQAAAE2Nn82cXZ2dnZ2dnZ20Coq0DPQ0P/gM9DQ//9//9AAAAHSu9DRkNAABgAA/xQUAAAGfzYkNjY0Nks2AAQeVTb/AAABNn////8= 0 -1 +BAABAgMEBAgJCgsEDA0ODwQQERITBAQ0NTY3BDg5OjsEPD0iIwQkJSYnBD8pKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/BEBFRkcESElKSwRMTUNPBFBRUlsEVFVWVwRYWVpbBFxNXl8EYGFiYwRkZWZnBGhpamsEbG0eHwQgISIjBCQlJicEKCkqKwQsLScvBICBgoME+oWGhwSIiYqLBDQ1NjcEODk9Pj8EQEFCQw== 0 -1 +AgAAAhBiAgAAAhAiAQEBAgFXAhBiAgAAAhABAgFXAQECEGICAAACECIBVwEBAgFXAQEBAQIBVwAAAQ== 0 56 AgAAAhBiAgAAAhAiAQEBAgFXAhBiAgAAAhABAgFXAQECEGICAAACECIBVwEBAgFXAQEBAQIBVwA= 129 \000\000.\016b.\000\000.\016\".\001.\002.W.\016b.\000\000.\016\001.\001W.\001.\016b.\000\000.\016\".W.\001.\001W.\001.\001.\001W +wMAAAcDAwMDANgMDAwMDAwMDA/oAAA== 16 5 AwMD+gA= 13 \003\003\250 diff --git a/resolv/tst-ns_name_compress.c b/resolv/tst-ns_name_compress.c new file mode 100644 index 0000000000..c1262e0ec1 --- /dev/null +++ b/resolv/tst-ns_name_compress.c @@ -0,0 +1,76 @@ +/* Test ns_name_compress corner cases. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <resolv.h> +#include <stdlib.h> +#include <string.h> +#include <support/check.h> +#include <support/support.h> + +/* Check that we can process names which fit into the destination + buffer exactly. See bug 21359. */ +static void +test_exact_fit (const char *name, size_t length) +{ + unsigned char *buf = xmalloc (length + 1); + memset (buf, '$', length + 1); + enum { ptr_count = 5 }; + const unsigned char *dnptrs[ptr_count] = { buf, }; + int ret = ns_name_compress (name, buf, length, + dnptrs, dnptrs + ptr_count); + if (ret < 0) + { + support_record_failure (); + printf ("error: ns_name_compress for %s/%zu failed\n", name, length); + return; + } + if ((size_t) ret != length) + { + support_record_failure (); + printf ("error: ns_name_compress for %s/%zu result mismatch: %d\n", + name, length, ret); + } + if (buf[length] != '$') + { + support_record_failure (); + printf ("error: ns_name_compress for %s/%zu padding write\n", + name, length); + } + free (buf); +} + +static int +do_test (void) +{ + test_exact_fit ("abc", 5); + test_exact_fit ("abc.", 5); + { + char long_name[] + = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa." + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."; + TEST_VERIFY (strlen (long_name) == NS_MAXCDNAME - 1); + test_exact_fit (long_name, NS_MAXCDNAME); + long_name[sizeof (long_name) - 1] = '\0'; + test_exact_fit (long_name, NS_MAXCDNAME); + } + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-ns_name_pton.c b/resolv/tst-ns_name_pton.c new file mode 100644 index 0000000000..6640ed3021 --- /dev/null +++ b/resolv/tst-ns_name_pton.c @@ -0,0 +1,210 @@ +/* Tests for ns_name_pton. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <arpa/nameser.h> +#include <array_length.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <support/check.h> +#include <support/support.h> +#include <support/test-driver.h> + +/* Bits which indicate which functions are supposed to report + success. */ +enum + { + hnok = 1, + dnok = 2, + mailok = 4, + ownok = 8, + allnomailok = hnok | dnok | ownok, + allok = hnok | dnok | mailok | ownok + }; + +/* A string of 60 characters. */ +#define STRING60 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + +/* A string of 63 characters (maximum label length). */ +#define STRING63 STRING60 "zzz" + +/* A string of 60 bytes (non-ASCII). */ +#define STRING60OCT \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \ + "\377\377\377\377\377\377\377\377\377" + +/* A string of 63 bytes (non-ASCII). */ +#define STRING63OCT STRING60OCT "\377\377\377" + +/* A string of 60 bytes (non-ASCII, quoted decimal). */ +#define STRING60DEC \ + "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ + "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ + "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ + "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ + "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \ + "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" + +/* A string of 63 bytes (non-ASCII, quoted decimal). */ +#define STRING63DEC STRING60DEC "\\255\\255\\255" + +/* Combines a test name with the expected results. */ +struct test_case +{ + const char *dn; + const char *back; /* Expected test result converted using ns_name_ntop. */ + bool fully_qualified; /* True if the domain name has a trailing dot. */ +}; + +static const struct test_case tests[] = + { + { "", ".", false }, + { ".", ".", true }, + { "..", NULL, }, + { "www", "www", false }, + { "www.", "www", true }, + { "www\\.", "www\\.", false }, + { ".www", NULL, }, + { ".www\\.", NULL, }, + { "example.com", "example.com", false }, + { "example.com.", "example.com", true }, + { ".example.com", NULL, }, + { ".example.com.", NULL, }, + { "example\\.com", "example\\.com", false }, + { "example\\.com.", "example\\.com", true }, + { "example..", NULL, }, + { "example..com", NULL, }, + { "example..com", NULL, }, + { "\\0", NULL, }, + { "\\00", NULL, }, + { "\\000", "\\000", false }, + { "\\1", NULL, }, + { "\\01", NULL, }, + { "\\001", "\\001", false }, + { "\\1x", NULL, }, + { "\\01x", NULL, }, + { "\\001x", "\\001x", false }, + { "\\256", NULL, }, + { "\\0641", "\\@1", false }, + { "\\0011", "\\0011", false }, + { STRING63, STRING63, false }, + { STRING63 ".", STRING63, true }, + { STRING63 "z", NULL, }, + { STRING63 "\\.", NULL, }, + { STRING60 "zz\\.", STRING60 "zz\\.", false }, + { STRING60 "zz\\..", STRING60 "zz\\.", true }, + { STRING63 "." STRING63 "." STRING63 "." STRING60 "z", + STRING63 "." STRING63 "." STRING63 "." STRING60 "z", false }, + { STRING63 "." STRING63 "." STRING63 "." STRING60 "z.", + STRING63 "." STRING63 "." STRING63 "." STRING60 "z", true }, + { STRING63 "." STRING63 "." STRING63 "." STRING60 "zz", NULL, }, + { STRING63 "." STRING63 "." STRING63 "." STRING60 "zzz", NULL, }, + { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT "\377", + STRING63DEC "." STRING63DEC "." STRING63DEC "." STRING60DEC "\\255", + false }, + { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT "\377.", + STRING63DEC "." STRING63DEC "." STRING63DEC "." STRING60DEC "\\255", + true }, + { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT + "\377\377", NULL, }, + { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT + "\377\377\377", NULL, }, + { "\\", NULL, }, + { "\\\\", "\\\\", false }, + { "\\\\.", "\\\\", true }, + { "\\\\\\", NULL, }, + { "a\\", NULL, }, + { "a.\\", NULL, }, + { "a.b\\", NULL, }, + }; + +static int +do_test (void) +{ + unsigned char *wire = xmalloc (NS_MAXCDNAME); + char *text = xmalloc (NS_MAXDNAME); + for (const struct test_case *test = tests; test < array_end (tests); ++test) + { + if (test_verbose) + printf ("info: testing domain name [[[%s]]]\n", test->dn); + int ret = ns_name_pton (test->dn, wire, NS_MAXCDNAME); + if (ret == -1) + { + if (test->back != NULL) + { + support_record_failure (); + printf ("error: unexpected decoding failure for [[%s]]\n", + test->dn); + } + /* Otherwise, we have an expected decoding failure. */ + continue; + } + + if (ret < -1 || ret > 1) + { + support_record_failure (); + printf ("error: invalid return value %d for [[%s]]\n", + ret, test->dn); + continue; + } + + int ret2 = ns_name_ntop (wire, text, NS_MAXDNAME); + + if (ret2 < 0) + { + support_record_failure (); + printf ("error: failure to convert back [[%s]]\n", test->dn); + } + + if (test->back == NULL) + { + support_record_failure (); + printf ("error: unexpected success converting [[%s]]\n", test->dn); + if (ret2 >= 1) + printf ("error: result converts back to [[%s]]\n", test->dn); + continue; + } + + if (strcmp (text, test->back) != 0) + { + support_record_failure (); + printf ("error: back-conversion of [[%s]] did not match\n", + test->dn); + printf ("error: expected: [[%s]]\n", test->back); + printf ("error: actual: [[%s]]\n", text); + } + + if (ret != test->fully_qualified) + { + support_record_failure (); + printf ("error: invalid fully-qualified status for [[%s]]\n", + test->dn); + printf ("error: expected: %d\n", (int) test->fully_qualified); + printf ("error: actual: %d\n", ret); + } + } + + free (text); + free (wire); + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-p_secstodate.c b/resolv/tst-p_secstodate.c new file mode 100644 index 0000000000..8d5faa2fa1 --- /dev/null +++ b/resolv/tst-p_secstodate.c @@ -0,0 +1,84 @@ +/* Test __p_secstodate compat symbol. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <array_length.h> +#include <limits.h> +#include <resolv.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> + +#include <shlib-compat.h> + +#if TEST_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_27) + +char *__p_secstodate (unsigned long int); +compat_symbol_reference (libresolv, __p_secstodate, __p_secstodate, GLIBC_2_0); + +struct test +{ + /* Argument to __p_secstodate. */ + unsigned long int in; + /* Expected output. */ + const char *out; +}; + +static const struct test tests[] = + { + { 0UL, "19700101000000" }, + { 12345UL, "19700101032545" }, + { 999999999UL, "20010909014639" }, + { 2147483647UL, "20380119031407" }, + { 2147483648UL, "<overflow>" }, + { 4294967295UL, "<overflow>" }, +# if ULONG_MAX > 0xffffffffUL + { 4294967296UL, "<overflow>" }, + { 9999999999UL, "<overflow>" }, + { LONG_MAX, "<overflow>" }, + { ULONG_MAX, "<overflow>" }, +# endif + }; + +static int +do_test (void) +{ + int ret = 0; + for (size_t i = 0; i < array_length (tests); i++) + { + char *p = __p_secstodate (tests[i].in); + printf ("Test %zu: %lu -> %s\n", i, tests[i].in, p); + if (strcmp (p, tests[i].out) != 0) + { + printf ("test %zu failed", i); + ret = 1; + } + } + return ret; +} + +#else + +static int +do_test (void) +{ + return 77; +} + +#endif + +#include <support/test-driver.c> diff --git a/resolv/tst-res_hconf_reorder.c b/resolv/tst-res_hconf_reorder.c index 2ef7f073ca..a16a6b2112 100644 --- a/resolv/tst-res_hconf_reorder.c +++ b/resolv/tst-res_hconf_reorder.c @@ -1,6 +1,6 @@ /* BZ #17977 _res_hconf_reorder_addrs test. - Copyright (C) 2015-2016 Free Software Foundation, Inc. + Copyright (C) 2015-2018 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -19,6 +19,7 @@ #include <errno.h> #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <time.h> #include <dlfcn.h> diff --git a/resolv/tst-res_hnok.c b/resolv/tst-res_hnok.c new file mode 100644 index 0000000000..a000cfd895 --- /dev/null +++ b/resolv/tst-res_hnok.c @@ -0,0 +1,169 @@ +/* Tests for res_hnok and related functions. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <array_length.h> +#include <resolv.h> +#include <string.h> +#include <support/check.h> +#include <support/test-driver.h> + +/* Bits which indicate which functions are supposed to report + success. */ +enum + { + hnok = 1, + dnok = 2, + mailok = 4, + ownok = 8, + allnomailok = hnok | dnok | ownok, + allok = hnok | dnok | mailok | ownok + }; + +/* A string of 60 characters. */ +#define STRING60 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" + +/* A string of 63 characters (maximum label length). */ +#define STRING63 STRING60 "zzz" + +/* Combines a test name with the expected results. */ +struct test_case +{ + const char *dn; + unsigned int result; /* Combination of the *ok flags. */ +}; + +static const struct test_case tests[] = + { + { "", allok }, + { ".", allok }, + { "..", 0 }, + { "www", allnomailok }, + { "www.", allnomailok }, + { "example", allnomailok }, + { "example.com", allok }, + { "www.example.com", allok }, + { "www.example.com.", allok }, + { "www-.example.com.", allok }, + { "www.-example.com.", allok }, + { "*.example.com", dnok | mailok | ownok }, + { "-v", dnok }, + { "-v.example.com", mailok | dnok }, + { "**.example.com", dnok | mailok }, + { "www.example.com\\", 0 }, + { STRING63, allnomailok }, + { STRING63 ".", allnomailok }, + { STRING63 "\\.", 0 }, + { STRING63 "z", 0 }, + { STRING63 ".example.com", allok }, + { STRING63 "." STRING63 "." STRING63 "." STRING60 "z", allok }, + { STRING63 "." STRING63 "." STRING63 "." STRING60 "z.", allok }, + { STRING63 "." STRING63 "." STRING63 "." STRING60 "zz", 0 }, + { STRING63 "." STRING63 "." STRING63 "." STRING60 "zzz", 0 }, + { "hostmaster@mail.example.com", dnok | mailok }, + { "hostmaster\\@mail.example.com", dnok | mailok }, + { "with whitespace", 0 }, + { "with\twhitespace", 0 }, + { "with\nwhitespace", 0 }, + { "with.whitespace ", 0 }, + { "with.whitespace\t", 0 }, + { "with.whitespace\n", 0 }, + { "with\\ whitespace", 0 }, + { "with\\\twhitespace", 0 }, + { "with\\\nwhitespace", 0 }, + { "with.whitespace\\ ", 0 }, + { "with.whitespace\\\t", 0 }, + { "with.whitespace\\\n", 0 }, + }; + +/* Run test case *TEST with FUNC (named FUNCNAME) and report an error + if the result does not match the result flag at BIT. */ +static void +one_test (const struct test_case *test, const char *funcname, + int (*func) (const char *), unsigned int bit) +{ + int expected = (test->result & bit) != 0; + int actual = func (test->dn); + if (actual != expected) + { + support_record_failure (); + printf ("error: %s (\"%s\"): expected=%d, actual=%d\n", + funcname, test->dn, expected, actual); + } +} + +/* Run 255 tests using all the bytes from 1 to 255, surround the byte + with the strings PREFIX and SUFFIX, and check that FUNC (named + FUNCNAME) accepts only those bytes listed in ACCEPTED. */ +static void +one_char (const char *prefix, const char *accepted, const char *suffix, + const char *funcname, int (*func) (const char *)) +{ + for (int ch = 1; ch <= 255; ++ch) + { + char dn[1024]; + snprintf (dn, sizeof (dn), "%s%c%s", prefix, ch, suffix); + int expected = strchr (accepted, ch) != NULL; + int actual = func (dn); + if (actual != expected) + { + support_record_failure (); + printf ("error: %s (\"%s\"): expected=%d, actual=%d\n", + funcname, dn, expected, actual); + } + } +} + +#define LETTERSDIGITS \ + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" + +#define PRINTABLE \ + "!\"#$%&'()*+,/:;<=>?@[\\]^`{|}~" + +static int +do_test (void) +{ + for (const struct test_case *test = tests; test < array_end (tests); ++test) + { + if (test_verbose) + printf ("info: testing domain name [[[%s]]] (0x%x)\n", + test->dn, test->result); + one_test (test, "res_hnok", res_hnok, hnok); + one_test (test, "res_dnok", res_dnok, dnok); + one_test (test, "res_mailok", res_mailok, mailok); + one_test (test, "res_ownok", res_ownok, ownok); + } + + one_char + ("", LETTERSDIGITS "._", "", "res_hnok", res_hnok); + one_char + ("middle", + LETTERSDIGITS ".-_\\", /* "middle\\suffix" == "middlesuffix", so good. */ + "suffix", "res_hnok", res_hnok); + one_char + ("middle", + LETTERSDIGITS ".-_" PRINTABLE, + "suffix.example", "res_mailok", res_mailok); + one_char + ("mailbox.middle", + LETTERSDIGITS ".-_\\", + "suffix.example", "res_mailok", res_mailok); + + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-res_use_inet6.c b/resolv/tst-res_use_inet6.c new file mode 100644 index 0000000000..0170335741 --- /dev/null +++ b/resolv/tst-res_use_inet6.c @@ -0,0 +1,509 @@ +/* Basic functionality tests for inet6 option processing. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <ctype.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <support/check.h> +#include <support/check_nss.h> +#include <support/resolv_test.h> +#include <support/support.h> +#include <support/xthread.h> + +/* Handle IPv4 reverse lookup responses. Product a PTR record + A-B-C-D.v4.example. */ +static void +response_ptr_v4 (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + int bytes[4]; + int offset = -1; + TEST_VERIFY (sscanf (qname, "%d.%d.%d.%d.in-addr.arpa%n", + bytes + 0, bytes + 1, bytes + 2, bytes + 3, + &offset) == 4); + TEST_VERIFY (offset == strlen (qname)); + resolv_response_init (b, (struct resolv_response_flags) {}); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, qname, qclass, T_PTR, 0); + char *name = xasprintf ("%d-%d-%d-%d.v4.example", + bytes[3], bytes[2], bytes[1], bytes[0]); + resolv_response_add_name (b, name); + free (name); + resolv_response_close_record (b); +} + +/* Handle IPv6 reverse lookup responses. Produce a PTR record + <32 hex digits>.v6.example. */ +static void +response_ptr_v6 (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + + TEST_VERIFY_EXIT (strlen (qname) > 64); + + char bytes[33]; + for (int i = 0; i < 64; ++i) + if ((i % 2) == 0) + { + TEST_VERIFY (isxdigit ((unsigned char) qname[i])); + bytes[31 - i / 2] = qname[i]; + } + else + TEST_VERIFY_EXIT (qname[i] == '.'); + bytes[32] = '\0'; + + resolv_response_init (b, (struct resolv_response_flags) {}); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, qname, qclass, T_PTR, 0); + char *name = xasprintf ("%s.v6.example", bytes); + resolv_response_add_name (b, name); + free (name); + resolv_response_close_record (b); +} + +/* Produce a response based on QNAME: Certain characters in the first + label of QNAME trigger the inclusion of resource records: + + 'a' A record (IPv4 address) + 'q' AAAA record (quad A record, IPv6 address) + 'p' PTR record + 'm' record type must match QTYPE (no additional records) + '6' stop flag processing if QTYPE == AAAA + + For 'a' and 'q', QTYPE is ignored for record type selection if 'm' + is not specified. + + in-addr.arpa and ip6.arpa queries are handled separately in + response_ptr_v4 and response_ptr_v6. */ +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + if (strstr (qname, ".in-addr.arpa") != NULL) + return response_ptr_v4 (ctx, b, qname, qclass, qtype); + else if (strstr (qname, ".ip6.arpa") != NULL) + return response_ptr_v6 (ctx, b, qname, qclass, qtype); + + bool include_a = false; + bool include_aaaa = false; + bool include_match = false; + bool include_ptr = false; + for (const char *p = qname; *p != '.' && *p != '\0'; ++p) + { + if (*p == 'a') + include_a = true; + else if (*p == 'q') + include_aaaa = true; + else if (*p == 'm') + include_match = true; + else if (*p == 'p') + include_ptr = true; + else if (*p == '6' && qtype == T_AAAA) + break; + } + if (include_match) + { + if (qtype == T_A) + include_aaaa = false; + else if (qtype == T_AAAA) + include_a = false; + } + + resolv_response_init (b, (struct resolv_response_flags) {}); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + if (include_a) + { + char ipv4[4] = {192, 0, 2, 17}; + resolv_response_open_record (b, qname, qclass, T_A, 0); + resolv_response_add_data (b, &ipv4, sizeof (ipv4)); + resolv_response_close_record (b); + } + if (include_aaaa) + { + char ipv6[16] + = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + resolv_response_open_record (b, qname, qclass, T_AAAA, 0); + resolv_response_add_data (b, &ipv6, sizeof (ipv6)); + resolv_response_close_record (b); + } + if (include_ptr) + { + resolv_response_open_record (b, qname, qclass, T_PTR, 0); + resolv_response_add_name (b, "ptr-target.example"); + resolv_response_close_record (b); + } +} + +/* Test that getaddrinfo is not influenced by RES_USE_INET6. */ +static void +test_gai (void) +{ + { + struct addrinfo hints = + { + .ai_family = AF_UNSPEC, + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP, + }; + struct addrinfo *ai; + int ret = getaddrinfo ("qam.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_UNSPEC qam.example", ai, ret, + "address: STREAM/TCP 192.0.2.17 80\n" + "address: STREAM/TCP 2001:db8::1 80\n"); + if (ret == 0) + freeaddrinfo (ai); + ret = getaddrinfo ("am.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_UNSPEC am.example", ai, ret, + "address: STREAM/TCP 192.0.2.17 80\n"); + if (ret == 0) + freeaddrinfo (ai); + ret = getaddrinfo ("qa.example", "80", &hints, &ai); + /* Combined A/AAAA responses currently result in address + duplication. */ + check_addrinfo ("getaddrinfo AF_UNSPEC qa.example", ai, ret, + "address: STREAM/TCP 192.0.2.17 80\n" + "address: STREAM/TCP 192.0.2.17 80\n" + "address: STREAM/TCP 2001:db8::1 80\n" + "address: STREAM/TCP 2001:db8::1 80\n"); + if (ret == 0) + freeaddrinfo (ai); + } + { + struct addrinfo hints = + { + .ai_family = AF_INET, + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP, + }; + struct addrinfo *ai; + int ret = getaddrinfo ("qam.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_INET qam.example", ai, ret, + "address: STREAM/TCP 192.0.2.17 80\n"); + if (ret == 0) + freeaddrinfo (ai); + ret = getaddrinfo ("am.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_INET am.example", ai, ret, + "address: STREAM/TCP 192.0.2.17 80\n"); + if (ret == 0) + freeaddrinfo (ai); + ret = getaddrinfo ("qa.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_INET qa.example", ai, ret, + "address: STREAM/TCP 192.0.2.17 80\n"); + if (ret == 0) + freeaddrinfo (ai); + } + { + struct addrinfo hints = + { + .ai_family = AF_INET6, + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP, + }; + struct addrinfo *ai; + int ret = getaddrinfo ("qa.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo (AF_INET6)", ai, ret, + "address: STREAM/TCP 2001:db8::1 80\n"); + if (ret == 0) + freeaddrinfo (ai); + ret = getaddrinfo ("am.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_INET6 am.example", ai, ret, + "error: No address associated with hostname\n"); + if (ret == 0) + freeaddrinfo (ai); + ret = getaddrinfo ("qam.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_INET6 qam.example", ai, ret, + "address: STREAM/TCP 2001:db8::1 80\n"); + if (ret == 0) + freeaddrinfo (ai); + } +} + +/* Test gethostbyaddr and getnameinfo. The results are independent of + RES_USE_INET6. */ +static void +test_reverse (void) +{ + { + char ipv4[4] = { 192, 0, 2, 17 }; + check_hostent ("gethostbyaddr AF_INET", + gethostbyaddr (ipv4, sizeof (ipv4), AF_INET), + "name: 192-0-2-17.v4.example\n" + "address: 192.0.2.17\n"); + } + { + char ipv6[16] + = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + check_hostent ("gethostbyaddr AF_INET", + gethostbyaddr (ipv6, sizeof (ipv6), AF_INET6), + "name: 20010db8000000000000000000000001.v6.example\n" + "address: 2001:db8::1\n"); + } + + { + struct sockaddr_in addr = + { + .sin_family = AF_INET, + .sin_addr = { .s_addr = htonl (0xc0000211) }, + .sin_port = htons (80) + }; + char host[NI_MAXHOST]; + char service[NI_MAXSERV]; + int ret = getnameinfo ((struct sockaddr *) &addr, sizeof (addr), + host, sizeof (host), service, sizeof (service), + NI_NUMERICSERV); + TEST_VERIFY (ret == 0); + TEST_VERIFY (strcmp (host, "192-0-2-17.v4.example") == 0); + TEST_VERIFY (strcmp (service, "80") == 0); + } + { + char ipv6[16] + = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + struct sockaddr_in6 addr = + { + .sin6_family = AF_INET6, + .sin6_port = htons (80), + }; + TEST_VERIFY (sizeof (ipv6) == sizeof (addr.sin6_addr)); + memcpy (&addr.sin6_addr, ipv6, sizeof (addr.sin6_addr)); + char host[NI_MAXHOST]; + char service[NI_MAXSERV]; + int ret = getnameinfo ((struct sockaddr *) &addr, sizeof (addr), + host, sizeof (host), service, sizeof (service), + NI_NUMERICSERV); + TEST_VERIFY (ret == 0); + TEST_VERIFY + (strcmp (host, "20010db8000000000000000000000001.v6.example") == 0); + TEST_VERIFY (strcmp (service, "80") == 0); + } +} + +/* Test that gethostbyname2 is mostly not influenced by + RES_USE_INET6. */ +static void +test_get2_any (void) +{ + check_hostent ("gethostbyname2 AF_INET am.example", + gethostbyname2 ("am.example", AF_INET), + "name: am.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname2 AF_INET a.example", + gethostbyname2 ("a.example", AF_INET), + "name: a.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname2 AF_INET qm.example", + gethostbyname2 ("qm.example", AF_INET), + "error: NO_ADDRESS\n"); + check_hostent ("gethostbyname2 AF_INET q.example", + gethostbyname2 ("q.example", AF_INET), + "error: NO_RECOVERY\n"); + check_hostent ("gethostbyname2 AF_INET qam.example", + gethostbyname2 ("qam.example", AF_INET), + "name: qam.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname2 AF_INET qa.example", + gethostbyname2 ("qa.example", AF_INET), + "name: qa.example\n" + "address: 192.0.2.17\n"); + + check_hostent ("gethostbyname2 AF_INET6 qm.example", + gethostbyname2 ("qm.example", AF_INET6), + "name: qm.example\n" + "address: 2001:db8::1\n"); + check_hostent ("gethostbyname2 AF_INET6 q.example", + gethostbyname2 ("q.example", AF_INET6), + "name: q.example\n" + "address: 2001:db8::1\n"); + check_hostent ("gethostbyname2 AF_INET6 qam.example", + gethostbyname2 ("qam.example", AF_INET6), + "name: qam.example\n" + "address: 2001:db8::1\n"); + check_hostent ("gethostbyname2 AF_INET6 qa.example", + gethostbyname2 ("qa.example", AF_INET6), + "name: qa.example\n" + "address: 2001:db8::1\n"); + /* Additional AF_INET6 tests depend on RES_USE_INET6; see below. */ + + test_reverse (); +} + +/* gethostbyname2 tests with RES_USE_INET6 disabled. */ +static void +test_get2_no_inet6 (void) +{ + test_get2_any (); + + check_hostent ("gethostbyname2 AF_INET6 am.example", + gethostbyname2 ("am.example", AF_INET6), + "error: NO_ADDRESS\n"); + check_hostent ("gethostbyname2 AF_INET6 a.example", + gethostbyname2 ("a.example", AF_INET6), + "error: NO_RECOVERY\n"); +} + +/* gethostbyname2 tests with RES_USE_INET6 enabled. */ +static void +test_get2_inet6 (void) +{ + test_get2_any (); + + check_hostent ("gethostbyname2 AF_INET6 am.example", + gethostbyname2 ("am.example", AF_INET6), + "name: am.example\n" + "address: ::ffff:192.0.2.17\n"); + check_hostent ("gethostbyname2 AF_INET6 a.example", + gethostbyname2 ("a.example", AF_INET6), + "error: NO_RECOVERY\n"); +} + +/* Collection of tests which assume no RES_USE_INET6 flag. */ +static void +test_no_inet6 (void) +{ + check_hostent ("gethostbyname (\"a.example\")", + gethostbyname ("a.example"), + "name: a.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname (\"qa.example\")", + gethostbyname ("qa.example"), + "name: qa.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname (\"am.example\")", + gethostbyname ("am.example"), + "name: am.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname (\"amp.example\")", + gethostbyname ("amp.example"), + "name: amp.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname (\"qam.example\")", + gethostbyname ("qam.example"), + "name: qam.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname (\"q.example\")", + gethostbyname ("q.example"), + "error: NO_RECOVERY\n"); + check_hostent ("gethostbyname (\"qm.example\")", + gethostbyname ("qm.example"), + "error: NO_ADDRESS\n"); + test_get2_no_inet6 (); + test_get2_no_inet6 (); + test_gai (); + test_get2_no_inet6 (); + test_get2_no_inet6 (); +} + +static void * +threadfunc (void *ignored) +{ + struct resolv_test *obj = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response + }); + + TEST_VERIFY ((_res.options & RES_USE_INET6) == 0); + test_no_inet6 (); + + _res.options |= RES_USE_INET6; + check_hostent ("gethostbyname (\"a.inet6.example\")", + gethostbyname ("a.inet6.example"), + "error: NO_RECOVERY\n"); + check_hostent ("gethostbyname (\"am.inet6.example\")", + gethostbyname ("am.inet6.example"), + "name: am.inet6.example\n" + "address: ::ffff:192.0.2.17\n"); + check_hostent ("gethostbyname (\"qa.inet6.example\")", + gethostbyname ("qa.inet6.example"), + "name: qa.inet6.example\n" + "address: 2001:db8::1\n"); + check_hostent ("gethostbyname (\"qam.inet6.example\")", + gethostbyname ("qam.inet6.example"), + "name: qam.inet6.example\n" + "address: 2001:db8::1\n"); + check_hostent ("gethostbyname (\"q.inet6.example\")", + gethostbyname ("q.inet6.example"), + "name: q.inet6.example\n" + "address: 2001:db8::1\n"); + check_hostent ("gethostbyname (\"qm.inet6.example\")", + gethostbyname ("qm.inet6.example"), + "name: qm.inet6.example\n" + "address: 2001:db8::1\n"); + check_hostent ("gethostbyname (\"amp.inet6.example\")", + gethostbyname ("amp.inet6.example"), + "error: NO_RECOVERY\n"); + check_hostent ("gethostbyname (\"qmp.inet6.example\")", + gethostbyname ("qmp.inet6.example"), + "name: qmp.inet6.example\n" + "address: 2001:db8::1\n"); + check_hostent ("gethostbyname (\"ap.inet6.example\")", + gethostbyname ("ap.inet6.example"), + "error: NO_RECOVERY\n"); + check_hostent ("gethostbyname (\"6ap.inet6.example\")", + gethostbyname ("6ap.inet6.example"), + "name: 6ap.inet6.example\n" + "address: ::ffff:192.0.2.17\n"); + check_hostent ("gethostbyname (\"am6p.inet6.example\")", + gethostbyname ("am6p.inet6.example"), + "name: am6p.inet6.example\n" + "address: ::ffff:192.0.2.17\n"); + check_hostent ("gethostbyname (\"qp.inet6.example\")", + gethostbyname ("qp.inet6.example"), + "name: qp.inet6.example\n" + "address: 2001:db8::1\n"); + test_get2_inet6 (); + test_get2_inet6 (); + test_gai (); + test_get2_inet6 (); + test_get2_inet6 (); + + TEST_VERIFY (_res.options & RES_USE_INET6); + _res.options &= ~RES_USE_INET6; + test_no_inet6 (); + + resolv_test_end (obj); + + return NULL; +} + +static int +do_test (void) +{ + resolv_test_init (); + + /* Attempt to run on a non-main thread first. */ + { + pthread_t thr = xpthread_create (NULL, threadfunc, NULL); + xpthread_join (thr); + } + + /* Try the main thread next. */ + threadfunc (NULL); + + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-resolv-ai_idn-common.c b/resolv/tst-resolv-ai_idn-common.c new file mode 100644 index 0000000000..e7c4030e1c --- /dev/null +++ b/resolv/tst-resolv-ai_idn-common.c @@ -0,0 +1,569 @@ +/* Common code for AI_IDN/NI_IDN tests. + Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* Before including this file, TEST_USE_UTF8 must be defined to 1 or + 0, depending on whether a UTF-8 locale is used or a Latin-1 + locale. */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <support/check.h> +#include <support/check_nss.h> +#include <support/resolv_test.h> +#include <support/support.h> + +/* Name of the shared object for libidn2. */ +#define LIBIDN2_SONAME "libidn2.so.0" + +#if TEST_USE_UTF8 +/* UTF-8 encoding of "nämchen" (German for “namelet”). */ +# define NAEMCHEN "n\xC3\xA4mchen" + +/* UTF-8 encoding of "שם" (Hebrew for “name”). */ +# define SHEM "\xD7\xA9\xD7\x9D" + +/* UTF-8 encoding of "buße" (German for “penance”). This used to be + encoded as "busse" (“busses”) in IDNA2003. */ +# define BUSSE "bu\xC3\x9F""e" + +#else +/* Latin-1 encodings, as far as they are available. */ + +# define NAEMCHEN "n\xE4mchen" +# define BUSSE "bu\xDF""e" + +#endif + +/* IDNA encoding of NAEMCHEN. */ +#define NAEMCHEN_IDNA "xn--nmchen-bua" + +/* IDNA encoding of NAEMCHEN "_zwo". */ +#define NAEMCHEN_ZWO_IDNA "xn--nmchen_zwo-q5a" + +/* IDNA encoding of SHEM. */ +#define SHEM_IDNA "xn--iebx" + +/* IDNA encoding of BUSSE. */ +#define BUSSE_IDNA "xn--bue-6ka" + +/* IDNA encoding of "שם1". */ +#define SHEM1_IDNA "xn--1-qic9a" + +/* Another IDNA name. */ +#define ANDERES_NAEMCHEN "anderes-" NAEMCHEN +#define ANDERES_NAEMCHEN_IDNA "xn--anderes-nmchen-eib" + +/* Controls the kind of test data in a PTR lookup response. */ +enum gni_test + { + gni_non_idn_name, + gni_non_idn_cname_to_non_idn_name, + gni_non_idn_cname_to_idn_name, + gni_idn_name, + gni_idn_shem, + gni_idn_shem1, + gni_idn_cname_to_non_idn_name, + gni_idn_cname_to_idn_name, + gni_invalid_idn_1, + gni_invalid_idn_2, + }; + +/* Called from response below. The LSB (first byte) controls what + goes into the response, see enum gni_test. */ +static void +response_ptr (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, const char *qname) +{ + int comp[4] = { 0 }; + TEST_COMPARE (sscanf (qname, "%d.%d.%d.%d.in-addr.arpa", + &comp[0], &comp[1], &comp[2], &comp[3]), 4); + const char *next_name; + switch ((enum gni_test) comp[0]) + { + /* First name in response is non-IDN name. */ + case gni_non_idn_name: + resolv_response_open_record (b, qname, C_IN, T_PTR, 0); + resolv_response_add_name (b, "non-idn.example"); + resolv_response_close_record (b); + return; + case gni_non_idn_cname_to_non_idn_name: + resolv_response_open_record (b, qname, C_IN, T_CNAME, 0); + next_name = "non-idn-cname.example"; + resolv_response_add_name (b, next_name); + resolv_response_close_record (b); + resolv_response_open_record (b, next_name, C_IN, T_PTR, 0); + resolv_response_add_name (b, "non-idn-name.example"); + resolv_response_close_record (b); + return; + case gni_non_idn_cname_to_idn_name: + resolv_response_open_record (b, qname, C_IN, T_CNAME, 0); + next_name = "non-idn-cname.example"; + resolv_response_add_name (b, next_name); + resolv_response_close_record (b); + resolv_response_open_record (b, next_name, C_IN, T_PTR, 0); + resolv_response_add_name (b, NAEMCHEN_IDNA ".example"); + resolv_response_close_record (b); + return; + + /* First name in response is IDN name. */ + case gni_idn_name: + resolv_response_open_record (b, qname, C_IN, T_PTR, 0); + resolv_response_add_name (b, "xn--nmchen-bua.example"); + resolv_response_close_record (b); + return; + case gni_idn_shem: + resolv_response_open_record (b, qname, C_IN, T_PTR, 0); + resolv_response_add_name (b, SHEM_IDNA ".example"); + resolv_response_close_record (b); + return; + case gni_idn_shem1: + resolv_response_open_record (b, qname, C_IN, T_PTR, 0); + resolv_response_add_name (b, SHEM1_IDNA ".example"); + resolv_response_close_record (b); + return; + case gni_idn_cname_to_non_idn_name: + resolv_response_open_record (b, qname, C_IN, T_CNAME, 0); + next_name = NAEMCHEN_IDNA ".example"; + resolv_response_add_name (b, next_name); + resolv_response_close_record (b); + resolv_response_open_record (b, next_name, C_IN, T_PTR, 0); + resolv_response_add_name (b, "non-idn-name.example"); + resolv_response_close_record (b); + return; + case gni_idn_cname_to_idn_name: + resolv_response_open_record (b, qname, C_IN, T_CNAME, 0); + next_name = NAEMCHEN_IDNA ".example"; + resolv_response_add_name (b, next_name); + resolv_response_close_record (b); + resolv_response_open_record (b, next_name, C_IN, T_PTR, 0); + resolv_response_add_name (b, ANDERES_NAEMCHEN_IDNA ".example"); + resolv_response_close_record (b); + return; + + /* Invalid IDN encodings. */ + case gni_invalid_idn_1: + resolv_response_open_record (b, qname, C_IN, T_PTR, 0); + resolv_response_add_name (b, "xn---.example"); + resolv_response_close_record (b); + return; + case gni_invalid_idn_2: + resolv_response_open_record (b, qname, C_IN, T_PTR, 0); + resolv_response_add_name (b, "xn--x.example"); + resolv_response_close_record (b); + return; + } + FAIL_EXIT1 ("invalid PTR query: %s", qname); +} + +/* For PTR responses, see above. A/AAAA queries can request + additional CNAMEs in the response by include ".cname." and + ".idn-cname." in the query. The LSB in the address contains the + first byte of the QNAME. */ +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + TEST_VERIFY_EXIT (qclass == C_IN); + + for (const char *p = qname; *p != '\0'; ++p) + if (!(('0' <= *p && *p <= '9') + || ('a' <= *p && *p <= 'z') + || ('A' <= *p && *p <= 'Z') + || *p == '.' || *p == '-' || *p == '_')) + { + /* Non-ASCII query. Reply with NXDOMAIN. */ + struct resolv_response_flags flags = { .rcode = 3 }; + resolv_response_init (b, flags); + resolv_response_add_question (b, qname, qclass, qtype); + return; + } + + struct resolv_response_flags flags = { 0 }; + resolv_response_init (b, flags); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + + if (qtype == T_PTR) + { + response_ptr (ctx, b, qname); + return; + } + + bool with_cname = strstr (qname, ".cname.") != NULL; + bool with_idn_cname = strstr (qname, ".idn-cname.") != NULL; + + const char *next_name = qname; + if (with_cname) + { + next_name = "non-idn-cname.example"; + resolv_response_open_record (b, qname, C_IN, T_CNAME, 0); + resolv_response_add_name (b, next_name); + resolv_response_close_record (b); + } + if (with_idn_cname) + { + next_name = ANDERES_NAEMCHEN_IDNA ".example"; + resolv_response_open_record (b, qname, C_IN, T_CNAME, 0); + resolv_response_add_name (b, next_name); + resolv_response_close_record (b); + } + + resolv_response_open_record (b, next_name, C_IN, qtype, 0); + switch (qtype) + { + case T_A: + { + char addr[4] = { 192, 0, 2, qname[0] }; + resolv_response_add_data (b, &addr, sizeof (addr)); + } + break; + case T_AAAA: + { + char addr[16] + = { 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + qname[0] }; + resolv_response_add_data (b, &addr, sizeof (addr)); + } + default: + FAIL_EXIT1 ("invalid qtype: %d", qtype); + } + resolv_response_close_record (b); +} + +/* Check the result of a getaddrinfo call. */ +static void +check_ai (const char *name, int ai_flags, const char *expected) +{ + struct addrinfo hints = + { + .ai_flags = ai_flags, + .ai_family = AF_INET, + .ai_socktype = SOCK_STREAM, + }; + struct addrinfo *ai; + char *query = xasprintf ("%s:80 AF_INET/0x%x", name, ai_flags); + int ret = getaddrinfo (name, "80", &hints, &ai); + check_addrinfo (query, ai, ret, expected); + if (ret == 0) + freeaddrinfo (ai); + free (query); +} + +/* Run one getnameinfo test. FLAGS is automatically augmented with + NI_NUMERICSERV. */ +static void +gni_test (enum gni_test code, unsigned int flags, const char *expected) +{ + struct sockaddr_in sin = + { + .sin_family = AF_INET, + .sin_port = htons (80), + .sin_addr = { htonl (0xc0000200 | code) }, /* 192.0.2.0/24 network. */ + }; + char host[1024]; + char service[1024]; + int ret = getnameinfo ((const struct sockaddr *) &sin, sizeof (sin), + host, sizeof (host), service, sizeof (service), + flags| NI_NUMERICSERV); + if (ret != 0) + { + if (expected == NULL) + TEST_COMPARE (ret, EAI_IDN_ENCODE); + else + { + support_record_failure (); + printf ("error: getnameinfo failed (code %d, flags 0x%x): %s (%d)\n", + (int) code, flags, gai_strerror (ret), ret); + } + } + else if (ret == 0 && expected == NULL) + { + support_record_failure (); + printf ("error: getnameinfo unexpected success (code %d, flags 0x%x)\n", + (int) code, flags); + } + else if (strcmp (host, expected) != 0 || strcmp (service, "80") != 0) + { + support_record_failure (); + printf ("error: getnameinfo test failure (code %d, flags 0x%x)\n" + " expected host: \"%s\"\n" + " expected service: \"80\"\n" + " actual host: \"%s\"\n" + " actual service: \"%s\"\n", + (int) code, flags, expected, host, service); + } +} + +/* Tests for getaddrinfo which assume a working libidn2 library. */ +__attribute__ ((unused)) +static void +gai_tests_with_libidn2 (void) +{ + /* No CNAME. */ + check_ai ("non-idn.example", 0, + "address: STREAM/TCP 192.0.2.110 80\n"); + check_ai ("non-idn.example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.110 80\n"); + check_ai ("non-idn.example", AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: non-idn.example\n" + "address: STREAM/TCP 192.0.2.110 80\n"); + + check_ai (NAEMCHEN ".example", 0, + "error: Name or service not known\n"); + check_ai (NAEMCHEN ".example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (NAEMCHEN ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: " NAEMCHEN ".example\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + +#if TEST_USE_UTF8 + check_ai (SHEM ".example", 0, + "error: Name or service not known\n"); + check_ai (SHEM ".example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (SHEM ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: " SHEM ".example\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (SHEM ".example", AI_IDN | AI_CANONNAME, + "flags: AI_CANONNAME AI_IDN\n" + "canonname: " SHEM_IDNA ".example\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (SHEM "1.example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (SHEM "1.example", AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: " SHEM "1.example\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (SHEM "1.example", AI_IDN | AI_CANONNAME, + "flags: AI_CANONNAME AI_IDN\n" + "canonname: " SHEM1_IDNA ".example\n" + "address: STREAM/TCP 192.0.2.120 80\n"); +#endif + + /* Check that non-transitional mode is active. German sharp S + should not turn into SS. */ + check_ai (BUSSE ".example", 0, + "error: Name or service not known\n"); + check_ai (BUSSE ".example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (BUSSE ".example", AI_IDN | AI_CANONNAME, + "flags: AI_CANONNAME AI_IDN\n" + "canonname: " BUSSE_IDNA ".example\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (BUSSE ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: " BUSSE ".example\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + + /* Check that Unicode TR 46 mode is active. Underscores should be + permitted in IDNA components. */ + check_ai (NAEMCHEN "_zwo.example", 0, + "error: Name or service not known\n"); + check_ai (NAEMCHEN "_zwo.example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (NAEMCHEN "_zwo.example", AI_IDN | AI_CANONNAME, + "flags: AI_CANONNAME AI_IDN\n" + "canonname: " NAEMCHEN_ZWO_IDNA ".example\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (NAEMCHEN "_zwo.example", AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: " NAEMCHEN "_zwo.example\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + + /* No CNAME, but already IDN-encoded. */ + check_ai (NAEMCHEN_IDNA ".example", 0, + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (NAEMCHEN_IDNA ".example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (NAEMCHEN_IDNA ".example", AI_IDN | AI_CANONNAME, + "flags: AI_CANONNAME AI_IDN\n" + "canonname: " NAEMCHEN_IDNA ".example\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (NAEMCHEN_IDNA ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: " NAEMCHEN ".example\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (SHEM_IDNA ".example", 0, + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (SHEM_IDNA ".example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + check_ai (SHEM_IDNA ".example", AI_IDN | AI_CANONNAME, + "flags: AI_CANONNAME AI_IDN\n" + "canonname: " SHEM_IDNA ".example\n" + "address: STREAM/TCP 192.0.2.120 80\n"); +#if TEST_USE_UTF8 + check_ai (SHEM_IDNA ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: " SHEM ".example\n" + "address: STREAM/TCP 192.0.2.120 80\n"); +#else + check_ai (SHEM_IDNA ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: " SHEM_IDNA ".example\n" + "address: STREAM/TCP 192.0.2.120 80\n"); +#endif + + /* Invalid IDNA canonical name is returned as-is. */ + check_ai ("xn---.example", AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_CANONIDN\n" + "canonname: xn---.example\n" + "address: STREAM/TCP 192.0.2.120 80\n"); + + /* Non-IDN CNAME. */ + check_ai ("with.cname.example", 0, + "address: STREAM/TCP 192.0.2.119 80\n"); + check_ai ("with.cname.example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.119 80\n"); + check_ai ("with.cname.example", AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: non-idn-cname.example\n" + "address: STREAM/TCP 192.0.2.119 80\n"); + + check_ai ("with.cname." NAEMCHEN ".example", 0, + "error: Name or service not known\n"); + check_ai ("with.cname." NAEMCHEN ".example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.119 80\n"); + check_ai ("with.cname." NAEMCHEN ".example", AI_IDN | AI_CANONNAME, + "flags: AI_CANONNAME AI_IDN\n" + "canonname: non-idn-cname.example\n" + "address: STREAM/TCP 192.0.2.119 80\n"); + check_ai ("with.cname." NAEMCHEN ".example", + AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: non-idn-cname.example\n" + "address: STREAM/TCP 192.0.2.119 80\n"); + + /* IDN CNAME. */ + check_ai ("With.idn-cname.example", 0, + "address: STREAM/TCP 192.0.2.87 80\n"); + check_ai ("With.idn-cname.example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.87 80\n"); + check_ai ("With.idn-cname.example", AI_IDN | AI_CANONNAME, + "flags: AI_CANONNAME AI_IDN\n" + "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n" + "address: STREAM/TCP 192.0.2.87 80\n"); + check_ai ("With.idn-cname.example", + AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: " ANDERES_NAEMCHEN ".example\n" + "address: STREAM/TCP 192.0.2.87 80\n"); + + check_ai ("With.idn-cname." NAEMCHEN ".example", 0, + "error: Name or service not known\n"); + check_ai ("With.idn-cname." NAEMCHEN ".example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.119 80\n"); + check_ai ("With.idn-cname." NAEMCHEN ".example", AI_IDN | AI_CANONNAME, + "flags: AI_CANONNAME AI_IDN\n" + "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n" + "address: STREAM/TCP 192.0.2.119 80\n"); + check_ai ("With.idn-cname." NAEMCHEN ".example", + AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: " ANDERES_NAEMCHEN ".example\n" + "address: STREAM/TCP 192.0.2.119 80\n"); + + /* Non-IDN to IDN CNAME chain. */ + check_ai ("both.cname.idn-cname.example", 0, + "address: STREAM/TCP 192.0.2.98 80\n"); + check_ai ("both.cname.idn-cname.example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.98 80\n"); + check_ai ("both.cname.idn-cname.example", AI_IDN | AI_CANONNAME, + "flags: AI_CANONNAME AI_IDN\n" + "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n" + "address: STREAM/TCP 192.0.2.98 80\n"); + check_ai ("both.cname.idn-cname.example", + AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: " ANDERES_NAEMCHEN ".example\n" + "address: STREAM/TCP 192.0.2.98 80\n"); + + check_ai ("both.cname.idn-cname." NAEMCHEN ".example", 0, + "error: Name or service not known\n"); + check_ai ("both.cname.idn-cname." NAEMCHEN ".example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.98 80\n"); + check_ai ("both.cname.idn-cname." NAEMCHEN ".example", + AI_IDN | AI_CANONNAME, + "flags: AI_CANONNAME AI_IDN\n" + "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n" + "address: STREAM/TCP 192.0.2.98 80\n"); + check_ai ("both.cname.idn-cname." NAEMCHEN ".example", + AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: " ANDERES_NAEMCHEN ".example\n" + "address: STREAM/TCP 192.0.2.98 80\n"); +} + +/* Tests for getnameinfo which assume a working libidn2 library. */ +__attribute__ ((unused)) +static void +gni_tests_with_libidn2 (void) +{ + gni_test (gni_non_idn_name, 0, "non-idn.example"); + gni_test (gni_non_idn_name, NI_IDN, "non-idn.example"); + gni_test (gni_non_idn_name, NI_NUMERICHOST, "192.0.2.0"); + gni_test (gni_non_idn_name, NI_NUMERICHOST | NI_IDN, "192.0.2.0"); + + gni_test (gni_non_idn_cname_to_non_idn_name, 0, "non-idn-name.example"); + gni_test (gni_non_idn_cname_to_non_idn_name, NI_IDN, "non-idn-name.example"); + + gni_test (gni_non_idn_cname_to_idn_name, 0, NAEMCHEN_IDNA ".example"); + gni_test (gni_non_idn_cname_to_idn_name, NI_IDN, NAEMCHEN ".example"); + + gni_test (gni_idn_name, 0, NAEMCHEN_IDNA ".example"); + gni_test (gni_idn_name, NI_IDN, NAEMCHEN ".example"); + gni_test (gni_idn_shem, 0, SHEM_IDNA ".example"); + gni_test (gni_idn_shem1, 0, SHEM1_IDNA ".example"); +#if TEST_USE_UTF8 + gni_test (gni_idn_shem, NI_IDN, SHEM ".example"); + gni_test (gni_idn_shem1, NI_IDN, SHEM "1.example"); +#else + gni_test (gni_idn_shem, NI_IDN, SHEM_IDNA ".example"); + gni_test (gni_idn_shem1, NI_IDN, SHEM1_IDNA ".example"); +#endif + + gni_test (gni_idn_cname_to_non_idn_name, 0, "non-idn-name.example"); + gni_test (gni_idn_cname_to_non_idn_name, NI_IDN, "non-idn-name.example"); + + gni_test (gni_idn_cname_to_idn_name, 0, ANDERES_NAEMCHEN_IDNA ".example"); + gni_test (gni_idn_cname_to_idn_name, NI_IDN, ANDERES_NAEMCHEN ".example"); + + /* Test encoding errors. */ + gni_test (gni_invalid_idn_1, 0, "xn---.example"); + gni_test (gni_invalid_idn_1, NI_IDN, "xn---.example"); + gni_test (gni_invalid_idn_2, 0, "xn--x.example"); + gni_test (gni_invalid_idn_2, NI_IDN, "xn--x.example"); +} diff --git a/resolv/tst-resolv-ai_idn-latin1.c b/resolv/tst-resolv-ai_idn-latin1.c new file mode 100644 index 0000000000..fb60f3261e --- /dev/null +++ b/resolv/tst-resolv-ai_idn-latin1.c @@ -0,0 +1,50 @@ +/* Test getaddrinfo and getnameinfo with AI_IDN, NI_IDN (Latin-1). + Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + + +#define TEST_USE_UTF8 0 +#include "tst-resolv-ai_idn-common.c" + +#include <locale.h> +#include <support/xdlfcn.h> + +static int +do_test (void) +{ + void *handle = dlopen (LIBIDN2_SONAME, RTLD_LAZY); + if (handle == NULL) + FAIL_UNSUPPORTED ("libidn2 not installed"); + + if (setlocale (LC_CTYPE, "en_US.ISO-8859-1") == NULL) + FAIL_EXIT1 ("setlocale: %m"); + + struct resolv_test *aux = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response, + }); + + gai_tests_with_libidn2 (); + gni_tests_with_libidn2 (); + + resolv_test_end (aux); + xdlclose (handle); + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-resolv-ai_idn-nolibidn2.c b/resolv/tst-resolv-ai_idn-nolibidn2.c new file mode 100644 index 0000000000..7203c23f3c --- /dev/null +++ b/resolv/tst-resolv-ai_idn-nolibidn2.c @@ -0,0 +1,151 @@ +/* Test getaddrinfo and getnameinfo without usable libidn2. + Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_USE_UTF8 1 +#include "tst-resolv-ai_idn-common.c" + +#include <locale.h> +#include <support/xdlfcn.h> + +/* Tests for getaddrinfo. */ +static void +gai_tests (void) +{ + /* No CNAME. */ + check_ai ("non-idn.example", 0, + "address: STREAM/TCP 192.0.2.110 80\n"); + check_ai ("non-idn.example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.110 80\n"); + check_ai ("non-idn.example", AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: non-idn.example\n" + "address: STREAM/TCP 192.0.2.110 80\n"); + + /* This gets passed over the network to the server, so it will + result in an NXDOMAIN error. */ + check_ai (NAEMCHEN ".example", 0, + "error: Name or service not known\n"); + /* Due to missing libidn2, this fails inside getaddrinfo. */ + check_ai (NAEMCHEN ".example", AI_IDN, + "error: Parameter string not correctly encoded\n"); + check_ai (NAEMCHEN ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN, + "error: Parameter string not correctly encoded\n"); + + /* Non-IDN CNAME. */ + check_ai ("with.cname.example", 0, + "address: STREAM/TCP 192.0.2.119 80\n"); + check_ai ("with.cname.example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.119 80\n"); + check_ai ("with.cname.example", AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: non-idn-cname.example\n" + "address: STREAM/TCP 192.0.2.119 80\n"); + + /* IDN CNAME. */ + check_ai ("With.idn-cname.example", 0, + "address: STREAM/TCP 192.0.2.87 80\n"); + check_ai ("With.idn-cname.example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.87 80\n"); + check_ai ("With.idn-cname.example", AI_IDN | AI_CANONNAME, + "flags: AI_CANONNAME AI_IDN\n" + "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n" + "address: STREAM/TCP 192.0.2.87 80\n"); + check_ai ("With.idn-cname.example", + AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n" + "address: STREAM/TCP 192.0.2.87 80\n"); + + /* Non-IDN to IDN CNAME chain. */ + check_ai ("both.cname.idn-cname.example", 0, + "address: STREAM/TCP 192.0.2.98 80\n"); + check_ai ("both.cname.idn-cname.example", AI_IDN, + "flags: AI_IDN\n" + "address: STREAM/TCP 192.0.2.98 80\n"); + check_ai ("both.cname.idn-cname.example", AI_IDN | AI_CANONNAME, + "flags: AI_CANONNAME AI_IDN\n" + "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n" + "address: STREAM/TCP 192.0.2.98 80\n"); + check_ai ("both.cname.idn-cname.example", + AI_IDN | AI_CANONNAME | AI_CANONIDN, + "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n" + "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n" + "address: STREAM/TCP 192.0.2.98 80\n"); +} + +/* Tests for getnameinfo. */ +static void +gni_tests (void) +{ + /* All non-IDN an IDN results are the same due to lack of libidn2 + support. */ + for (int do_ni_idn = 0; do_ni_idn < 2; ++do_ni_idn) + { + int flags = 0; + if (do_ni_idn) + flags |= NI_IDN; + + gni_test (gni_non_idn_name, flags, "non-idn.example"); + gni_test (gni_non_idn_name, flags | NI_NUMERICHOST, "192.0.2.0"); + gni_test (gni_non_idn_cname_to_non_idn_name, flags, + "non-idn-name.example"); + gni_test (gni_non_idn_cname_to_idn_name, flags, + NAEMCHEN_IDNA ".example"); + gni_test (gni_idn_name, flags, NAEMCHEN_IDNA ".example"); + gni_test (gni_idn_cname_to_non_idn_name, flags, "non-idn-name.example"); + gni_test (gni_idn_cname_to_idn_name, flags, + ANDERES_NAEMCHEN_IDNA ".example"); + + /* Test encoding errors. */ + gni_test (gni_invalid_idn_1, flags, "xn---.example"); + gni_test (gni_invalid_idn_2, flags, "xn--x.example"); +} +} + +static int +do_test (void) +{ + void *handle = xdlopen ("tst-no-libidn2.so", RTLD_LAZY); + { + /* Verify that this replaced libidn2. */ + void *handle2 = xdlopen (LIBIDN2_SONAME, RTLD_LAZY | RTLD_NOLOAD); + TEST_VERIFY (handle2 == handle); + xdlclose (handle2); + } + + if (setlocale (LC_CTYPE, "en_US.UTF-8") == NULL) + FAIL_EXIT1 ("setlocale: %m"); + + struct resolv_test *aux = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response, + }); + + gai_tests (); + gni_tests (); + + resolv_test_end (aux); + xdlclose (handle); + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-resolv-ai_idn.c b/resolv/tst-resolv-ai_idn.c new file mode 100644 index 0000000000..df8203b14a --- /dev/null +++ b/resolv/tst-resolv-ai_idn.c @@ -0,0 +1,49 @@ +/* Test getaddrinfo and getnameinfo with AI_IDN, NI_IDN (UTF-8). + Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_USE_UTF8 1 +#include "tst-resolv-ai_idn-common.c" + +#include <locale.h> +#include <support/xdlfcn.h> + +static int +do_test (void) +{ + void *handle = dlopen (LIBIDN2_SONAME, RTLD_LAZY); + if (handle == NULL) + FAIL_UNSUPPORTED ("libidn2 not installed"); + + if (setlocale (LC_CTYPE, "en_US.UTF-8") == NULL) + FAIL_EXIT1 ("setlocale: %m"); + + struct resolv_test *aux = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response, + }); + + gai_tests_with_libidn2 (); + gni_tests_with_libidn2 (); + + resolv_test_end (aux); + xdlclose (handle); + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-resolv-basic.c b/resolv/tst-resolv-basic.c new file mode 100644 index 0000000000..e607d24084 --- /dev/null +++ b/resolv/tst-resolv-basic.c @@ -0,0 +1,503 @@ +/* Test basic nss_dns functionality and the resolver test harness itself. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <support/check.h> +#include <support/check_nss.h> +#include <support/format_nss.h> +#include <support/resolv_test.h> +#include <support/support.h> + +#define LONG_NAME \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaax." \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay." \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz." \ + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaat" + +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + TEST_VERIFY_EXIT (qname != NULL); + + /* The "t." prefix can be used to request TCP fallback. */ + bool force_tcp; + if (strncmp ("t.", qname, 2) == 0) + force_tcp = true; + else + force_tcp = false; + const char *qname_compare; + if (force_tcp) + qname_compare = qname + 2; + else + qname_compare = qname; + enum {www, alias, nxdomain, long_name, nodata} requested_qname; + if (strcmp (qname_compare, "www.example") == 0) + requested_qname = www; + else if (strcmp (qname_compare, "alias.example") == 0) + requested_qname = alias; + else if (strcmp (qname_compare, "nxdomain.example") == 0) + requested_qname = nxdomain; + else if (strcmp (qname_compare, LONG_NAME) == 0) + requested_qname = long_name; + else if (strcmp (qname_compare, "nodata.example") == 0) + requested_qname = nodata; + else + { + support_record_failure (); + printf ("error: unexpected QNAME: %s\n", qname); + return; + } + TEST_VERIFY_EXIT (qclass == C_IN); + struct resolv_response_flags flags = {.tc = force_tcp && !ctx->tcp}; + if (requested_qname == nxdomain) + flags.rcode = 3; /* NXDOMAIN */ + resolv_response_init (b, flags); + resolv_response_add_question (b, qname, qclass, qtype); + if (requested_qname == nxdomain || flags.tc) + return; + + resolv_response_section (b, ns_s_an); + switch (requested_qname) + { + case www: + case long_name: + resolv_response_open_record (b, qname, qclass, qtype, 0); + break; + case alias: + resolv_response_open_record (b, qname, qclass, T_CNAME, 0); + resolv_response_add_name (b, "www.example"); + resolv_response_close_record (b); + resolv_response_open_record (b, "www.example", qclass, qtype, 0); + break; + case nodata: + return; + case nxdomain: + FAIL_EXIT1 ("unreachable"); + } + switch (qtype) + { + case T_A: + { + char ipv4[4] = {192, 0, 2, 17}; + ipv4[3] += requested_qname + 2 * ctx->tcp + 4 * ctx->server_index; + resolv_response_add_data (b, &ipv4, sizeof (ipv4)); + } + break; + case T_AAAA: + { + char ipv6[16] + = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + ipv6[15] += requested_qname + 2 * ctx->tcp + 4 * ctx->server_index; + resolv_response_add_data (b, &ipv6, sizeof (ipv6)); + } + break; + default: + support_record_failure (); + printf ("error: unexpected QTYPE: %s/%u/%u\n", + qname, qclass, qtype); + } + resolv_response_close_record (b); +} + +static void +check_h (const char *name, int family, const char *expected) +{ + if (family == AF_INET) + { + char *query = xasprintf ("gethostbyname (\"%s\")", name); + check_hostent (query, gethostbyname (name), expected); + free (query); + } + { + char *query = xasprintf ("gethostbyname2 (\"%s\", %d)", name, family); + check_hostent (query, gethostbyname2 (name, family), expected); + free (query); + } + + bool too_small = true; + for (unsigned int offset = 0; offset < 8; ++offset) + for (unsigned int size = 1; too_small; ++size) + { + char *buf = xmalloc (offset + size); + too_small = false; + + struct hostent hostbuf; + struct hostent *result; + int herror; + if (family == AF_INET) + { + char *query = xasprintf ("gethostbyname (\"%s\") %u/%u", + name, offset, size); + int ret = gethostbyname_r + (name, &hostbuf, buf + offset, size, &result, &herror); + if (ret == 0) + { + h_errno = herror; + check_hostent (query, result, expected); + } + else if (ret == ERANGE) + too_small = true; + else + { + errno = ret; + FAIL_EXIT1 ("gethostbyname_r: %m"); + } + free (query); + memset (buf, 0, offset + size); + } + char *query = xasprintf ("gethostbyname2 (\"%s\", %d) %u/%u", + name, family, offset, size); + int ret = gethostbyname2_r + (name, family, &hostbuf, buf + offset, size, &result, &herror); + if (ret == 0) + { + h_errno = herror; + check_hostent (query, result, expected); + } + else if (ret == ERANGE) + too_small = true; + else + { + errno = ret; + FAIL_EXIT1 ("gethostbyname_r: %m"); + } + free (buf); + free (query); + } +} + +static void +check_ai_hints (const char *name, const char *service, + struct addrinfo hints, const char *expected) +{ + struct addrinfo *ai; + char *query = xasprintf ("%s:%s [%d]/0x%x", name, service, + hints.ai_family, hints.ai_flags); + int ret = getaddrinfo (name, service, &hints, &ai); + check_addrinfo (query, ai, ret, expected); + if (ret == 0) + freeaddrinfo (ai); + free (query); +} + +static void +check_ai (const char *name, const char *service, + int family, const char *expected) +{ + return check_ai_hints (name, service, + (struct addrinfo) { .ai_family = family, }, + expected); +} + +/* Test for bug 21295: getaddrinfo used to discard address information + instead of merging it. */ +static void +test_bug_21295 (void) +{ + /* The address order is unpredictable. There are two factors which + contribute to that: The stub resolver does not perform proper + response matching for A/AAAA queries (an A response could be + associated with an AAAA query and vice versa), and without + namespaces, system configuration could affect address + ordering. */ + for (int do_tcp = 0; do_tcp < 2; ++do_tcp) + { + const struct addrinfo hints = + { + .ai_family = AF_INET6, + .ai_socktype = SOCK_STREAM, + .ai_flags = AI_V4MAPPED | AI_ALL, + }; + const char *qname; + if (do_tcp) + qname = "t.www.example"; + else + qname = "www.example"; + struct addrinfo *ai = NULL; + int ret = getaddrinfo (qname, "80", &hints, &ai); + TEST_VERIFY_EXIT (ret == 0); + + const char *expected_a; + const char *expected_b; + if (do_tcp) + { + expected_a = "flags: AI_V4MAPPED AI_ALL\n" + "address: STREAM/TCP 2001:db8::3 80\n" + "address: STREAM/TCP ::ffff:192.0.2.19 80\n"; + expected_b = "flags: AI_V4MAPPED AI_ALL\n" + "address: STREAM/TCP ::ffff:192.0.2.19 80\n" + "address: STREAM/TCP 2001:db8::3 80\n"; + } + else + { + expected_a = "flags: AI_V4MAPPED AI_ALL\n" + "address: STREAM/TCP 2001:db8::1 80\n" + "address: STREAM/TCP ::ffff:192.0.2.17 80\n"; + expected_b = "flags: AI_V4MAPPED AI_ALL\n" + "address: STREAM/TCP ::ffff:192.0.2.17 80\n" + "address: STREAM/TCP 2001:db8::1 80\n"; + } + + char *actual = support_format_addrinfo (ai, ret); + if (!(strcmp (actual, expected_a) == 0 + || strcmp (actual, expected_b) == 0)) + { + support_record_failure (); + printf ("error: %s: unexpected response (TCP: %d):\n%s\n", + __func__, do_tcp, actual); + } + free (actual); + freeaddrinfo (ai); + } +} + +/* Run tests which do not expect any data. */ +static void +test_nodata_nxdomain (void) +{ + /* Iterate through different address families. */ + int families[] = { AF_UNSPEC, AF_INET, AF_INET6, -1 }; + for (int i = 0; families[i] >= 0; ++i) + /* If do_tcp, prepend "t." to the name to trigger TCP + fallback. */ + for (int do_tcp = 0; do_tcp < 2; ++do_tcp) + /* If do_nxdomain, trigger an NXDOMAIN error (DNS failure), + otherwise use a NODATA response (empty but successful + answer). */ + for (int do_nxdomain = 0; do_nxdomain < 2; ++do_nxdomain) + { + int family = families[i]; + char *name = xasprintf ("%s%s.example", + do_tcp ? "t." : "", + do_nxdomain ? "nxdomain" : "nodata"); + + if (family != AF_UNSPEC) + { + if (do_nxdomain) + check_h (name, family, "error: HOST_NOT_FOUND\n"); + else + check_h (name, family, "error: NO_ADDRESS\n"); + } + + const char *expected; + if (do_nxdomain) + expected = "error: Name or service not known\n"; + else + expected = "error: No address associated with hostname\n"; + + check_ai (name, "80", family, expected); + + struct addrinfo hints = + { + .ai_family = family, + .ai_flags = AI_V4MAPPED | AI_ALL, + }; + check_ai_hints (name, "80", hints, expected); + hints.ai_flags |= AI_CANONNAME; + check_ai_hints (name, "80", hints, expected); + + free (name); + } +} + +static int +do_test (void) +{ + struct resolv_test *aux = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response, + }); + + check_h ("www.example", AF_INET, + "name: www.example\n" + "address: 192.0.2.17\n"); + check_h ("alias.example", AF_INET, + "name: www.example\n" + "alias: alias.example\n" + "address: 192.0.2.18\n"); + check_h ("www.example", AF_INET6, + "name: www.example\n" + "address: 2001:db8::1\n"); + check_h ("alias.example", AF_INET6, + "name: www.example\n" + "alias: alias.example\n" + "address: 2001:db8::2\n"); + check_h (LONG_NAME, AF_INET, + "name: " LONG_NAME "\n" + "address: 192.0.2.20\n"); + + check_ai ("www.example", "80", AF_UNSPEC, + "address: STREAM/TCP 192.0.2.17 80\n" + "address: DGRAM/UDP 192.0.2.17 80\n" + "address: RAW/IP 192.0.2.17 80\n" + "address: STREAM/TCP 2001:db8::1 80\n" + "address: DGRAM/UDP 2001:db8::1 80\n" + "address: RAW/IP 2001:db8::1 80\n"); + check_ai_hints ("www.example", "80", + (struct addrinfo) { .ai_family = AF_UNSPEC, + .ai_flags = AI_CANONNAME, }, + "flags: AI_CANONNAME\n" + "canonname: www.example\n" + "address: STREAM/TCP 192.0.2.17 80\n" + "address: DGRAM/UDP 192.0.2.17 80\n" + "address: RAW/IP 192.0.2.17 80\n" + "address: STREAM/TCP 2001:db8::1 80\n" + "address: DGRAM/UDP 2001:db8::1 80\n" + "address: RAW/IP 2001:db8::1 80\n"); + check_ai ("alias.example", "80", AF_UNSPEC, + "address: STREAM/TCP 192.0.2.18 80\n" + "address: DGRAM/UDP 192.0.2.18 80\n" + "address: RAW/IP 192.0.2.18 80\n" + "address: STREAM/TCP 2001:db8::2 80\n" + "address: DGRAM/UDP 2001:db8::2 80\n" + "address: RAW/IP 2001:db8::2 80\n"); + check_ai_hints ("alias.example", "80", + (struct addrinfo) { .ai_family = AF_UNSPEC, + .ai_flags = AI_CANONNAME, }, + "flags: AI_CANONNAME\n" + "canonname: www.example\n" + "address: STREAM/TCP 192.0.2.18 80\n" + "address: DGRAM/UDP 192.0.2.18 80\n" + "address: RAW/IP 192.0.2.18 80\n" + "address: STREAM/TCP 2001:db8::2 80\n" + "address: DGRAM/UDP 2001:db8::2 80\n" + "address: RAW/IP 2001:db8::2 80\n"); + check_ai (LONG_NAME, "80", AF_UNSPEC, + "address: STREAM/TCP 192.0.2.20 80\n" + "address: DGRAM/UDP 192.0.2.20 80\n" + "address: RAW/IP 192.0.2.20 80\n" + "address: STREAM/TCP 2001:db8::4 80\n" + "address: DGRAM/UDP 2001:db8::4 80\n" + "address: RAW/IP 2001:db8::4 80\n"); + check_ai ("www.example", "80", AF_INET, + "address: STREAM/TCP 192.0.2.17 80\n" + "address: DGRAM/UDP 192.0.2.17 80\n" + "address: RAW/IP 192.0.2.17 80\n"); + check_ai_hints ("www.example", "80", + (struct addrinfo) { .ai_family = AF_INET, + .ai_flags = AI_CANONNAME, }, + "flags: AI_CANONNAME\n" + "canonname: www.example\n" + "address: STREAM/TCP 192.0.2.17 80\n" + "address: DGRAM/UDP 192.0.2.17 80\n" + "address: RAW/IP 192.0.2.17 80\n"); + check_ai ("alias.example", "80", AF_INET, + "address: STREAM/TCP 192.0.2.18 80\n" + "address: DGRAM/UDP 192.0.2.18 80\n" + "address: RAW/IP 192.0.2.18 80\n"); + check_ai_hints ("alias.example", "80", + (struct addrinfo) { .ai_family = AF_INET, + .ai_flags = AI_CANONNAME, }, + "flags: AI_CANONNAME\n" + "canonname: www.example\n" + "address: STREAM/TCP 192.0.2.18 80\n" + "address: DGRAM/UDP 192.0.2.18 80\n" + "address: RAW/IP 192.0.2.18 80\n"); + check_ai (LONG_NAME, "80", AF_INET, + "address: STREAM/TCP 192.0.2.20 80\n" + "address: DGRAM/UDP 192.0.2.20 80\n" + "address: RAW/IP 192.0.2.20 80\n"); + check_ai ("www.example", "80", AF_INET6, + "address: STREAM/TCP 2001:db8::1 80\n" + "address: DGRAM/UDP 2001:db8::1 80\n" + "address: RAW/IP 2001:db8::1 80\n"); + check_ai_hints ("www.example", "80", + (struct addrinfo) { .ai_family = AF_INET6, + .ai_flags = AI_CANONNAME, }, + "flags: AI_CANONNAME\n" + "canonname: www.example\n" + "address: STREAM/TCP 2001:db8::1 80\n" + "address: DGRAM/UDP 2001:db8::1 80\n" + "address: RAW/IP 2001:db8::1 80\n"); + check_ai ("alias.example", "80", AF_INET6, + "address: STREAM/TCP 2001:db8::2 80\n" + "address: DGRAM/UDP 2001:db8::2 80\n" + "address: RAW/IP 2001:db8::2 80\n"); + check_ai_hints ("alias.example", "80", + (struct addrinfo) { .ai_family = AF_INET6, + .ai_flags = AI_CANONNAME, }, + "flags: AI_CANONNAME\n" + "canonname: www.example\n" + "address: STREAM/TCP 2001:db8::2 80\n" + "address: DGRAM/UDP 2001:db8::2 80\n" + "address: RAW/IP 2001:db8::2 80\n"); + check_ai (LONG_NAME, "80", AF_INET6, + "address: STREAM/TCP 2001:db8::4 80\n" + "address: DGRAM/UDP 2001:db8::4 80\n" + "address: RAW/IP 2001:db8::4 80\n"); + + check_h ("t.www.example", AF_INET, + "name: t.www.example\n" + "address: 192.0.2.19\n"); + check_h ("t.alias.example", AF_INET, + "name: www.example\n" + "alias: t.alias.example\n" + "address: 192.0.2.20\n"); + check_h ("t.www.example", AF_INET6, + "name: t.www.example\n" + "address: 2001:db8::3\n"); + check_h ("t.alias.example", AF_INET6, + "name: www.example\n" + "alias: t.alias.example\n" + "address: 2001:db8::4\n"); + check_ai ("t.www.example", "80", AF_UNSPEC, + "address: STREAM/TCP 192.0.2.19 80\n" + "address: DGRAM/UDP 192.0.2.19 80\n" + "address: RAW/IP 192.0.2.19 80\n" + "address: STREAM/TCP 2001:db8::3 80\n" + "address: DGRAM/UDP 2001:db8::3 80\n" + "address: RAW/IP 2001:db8::3 80\n"); + check_ai ("t.alias.example", "80", AF_UNSPEC, + "address: STREAM/TCP 192.0.2.20 80\n" + "address: DGRAM/UDP 192.0.2.20 80\n" + "address: RAW/IP 192.0.2.20 80\n" + "address: STREAM/TCP 2001:db8::4 80\n" + "address: DGRAM/UDP 2001:db8::4 80\n" + "address: RAW/IP 2001:db8::4 80\n"); + check_ai ("t.www.example", "80", AF_INET, + "address: STREAM/TCP 192.0.2.19 80\n" + "address: DGRAM/UDP 192.0.2.19 80\n" + "address: RAW/IP 192.0.2.19 80\n"); + check_ai ("t.alias.example", "80", AF_INET, + "address: STREAM/TCP 192.0.2.20 80\n" + "address: DGRAM/UDP 192.0.2.20 80\n" + "address: RAW/IP 192.0.2.20 80\n"); + check_ai ("t.www.example", "80", AF_INET6, + "address: STREAM/TCP 2001:db8::3 80\n" + "address: DGRAM/UDP 2001:db8::3 80\n" + "address: RAW/IP 2001:db8::3 80\n"); + check_ai ("t.alias.example", "80", AF_INET6, + "address: STREAM/TCP 2001:db8::4 80\n" + "address: DGRAM/UDP 2001:db8::4 80\n" + "address: RAW/IP 2001:db8::4 80\n"); + + test_bug_21295 (); + test_nodata_nxdomain (); + + resolv_test_end (aux); + + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-resolv-binary.c b/resolv/tst-resolv-binary.c new file mode 100644 index 0000000000..e7e6d87994 --- /dev/null +++ b/resolv/tst-resolv-binary.c @@ -0,0 +1,120 @@ +/* Test handling of binary domain names with res_send. + Copyright (C) 2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <resolv.h> +#include <string.h> +#include <support/check.h> +#include <support/resolv_test.h> + +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + TEST_COMPARE (qclass, C_IN); + TEST_COMPARE (qtype, T_TXT); + TEST_VERIFY (strlen (qname) <= 255); + + struct resolv_response_flags flags = { 0 }; + resolv_response_init (b, flags); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, qname, qclass, T_TXT, 0x12345678); + unsigned char qnamelen = strlen (qname); + resolv_response_add_data (b, &qnamelen, 1); + resolv_response_add_data (b, qname, qnamelen); + resolv_response_close_record (b); +} + +static int +do_test (void) +{ + struct resolv_test *aux = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response, + }); + + for (int b = 0; b <= 255; ++b) + { + unsigned char query[] = + { + b, b, /* Transaction ID. */ + 1, 0, /* Query with RD flag. */ + 0, 1, /* One question. */ + 0, 0, 0, 0, 0, 0, /* The other sections are empty. */ + 1, b, 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0, + 0, T_TXT, /* TXT query. */ + 0, 1, /* Class IN. */ + }; + unsigned char response[512]; + int ret = res_send (query, sizeof (query), response, sizeof (response)); + + char expected_name[20]; + /* The name is uncompressed in the query, so we can reference it + directly. */ + TEST_VERIFY_EXIT (ns_name_ntop (query + 12, expected_name, + sizeof (expected_name)) >= 0); + TEST_COMPARE (ret, + (ssize_t) sizeof (query) + + 2 /* Compression reference. */ + + 2 + 2 + 4 + 2 /* Type, class, TTL, RDATA length. */ + + 1 /* Pascal-style string length. */ + + strlen (expected_name)); + + /* Mark as answer, with recursion available, and one answer. */ + query[2] = 0x81; + query[3] = 0x80; + query[7] = 1; + + /* Prefix of the response must match the query. */ + TEST_COMPARE (memcmp (response, query, sizeof (query)), 0); + + /* The actual answer follows, starting with the compression + reference. */ + unsigned char *p = response + sizeof (query); + TEST_COMPARE (*p++, 0xc0); + TEST_COMPARE (*p++, 0x0c); + + /* Type and class. */ + TEST_COMPARE (*p++, 0); + TEST_COMPARE (*p++, T_TXT); + TEST_COMPARE (*p++, 0); + TEST_COMPARE (*p++, C_IN); + + /* TTL. */ + TEST_COMPARE (*p++, 0x12); + TEST_COMPARE (*p++, 0x34); + TEST_COMPARE (*p++, 0x56); + TEST_COMPARE (*p++, 0x78); + + /* RDATA length. */ + TEST_COMPARE (*p++, 0); + TEST_COMPARE (*p++, 1 + strlen (expected_name)); + + /* RDATA. */ + TEST_COMPARE (*p++, strlen (expected_name)); + TEST_COMPARE (memcmp (p, expected_name, strlen (expected_name)), 0); + } + + resolv_test_end (aux); + + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-resolv-canonname.c b/resolv/tst-resolv-canonname.c new file mode 100644 index 0000000000..3f0e68b0f8 --- /dev/null +++ b/resolv/tst-resolv-canonname.c @@ -0,0 +1,313 @@ +/* Test _nss_dns_getcanonname_r corner cases. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <dlfcn.h> +#include <errno.h> +#include <gnu/lib-names.h> +#include <netdb.h> +#include <nss.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <support/check.h> +#include <support/resolv_test.h> +#include <support/support.h> + +/* _nss_dns_getcanonname_r is not called during regular operation + because nss_dns directly provides a canonical name, so we have to + test it directly. The function pointer is initialized by do_test + below. */ +static enum nss_status +(*getcanonname) (const char *name, char *buffer, size_t buflen, + char **result, int *errnop, int *h_errnop); + +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + int code; + { + char *tail; + if (sscanf (qname, "code%d.%ms", &code, &tail) != 2 + || strcmp (tail, "example") != 0) + FAIL_EXIT1 ("error: invalid QNAME: %s\n", qname); + free (tail); + } + + switch (code) + { + case 1: + resolv_response_init (b, (struct resolv_response_flags) {}); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, "www.example", qclass, qtype, 0); + resolv_response_add_data (b, "\xC0\x00\x02\x01", 4); + resolv_response_close_record (b); + break; + case 2: + resolv_response_init (b, (struct resolv_response_flags) {}); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + if (qtype == T_AAAA) + { + resolv_response_open_record (b, "www.example", qclass, qtype, 0); + resolv_response_add_data (b, "\xC0\x00\x02\x01", 4); + resolv_response_close_record (b); + for (int i = 0; i < 30000; ++i) + resolv_response_add_data (b, "", 1); + } + break; + case 3: + resolv_response_init (b, (struct resolv_response_flags) {}); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + if (qtype == T_AAAA) + { + resolv_response_open_record (b, "www.example", qclass, qtype, 0); + resolv_response_add_data (b, "\xC0\x00\x02\x01", 4); + resolv_response_close_record (b); + } + else + { + for (int i = 0; i < 30000; ++i) + resolv_response_add_data (b, "", 1); + } + break; + case 4: + resolv_response_init (b, (struct resolv_response_flags) {}); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, qname, qclass, T_CNAME, 0); + resolv_response_add_name (b, "www.example"); + resolv_response_close_record (b); + resolv_response_open_record (b, "www.example", qclass, qtype, 0); + resolv_response_add_data (b, "\xC0\x00\x02\x01", 4); + resolv_response_close_record (b); + break; + case 5: + resolv_response_init (b, (struct resolv_response_flags) {}); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, qname, qclass, T_CNAME, 0); + resolv_response_add_name (b, "www.example"); + resolv_response_close_record (b); + resolv_response_open_record (b, qname, qclass, T_CNAME, 0); + resolv_response_add_name (b, "www1.example"); + resolv_response_close_record (b); + resolv_response_open_record (b, "www1.example", qclass, qtype, 0); + resolv_response_add_data (b, "\xC0\x00\x02\x01", 4); + resolv_response_close_record (b); + break; + case 6: + resolv_response_init (b, (struct resolv_response_flags) {}); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, qname, qclass, T_CNAME, 0); + resolv_response_add_name (b, "www.example"); + resolv_response_close_record (b); + resolv_response_open_record (b, qname, qclass, 46 /* RRSIG */, 0); + resolv_response_add_name (b, "."); + resolv_response_close_record (b); + resolv_response_open_record (b, "www.example", qclass, qtype, 0); + resolv_response_add_data (b, "\xC0\x00\x02\x01", 4); + resolv_response_close_record (b); + break; + case 102: + if (!ctx->tcp) + { + resolv_response_init (b, (struct resolv_response_flags) {.tc = true}); + resolv_response_add_question (b, qname, qclass, qtype); + } + else + { + resolv_response_init + (b, (struct resolv_response_flags) {.ancount = 1}); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, qname, qclass, T_CNAME, 0); + size_t to_fill = 65535 - resolv_response_length (b) + - 2 /* length, "n" */ - 2 /* compression reference */ + - 2 /* RR type */; + for (size_t i = 0; i < to_fill; ++i) + resolv_response_add_data (b, "", 1); + resolv_response_close_record (b); + resolv_response_add_name (b, "n.example"); + uint16_t rrtype = htons (T_CNAME); + resolv_response_add_data (b, &rrtype, sizeof (rrtype)); + } + break; + case 103: + /* NODATA repsonse. */ + resolv_response_init (b, (struct resolv_response_flags) {}); + resolv_response_add_question (b, qname, qclass, qtype); + break; + case 104: + resolv_response_init (b, (struct resolv_response_flags) {.ancount = 1}); + resolv_response_add_question (b, qname, qclass, qtype); + /* No RR metadata. */ + resolv_response_add_name (b, "www.example"); + break; + case 105: + if (qtype == T_A) + { + resolv_response_init (b, (struct resolv_response_flags) {}); + resolv_response_add_question (b, qname, qclass, qtype); + /* No data, trigger AAAA query. */ + } + else + { + resolv_response_init + (b, (struct resolv_response_flags) {.ancount = 1}); + resolv_response_add_question (b, qname, qclass, qtype); + /* No RR metadata. */ + resolv_response_add_name + (b, "long-name-exceed-previously-initialized-buffer.example"); + } + break; + case 106: + resolv_response_init (b, (struct resolv_response_flags) {.ancount = 1}); + resolv_response_add_question (b, qname, qclass, qtype); + /* No RR metadata. */ + resolv_response_add_name (b, "www.example"); + resolv_response_add_data (b, "\xff\xff", 2); + break; + case 107: + if (qtype == T_A) + { + resolv_response_init (b, (struct resolv_response_flags) {}); + resolv_response_add_question (b, qname, qclass, qtype); + /* No data, trigger AAAA query. */ + } + else + { + resolv_response_init + (b, (struct resolv_response_flags) {.ancount = 1}); + resolv_response_add_question (b, qname, qclass, qtype); + /* No RR metadata. */ + resolv_response_add_name (b, "www.example"); + resolv_response_add_data (b, "\xff\xff", 2); + } + break; + default: + FAIL_EXIT1 ("error: invalid QNAME: %s (code %d)\n", qname, code); + } +} + +static void +check (int code, const char *expected) +{ + char qname[200]; + snprintf (qname, sizeof (qname), "code%d.example", code); + char *result; + enum nss_status status; + { + enum { buffer_size = 4096 }; + char *buffer = xmalloc (buffer_size); + char *temp_result; + int temp_errno; + int temp_herrno; + status = getcanonname + (qname, buffer, buffer_size, &temp_result, &temp_errno, &temp_herrno); + if (status == NSS_STATUS_SUCCESS) + result = xstrdup (temp_result); + else + { + errno = temp_errno; + h_errno = temp_herrno; + } + free (buffer); + } + + if (status == NSS_STATUS_SUCCESS) + { + if (expected != NULL) + { + if (strcmp (result, expected) != 0) + { + support_record_failure (); + printf ("error: getcanonname (%s) failed\n", qname); + printf ("error: expected: %s\n", expected); + printf ("error: actual: %s\n", result); + free (result); + return; + } + } + else + { + support_record_failure (); + printf ("error: getcanonname (%s) unexpected success\n", qname); + printf ("error: actual: %s\n", result); + free (result); + return; + } + free (result); + } + else + { + if (expected != NULL) + { + support_record_failure (); + printf ("error: getcanonname (%s) failed\n", qname); + printf ("error: expected: %s\n", expected); + return; + } + } +} + + +static int +do_test (void) +{ + void *nss_dns_handle = dlopen (LIBNSS_DNS_SO, RTLD_LAZY); + if (nss_dns_handle == NULL) + FAIL_EXIT1 ("could not dlopen %s: %s", LIBNSS_DNS_SO, dlerror ()); + { + const char *func = "_nss_dns_getcanonname_r"; + void *ptr = dlsym (nss_dns_handle, func); + if (ptr == NULL) + FAIL_EXIT1 ("could not look up %s: %s", func, dlerror ()); + getcanonname = ptr; + } + + struct resolv_test *aux = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response, + }); + + check (1, "www.example"); + check (2, "www.example"); + check (3, "www.example"); + check (4, "www.example"); + check (5, "www1.example"); + + /* This should really result in "www.example", but the fake RRSIG + record causes the current implementation to stop parsing. */ + check (6, NULL); + + for (int i = 102; i <= 107; ++i) + check (i, NULL); + + resolv_test_end (aux); + + TEST_VERIFY (dlclose (nss_dns_handle) == 0); + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-resolv-edns.c b/resolv/tst-resolv-edns.c new file mode 100644 index 0000000000..3f2367ca57 --- /dev/null +++ b/resolv/tst-resolv-edns.c @@ -0,0 +1,532 @@ +/* Test EDNS handling in the stub resolver. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <support/check.h> +#include <support/resolv_test.h> +#include <support/support.h> +#include <support/test-driver.h> +#include <support/xthread.h> + +/* Data produced by a test query. */ +struct response_data +{ + char *qname; + uint16_t qtype; + struct resolv_edns_info edns; +}; + +/* Global array used by put_response and get_response to record + response data. The test DNS server returns the index of the array + element which contains the actual response data. This enables the + test case to return arbitrary amounts of data with the limited + number of bits which fit into an IP addres. + + The volatile specifier is needed because the test case accesses + these variables from a callback function called from a function + which is marked as __THROW (i.e., a leaf function which actually is + not). */ +static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +static struct response_data ** volatile response_data_array; +volatile static size_t response_data_count; + +/* Extract information from the query, store it in a struct + response_data object, and return its index in the + response_data_array. */ +static unsigned int +put_response (const struct resolv_response_context *ctx, + const char *qname, uint16_t qtype) +{ + xpthread_mutex_lock (&mutex); + ++response_data_count; + /* We only can represent 2**24 indexes in 10.0.0.0/8. */ + TEST_VERIFY (response_data_count < (1 << 24)); + response_data_array = xrealloc + (response_data_array, sizeof (*response_data_array) * response_data_count); + unsigned int index = response_data_count - 1; + struct response_data *data = xmalloc (sizeof (*data)); + *data = (struct response_data) + { + .qname = xstrdup (qname), + .qtype = qtype, + .edns = ctx->edns, + }; + response_data_array[index] = data; + xpthread_mutex_unlock (&mutex); + return index; +} + +/* Verify the index into the response_data array and return the data + at it. */ +static struct response_data * +get_response (unsigned int index) +{ + xpthread_mutex_lock (&mutex); + TEST_VERIFY_EXIT (index < response_data_count); + struct response_data *result = response_data_array[index]; + xpthread_mutex_unlock (&mutex); + return result; +} + +/* Deallocate all response data. */ +static void +free_response_data (void) +{ + xpthread_mutex_lock (&mutex); + size_t count = response_data_count; + struct response_data **array = response_data_array; + for (unsigned int i = 0; i < count; ++i) + { + struct response_data *data = array[i]; + free (data->qname); + free (data); + } + free (array); + response_data_array = NULL; + response_data_count = 0; + xpthread_mutex_unlock (&mutex); +} + +#define EDNS_PROBE_EXAMPLE "edns-probe.example" + +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + TEST_VERIFY_EXIT (qname != NULL); + + const char *qname_compare = qname; + + /* The "formerr." prefix can be used to request a FORMERR response on the + first server. */ + bool send_formerr; + if (strncmp ("formerr.", qname, strlen ("formerr.")) == 0) + { + send_formerr = true; + qname_compare = qname + strlen ("formerr."); + } + else + { + send_formerr = false; + qname_compare = qname; + } + + /* The "tcp." prefix can be used to request TCP fallback. */ + bool force_tcp; + if (strncmp ("tcp.", qname_compare, strlen ("tcp.")) == 0) + { + force_tcp = true; + qname_compare += strlen ("tcp."); + } + else + force_tcp = false; + + enum {edns_probe} requested_qname; + if (strcmp (qname_compare, EDNS_PROBE_EXAMPLE) == 0) + requested_qname = edns_probe; + else + { + support_record_failure (); + printf ("error: unexpected QNAME: %s (reduced: %s)\n", + qname, qname_compare); + return; + } + TEST_VERIFY_EXIT (qclass == C_IN); + struct resolv_response_flags flags = { }; + flags.tc = force_tcp && !ctx->tcp; + if (!flags.tc && send_formerr && ctx->server_index == 0) + /* Send a FORMERR for the first full response from the first + server. */ + flags.rcode = 1; /* FORMERR */ + resolv_response_init (b, flags); + resolv_response_add_question (b, qname, qclass, qtype); + if (flags.tc || flags.rcode != 0) + return; + + if (test_verbose) + printf ("info: edns=%d payload_size=%d\n", + ctx->edns.active, ctx->edns.payload_size); + + /* Encode the response_data object in multiple address records. + Each record carries two bytes of payload data, and an index. */ + resolv_response_section (b, ns_s_an); + switch (requested_qname) + { + case edns_probe: + { + unsigned int index = put_response (ctx, qname, qtype); + switch (qtype) + { + case T_A: + { + uint32_t addr = htonl (0x0a000000 | index); + resolv_response_open_record (b, qname, qclass, qtype, 0); + resolv_response_add_data (b, &addr, sizeof (addr)); + resolv_response_close_record (b); + } + break; + case T_AAAA: + { + char addr[16] + = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + index >> 16, index >> 8, index}; + resolv_response_open_record (b, qname, qclass, qtype, 0); + resolv_response_add_data (b, &addr, sizeof (addr)); + resolv_response_close_record (b); + } + } + } + break; + } +} + +/* Update *DATA with data from ADDRESS of SIZE. Set the corresponding + flag in SHADOW for each byte written. */ +static struct response_data * +decode_address (const void *address, size_t size) +{ + switch (size) + { + case 4: + TEST_VERIFY (memcmp (address, "\x0a", 1) == 0); + break; + case 16: + TEST_VERIFY (memcmp (address, "\x20\x01\x0d\xb8", 4) == 0); + break; + default: + FAIL_EXIT1 ("unexpected address size %zu", size); + } + const unsigned char *addr = address; + unsigned int index = addr[size - 3] * 256 * 256 + + addr[size - 2] * 256 + + addr[size - 1]; + return get_response (index); +} + +static struct response_data * +decode_hostent (struct hostent *e) +{ + TEST_VERIFY_EXIT (e != NULL); + TEST_VERIFY_EXIT (e->h_addr_list[0] != NULL); + TEST_VERIFY (e->h_addr_list[1] == NULL); + return decode_address (e->h_addr_list[0], e->h_length); +} + +static struct response_data * +decode_addrinfo (struct addrinfo *ai, int family) +{ + struct response_data *data = NULL; + while (ai != NULL) + { + if (ai->ai_family == family) + { + struct response_data *new_data; + switch (family) + { + case AF_INET: + { + struct sockaddr_in *pin = (struct sockaddr_in *) ai->ai_addr; + new_data = decode_address (&pin->sin_addr.s_addr, 4); + } + break; + case AF_INET6: + { + struct sockaddr_in6 *pin = (struct sockaddr_in6 *) ai->ai_addr; + new_data = decode_address (&pin->sin6_addr.s6_addr, 16); + } + break; + default: + FAIL_EXIT1 ("invalid address family %d", ai->ai_family); + } + if (data == NULL) + data = new_data; + else + /* Check pointer equality because this should be the same + response (same index). */ + TEST_VERIFY (data == new_data); + } + ai = ai->ai_next; + } + TEST_VERIFY_EXIT (data != NULL); + return data; +} + +/* Updated by the main test loop in accordance with what is set in + _res.options. */ +static bool use_edns; +static bool use_dnssec; + +/* Verify the decoded response data against the flags above. */ +static void +verify_response_data_payload (struct response_data *data, + size_t expected_payload) +{ + bool edns = use_edns || use_dnssec; + TEST_VERIFY (data->edns.active == edns); + if (!edns) + expected_payload = 0; + if (data->edns.payload_size != expected_payload) + { + support_record_failure (); + printf ("error: unexpected payload size %d (edns=%d)\n", + (int) data->edns.payload_size, edns); + } + uint16_t expected_flags = 0; + if (use_dnssec) + expected_flags |= 0x8000; /* DO flag. */ + if (data->edns.flags != expected_flags) + { + support_record_failure (); + printf ("error: unexpected EDNS flags 0x%04x (edns=%d)\n", + (int) data->edns.flags, edns); + } +} + +/* Same as verify_response_data_payload, but use the default + payload. */ +static void +verify_response_data (struct response_data *data) +{ + verify_response_data_payload (data, 1200); +} + +static void +check_hostent (struct hostent *e) +{ + TEST_VERIFY_EXIT (e != NULL); + verify_response_data (decode_hostent (e)); +} + +static void +do_ai (int family) +{ + struct addrinfo hints = { .ai_family = family }; + struct addrinfo *ai; + int ret = getaddrinfo (EDNS_PROBE_EXAMPLE, "80", &hints, &ai); + TEST_VERIFY_EXIT (ret == 0); + switch (family) + { + case AF_INET: + case AF_INET6: + verify_response_data (decode_addrinfo (ai, family)); + break; + case AF_UNSPEC: + verify_response_data (decode_addrinfo (ai, AF_INET)); + verify_response_data (decode_addrinfo (ai, AF_INET6)); + break; + default: + FAIL_EXIT1 ("invalid address family %d", family); + } + freeaddrinfo (ai); +} + +enum res_op +{ + res_op_search, + res_op_query, + res_op_querydomain, + res_op_nsearch, + res_op_nquery, + res_op_nquerydomain, + + res_op_last = res_op_nquerydomain, +}; + +static const char * +res_op_string (enum res_op op) +{ + switch (op) + { + case res_op_search: + return "res_search"; + case res_op_query: + return "res_query"; + case res_op_querydomain: + return "res_querydomain"; + case res_op_nsearch: + return "res_nsearch"; + case res_op_nquery: + return "res_nquery"; + case res_op_nquerydomain: + return "res_nquerydomain"; + } + FAIL_EXIT1 ("invalid res_op value %d", (int) op); +} + +/* Call libresolv function OP to look up PROBE_NAME, with an answer + buffer of SIZE bytes. Check that the advertised UDP buffer size is + in fact EXPECTED_BUFFER_SIZE. */ +static void +do_res_search (const char *probe_name, enum res_op op, size_t size, + size_t expected_buffer_size) +{ + if (test_verbose) + printf ("info: testing %s with buffer size %zu\n", + res_op_string (op), size); + unsigned char *buffer = xmalloc (size); + int ret = -1; + switch (op) + { + case res_op_search: + ret = res_search (probe_name, C_IN, T_A, buffer, size); + break; + case res_op_query: + ret = res_query (probe_name, C_IN, T_A, buffer, size); + break; + case res_op_nsearch: + ret = res_nsearch (&_res, probe_name, C_IN, T_A, buffer, size); + break; + case res_op_nquery: + ret = res_nquery (&_res, probe_name, C_IN, T_A, buffer, size); + break; + case res_op_querydomain: + case res_op_nquerydomain: + { + char *example_stripped = xstrdup (probe_name); + char *dot_example = strstr (example_stripped, ".example"); + if (dot_example != NULL && strcmp (dot_example, ".example") == 0) + { + /* Truncate the domain name. */ + *dot_example = '\0'; + if (op == res_op_querydomain) + ret = res_querydomain + (example_stripped, "example", C_IN, T_A, buffer, size); + else + ret = res_nquerydomain + (&_res, example_stripped, "example", C_IN, T_A, buffer, size); + } + else + FAIL_EXIT1 ("invalid probe name: %s", probe_name); + free (example_stripped); + } + break; + } + TEST_VERIFY_EXIT (ret > 12); + unsigned char *end = buffer + ret; + + HEADER *hd = (HEADER *) buffer; + TEST_VERIFY (ntohs (hd->qdcount) == 1); + TEST_VERIFY (ntohs (hd->ancount) == 1); + /* Skip over the header. */ + unsigned char *p = buffer + sizeof (*hd); + /* Skip over the question. */ + ret = dn_skipname (p, end); + TEST_VERIFY_EXIT (ret > 0); + p += ret; + TEST_VERIFY_EXIT (end - p >= 4); + p += 4; + /* Skip over the RNAME and the RR header, but stop at the RDATA + length. */ + ret = dn_skipname (p, end); + TEST_VERIFY_EXIT (ret > 0); + p += ret; + TEST_VERIFY_EXIT (end - p >= 2 + 2 + 4 + 2 + 4); + p += 2 + 2 + 4; + /* The IP address should be 4 bytes long. */ + TEST_VERIFY_EXIT (p[0] == 0); + TEST_VERIFY_EXIT (p[1] == 4); + /* Extract the address information. */ + p += 2; + struct response_data *data = decode_address (p, 4); + + verify_response_data_payload (data, expected_buffer_size); + + free (buffer); +} + +static void +run_test (const char *probe_name) +{ + if (test_verbose) + printf ("\ninfo: * use_edns=%d use_dnssec=%d\n", + use_edns, use_dnssec); + check_hostent (gethostbyname (probe_name)); + check_hostent (gethostbyname2 (probe_name, AF_INET)); + check_hostent (gethostbyname2 (probe_name, AF_INET6)); + do_ai (AF_UNSPEC); + do_ai (AF_INET); + do_ai (AF_INET6); + + for (int op = 0; op <= res_op_last; ++op) + { + do_res_search (probe_name, op, 301, 512); + do_res_search (probe_name, op, 511, 512); + do_res_search (probe_name, op, 512, 512); + do_res_search (probe_name, op, 513, 513); + do_res_search (probe_name, op, 657, 657); + do_res_search (probe_name, op, 1199, 1199); + do_res_search (probe_name, op, 1200, 1200); + do_res_search (probe_name, op, 1201, 1200); + do_res_search (probe_name, op, 65535, 1200); + } +} + +static int +do_test (void) +{ + for (int do_edns = 0; do_edns < 2; ++do_edns) + for (int do_dnssec = 0; do_dnssec < 2; ++do_dnssec) + for (int do_tcp = 0; do_tcp < 2; ++do_tcp) + for (int do_formerr = 0; do_formerr < 2; ++do_formerr) + { + struct resolv_test *aux = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response, + }); + + use_edns = do_edns; + if (do_edns) + _res.options |= RES_USE_EDNS0; + use_dnssec = do_dnssec; + if (do_dnssec) + _res.options |= RES_USE_DNSSEC; + + char *probe_name = xstrdup (EDNS_PROBE_EXAMPLE); + if (do_tcp) + { + char *n = xasprintf ("tcp.%s", probe_name); + free (probe_name); + probe_name = n; + } + if (do_formerr) + { + /* Send a garbage query in an attempt to trigger EDNS + fallback. */ + char *n = xasprintf ("formerr.%s", probe_name); + gethostbyname (n); + free (n); + } + + run_test (probe_name); + + free (probe_name); + resolv_test_end (aux); + } + + free_response_data (); + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-resolv-network.c b/resolv/tst-resolv-network.c new file mode 100644 index 0000000000..4b862d57e6 --- /dev/null +++ b/resolv/tst-resolv-network.c @@ -0,0 +1,303 @@ +/* Test getnetbyname and getnetbyaddr. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <netdb.h> +#include <stdlib.h> +#include <string.h> +#include <support/check.h> +#include <support/check_nss.h> +#include <support/resolv_test.h> +#include <support/support.h> +#include <support/xmemstream.h> + +static void +send_ptr (struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype, + const char *alias) +{ + resolv_response_init (b, (struct resolv_response_flags) {}); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, qname, qclass, T_PTR, 0); + resolv_response_add_name (b, alias); + resolv_response_close_record (b); +} + +static void +handle_code (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype, + int code) +{ + switch (code) + { + case 1: + send_ptr (b, qname, qclass, qtype, "1.in-addr.arpa"); + break; + case 2: + send_ptr (b, qname, qclass, qtype, "2.1.in-addr.arpa"); + break; + case 3: + send_ptr (b, qname, qclass, qtype, "3.2.1.in-addr.arpa"); + break; + case 4: + send_ptr (b, qname, qclass, qtype, "4.3.2.1.in-addr.arpa"); + break; + case 5: + /* Test multiple PTR records. */ + resolv_response_init (b, (struct resolv_response_flags) {}); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, qname, qclass, T_PTR, 0); + resolv_response_add_name (b, "127.in-addr.arpa"); + resolv_response_close_record (b); + resolv_response_open_record (b, qname, qclass, T_PTR, 0); + resolv_response_add_name (b, "0.in-addr.arpa"); + resolv_response_close_record (b); + break; + case 6: + /* Test skipping of RRSIG record. */ + resolv_response_init (b, (struct resolv_response_flags) { }); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + + resolv_response_open_record (b, qname, qclass, T_PTR, 0); + resolv_response_add_name (b, "127.in-addr.arpa"); + resolv_response_close_record (b); + + resolv_response_open_record (b, qname, qclass, 46 /* RRSIG */, 0); + { + char buf[500]; + memset (buf, 0x3f, sizeof (buf)); + resolv_response_add_data (b, buf, sizeof (buf)); + } + resolv_response_close_record (b); + + resolv_response_open_record (b, qname, qclass, T_PTR, 0); + resolv_response_add_name (b, "0.in-addr.arpa"); + resolv_response_close_record (b); + break; + case 7: + /* Test CNAME handling. */ + resolv_response_init (b, (struct resolv_response_flags) { }); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, qname, qclass, T_CNAME, 0); + resolv_response_add_name (b, "cname.example"); + resolv_response_close_record (b); + resolv_response_open_record (b, "cname.example", qclass, T_PTR, 0); + resolv_response_add_name (b, "4.3.2.1.in-addr.arpa"); + resolv_response_close_record (b); + break; + + case 100: + resolv_response_init (b, (struct resolv_response_flags) { .rcode = 0, }); + resolv_response_add_question (b, qname, qclass, qtype); + break; + case 101: + resolv_response_init (b, (struct resolv_response_flags) + { .rcode = NXDOMAIN, }); + resolv_response_add_question (b, qname, qclass, qtype); + break; + case 102: + resolv_response_init (b, (struct resolv_response_flags) {.rcode = SERVFAIL}); + resolv_response_add_question (b, qname, qclass, qtype); + break; + case 103: + /* Check response length matching. */ + if (!ctx->tcp) + { + resolv_response_init (b, (struct resolv_response_flags) {.tc = true}); + resolv_response_add_question (b, qname, qclass, qtype); + } + else + { + resolv_response_init (b, (struct resolv_response_flags) {.ancount = 1}); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, qname, qclass, T_PTR, 0); + resolv_response_add_name (b, "127.in-addr.arpa"); + resolv_response_close_record (b); + resolv_response_open_record (b, qname, qclass, T_PTR, 0); + resolv_response_add_name (b, "example"); + resolv_response_close_record (b); + + resolv_response_open_record (b, qname, qclass, T_PTR, 0); + size_t to_fill = 65535 - resolv_response_length (b) + - 2 /* length, "n" */ - 2 /* compression reference */ + - 2 /* RR type */; + for (size_t i = 0; i < to_fill; ++i) + resolv_response_add_data (b, "", 1); + resolv_response_close_record (b); + resolv_response_add_name (b, "n.example"); + uint16_t rrtype = htons (T_PTR); + resolv_response_add_data (b, &rrtype, sizeof (rrtype)); + } + break; + default: + FAIL_EXIT1 ("invalid QNAME: %s (code %d)", qname, code); + } +} + +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + int code; + if (strstr (qname, "in-addr.arpa") == NULL) + { + char *tail; + if (sscanf (qname, "code%d.%ms", &code, &tail) != 2 + || strcmp (tail, "example") != 0) + FAIL_EXIT1 ("invalid QNAME: %s", qname); + free (tail); + handle_code (ctx, b, qname, qclass, qtype, code); + } + else + { + /* Reverse lookup. */ + int components[4]; + char *tail; + if (sscanf (qname, "%d.%d.%d.%d.%ms", + components, components + 1, components + 2, components + 3, + &tail) != 5 + || strcmp (tail, "in-addr.arpa") != 0) + FAIL_EXIT1 ("invalid QNAME: %s", qname); + free (tail); + handle_code (ctx, b, qname, qclass, qtype, components[3]); + } +} + +static void +check_reverse (int code, const char *expected) +{ + char *query = xasprintf ("code=%d", code); + check_netent (query, getnetbyaddr (code, AF_INET), expected); + free (query); +} + +/* Test for CVE-2016-3075. */ +static void +check_long_name (void) +{ + struct xmemstream mem; + xopen_memstream (&mem); + + char label[65]; + memset (label, 'x', 63); + label[63] = '.'; + label[64] = '\0'; + for (unsigned i = 0; i < 64 * 1024 * 1024 / strlen (label); ++i) + fprintf (mem.out, "%s", label); + + xfclose_memstream (&mem); + + check_netent ("long name", getnetbyname (mem.buffer), + "error: NO_RECOVERY\n"); + + free (mem.buffer); +} + +static int +do_test (void) +{ + struct resolv_test *obj = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response + }); + + /* Lookup by name, success cases. */ + check_netent ("code1.example", getnetbyname ("code1.example"), + "alias: 1.in-addr.arpa\n" + "net: 0x00000001\n"); + check_netent ("code2.example", getnetbyname ("code2.example"), + "alias: 2.1.in-addr.arpa\n" + "net: 0x00000102\n"); + check_netent ("code3.example", getnetbyname ("code3.example"), + "alias: 3.2.1.in-addr.arpa\n" + "net: 0x00010203\n"); + check_netent ("code4.example", getnetbyname ("code4.example"), + "alias: 4.3.2.1.in-addr.arpa\n" + "net: 0x01020304\n"); + check_netent ("code5.example", getnetbyname ("code5.example"), + "alias: 127.in-addr.arpa\n" + "alias: 0.in-addr.arpa\n" + "net: 0x0000007f\n"); + check_netent ("code6.example", getnetbyname ("code6.example"), + "alias: 127.in-addr.arpa\n" + "alias: 0.in-addr.arpa\n" + "net: 0x0000007f\n"); + check_netent ("code7.example", getnetbyname ("code7.example"), + "alias: 4.3.2.1.in-addr.arpa\n" + "net: 0x01020304\n"); + + /* Lookup by name, failure cases. */ + check_netent ("code100.example", getnetbyname ("code100.example"), + "error: NO_ADDRESS\n"); + check_netent ("code101.example", getnetbyname ("code101.example"), + "error: HOST_NOT_FOUND\n"); + check_netent ("code102.example", getnetbyname ("code102.example"), + "error: TRY_AGAIN\n"); + check_netent ("code103.example", getnetbyname ("code103.example"), + "error: NO_RECOVERY\n"); + + /* Lookup by address, success cases. */ + check_reverse (1, + "name: 1.in-addr.arpa\n" + "net: 0x00000001\n"); + check_reverse (2, + "name: 2.1.in-addr.arpa\n" + "net: 0x00000002\n"); + check_reverse (3, + "name: 3.2.1.in-addr.arpa\n" + "net: 0x00000003\n"); + check_reverse (4, + "name: 4.3.2.1.in-addr.arpa\n" + "net: 0x00000004\n"); + check_reverse (5, + "name: 127.in-addr.arpa\n" + "alias: 0.in-addr.arpa\n" + "net: 0x00000005\n"); + check_reverse (6, + "name: 127.in-addr.arpa\n" + "alias: 0.in-addr.arpa\n" + "net: 0x00000006\n"); + check_reverse (7, + "name: 4.3.2.1.in-addr.arpa\n" + "net: 0x00000007\n"); + + /* Lookup by address, failure cases. */ + check_reverse (100, + "error: NO_ADDRESS\n"); + check_reverse (101, + "error: HOST_NOT_FOUND\n"); + check_reverse (102, + "error: TRY_AGAIN\n"); + check_reverse (103, + "error: NO_RECOVERY\n"); + + check_long_name (); + + resolv_test_end (obj); + + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-resolv-qtypes.c b/resolv/tst-resolv-qtypes.c new file mode 100644 index 0000000000..b207e82fc4 --- /dev/null +++ b/resolv/tst-resolv-qtypes.c @@ -0,0 +1,185 @@ +/* Exercise low-level query functions with different QTYPEs. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <resolv.h> +#include <string.h> +#include <support/check.h> +#include <support/check_nss.h> +#include <support/resolv_test.h> +#include <support/support.h> +#include <support/test-driver.h> +#include <support/xmemstream.h> + +/* If ture, the response function will send the actual response packet + over TCP instead of UDP. */ +static volatile bool force_tcp; + +/* Send back a fake resource record matching the QTYPE. */ +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + if (force_tcp && ctx->tcp) + { + resolv_response_init (b, (struct resolv_response_flags) { .tc = 1 }); + resolv_response_add_question (b, qname, qclass, qtype); + return; + } + + resolv_response_init (b, (struct resolv_response_flags) { }); + resolv_response_add_question (b, qname, qclass, qtype); + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, qname, qclass, qtype, 0); + resolv_response_add_data (b, &qtype, sizeof (qtype)); + resolv_response_close_record (b); +} + +static const char domain[] = "www.example.com"; + +static int +wrap_res_query (int type, unsigned char *answer, int answer_length) +{ + return res_query (domain, C_IN, type, answer, answer_length); +} + +static int +wrap_res_search (int type, unsigned char *answer, int answer_length) +{ + return res_query (domain, C_IN, type, answer, answer_length); +} + +static int +wrap_res_querydomain (int type, unsigned char *answer, int answer_length) +{ + return res_querydomain ("www", "example.com", C_IN, type, + answer, answer_length); +} + +static int +wrap_res_send (int type, unsigned char *answer, int answer_length) +{ + unsigned char buf[512]; + int ret = res_mkquery (QUERY, domain, C_IN, type, + (const unsigned char *) "", 0, NULL, + buf, sizeof (buf)); + if (type < 0 || type >= 65536) + { + /* res_mkquery fails for out-of-range record types. */ + TEST_VERIFY_EXIT (ret == -1); + return -1; + } + TEST_VERIFY_EXIT (ret > 12); /* DNS header length. */ + return res_send (buf, ret, answer, answer_length); +} + +static int +wrap_res_nquery (int type, unsigned char *answer, int answer_length) +{ + return res_nquery (&_res, domain, C_IN, type, answer, answer_length); +} + +static int +wrap_res_nsearch (int type, unsigned char *answer, int answer_length) +{ + return res_nquery (&_res, domain, C_IN, type, answer, answer_length); +} + +static int +wrap_res_nquerydomain (int type, unsigned char *answer, int answer_length) +{ + return res_nquerydomain (&_res, "www", "example.com", C_IN, type, + answer, answer_length); +} + +static int +wrap_res_nsend (int type, unsigned char *answer, int answer_length) +{ + unsigned char buf[512]; + int ret = res_nmkquery (&_res, QUERY, domain, C_IN, type, + (const unsigned char *) "", 0, NULL, + buf, sizeof (buf)); + if (type < 0 || type >= 65536) + { + /* res_mkquery fails for out-of-range record types. */ + TEST_VERIFY_EXIT (ret == -1); + return -1; + } + TEST_VERIFY_EXIT (ret > 12); /* DNS header length. */ + return res_nsend (&_res, buf, ret, answer, answer_length); +} + +static void +test_function (const char *fname, + int (*func) (int type, + unsigned char *answer, int answer_length)) +{ + unsigned char buf[512]; + for (int tcp = 0; tcp < 2; ++tcp) + { + force_tcp = tcp; + for (unsigned int type = 1; type <= 65535; ++type) + { + if (test_verbose) + printf ("info: sending QTYPE %d with %s (tcp=%d)\n", + type, fname, tcp); + int ret = func (type, buf, sizeof (buf)); + if (ret != 47) + FAIL_EXIT1 ("%s tcp=%d qtype=%d return value %d", + fname,tcp, type, ret); + /* One question, one answer record. */ + TEST_VERIFY (memcmp (buf + 4, "\0\1\0\1\0\0\0\0", 8) == 0); + /* Question section. */ + static const char qname[] = "\3www\7example\3com"; + size_t qname_length = sizeof (qname); + TEST_VERIFY (memcmp (buf + 12, qname, qname_length) == 0); + /* RDATA part of answer. */ + uint16_t type16 = type; + TEST_VERIFY (memcmp (buf + ret - 2, &type16, sizeof (type16)) == 0); + } + } + + TEST_VERIFY (func (-1, buf, sizeof (buf) == -1)); + TEST_VERIFY (func (65536, buf, sizeof (buf) == -1)); +} + +static int +do_test (void) +{ + struct resolv_redirect_config config = + { + .response_callback = response, + }; + struct resolv_test *obj = resolv_test_start (config); + + test_function ("res_query", &wrap_res_query); + test_function ("res_search", &wrap_res_search); + test_function ("res_querydomain", &wrap_res_querydomain); + test_function ("res_send", &wrap_res_send); + + test_function ("res_nquery", &wrap_res_nquery); + test_function ("res_nsearch", &wrap_res_nsearch); + test_function ("res_nquerydomain", &wrap_res_nquerydomain); + test_function ("res_nsend", &wrap_res_nsend); + + resolv_test_end (obj); + return 0; +} + +#define TIMEOUT 300 +#include <support/test-driver.c> diff --git a/resolv/tst-resolv-res_init-multi.c b/resolv/tst-resolv-res_init-multi.c new file mode 100644 index 0000000000..1aacea49ca --- /dev/null +++ b/resolv/tst-resolv-res_init-multi.c @@ -0,0 +1,89 @@ +/* Multi-threaded test for resolver initialization. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <netdb.h> +#include <resolv.h> +#include <stdlib.h> +#include <support/check.h> +#include <support/support.h> +#include <support/xthread.h> + +/* Whether name lookups succeed does not really matter. We use this + to trigger initialization of the resolver. */ +static const char *test_hostname = "www.gnu.org"; + +/* The different initialization methods. */ +enum test_type { init, byname, gai }; +enum { type_count = 3 }; + +/* Thread function. Perform a few resolver options. */ +static void * +thread_func (void *closure) +{ + enum test_type *ptype = closure; + /* Perform a few calls to the requested operation. */ + TEST_VERIFY (*ptype >= 0); + TEST_VERIFY (*ptype < (int) type_count); + for (int i = 0; i < 3; ++i) + switch (*ptype) + { + case init: + res_init (); + break; + case byname: + gethostbyname (test_hostname); + break; + case gai: + { + struct addrinfo hints = { 0, }; + struct addrinfo *ai = NULL; + if (getaddrinfo (test_hostname, "80", &hints, &ai) == 0) + freeaddrinfo (ai); + } + break; + } + free (ptype); + return NULL; +} + +static int +do_test (void) +{ + /* Start a small number of threads which perform resolver + operations. */ + enum { thread_count = 30 }; + + pthread_t threads[thread_count]; + for (int i = 0; i < thread_count; ++i) + { + enum test_type *ptype = xmalloc (sizeof (*ptype)); + *ptype = i % type_count; + threads[i] = xpthread_create (NULL, thread_func, ptype); + } + for (int i = 0; i < type_count; ++i) + { + enum test_type *ptype = xmalloc (sizeof (*ptype)); + *ptype = i; + thread_func (ptype); + } + for (int i = 0; i < thread_count; ++i) + xpthread_join (threads[i]); + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c new file mode 100644 index 0000000000..a5061e6d4f --- /dev/null +++ b/resolv/tst-resolv-res_init-skeleton.c @@ -0,0 +1,1096 @@ +/* Test parsing of /etc/resolv.conf. Genric version. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* Before including this file, TEST_THREAD has to be defined to 0 or + 1, depending on whether the threading tests should be compiled + in. */ + +#include <arpa/inet.h> +#include <errno.h> +#include <gnu/lib-names.h> +#include <netdb.h> +#include <resolv/resolv-internal.h> /* For DEPRECATED_RES_USE_INET6. */ +#include <resolv/resolv_context.h> +#include <stdio.h> +#include <stdlib.h> +#include <support/capture_subprocess.h> +#include <support/check.h> +#include <support/namespace.h> +#include <support/run_diff.h> +#include <support/support.h> +#include <support/temp_file.h> +#include <support/test-driver.h> +#include <support/xsocket.h> +#include <support/xstdio.h> +#include <support/xunistd.h> + +#if TEST_THREAD +# include <support/xthread.h> +#endif + +/* This is the host name used to ensure predictable behavior of + res_init. */ +static const char *const test_hostname = "www.example.com"; + +struct support_chroot *chroot_env; + +static void +prepare (int argc, char **argv) +{ + chroot_env = support_chroot_create + ((struct support_chroot_configuration) + { + .resolv_conf = "", + }); +} + +/* Verify that the chroot environment has been set up. */ +static void +check_chroot_working (void *closure) +{ + xchroot (chroot_env->path_chroot); + FILE *fp = xfopen (_PATH_RESCONF, "r"); + xfclose (fp); + + TEST_VERIFY_EXIT (res_init () == 0); + TEST_VERIFY (_res.options & RES_INIT); + + char buf[100]; + if (gethostname (buf, sizeof (buf)) < 0) + FAIL_EXIT1 ("gethostname: %m"); + if (strcmp (buf, test_hostname) != 0) + FAIL_EXIT1 ("unexpected host name: %s", buf); +} + +/* If FLAG is set in *OPTIONS, write NAME to FP, and clear it in + *OPTIONS. */ +static void +print_option_flag (FILE *fp, int *options, int flag, const char *name) +{ + if (*options & flag) + { + fprintf (fp, " %s", name); + *options &= ~flag; + } +} + +/* Write a decoded version of the resolver configuration *RESP to the + stream FP. */ +static void +print_resp (FILE *fp, res_state resp) +{ + struct resolv_context *ctx = __resolv_context_get_override (resp); + TEST_VERIFY_EXIT (ctx != NULL); + if (ctx->conf == NULL) + fprintf (fp, "; extended resolver state missing\n"); + + /* The options directive. */ + { + /* RES_INIT is used internally for tracking initialization. */ + TEST_VERIFY (resp->options & RES_INIT); + /* Also mask out other default flags which cannot be set through + the options directive. */ + int options + = resp->options & ~(RES_INIT | RES_RECURSE | RES_DEFNAMES | RES_DNSRCH); + if (options != 0 + || resp->ndots != 1 + || resp->retrans != RES_TIMEOUT + || resp->retry != RES_DFLRETRY) + { + fputs ("options", fp); + if (resp->ndots != 1) + fprintf (fp, " ndots:%d", resp->ndots); + if (resp->retrans != RES_TIMEOUT) + fprintf (fp, " timeout:%d", resp->retrans); + if (resp->retry != RES_DFLRETRY) + fprintf (fp, " attempts:%d", resp->retry); + print_option_flag (fp, &options, RES_USEVC, "use-vc"); + print_option_flag (fp, &options, DEPRECATED_RES_USE_INET6, "inet6"); + print_option_flag (fp, &options, RES_ROTATE, "rotate"); + print_option_flag (fp, &options, RES_USE_EDNS0, "edns0"); + print_option_flag (fp, &options, RES_SNGLKUP, + "single-request"); + print_option_flag (fp, &options, RES_SNGLKUPREOP, + "single-request-reopen"); + print_option_flag (fp, &options, RES_NOTLDQUERY, "no-tld-query"); + print_option_flag (fp, &options, RES_NORELOAD, "no-reload"); + fputc ('\n', fp); + if (options != 0) + fprintf (fp, "; error: unresolved option bits: 0x%x\n", options); + } + } + + /* The search and domain directives. */ + if (resp->dnsrch[0] != NULL) + { + fputs ("search", fp); + for (int i = 0; i < MAXDNSRCH && resp->dnsrch[i] != NULL; ++i) + { + fputc (' ', fp); + fputs (resp->dnsrch[i], fp); + } + fputc ('\n', fp); + } + else if (resp->defdname[0] != '\0') + fprintf (fp, "domain %s\n", resp->defdname); + + /* The extended search path. */ + { + size_t i = 0; + while (true) + { + const char *name = __resolv_context_search_list (ctx, i); + if (name == NULL) + break; + fprintf (fp, "; search[%zu]: %s\n", i, name); + ++i; + } + } + + /* The sortlist directive. */ + if (resp->nsort > 0) + { + fputs ("sortlist", fp); + for (int i = 0; i < resp->nsort && i < MAXRESOLVSORT; ++i) + { + char net[20]; + if (inet_ntop (AF_INET, &resp->sort_list[i].addr, + net, sizeof (net)) == NULL) + FAIL_EXIT1 ("inet_ntop: %m\n"); + char mask[20]; + if (inet_ntop (AF_INET, &resp->sort_list[i].mask, + mask, sizeof (mask)) == NULL) + FAIL_EXIT1 ("inet_ntop: %m\n"); + fprintf (fp, " %s/%s", net, mask); + } + fputc ('\n', fp); + } + + /* The nameserver directives. */ + for (size_t i = 0; i < resp->nscount; ++i) + { + char host[NI_MAXHOST]; + char service[NI_MAXSERV]; + + /* See get_nsaddr in res_send.c. */ + void *addr; + size_t addrlen; + if (resp->nsaddr_list[i].sin_family == 0 + && resp->_u._ext.nsaddrs[i] != NULL) + { + addr = resp->_u._ext.nsaddrs[i]; + addrlen = sizeof (*resp->_u._ext.nsaddrs[i]); + } + else + { + addr = &resp->nsaddr_list[i]; + addrlen = sizeof (resp->nsaddr_list[i]); + } + + int ret = getnameinfo (addr, addrlen, + host, sizeof (host), service, sizeof (service), + NI_NUMERICHOST | NI_NUMERICSERV); + if (ret != 0) + { + if (ret == EAI_SYSTEM) + fprintf (fp, "; error: getnameinfo: %m\n"); + else + fprintf (fp, "; error: getnameinfo: %s\n", gai_strerror (ret)); + } + else + { + fprintf (fp, "nameserver %s\n", host); + if (strcmp (service, "53") != 0) + fprintf (fp, "; unrepresentable port number %s\n\n", service); + } + } + + /* The extended name server list. */ + { + size_t i = 0; + while (true) + { + const struct sockaddr *addr = __resolv_context_nameserver (ctx, i); + if (addr == NULL) + break; + size_t addrlen; + switch (addr->sa_family) + { + case AF_INET: + addrlen = sizeof (struct sockaddr_in); + break; + case AF_INET6: + addrlen = sizeof (struct sockaddr_in6); + break; + default: + FAIL_EXIT1 ("invalid address family %d", addr->sa_family); + } + + char host[NI_MAXHOST]; + char service[NI_MAXSERV]; + int ret = getnameinfo (addr, addrlen, + host, sizeof (host), service, sizeof (service), + NI_NUMERICHOST | NI_NUMERICSERV); + + if (ret != 0) + { + if (ret == EAI_SYSTEM) + fprintf (fp, "; error: getnameinfo: %m\n"); + else + fprintf (fp, "; error: getnameinfo: %s\n", gai_strerror (ret)); + } + else + fprintf (fp, "; nameserver[%zu]: [%s]:%s\n", i, host, service); + ++i; + } + } + + TEST_VERIFY (!ferror (fp)); + + __resolv_context_put (ctx); +} + +/* Parameters of one test case. */ +struct test_case +{ + /* A short, descriptive name of the test. */ + const char *name; + + /* The contents of the /etc/resolv.conf file. */ + const char *conf; + + /* The expected output from print_resp. */ + const char *expected; + + /* Setting for the LOCALDOMAIN environment variable. NULL if the + variable is not to be set. */ + const char *localdomain; + + /* Setting for the RES_OPTIONS environment variable. NULL if the + variable is not to be set. */ + const char *res_options; + + /* Override the system host name. NULL means that no change is made + and the default is used (test_hostname). */ + const char *hostname; +}; + +enum test_init +{ + test_init, + test_ninit, + test_mkquery, + test_gethostbyname, + test_getaddrinfo, + test_init_method_last = test_getaddrinfo +}; + +static const char *const test_init_names[] = + { + [test_init] = "res_init", + [test_ninit] = "res_ninit", + [test_mkquery] = "res_mkquery", + [test_gethostbyname] = "gethostbyname", + [test_getaddrinfo] = "getaddrinfo", + }; + +/* Closure argument for run_res_init. */ +struct test_context +{ + enum test_init init; + const struct test_case *t; +}; + +static void +setup_nss_dns_and_chroot (void) +{ + /* Load nss_dns outside of the chroot. */ + if (dlopen (LIBNSS_DNS_SO, RTLD_LAZY) == NULL) + FAIL_EXIT1 ("could not load " LIBNSS_DNS_SO ": %s", dlerror ()); + xchroot (chroot_env->path_chroot); + /* Force the use of nss_dns. */ + __nss_configure_lookup ("hosts", "dns"); +} + +/* Run res_ninit or res_init in a subprocess and dump the parsed + resolver state to standard output. */ +static void +run_res_init (void *closure) +{ + struct test_context *ctx = closure; + TEST_VERIFY (getenv ("LOCALDOMAIN") == NULL); + TEST_VERIFY (getenv ("RES_OPTIONS") == NULL); + if (ctx->t->localdomain != NULL) + setenv ("LOCALDOMAIN", ctx->t->localdomain, 1); + if (ctx->t->res_options != NULL) + setenv ("RES_OPTIONS", ctx->t->res_options, 1); + if (ctx->t->hostname != NULL) + { +#ifdef CLONE_NEWUTS + /* This test needs its own namespace, to avoid changing the host + name for the parent, too. */ + TEST_VERIFY_EXIT (unshare (CLONE_NEWUTS) == 0); + if (sethostname (ctx->t->hostname, strlen (ctx->t->hostname)) != 0) + FAIL_EXIT1 ("sethostname (\"%s\"): %m", ctx->t->hostname); +#else + FAIL_UNSUPPORTED ("clone (CLONE_NEWUTS) not supported"); +#endif + } + + switch (ctx->init) + { + case test_init: + xchroot (chroot_env->path_chroot); + TEST_VERIFY (res_init () == 0); + print_resp (stdout, &_res); + return; + + case test_ninit: + xchroot (chroot_env->path_chroot); + res_state resp = xmalloc (sizeof (*resp)); + memset (resp, 0, sizeof (*resp)); + TEST_VERIFY (res_ninit (resp) == 0); + print_resp (stdout, resp); + res_nclose (resp); + free (resp); + return; + + case test_mkquery: + xchroot (chroot_env->path_chroot); + unsigned char buf[512]; + TEST_VERIFY (res_mkquery (QUERY, "www.example", + C_IN, ns_t_a, NULL, 0, + NULL, buf, sizeof (buf)) > 0); + print_resp (stdout, &_res); + return; + + case test_gethostbyname: + setup_nss_dns_and_chroot (); + /* Trigger implicit initialization of the _res structure. The + actual lookup result is immaterial. */ + (void )gethostbyname ("www.example"); + print_resp (stdout, &_res); + return; + + case test_getaddrinfo: + setup_nss_dns_and_chroot (); + /* Trigger implicit initialization of the _res structure. The + actual lookup result is immaterial. */ + struct addrinfo *ai; + (void) getaddrinfo ("www.example", NULL, NULL, &ai); + print_resp (stdout, &_res); + return; + } + + FAIL_EXIT1 ("invalid init method %d", ctx->init); +} + +#if TEST_THREAD +/* Helper function which calls run_res_init from a thread. */ +static void * +run_res_init_thread_func (void *closure) +{ + run_res_init (closure); + return NULL; +} + +/* Variant of res_run_init which runs the function on a non-main + thread. */ +static void +run_res_init_on_thread (void *closure) +{ + xpthread_join (xpthread_create (NULL, run_res_init_thread_func, closure)); +} +#endif /* TEST_THREAD */ + +struct test_case test_cases[] = + { + {.name = "empty file", + .conf = "", + .expected = "search example.com\n" + "; search[0]: example.com\n" + "nameserver 127.0.0.1\n" + "; nameserver[0]: [127.0.0.1]:53\n" + }, + {.name = "empty file, no-dot hostname", + .conf = "", + .expected = "nameserver 127.0.0.1\n" + "; nameserver[0]: [127.0.0.1]:53\n", + .hostname = "example", + }, + {.name = "empty file with LOCALDOMAIN", + .conf = "", + .expected = "search example.net\n" + "; search[0]: example.net\n" + "nameserver 127.0.0.1\n" + "; nameserver[0]: [127.0.0.1]:53\n", + .localdomain = "example.net", + }, + {.name = "empty file with RES_OPTIONS", + .conf = "", + .expected = "options attempts:5 edns0\n" + "search example.com\n" + "; search[0]: example.com\n" + "nameserver 127.0.0.1\n" + "; nameserver[0]: [127.0.0.1]:53\n", + .res_options = "edns0 attempts:5", + }, + {.name = "empty file with RES_OPTIONS and LOCALDOMAIN", + .conf = "", + .expected = "options attempts:5 edns0\n" + "search example.org\n" + "; search[0]: example.org\n" + "nameserver 127.0.0.1\n" + "; nameserver[0]: [127.0.0.1]:53\n", + .localdomain = "example.org", + .res_options = "edns0 attempts:5", + }, + {.name = "basic", + .conf = "search corp.example.com example.com\n" + "nameserver 192.0.2.1\n", + .expected = "search corp.example.com example.com\n" + "; search[0]: corp.example.com\n" + "; search[1]: example.com\n" + "nameserver 192.0.2.1\n" + "; nameserver[0]: [192.0.2.1]:53\n" + }, + {.name = "basic with no-dot hostname", + .conf = "search corp.example.com example.com\n" + "nameserver 192.0.2.1\n", + .expected = "search corp.example.com example.com\n" + "; search[0]: corp.example.com\n" + "; search[1]: example.com\n" + "nameserver 192.0.2.1\n" + "; nameserver[0]: [192.0.2.1]:53\n", + .hostname = "example", + }, + {.name = "basic no-reload", + .conf = "options no-reload\n" + "search corp.example.com example.com\n" + "nameserver 192.0.2.1\n", + .expected = "options no-reload\n" + "search corp.example.com example.com\n" + "; search[0]: corp.example.com\n" + "; search[1]: example.com\n" + "nameserver 192.0.2.1\n" + "; nameserver[0]: [192.0.2.1]:53\n" + }, + {.name = "basic no-reload via RES_OPTIONS", + .conf = "search corp.example.com example.com\n" + "nameserver 192.0.2.1\n", + .expected = "options no-reload\n" + "search corp.example.com example.com\n" + "; search[0]: corp.example.com\n" + "; search[1]: example.com\n" + "nameserver 192.0.2.1\n" + "; nameserver[0]: [192.0.2.1]:53\n", + .res_options = "no-reload" + }, + {.name = "whitespace", + .conf = "# This test covers comment and whitespace processing " + " (trailing whitespace,\n" + "# missing newline at end of file).\n" + "\n" + ";search commented out\n" + "search corp.example.com\texample.com \n" + "#nameserver 192.0.2.3\n" + "nameserver 192.0.2.1 \n" + "nameserver 192.0.2.2", /* No \n at end of file. */ + .expected = "search corp.example.com example.com\n" + "; search[0]: corp.example.com\n" + "; search[1]: example.com\n" + "nameserver 192.0.2.1\n" + "nameserver 192.0.2.2\n" + "; nameserver[0]: [192.0.2.1]:53\n" + "; nameserver[1]: [192.0.2.2]:53\n" + }, + {.name = "domain", + .conf = "domain example.net\n" + "nameserver 192.0.2.1\n", + .expected = "search example.net\n" + "; search[0]: example.net\n" + "nameserver 192.0.2.1\n" + "; nameserver[0]: [192.0.2.1]:53\n" + }, + {.name = "domain space", + .conf = "domain example.net \n" + "nameserver 192.0.2.1\n", + .expected = "search example.net\n" + "; search[0]: example.net\n" + "nameserver 192.0.2.1\n" + "; nameserver[0]: [192.0.2.1]:53\n" + }, + {.name = "domain tab", + .conf = "domain example.net\t\n" + "nameserver 192.0.2.1\n", + .expected = "search example.net\n" + "; search[0]: example.net\n" + "nameserver 192.0.2.1\n" + "; nameserver[0]: [192.0.2.1]:53\n" + }, + {.name = "domain override", + .conf = "search example.com example.org\n" + "nameserver 192.0.2.1\n" + "domain example.net", /* No \n at end of file. */ + .expected = "search example.net\n" + "; search[0]: example.net\n" + "nameserver 192.0.2.1\n" + "; nameserver[0]: [192.0.2.1]:53\n" + }, + {.name = "option values, multiple servers", + .conf = "options\tinet6\tndots:3 edns0\tattempts:5\ttimeout:19\n" + "domain example.net\n" + ";domain comment\n" + "search corp.example.com\texample.com\n" + "nameserver 192.0.2.1\n" + "nameserver ::1\n" + "nameserver 192.0.2.2\n", + .expected = "options ndots:3 timeout:19 attempts:5 inet6 edns0\n" + "search corp.example.com example.com\n" + "; search[0]: corp.example.com\n" + "; search[1]: example.com\n" + "nameserver 192.0.2.1\n" + "nameserver ::1\n" + "nameserver 192.0.2.2\n" + "; nameserver[0]: [192.0.2.1]:53\n" + "; nameserver[1]: [::1]:53\n" + "; nameserver[2]: [192.0.2.2]:53\n" + }, + {.name = "out-of-range option vales", + .conf = "options use-vc timeout:999 attempts:999 ndots:99\n" + "search example.com\n", + .expected = "options ndots:15 timeout:30 attempts:5 use-vc\n" + "search example.com\n" + "; search[0]: example.com\n" + "nameserver 127.0.0.1\n" + "; nameserver[0]: [127.0.0.1]:53\n" + }, + {.name = "repeated directives", + .conf = "options ndots:3 use-vc\n" + "options edns0 ndots:2\n" + "domain corp.example\n" + "search example.net corp.example.com example.com\n" + "search example.org\n" + "search\n", + .expected = "options ndots:2 use-vc edns0\n" + "search example.org\n" + "; search[0]: example.org\n" + "nameserver 127.0.0.1\n" + "; nameserver[0]: [127.0.0.1]:53\n" + }, + {.name = "many name servers, sortlist", + .conf = "options single-request\n" + "search example.org example.com example.net corp.example.com\n" + "sortlist 192.0.2.0/255.255.255.0\n" + "nameserver 192.0.2.1\n" + "nameserver 192.0.2.2\n" + "nameserver 192.0.2.3\n" + "nameserver 192.0.2.4\n" + "nameserver 192.0.2.5\n" + "nameserver 192.0.2.6\n" + "nameserver 192.0.2.7\n" + "nameserver 192.0.2.8\n", + .expected = "options single-request\n" + "search example.org example.com example.net corp.example.com\n" + "; search[0]: example.org\n" + "; search[1]: example.com\n" + "; search[2]: example.net\n" + "; search[3]: corp.example.com\n" + "sortlist 192.0.2.0/255.255.255.0\n" + "nameserver 192.0.2.1\n" + "nameserver 192.0.2.2\n" + "nameserver 192.0.2.3\n" + "; nameserver[0]: [192.0.2.1]:53\n" + "; nameserver[1]: [192.0.2.2]:53\n" + "; nameserver[2]: [192.0.2.3]:53\n" + "; nameserver[3]: [192.0.2.4]:53\n" + "; nameserver[4]: [192.0.2.5]:53\n" + "; nameserver[5]: [192.0.2.6]:53\n" + "; nameserver[6]: [192.0.2.7]:53\n" + "; nameserver[7]: [192.0.2.8]:53\n" + }, + {.name = "IPv4 and IPv6 nameservers", + .conf = "options single-request\n" + "search example.org example.com example.net corp.example.com" + " legacy.example.com\n" + "sortlist 192.0.2.0\n" + "nameserver 192.0.2.1\n" + "nameserver 2001:db8::2\n" + "nameserver 192.0.2.3\n" + "nameserver 2001:db8::4\n" + "nameserver 192.0.2.5\n" + "nameserver 2001:db8::6\n" + "nameserver 192.0.2.7\n" + "nameserver 2001:db8::8\n", + .expected = "options single-request\n" + "search example.org example.com example.net corp.example.com" + " legacy.example.com\n" + "; search[0]: example.org\n" + "; search[1]: example.com\n" + "; search[2]: example.net\n" + "; search[3]: corp.example.com\n" + "; search[4]: legacy.example.com\n" + "sortlist 192.0.2.0/255.255.255.0\n" + "nameserver 192.0.2.1\n" + "nameserver 2001:db8::2\n" + "nameserver 192.0.2.3\n" + "; nameserver[0]: [192.0.2.1]:53\n" + "; nameserver[1]: [2001:db8::2]:53\n" + "; nameserver[2]: [192.0.2.3]:53\n" + "; nameserver[3]: [2001:db8::4]:53\n" + "; nameserver[4]: [192.0.2.5]:53\n" + "; nameserver[5]: [2001:db8::6]:53\n" + "; nameserver[6]: [192.0.2.7]:53\n" + "; nameserver[7]: [2001:db8::8]:53\n", + }, + {.name = "garbage after nameserver", + .conf = "nameserver 192.0.2.1 garbage\n" + "nameserver 192.0.2.2:5353\n" + "nameserver 192.0.2.3 5353\n", + .expected = "search example.com\n" + "; search[0]: example.com\n" + "nameserver 192.0.2.1\n" + "nameserver 192.0.2.3\n" + "; nameserver[0]: [192.0.2.1]:53\n" + "; nameserver[1]: [192.0.2.3]:53\n" + }, + {.name = "RES_OPTIONS is cummulative", + .conf = "options timeout:7 ndots:2 use-vc\n" + "nameserver 192.0.2.1\n", + .expected = "options ndots:3 timeout:7 attempts:5 use-vc edns0\n" + "search example.com\n" + "; search[0]: example.com\n" + "nameserver 192.0.2.1\n" + "; nameserver[0]: [192.0.2.1]:53\n", + .res_options = "attempts:5 ndots:3 edns0 ", + }, + {.name = "many search list entries (bug 19569)", + .conf = "nameserver 192.0.2.1\n" + "search corp.example.com support.example.com" + " community.example.org wan.example.net vpn.example.net" + " example.com example.org example.net\n", + .expected = "search corp.example.com support.example.com" + " community.example.org wan.example.net vpn.example.net example.com\n" + "; search[0]: corp.example.com\n" + "; search[1]: support.example.com\n" + "; search[2]: community.example.org\n" + "; search[3]: wan.example.net\n" + "; search[4]: vpn.example.net\n" + "; search[5]: example.com\n" + "; search[6]: example.org\n" + "; search[7]: example.net\n" + "nameserver 192.0.2.1\n" + "; nameserver[0]: [192.0.2.1]:53\n" + }, + {.name = "very long search list entries (bug 21475)", + .conf = "nameserver 192.0.2.1\n" + "search example.com " +#define H63 "this-host-name-is-longer-than-yours-yes-I-really-really-mean-it" +#define D63 "this-domain-name-is-as-long-as-the-previous-name--63-characters" + " " H63 "." D63 ".example.org" + " " H63 "." D63 ".example.net\n", + .expected = "search example.com " H63 "." D63 ".example.org\n" + "; search[0]: example.com\n" + "; search[1]: " H63 "." D63 ".example.org\n" + "; search[2]: " H63 "." D63 ".example.net\n" +#undef H63 +#undef D63 + "nameserver 192.0.2.1\n" + "; nameserver[0]: [192.0.2.1]:53\n" + }, + { NULL } + }; + +/* Run the indicated test case. This function assumes that the chroot + contents has already been set up. */ +static void +test_file_contents (const struct test_case *t) +{ +#if TEST_THREAD + for (int do_thread = 0; do_thread < 2; ++do_thread) +#endif + for (int init_method = 0; init_method <= test_init_method_last; + ++init_method) + { + if (test_verbose > 0) + printf ("info: testing init method %s\n", + test_init_names[init_method]); + struct test_context ctx = { .init = init_method, .t = t }; + void (*func) (void *) = run_res_init; +#if TEST_THREAD + if (do_thread) + func = run_res_init_on_thread; +#endif + struct support_capture_subprocess proc + = support_capture_subprocess (func, &ctx); + if (strcmp (proc.out.buffer, t->expected) != 0) + { + support_record_failure (); + printf ("error: output mismatch for %s (init method %s)\n", + t->name, test_init_names[init_method]); + support_run_diff ("expected", t->expected, + "actual", proc.out.buffer); + } + support_capture_subprocess_check (&proc, t->name, 0, + sc_allow_stdout); + support_capture_subprocess_free (&proc); + } +} + +/* Special tests which do not follow the general pattern. */ +enum { special_tests_count = 11 }; + +/* Implementation of special tests. */ +static void +special_test_callback (void *closure) +{ + unsigned int *test_indexp = closure; + unsigned test_index = *test_indexp; + TEST_VERIFY (test_index < special_tests_count); + if (test_verbose > 0) + printf ("info: special test %u\n", test_index); + xchroot (chroot_env->path_chroot); + + switch (test_index) + { + case 0: + case 1: + /* Second res_init with missing or empty file preserves + flags. */ + if (test_index == 1) + TEST_VERIFY (unlink (_PATH_RESCONF) == 0); + _res.options = RES_USE_EDNS0; + TEST_VERIFY (res_init () == 0); + /* First res_init clears flag. */ + TEST_VERIFY (!(_res.options & RES_USE_EDNS0)); + _res.options |= RES_USE_EDNS0; + TEST_VERIFY (res_init () == 0); + /* Second res_init preserves flag. */ + TEST_VERIFY (_res.options & RES_USE_EDNS0); + if (test_index == 1) + /* Restore empty file. */ + support_write_file_string (_PATH_RESCONF, ""); + break; + + case 2: + /* Second res_init is cumulative. */ + support_write_file_string (_PATH_RESCONF, + "options rotate\n" + "nameserver 192.0.2.1\n"); + _res.options = RES_USE_EDNS0; + TEST_VERIFY (res_init () == 0); + /* First res_init clears flag. */ + TEST_VERIFY (!(_res.options & RES_USE_EDNS0)); + /* And sets RES_ROTATE. */ + TEST_VERIFY (_res.options & RES_ROTATE); + _res.options |= RES_USE_EDNS0; + TEST_VERIFY (res_init () == 0); + /* Second res_init preserves flag. */ + TEST_VERIFY (_res.options & RES_USE_EDNS0); + TEST_VERIFY (_res.options & RES_ROTATE); + /* Reloading the configuration does not clear the explicitly set + flag. */ + support_write_file_string (_PATH_RESCONF, + "nameserver 192.0.2.1\n" + "nameserver 192.0.2.2\n"); + TEST_VERIFY (res_init () == 0); + TEST_VERIFY (_res.nscount == 2); + TEST_VERIFY (_res.options & RES_USE_EDNS0); + /* Whether RES_ROTATE (originally in resolv.conf, now removed) + should be preserved is subject to debate. See bug 21701. */ + /* TEST_VERIFY (!(_res.options & RES_ROTATE)); */ + break; + + case 3: + case 4: + case 5: + case 6: + support_write_file_string (_PATH_RESCONF, + "options edns0\n" + "nameserver 192.0.2.1\n"); + goto reload_tests; + case 7: /* 7 and the following tests are with no-reload. */ + case 8: + case 9: + case 10: + support_write_file_string (_PATH_RESCONF, + "options edns0 no-reload\n" + "nameserver 192.0.2.1\n"); + /* Fall through. */ + reload_tests: + for (int iteration = 0; iteration < 2; ++iteration) + { + switch (test_index) + { + case 3: + case 7: + TEST_VERIFY (res_init () == 0); + break; + case 4: + case 8: + { + unsigned char buf[512]; + TEST_VERIFY + (res_mkquery (QUERY, test_hostname, C_IN, T_A, + NULL, 0, NULL, buf, sizeof (buf)) > 0); + } + break; + case 5: + case 9: + gethostbyname (test_hostname); + break; + case 6: + case 10: + { + struct addrinfo *ai; + (void) getaddrinfo (test_hostname, NULL, NULL, &ai); + } + break; + } + /* test_index == 7 is res_init and performs a reload even + with no-reload. */ + if (iteration == 0 || test_index > 7) + { + TEST_VERIFY (_res.options & RES_USE_EDNS0); + TEST_VERIFY (!(_res.options & RES_ROTATE)); + if (test_index < 7) + TEST_VERIFY (!(_res.options & RES_NORELOAD)); + else + TEST_VERIFY (_res.options & RES_NORELOAD); + TEST_VERIFY (_res.nscount == 1); + /* File change triggers automatic reloading. */ + support_write_file_string (_PATH_RESCONF, + "options rotate\n" + "nameserver 192.0.2.1\n" + "nameserver 192.0.2.2\n"); + } + else + { + if (test_index != 3 && test_index != 7) + /* test_index 3, 7 are res_init; this function does + not reset flags. See bug 21701. */ + TEST_VERIFY (!(_res.options & RES_USE_EDNS0)); + TEST_VERIFY (_res.options & RES_ROTATE); + TEST_VERIFY (_res.nscount == 2); + } + } + break; + } +} + +#if TEST_THREAD +/* Helper function which calls special_test_callback from a + thread. */ +static void * +special_test_thread_func (void *closure) +{ + special_test_callback (closure); + return NULL; +} + +/* Variant of special_test_callback which runs the function on a + non-main thread. */ +static void +run_special_test_on_thread (void *closure) +{ + xpthread_join (xpthread_create (NULL, special_test_thread_func, closure)); +} +#endif /* TEST_THREAD */ + +/* Perform the requested special test in a subprocess using + special_test_callback. */ +static void +special_test (unsigned int test_index) +{ +#if TEST_THREAD + for (int do_thread = 0; do_thread < 2; ++do_thread) +#endif + { + void (*func) (void *) = special_test_callback; +#if TEST_THREAD + if (do_thread) + func = run_special_test_on_thread; +#endif + struct support_capture_subprocess proc + = support_capture_subprocess (func, &test_index); + char *test_name = xasprintf ("special test %u", test_index); + if (strcmp (proc.out.buffer, "") != 0) + { + support_record_failure (); + printf ("error: output mismatch for %s\n", test_name); + support_run_diff ("expected", "", + "actual", proc.out.buffer); + } + support_capture_subprocess_check (&proc, test_name, 0, sc_allow_stdout); + free (test_name); + support_capture_subprocess_free (&proc); + } +} + + +/* Dummy DNS server. It ensures that the probe queries sent by + gethostbyname and getaddrinfo receive a reply even if the system + applies a very strict rate limit to localhost. */ +static pid_t +start_dummy_server (void) +{ + int server_socket = xsocket (AF_INET, SOCK_DGRAM, 0); + { + struct sockaddr_in sin = + { + .sin_family = AF_INET, + .sin_addr = { .s_addr = htonl (INADDR_LOOPBACK) }, + .sin_port = htons (53), + }; + int ret = bind (server_socket, (struct sockaddr *) &sin, sizeof (sin)); + if (ret < 0) + { + if (errno == EACCES) + /* The port is reserved, which means we cannot start the + server. */ + return -1; + FAIL_EXIT1 ("cannot bind socket to port 53: %m"); + } + } + + pid_t pid = xfork (); + if (pid == 0) + { + /* Child process. Echo back queries as SERVFAIL responses. */ + while (true) + { + union + { + HEADER header; + unsigned char bytes[512]; + } packet; + struct sockaddr_in sin; + socklen_t sinlen = sizeof (sin); + + ssize_t ret = recvfrom + (server_socket, &packet, sizeof (packet), + MSG_NOSIGNAL, (struct sockaddr *) &sin, &sinlen); + if (ret < 0) + FAIL_EXIT1 ("recvfrom on fake server socket: %m"); + if (ret > sizeof (HEADER)) + { + /* Turn the query into a SERVFAIL response. */ + packet.header.qr = 1; + packet.header.rcode = ns_r_servfail; + + /* Send the response. */ + ret = sendto (server_socket, &packet, ret, + MSG_NOSIGNAL, (struct sockaddr *) &sin, sinlen); + if (ret < 0) + /* The peer may have closed socket prematurely, so + this is not an error. */ + printf ("warning: sending DNS server reply: %m\n"); + } + } + } + + /* In the parent, close the socket. */ + xclose (server_socket); + + return pid; +} + +static int +do_test (void) +{ + support_become_root (); + support_enter_network_namespace (); + if (!support_in_uts_namespace () || !support_can_chroot ()) + return EXIT_UNSUPPORTED; + + /* We are in an UTS namespace, so we can set the host name without + altering the state of the entire system. */ + if (sethostname (test_hostname, strlen (test_hostname)) != 0) + FAIL_EXIT1 ("sethostname: %m"); + + /* These environment variables affect resolv.conf parsing. */ + unsetenv ("LOCALDOMAIN"); + unsetenv ("RES_OPTIONS"); + + /* Ensure that the chroot setup worked. */ + { + struct support_capture_subprocess proc + = support_capture_subprocess (check_chroot_working, NULL); + support_capture_subprocess_check (&proc, "chroot", 0, sc_allow_none); + support_capture_subprocess_free (&proc); + } + + pid_t server = start_dummy_server (); + + for (size_t i = 0; test_cases[i].name != NULL; ++i) + { + if (test_verbose > 0) + printf ("info: running test: %s\n", test_cases[i].name); + TEST_VERIFY (test_cases[i].conf != NULL); + TEST_VERIFY (test_cases[i].expected != NULL); + + support_write_file_string (chroot_env->path_resolv_conf, + test_cases[i].conf); + + test_file_contents (&test_cases[i]); + + /* The expected output from the empty file test is used for + further tests. */ + if (test_cases[i].conf[0] == '\0') + { + if (test_verbose > 0) + printf ("info: special test: missing file\n"); + TEST_VERIFY (unlink (chroot_env->path_resolv_conf) == 0); + test_file_contents (&test_cases[i]); + + if (test_verbose > 0) + printf ("info: special test: dangling symbolic link\n"); + TEST_VERIFY (symlink ("does-not-exist", chroot_env->path_resolv_conf) == 0); + test_file_contents (&test_cases[i]); + TEST_VERIFY (unlink (chroot_env->path_resolv_conf) == 0); + + if (test_verbose > 0) + printf ("info: special test: unreadable file\n"); + support_write_file_string (chroot_env->path_resolv_conf, ""); + TEST_VERIFY (chmod (chroot_env->path_resolv_conf, 0) == 0); + test_file_contents (&test_cases[i]); + + /* Restore the empty file. */ + TEST_VERIFY (unlink (chroot_env->path_resolv_conf) == 0); + support_write_file_string (chroot_env->path_resolv_conf, ""); + } + } + + /* The tests which do not follow a regular pattern. */ + for (unsigned int test_index = 0; + test_index < special_tests_count; ++test_index) + special_test (test_index); + + if (server > 0) + { + if (kill (server, SIGTERM) < 0) + FAIL_EXIT1 ("could not terminate server process: %m"); + xwaitpid (server, NULL, 0); + } + + support_chroot_free (chroot_env); + return 0; +} + +#define PREPARE prepare +#include <support/test-driver.c> diff --git a/resolv/tst-resolv-res_init-thread.c b/resolv/tst-resolv-res_init-thread.c new file mode 100644 index 0000000000..8bb935e0f3 --- /dev/null +++ b/resolv/tst-resolv-res_init-thread.c @@ -0,0 +1,20 @@ +/* Test parsing of /etc/resolv.conf, threading version. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_THREAD 1 +#include "tst-resolv-res_init-skeleton.c" diff --git a/resolv/tst-resolv-res_init.c b/resolv/tst-resolv-res_init.c new file mode 100644 index 0000000000..bb91c9e3ad --- /dev/null +++ b/resolv/tst-resolv-res_init.c @@ -0,0 +1,20 @@ +/* Test parsing of /etc/resolv.conf, non-threading version. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#define TEST_THREAD 0 +#include "tst-resolv-res_init-skeleton.c" diff --git a/resolv/tst-resolv-res_ninit.c b/resolv/tst-resolv-res_ninit.c new file mode 100644 index 0000000000..46e72ab7ce --- /dev/null +++ b/resolv/tst-resolv-res_ninit.c @@ -0,0 +1,75 @@ +/* Test the creation of many struct __res_state objects. + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <mcheck.h> +#include <resolv.h> +#include <resolv/resolv_context.h> +#include <stdlib.h> +#include <support/check.h> + +/* Order the resolver states by their extended resolver state + index. */ +static int +sort_res_state (const void *a, const void *b) +{ + res_state left = (res_state) a; + res_state right = (res_state) b; + return memcmp (&left->_u._ext.__glibc_extension_index, + &right->_u._ext.__glibc_extension_index, + sizeof (left->_u._ext.__glibc_extension_index)); +} + +static int +do_test (void) +{ + mtrace (); + + enum { count = 100 * 1000 }; + res_state array = calloc (count, sizeof (*array)); + const struct resolv_conf *conf = NULL; + for (size_t i = 0; i < count; ++i) + { + TEST_VERIFY (res_ninit (array + i) == 0); + TEST_VERIFY (array[i].nscount > 0); + struct resolv_context *ctx = __resolv_context_get_override (array + i); + TEST_VERIFY_EXIT (ctx != NULL); + TEST_VERIFY (ctx->resp == array + i); + if (i == 0) + { + conf = ctx->conf; + TEST_VERIFY (conf != NULL); + } + else + /* The underyling configuration should be identical across all + res_state opjects because resolv.conf did not change. */ + TEST_VERIFY (ctx->conf == conf); + } + qsort (array, count, sizeof (*array), sort_res_state); + for (size_t i = 1; i < count; ++i) + /* All extension indices should be different. */ + TEST_VERIFY (sort_res_state (array + i - 1, array + i) < 0); + for (size_t i = 0; i < count; ++i) + res_nclose (array + i); + free (array); + + TEST_VERIFY (res_init () == 0); + return 0; +} + +#define TIMEOUT 50 +#include <support/test-driver.c> diff --git a/resolv/tst-resolv-rotate.c b/resolv/tst-resolv-rotate.c new file mode 100644 index 0000000000..15f52d03e8 --- /dev/null +++ b/resolv/tst-resolv-rotate.c @@ -0,0 +1,263 @@ +/* Check that RES_ROTATE works with few nameserver entries (bug 13028). + Copyright (C) 2017-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <netdb.h> +#include <resolv.h> +#include <stdlib.h> +#include <string.h> +#include <support/check.h> +#include <support/check_nss.h> +#include <support/resolv_test.h> +#include <support/test-driver.h> + +static volatile int drop_server = -1; +static volatile unsigned int query_counts[resolv_max_test_servers]; + +static const char address_ipv4[4] = {192, 0, 2, 1}; +static const char address_ipv6[16] + = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; + +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + if (ctx->server_index == drop_server) + { + resolv_response_drop (b); + resolv_response_close (b); + return; + } + + bool force_tcp = strncmp (qname, "2.", 2) == 0; + struct resolv_response_flags flags = {.tc = force_tcp && !ctx->tcp}; + resolv_response_init (b, flags); + resolv_response_add_question (b, qname, qclass, qtype); + if (flags.tc) + return; + + TEST_VERIFY_EXIT (ctx->server_index < resolv_max_test_servers); + ++query_counts[ctx->server_index]; + + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, qname, qclass, qtype, 0); + switch (qtype) + { + case T_A: + { + char addr[sizeof (address_ipv4)]; + memcpy (addr, address_ipv4, sizeof (address_ipv4)); + addr[3] = 1 + ctx->tcp; + resolv_response_add_data (b, addr, sizeof (addr)); + } + break; + case T_AAAA: + { + char addr[sizeof (address_ipv6)]; + memcpy (addr, address_ipv6, sizeof (address_ipv6)); + addr[15] = 1 + ctx->tcp; + resolv_response_add_data (b, addr, sizeof (addr)); + } + break; + case T_PTR: + if (force_tcp) + resolv_response_add_name (b, "2.host.example"); + else + resolv_response_add_name (b, "host.example"); + break; + default: + FAIL_EXIT1 ("unexpected QTYPE: %s/%u/%u", qname, qclass, qtype); + } + resolv_response_close_record (b); +} + +static void +check_forward_1 (const char *name, int family) +{ + unsigned char lsb; + if (strncmp (name, "2.", 2) == 0) + lsb = 2; + else + lsb = 1; + + char expected_hostent_v4[200]; + snprintf (expected_hostent_v4, sizeof (expected_hostent_v4), + "name: %s\naddress: 192.0.2.%d\n", name, lsb); + char expected_hostent_v6[200]; + snprintf (expected_hostent_v6, sizeof (expected_hostent_v6), + "name: %s\naddress: 2001:db8::%d\n", name, lsb); + char expected_ai[200]; + + unsigned char address[16]; + size_t address_length; + + char *expected_hostent; + switch (family) + { + case AF_INET: + expected_hostent = expected_hostent_v4; + snprintf (expected_ai, sizeof (expected_ai), + "address: STREAM/TCP 192.0.2.%d 80\n", lsb); + TEST_VERIFY_EXIT (sizeof (address_ipv4) == sizeof (struct in_addr)); + memcpy (address, address_ipv4, sizeof (address_ipv4)); + address_length = sizeof (address_ipv4); + break; + case AF_INET6: + expected_hostent = expected_hostent_v6; + snprintf (expected_ai, sizeof (expected_ai), + "address: STREAM/TCP 2001:db8::%d 80\n", lsb); + TEST_VERIFY_EXIT (sizeof (address_ipv6) == sizeof (struct in6_addr)); + memcpy (address, address_ipv6, sizeof (address_ipv6)); + address_length = sizeof (address_ipv6); + break; + case AF_UNSPEC: + expected_hostent = NULL; + snprintf (expected_ai, sizeof (expected_ai), + "address: STREAM/TCP 192.0.2.%d 80\n" + "address: STREAM/TCP 2001:db8::%d 80\n", + lsb, lsb); + address_length = 0; + break; + default: + FAIL_EXIT1 ("unknown address family %d", family); + } + + + if (family == AF_INET) + { + struct hostent *e = gethostbyname (name); + check_hostent (name, e, expected_hostent_v4); + } + + if (family != AF_UNSPEC) + { + struct hostent *e = gethostbyname2 (name, family); + check_hostent (name, e, expected_hostent); + } + + if (address_length > 0) + { + address[address_length - 1] = lsb; + struct hostent *e = gethostbyaddr (address, address_length, family); + check_hostent (name, e, expected_hostent); + } + + struct addrinfo hints = + { + .ai_family = family, + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP, + }; + struct addrinfo *ai; + int ret = getaddrinfo (name, "80", &hints, &ai); + check_addrinfo (name, ai, ret, expected_ai); + if (ret == 0) + { + for (struct addrinfo *p = ai; p != NULL; p = p->ai_next) + { + char host[200]; + ret = getnameinfo (p->ai_addr, p->ai_addrlen, + host, sizeof (host), + NULL, 0, /* service */ + 0); + if (ret != 0) + { + support_record_failure (); + printf ("error: getnameinfo: %d\n", ret); + } + else + { + if (lsb == 1) + TEST_VERIFY (strcmp (host, "host.example") == 0); + else + TEST_VERIFY (strcmp (host, "2.host.example") == 0); + } + } + freeaddrinfo (ai); + } +} + +static void +check_forward (int family) +{ + check_forward_1 ("host.example", family); + check_forward_1 ("2.host.example", family); +} + +static int +do_test (void) +{ + for (int force_tcp = 0; force_tcp < 2; ++force_tcp) + for (int nscount = 1; nscount <= 3; ++nscount) + for (int disable_server = -1; disable_server < nscount; ++disable_server) + for (drop_server = -1; drop_server < nscount; ++drop_server) + { + /* A disabled server will never receive queries and + therefore cannot drop them. */ + if (drop_server >= 0 && drop_server == disable_server) + continue; + /* No servers remaining to query, all queries are expected + to fail. */ + int broken_servers = (disable_server >= 0) + (drop_server >= 0); + if (nscount <= broken_servers) + continue; + + if (test_verbose > 0) + printf ("info: tcp=%d nscount=%d disable=%d drop=%d\n", + force_tcp, nscount, disable_server, drop_server); + struct resolv_redirect_config config = + { + .response_callback = response, + .nscount = nscount + }; + if (disable_server >= 0) + { + config.servers[disable_server].disable_udp = true; + config.servers[disable_server].disable_tcp = true; + } + + struct resolv_test *aux = resolv_test_start (config); + _res.options |= RES_ROTATE; + + /* Run a few queries to make sure that all of them + succeed. We always perform more than nscount queries, + so we cover all active servers due to RES_ROTATE. */ + for (size_t i = 0; i < resolv_max_test_servers; ++i) + query_counts[i] = 0; + check_forward (AF_INET); + check_forward (AF_INET6); + check_forward (AF_UNSPEC); + + for (int i = 0; i < nscount; ++i) + { + if (i != disable_server && i != drop_server + && query_counts[i] == 0) + { + support_record_failure (); + printf ("error: nscount=%d, but no query to server %d\n", + nscount, i); + } + } + + resolv_test_end (aux); + } + return 0; +} + +#define TIMEOUT 300 +#include <support/test-driver.c> diff --git a/resolv/tst-resolv-search.c b/resolv/tst-resolv-search.c new file mode 100644 index 0000000000..307ecdcbd6 --- /dev/null +++ b/resolv/tst-resolv-search.c @@ -0,0 +1,344 @@ +/* Test search/default domain name behavior. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <resolv.h> +#include <stdlib.h> +#include <string.h> +#include <support/check.h> +#include <support/check_nss.h> +#include <support/resolv_test.h> +#include <support/support.h> +#include <support/xmemstream.h> + +struct item +{ + const char *name; + int response; +}; + +const struct item items[] = + { + {"hostname.usersys.example.com", 1}, + {"hostname.corp.example.com", 1}, + {"hostname.example.com", 1}, + + {"mail.corp.example.com", 1}, + {"mail.example.com", 1}, + + {"file.corp.example.com", 2}, + {"file.corp", 1}, + {"file.example.com", 1}, + {"servfail-usersys.usersys.example.com", -ns_r_servfail}, + {"servfail-usersys.corp.example.com", 1}, + {"servfail-usersys.example.com", 1}, + {"servfail-corp.usersys.example.com", 1}, + {"servfail-corp.corp.example.com", -ns_r_servfail}, + {"servfail-corp.example.com", 1}, + {"www.example.com", 1}, + {"large.example.com", 200}, + + /* Test query amplification with a SERVFAIL response combined with + a large RRset. */ + {"large-servfail.usersys.example.com", -ns_r_servfail}, + {"large-servfail.example.com", 2000}, + {} + }; + +enum + { + name_not_found = -1, + name_no_data = -2 + }; + +static int +find_name (const char *name) +{ + for (int i = 0; items[i].name != NULL; ++i) + { + if (strcmp (name, items[i].name) == 0) + return i; + } + if (strcmp (name, "example.com") == 0 + || strcmp (name, "usersys.example.com") == 0 + || strcmp (name, "corp.example.com") == 0) + return name_no_data; + return name_not_found; +} + +static int rcode_override_server_index = -1; +static int rcode_override; + +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + if (ctx->server_index == rcode_override_server_index) + { + struct resolv_response_flags flags = {.rcode = rcode_override}; + resolv_response_init (b, flags); + resolv_response_add_question (b, qname, qclass, qtype); + return; + } + + int index = find_name (qname); + struct resolv_response_flags flags = {}; + if (index == name_not_found) + flags.rcode = ns_r_nxdomain; + else if (index >= 0 && items[index].response < 0) + flags.rcode = -items[index].response; + else if (index >= 0 && items[index].response > 5 && !ctx->tcp) + /* Force TCP if more than 5 addresses where requested. */ + flags.tc = true; + resolv_response_init (b, flags); + resolv_response_add_question (b, qname, qclass, qtype); + + if (flags.tc || index < 0 || items[index].response < 0) + return; + + resolv_response_section (b, ns_s_an); + + for (int i = 0; i < items[index].response; ++i) + { + resolv_response_open_record (b, qname, qclass, qtype, 0); + + switch (qtype) + { + case T_A: + { + char addr[4] = {10, index, i >> 8, i}; + resolv_response_add_data (b, addr, sizeof (addr)); + } + break; + case T_AAAA: + { + char addr[16] + = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, + 0, index + 1, (i + 1) >> 8, i + 1}; + resolv_response_add_data (b, addr, sizeof (addr)); + } + break; + default: + support_record_failure (); + printf ("error: unexpected QTYPE: %s/%u/%u\n", + qname, qclass, qtype); + } + resolv_response_close_record (b); + } +} + +enum output_format + { + format_get, format_gai + }; + +static void +format_expected_1 (FILE *out, int family, enum output_format format, int index) +{ + for (int i = 0; i < items[index].response; ++i) + { + char address[200]; + switch (family) + { + case AF_INET: + snprintf (address, sizeof (address), "10.%d.%d.%d", + index, (i >> 8) & 0xff, i & 0xff); + break; + case AF_INET6: + snprintf (address, sizeof (address), "2001:db8::%x:%x", + index + 1, i + 1); + break; + default: + FAIL_EXIT1 ("unreachable"); + } + + switch (format) + { + case format_get: + fprintf (out, "address: %s\n", address); + break; + case format_gai: + fprintf (out, "address: STREAM/TCP %s 80\n", address); + } + } +} + +static char * +format_expected (const char *fqdn, int family, enum output_format format) +{ + int index = find_name (fqdn); + TEST_VERIFY_EXIT (index >= 0); + struct xmemstream stream; + xopen_memstream (&stream); + + TEST_VERIFY_EXIT (items[index].response >= 0); + if (format == format_get) + fprintf (stream.out, "name: %s\n", items[index].name); + if (family == AF_INET || family == AF_UNSPEC) + format_expected_1 (stream.out, AF_INET, format, index); + if (family == AF_INET6 || family == AF_UNSPEC) + format_expected_1 (stream.out, AF_INET6, format, index); + + xfclose_memstream (&stream); + return stream.buffer; +} + +static void +do_get (const char *name, const char *fqdn, int family) +{ + char *expected = format_expected (fqdn, family, format_get); + if (family == AF_INET) + { + char *query = xasprintf ("gethostbyname (\"%s\")", name); + check_hostent (query, gethostbyname (name), expected); + free (query); + } + char *query = xasprintf ("gethostbyname2 (\"%s\", %d)", name, family); + check_hostent (query, gethostbyname2 (name, family), expected); + + /* Test res_search. */ + int qtype; + switch (family) + { + case AF_INET: + qtype = T_A; + break; + case AF_INET6: + qtype = T_AAAA; + break; + default: + qtype = -1; + } + if (qtype >= 0) + { + int sz = 512; + unsigned char *response = xmalloc (sz); + int ret = res_search (name, C_IN, qtype, response, sz); + TEST_VERIFY_EXIT (ret >= 0); + if (ret > sz) + { + /* Truncation. Retry with a larger buffer. */ + sz = 65535; + unsigned char *newptr = xrealloc (response, sz); + response = newptr; + + ret = res_search (name, C_IN, qtype, response, sz); + TEST_VERIFY_EXIT (ret >= 0); + TEST_VERIFY_EXIT (ret < sz); + } + check_dns_packet (query, response, ret, expected); + free (response); + } + + free (query); + free (expected); +} + +static void +do_gai (const char *name, const char *fqdn, int family) +{ + struct addrinfo hints = + { + .ai_family = family, + .ai_protocol = IPPROTO_TCP, + .ai_socktype = SOCK_STREAM + }; + struct addrinfo *ai; + char *query = xasprintf ("%s:80 [%d]", name, family); + int ret = getaddrinfo (name, "80", &hints, &ai); + char *expected = format_expected (fqdn, family, format_gai); + check_addrinfo (query, ai, ret, expected); + if (ret == 0) + freeaddrinfo (ai); + free (expected); + free (query); +} + +static void +do_both (const char *name, const char *fqdn) +{ + do_get (name, fqdn, AF_INET); + do_get (name, fqdn, AF_INET6); + do_gai (name, fqdn, AF_INET); + do_gai (name, fqdn, AF_INET6); + do_gai (name, fqdn, AF_UNSPEC); +} + +static void +do_test_all (bool unconnectable_server) +{ + struct resolv_redirect_config config = + { + .response_callback = response, + .search = {"usersys.example.com", "corp.example.com", "example.com"}, + }; + struct resolv_test *obj = resolv_test_start (config); + + if (unconnectable_server) + { + /* 255.255.255.255 results in an immediate connect failure. The + next server will supply the answer instead. This is a + triggering condition for bug 19791. */ + _res.nsaddr_list[0].sin_addr.s_addr = -1; + _res.nsaddr_list[0].sin_port = htons (53); + } + + do_both ("file", "file.corp.example.com"); + do_both ("www", "www.example.com"); + do_both ("servfail-usersys", "servfail-usersys.corp.example.com"); + do_both ("servfail-corp", "servfail-corp.usersys.example.com"); + do_both ("large", "large.example.com"); + do_both ("large-servfail", "large-servfail.example.com"); + do_both ("file.corp", "file.corp"); + + /* Check that SERVFAIL and REFUSED responses do not alter the search + path resolution. */ + rcode_override_server_index = 0; + rcode_override = ns_r_servfail; + do_both ("hostname", "hostname.usersys.example.com"); + do_both ("large", "large.example.com"); + do_both ("large-servfail", "large-servfail.example.com"); + rcode_override = ns_r_refused; + do_both ("hostname", "hostname.usersys.example.com"); + do_both ("large", "large.example.com"); + do_both ("large-servfail", "large-servfail.example.com"); + /* Likewise, but with an NXDOMAIN for the first search path + entry. */ + rcode_override = ns_r_servfail; + do_both ("mail", "mail.corp.example.com"); + rcode_override = ns_r_refused; + do_both ("mail", "mail.corp.example.com"); + /* Likewise, but with ndots handling. */ + rcode_override = ns_r_servfail; + do_both ("file.corp", "file.corp"); + rcode_override = ns_r_refused; + do_both ("file.corp", "file.corp"); + + resolv_test_end (obj); +} + +static int +do_test (void) +{ + for (int unconnectable_server = 0; unconnectable_server < 2; + ++unconnectable_server) + do_test_all (unconnectable_server); + return 0; +} + +#include <support/test-driver.c> diff --git a/resolv/tst-resolv-threads.c b/resolv/tst-resolv-threads.c new file mode 100644 index 0000000000..4222331d71 --- /dev/null +++ b/resolv/tst-resolv-threads.c @@ -0,0 +1,484 @@ +/* Test basic nss_dns functionality with multiple threads. + Copyright (C) 2016-2018 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* Unlike tst-resolv-basic, this test does not overwrite the _res + structure and relies on namespaces to achieve the redirection to + the test servers with a custom /etc/resolv.conf file. */ + +#include <dlfcn.h> +#include <errno.h> +#include <gnu/lib-names.h> +#include <netdb.h> +#include <resolv/resolv-internal.h> +#include <resolv/resolv_context.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <support/check.h> +#include <support/namespace.h> +#include <support/resolv_test.h> +#include <support/support.h> +#include <support/temp_file.h> +#include <support/test-driver.h> +#include <support/xthread.h> +#include <support/xunistd.h> + +/* Each client thread sends this many queries. */ +enum { queries_per_thread = 500 }; + +/* Return a small positive number identifying this thread. */ +static int +get_thread_number (void) +{ + static int __thread local; + if (local != 0) + return local; + static int global = 1; + local = __atomic_fetch_add (&global, 1, __ATOMIC_RELAXED); + return local; +} + +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + TEST_VERIFY_EXIT (qname != NULL); + + int counter = 0; + int thread = 0; + int dummy = 0; + TEST_VERIFY (sscanf (qname, "counter%d.thread%d.example.com%n", + &counter, &thread, &dummy) == 2); + TEST_VERIFY (dummy > 0); + + struct resolv_response_flags flags = { 0 }; + resolv_response_init (b, flags); + resolv_response_add_question (b, qname, qclass, qtype); + + resolv_response_section (b, ns_s_an); + resolv_response_open_record (b, qname, qclass, qtype, 0); + switch (qtype) + { + case T_A: + { + char ipv4[4] = {10, 0, counter, thread}; + resolv_response_add_data (b, &ipv4, sizeof (ipv4)); + } + break; + case T_AAAA: + { + char ipv6[16] + = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, + counter, 0, thread, 0, 0}; + resolv_response_add_data (b, &ipv6, sizeof (ipv6)); + } + break; + default: + support_record_failure (); + printf ("error: unexpected QTYPE: %s/%u/%u\n", + qname, qclass, qtype); + } + resolv_response_close_record (b); +} + +/* Check that the resolver configuration for this thread has an + extended resolver configuration. */ +static void +check_have_conf (void) +{ + struct resolv_context *ctx = __resolv_context_get (); + TEST_VERIFY_EXIT (ctx != NULL); + TEST_VERIFY (ctx->conf != NULL); + __resolv_context_put (ctx); +} + +/* Verify that E matches the expected response for FAMILY and + COUNTER. */ +static void +check_hostent (const char *caller, const char *function, const char *qname, + int ret, struct hostent *e, int family, int counter) +{ + if (ret != 0) + { + errno = ret; + support_record_failure (); + printf ("error: %s: %s for %s failed: %m\n", caller, function, qname); + return; + } + + TEST_VERIFY_EXIT (e != NULL); + TEST_VERIFY (strcmp (qname, e->h_name) == 0); + TEST_VERIFY (e->h_addrtype == family); + TEST_VERIFY_EXIT (e->h_addr_list[0] != NULL); + TEST_VERIFY (e->h_addr_list[1] == NULL); + switch (family) + { + case AF_INET: + { + char addr[4] = {10, 0, counter, get_thread_number ()}; + TEST_VERIFY (e->h_length == sizeof (addr)); + TEST_VERIFY (memcmp (e->h_addr_list[0], addr, sizeof (addr)) == 0); + } + break; + case AF_INET6: + { + char addr[16] + = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, + 0, counter, 0, get_thread_number (), 0, 0}; + TEST_VERIFY (e->h_length == sizeof (addr)); + TEST_VERIFY (memcmp (e->h_addr_list[0], addr, sizeof (addr)) == 0); + } + break; + default: + FAIL_EXIT1 ("%s: invalid address family %d", caller, family); + } + check_have_conf (); +} + +/* Check a getaddrinfo result. */ +static void +check_addrinfo (const char *caller, const char *qname, + int ret, struct addrinfo *ai, int family, int counter) +{ + if (ret != 0) + { + support_record_failure (); + printf ("error: %s: getaddrinfo for %s failed: %s\n", + caller, qname, gai_strerror (ret)); + return; + } + + TEST_VERIFY_EXIT (ai != NULL); + + /* Check that available data matches the requirements. */ + bool have_ipv4 = false; + bool have_ipv6 = false; + for (struct addrinfo *p = ai; p != NULL; p = p->ai_next) + { + TEST_VERIFY (p->ai_socktype == SOCK_STREAM); + TEST_VERIFY (p->ai_protocol == IPPROTO_TCP); + TEST_VERIFY_EXIT (p->ai_addr != NULL); + TEST_VERIFY (p->ai_addr->sa_family == p->ai_family); + + switch (p->ai_family) + { + case AF_INET: + { + TEST_VERIFY (!have_ipv4); + have_ipv4 = true; + struct sockaddr_in *sa = (struct sockaddr_in *) p->ai_addr; + TEST_VERIFY (p->ai_addrlen == sizeof (*sa)); + char addr[4] = {10, 0, counter, get_thread_number ()}; + TEST_VERIFY (memcmp (&sa->sin_addr, addr, sizeof (addr)) == 0); + TEST_VERIFY (ntohs (sa->sin_port) == 80); + } + break; + case AF_INET6: + { + TEST_VERIFY (!have_ipv6); + have_ipv6 = true; + struct sockaddr_in6 *sa = (struct sockaddr_in6 *) p->ai_addr; + TEST_VERIFY (p->ai_addrlen == sizeof (*sa)); + char addr[16] + = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, + 0, counter, 0, get_thread_number (), 0, 0}; + TEST_VERIFY (memcmp (&sa->sin6_addr, addr, sizeof (addr)) == 0); + TEST_VERIFY (ntohs (sa->sin6_port) == 80); + } + break; + default: + FAIL_EXIT1 ("%s: invalid address family %d", caller, family); + } + } + + switch (family) + { + case AF_INET: + TEST_VERIFY (have_ipv4); + TEST_VERIFY (!have_ipv6); + break; + case AF_INET6: + TEST_VERIFY (!have_ipv4); + TEST_VERIFY (have_ipv6); + break; + case AF_UNSPEC: + TEST_VERIFY (have_ipv4); + TEST_VERIFY (have_ipv6); + break; + default: + FAIL_EXIT1 ("%s: invalid address family %d", caller, family); + } + + check_have_conf (); +} + +/* This barrier ensures that all test threads begin their work + simultaneously. */ +static pthread_barrier_t barrier; + +/* Test gethostbyname2_r (if do_2 is false) or gethostbyname2_r with + AF_INET (if do_2 is true). */ +static void * +byname (bool do_2) +{ + int this_thread = get_thread_number (); + xpthread_barrier_wait (&barrier); + for (int i = 0; i < queries_per_thread; ++i) + { + char qname[100]; + snprintf (qname, sizeof (qname), "counter%d.thread%d.example.com", + i, this_thread); + struct hostent storage; + char buf[1000]; + struct hostent *e = NULL; + int herrno; + int ret; + if (do_2) + ret = gethostbyname_r (qname, &storage, buf, sizeof (buf), + &e, &herrno); + else + ret = gethostbyname2_r (qname, AF_INET, &storage, buf, sizeof (buf), + &e, &herrno); + check_hostent (__func__, do_2 ? "gethostbyname2_r" : "gethostbyname_r", + qname, ret, e, AF_INET, i); + } + check_have_conf (); + return NULL; +} + +/* Test gethostbyname_r. */ +static void * +thread_byname (void *closure) +{ + return byname (false); +} + +/* Test gethostbyname2_r with AF_INET. */ +static void * +thread_byname2 (void *closure) +{ + return byname (true); +} + +/* Call gethostbyname_r with RES_USE_INET6 (if do_2 is false), or + gethostbyname_r with AF_INET6 (if do_2 is true). */ +static void * +byname_inet6 (bool do_2) +{ + int this_thread = get_thread_number (); + xpthread_barrier_wait (&barrier); + if (!do_2) + { + res_init (); + _res.options |= DEPRECATED_RES_USE_INET6; + TEST_VERIFY (strcmp (_res.defdname, "example.com") == 0); + } + for (int i = 0; i < queries_per_thread; ++i) + { + char qname[100]; + snprintf (qname, sizeof (qname), "counter%d.thread%d.example.com", + i, this_thread); + struct hostent storage; + char buf[1000]; + struct hostent *e = NULL; + int herrno; + int ret; + if (do_2) + ret = gethostbyname2_r (qname, AF_INET6, &storage, buf, sizeof (buf), + &e, &herrno); + else + ret = gethostbyname_r (qname, &storage, buf, sizeof (buf), + &e, &herrno); + check_hostent (__func__, + do_2 ? "gethostbyname2_r" : "gethostbyname_r", + qname, ret, e, AF_INET6, i); + } + return NULL; +} + +/* Test gethostbyname_r with AF_INET6. */ +static void * +thread_byname_inet6 (void *closure) +{ + return byname_inet6 (false); +} + +/* Test gethostbyname2_r with AF_INET6. */ +static void * +thread_byname2_af_inet6 (void *closure) +{ + return byname_inet6 (true); +} + +/* Run getaddrinfo tests for FAMILY. */ +static void * +gai (int family, bool do_inet6) +{ + int this_thread = get_thread_number (); + xpthread_barrier_wait (&barrier); + if (do_inet6) + { + res_init (); + _res.options |= DEPRECATED_RES_USE_INET6; + check_have_conf (); + } + for (int i = 0; i < queries_per_thread; ++i) + { + char qname[100]; + snprintf (qname, sizeof (qname), "counter%d.thread%d.example.com", + i, this_thread); + struct addrinfo hints = + { + .ai_family = family, + .ai_socktype = SOCK_STREAM, + .ai_protocol = IPPROTO_TCP, + }; + struct addrinfo *ai; + int ret = getaddrinfo (qname, "80", &hints, &ai); + check_addrinfo (__func__, qname, ret, ai, family, i); + if (ret == 0) + freeaddrinfo (ai); + } + return NULL; +} + +/* Test getaddrinfo with AF_INET. */ +static void * +thread_gai_inet (void *closure) +{ + return gai (AF_INET, false); +} + +/* Test getaddrinfo with AF_INET6. */ +static void * +thread_gai_inet6 (void *closure) +{ + return gai (AF_INET6, false); +} + +/* Test getaddrinfo with AF_UNSPEC. */ +static void * +thread_gai_unspec (void *closure) +{ + return gai (AF_UNSPEC, false); +} + +/* Test getaddrinfo with AF_INET. */ +static void * +thread_gai_inet_inet6 (void *closure) +{ + return gai (AF_INET, true); +} + +/* Test getaddrinfo with AF_INET6. */ +static void * +thread_gai_inet6_inet6 (void *closure) +{ + return gai (AF_INET6, true); +} + +/* Test getaddrinfo with AF_UNSPEC. */ +static void * +thread_gai_unspec_inet6 (void *closure) +{ + return gai (AF_UNSPEC, true); +} + +/* Description of the chroot environment used to run the tests. */ +static struct support_chroot *chroot_env; + +/* Set up the chroot environment. */ +static void +prepare (int argc, char **argv) +{ + chroot_env = support_chroot_create + ((struct support_chroot_configuration) + { + .resolv_conf = + "search example.com\n" + "nameserver 127.0.0.1\n" + "nameserver 127.0.0.2\n" + "nameserver 127.0.0.3\n", + }); +} + +static int +do_test (void) +{ + support_become_root (); + if (!support_enter_network_namespace ()) + return EXIT_UNSUPPORTED; + if (!support_can_chroot ()) + return EXIT_UNSUPPORTED; + + /* Load the shared object outside of the chroot. */ + TEST_VERIFY (dlopen (LIBNSS_DNS_SO, RTLD_LAZY) != NULL); + + xchroot (chroot_env->path_chroot); + TEST_VERIFY_EXIT (chdir ("/") == 0); + + struct sockaddr_in server_address = + { + .sin_family = AF_INET, + .sin_addr = { .s_addr = htonl (INADDR_LOOPBACK) }, + .sin_port = htons (53) + }; + const struct sockaddr *server_addresses[1] = + { (const struct sockaddr *) &server_address }; + + struct resolv_test *aux = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response, + .nscount = 1, + .disable_redirect = true, + .server_address_overrides = server_addresses, + }); + + enum { thread_count = 10 }; + xpthread_barrier_init (&barrier, NULL, thread_count + 1); + pthread_t threads[thread_count]; + typedef void *(*thread_func) (void *); + thread_func thread_funcs[thread_count] = + { + thread_byname, + thread_byname2, + thread_byname_inet6, + thread_byname2_af_inet6, + thread_gai_inet, + thread_gai_inet6, + thread_gai_unspec, + thread_gai_inet_inet6, + thread_gai_inet6_inet6, + thread_gai_unspec_inet6, + }; + for (int i = 0; i < thread_count; ++i) + threads[i] = xpthread_create (NULL, thread_funcs[i], NULL); + xpthread_barrier_wait (&barrier); /* Start the test threads. */ + for (int i = 0; i < thread_count; ++i) + xpthread_join (threads[i]); + + resolv_test_end (aux); + support_chroot_free (chroot_env); + + return 0; +} + +#define PREPARE prepare +#include <support/test-driver.c> |