diff options
Diffstat (limited to 'REORG.TODO/resolv')
77 files changed, 20254 insertions, 0 deletions
diff --git a/REORG.TODO/resolv/Banner b/REORG.TODO/resolv/Banner new file mode 100644 index 0000000000..e585ed8532 --- /dev/null +++ b/REORG.TODO/resolv/Banner @@ -0,0 +1 @@ +BIND-8.2.3-T5B diff --git a/REORG.TODO/resolv/Depend b/REORG.TODO/resolv/Depend new file mode 100644 index 0000000000..6c1aa44e6e --- /dev/null +++ b/REORG.TODO/resolv/Depend @@ -0,0 +1 @@ +nptl diff --git a/REORG.TODO/resolv/Makefile b/REORG.TODO/resolv/Makefile new file mode 100644 index 0000000000..dc597ca097 --- /dev/null +++ b/REORG.TODO/resolv/Makefile @@ -0,0 +1,158 @@ +# Copyright (C) 1994-2017 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/>. + +# +# Sub-makefile for resolv portion of the library. +# +subdir := resolv + +include ../Makeconfig + +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 + +tests = tst-aton tst-leaks tst-inet_ntop +xtests = tst-leaks2 + +generate := mtrace-tst-leaks.out tst-leaks.mtrace tst-leaks2.mtrace + +extra-libs := libresolv libnss_dns +ifeq ($(have-thread-library),yes) +extra-libs += libanl +routines += gai_sigqueue + +tests += \ + tst-bug18665 \ + tst-bug18665-tcp \ + tst-ns_name \ + tst-ns_name_compress \ + tst-res_hconf_reorder \ + tst-res_use_inet6 \ + tst-resolv-basic \ + tst-resolv-edns \ + tst-resolv-network \ + tst-resolv-search \ + +# These tests need libdl. +ifeq (yes,$(build-shared)) +tests += \ + tst-resolv-canonname \ + +# uses DEPRECATED_RES_USE_INET6 from <resolv-internal.h>. +tests-internal += \ + tst-resolv-res_init \ + tst-resolv-res_init-thread \ + +endif + +# This test sends millions of packets and is rather slow. +xtests += tst-resolv-qtypes +endif +extra-libs-others = $(extra-libs) +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 \ + compat-hooks compat-gethnamaddr + +libanl-routines := gai_cancel gai_error gai_misc gai_notify gai_suspend \ + getaddrinfo_a + +subdir-dirs = nss_dns +vpath %.c nss_dns + +libnss_dns-routines := dns-host dns-network dns-canon +libnss_dns-inhibit-o = $(filter-out .os,$(object-suffixes)) +ifeq ($(build-static-nss),yes) +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 +endif +endif + +ifeq (,$(filter sunrpc,$(subdirs))) +# The netdb.h we install does '#include <rpc/netdb.h>', so one must exist. +# If sunrpc/ is built in this configuration, it installs a real <rpc/netdb.h>. +# If that's not going to happen, install our dummy file. +headers += rpc/netdb.h +endif + +generated += mtrace-tst-leaks.out tst-leaks.mtrace \ + mtrace-tst-leaks2.out tst-leaks2.mtrace + +include ../Rules + +CFLAGS-res_hconf.c = -fexceptions + +# The DNS NSS modules needs the resolver. +$(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 + +$(objpfx)tst-leaks: $(objpfx)libresolv.so +tst-leaks-ENV = MALLOC_TRACE=$(objpfx)tst-leaks.mtrace +$(objpfx)mtrace-tst-leaks.out: $(objpfx)tst-leaks.out + $(common-objpfx)malloc/mtrace $(objpfx)tst-leaks.mtrace > $@; \ + $(evaluate-test) + +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) + +$(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-basic: $(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-thread: $(libdl) $(objpfx)libresolv.so \ + $(shared-thread-library) +$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library) +$(objpfx)tst-resolv-search: $(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 + + +# This test case uses the deprecated RES_USE_INET6 resolver option. +CFLAGS-tst-res_use_inet6.c += -Wno-error diff --git a/REORG.TODO/resolv/README b/REORG.TODO/resolv/README new file mode 100644 index 0000000000..c50025168c --- /dev/null +++ b/REORG.TODO/resolv/README @@ -0,0 +1,152 @@ +The resolver in the GNU C Library +********************************* + +Starting with version 2.2, the resolver in the GNU C Library comes +from BIND 8. Only a subset of the src/lib/resolv part of libbind is +included here; basically the parts that are needed to provide the +functionality present in the resolver from BIND 4.9.7 that was +included in the previous release of the GNU C Library, augmented by +the parts needed to provide thread-safety. This means that support +for things as dynamic DNS updates and TSIG keys isn't included. If +you need those facilities, please take a look at the full BIND +distribution. + + +Differences +=========== + +The resolver in the GNU C Library still differs from what's in BIND +8.2.3-T5B: + +* The RES_DEBUG option (`options debug' in /etc/resolv.conf) has been + disabled. + +* The resolver in glibc allows underscores in domain names. + +* The <resolv.h> header in glibc includes <netinet/in.h> and + <arpa/nameser.h> to make it self-contained. + +* The `res_close' function in glibc only tries to close open files + referenced through `_res' if the RES_INIT bit is set in + `_res.options'. This fixes a potential security bug with programs + that bogusly call `res_close' without initialising the resolver + state first. Note that the thread-safe `res_nclose' still doesn't + check the RES_INIT bit. By the way, you're not really supposed to + call `res_close/res_nclose' directly. + +* The resolver in glibc can connect to a nameserver over IPv6. Just + specify the IPv6 address in /etc/resolv.conf. You cannot change the + address of an IPv6 nameserver dynamically in your program though. + + +Using the resolver in multi-threaded code +========================================= + +The traditional resolver interfaces `res_query', `res_search', +`res_mkquery', `res_send' and `res_init', used a static (global) +resolver state stored in the `_res' structure. Therefore, these +interfaces are not thread-safe. Therefore, BIND 8.2 introduced a set +of "new" interfaces `res_nquery', `res_nsearch', `res_nmkquery', +`res_nsend' and `res_ninit' that take a `res_state' as their first +argument, so you can use a per-thread resolver state. In glibc, when +you link with -lpthread, such a per-thread resolver state is already +present. It can be accessed using `_res', which has been redefined as +a macro, in a similar way to what has been done for the `errno' and +`h_errno' variables. This per-thread resolver state is also used for +the `gethostby*' family of functions, which means that for example +`gethostbyname_r' is now fully thread-safe and re-entrant. The +traditional resolver interfaces however, continue to use a single +resolver state and are therefore still thread-unsafe. The resolver +state is the same resolver state that is used for the initial ("main") +thread. + +This has the following consequences for existing binaries and source +code: + +* Single-threaded programs will continue to work. There should be no + user-visible changes when you recompile them. + +* Multi-threaded programs that use the traditional resolver interfaces + in the "main" thread should continue to work, except that they no + longer see any changes in the global resolver state caused by calls + to, for example, `gethostbyname' in other threads. Again there + should be no user-visible changes when you recompile these programs. + +* Multi-threaded programs that use the traditional resolver interfaces + in more than one thread should be just as buggy as before (there are + no problems if you use proper locking of course). If you recompile + these programs, manipulating the _res structure in threads other + than the "main" thread will seem to have no effect though. + +* 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. + +We recommend to use the new thread-safe interfaces in new code, since +the traditional interfaces have been deprecated by the BIND folks. +For compatibility with other (older) systems you might want to +continue to use those interfaces though. + + +Using the resolver in C++ code +============================== + +There resolver contains some hooks which will allow the user to +install some callback functions that make it possible to filter DNS +requests and responses. Although we do not encourage you to make use +of this facility at all, C++ developers should realise that it isn't +safe to throw exceptions from such callback functions. + + +Source code +=========== + +The following files come from the BIND distribution (currently version +8.2.3-T5B): + +src/include/ + arpa/nameser.h + arpa/nameser_compat.h + resolv.h + +src/lib/resolv/ + herror.c + res_comp.c + res_data.c + res_debug.c + res_debug.h + res_init.c + res_mkquery.c + res_query.c + res_send.c + +src/lib/nameser/ + ns_name.c + ns_netint.c + ns_parse.c + ns_print.c + ns_samedomain.c + ns_ttl.c + +src/lib/inet/ + inet_addr.c + inet_net_ntop.c + inet_net_pton.c + inet_neta.c + inet_ntop.c + inet_pton.c + nsap_addr.c + +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. + +res_libc.c is home-brewn, although parts of it are taken from res_data.c. + +res_hconf.c and res_hconf.h were contributed by David Mosberger, and +do not come from BIND. + +The files gethnamaddr.c, mapv4v6addr.h and mapv4v6hostent.h are +leftovers from BIND 4.9.7. diff --git a/REORG.TODO/resolv/Versions b/REORG.TODO/resolv/Versions new file mode 100644 index 0000000000..e561bce1a4 --- /dev/null +++ b/REORG.TODO/resolv/Versions @@ -0,0 +1,100 @@ +libc { + GLIBC_2.0 { + _res; + + # helper functions + __h_errno_location; + + # functions used in other libraries + __res_randomid; + + # variables in normal name space + h_errlist; h_nerr; + + # h* + herror; hstrerror; + + # r* + res_init; + } + GLIBC_2.2 { + # r* + __res_state; __res_init; __res_nclose; __res_ninit; _res_hconf; + } + GLIBC_PRIVATE { + __gai_sigqueue; + + __h_errno; __resp; + + __res_maybe_init; __res_iclose; + } +} + +libresolv { + GLIBC_2.0 { + _gethtbyaddr; _gethtbyname; _gethtbyname2; _gethtent; _getlong; + _getshort; _res_opcodes; _res_resultcodes; _sethtent; dn_expand; + inet_net_ntop; inet_net_pton; inet_neta; res_gethostbyaddr; + res_gethostbyname; res_gethostbyname2; res_mkquery; res_query; + res_querydomain; res_search; res_send_setqhook; res_send_setrhook; + # Variables + __p_class_syms; __p_type_syms; + # Private routines shared between libc/net, named, nslookup and others. + __b64_ntop; __b64_pton; + __dn_comp; __dn_count_labels; __dn_skipname; + __fp_nquery; __fp_query; __fp_resstat; __hostalias; + __loc_aton; __loc_ntoa; + __p_cdname; __p_cdnname; __p_class; __p_fqname; __p_fqnname; __p_option; + __p_query; __p_rr; __p_secstodate; __p_time; __p_type; + __putlong; __putshort; + __res_close; __res_dnok; __res_hnok; __res_isourserver; __res_mailok; + __res_nameinquery; __res_ownok; __res_queriesmatch; + __res_send; + __sym_ntop; __sym_ntos; __sym_ston; + } + GLIBC_2.2 { + __dn_expand; + __res_hostalias; __res_mkquery; __res_nmkquery; __res_nquery; + __res_nquerydomain; __res_nsearch; __res_nsend; __res_query; + __res_querydomain; __res_search; + } + GLIBC_2.3.2 { + __p_rcode; + } + GLIBC_2.9 { + ns_msg_getflag; + ns_get16; ns_get32; ns_put16; ns_put32; + ns_initparse; ns_skiprr; ns_parserr; + ns_sprintrr; ns_sprintrrf; + ns_format_ttl; ns_parse_ttl; + ns_datetosecs; + ns_name_ntol; ns_name_ntop; ns_name_pton; + ns_name_unpack; ns_name_pack; + ns_name_uncompress; ns_name_compress; + ns_name_skip; ns_name_rollback; + ns_samedomain; ns_subdomain; ns_makecanon; ns_samename; + } + GLIBC_PRIVATE { + # Needed in libnss_dns. + __ns_name_unpack; __ns_name_ntop; + __ns_get16; __ns_get32; + __libc_res_nquery; __libc_res_nsearch; + } +} + +libnss_dns { + GLIBC_PRIVATE { + _nss_dns_gethostbyaddr_r; _nss_dns_gethostbyname2_r; + _nss_dns_gethostbyname3_r; + _nss_dns_gethostbyname_r; _nss_dns_getnetbyaddr_r; + _nss_dns_getnetbyname_r; _nss_dns_getcanonname_r; + _nss_dns_gethostbyaddr2_r; + _nss_dns_gethostbyname4_r; + } +} + +libanl { + GLIBC_2.2.3 { + gai_cancel; gai_error; gai_suspend; getaddrinfo_a; + } +} diff --git a/REORG.TODO/resolv/arpa/nameser.h b/REORG.TODO/resolv/arpa/nameser.h new file mode 100644 index 0000000000..a99d5ec508 --- /dev/null +++ b/REORG.TODO/resolv/arpa/nameser.h @@ -0,0 +1,443 @@ +/* + * Copyright (c) 1983, 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. + */ + +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * 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. + */ + +#ifndef _ARPA_NAMESER_H_ +#define _ARPA_NAMESER_H_ + +#include <sys/param.h> +#include <sys/types.h> +#include <stdint.h> + +/* + * Define constants based on RFC 883, RFC 1034, RFC 1035 + */ +#define NS_PACKETSZ 512 /*%< default UDP packet size */ +#define NS_MAXDNAME 1025 /*%< maximum domain name */ +#define NS_MAXMSG 65535 /*%< maximum message size */ +#define NS_MAXCDNAME 255 /*%< maximum compressed domain name */ +#define NS_MAXLABEL 63 /*%< maximum length of domain label */ +#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 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. */ +#define NS_DEFAULTPORT 53 /*%< For both TCP and UDP. */ +/* + * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord() + * in synch with it. + */ +typedef enum __ns_sect { + ns_s_qd = 0, /*%< Query: Question. */ + ns_s_zn = 0, /*%< Update: Zone. */ + ns_s_an = 1, /*%< Query: Answer. */ + ns_s_pr = 1, /*%< Update: Prerequisites. */ + ns_s_ns = 2, /*%< Query: Name servers. */ + ns_s_ud = 2, /*%< Update: Update. */ + ns_s_ar = 3, /*%< Query|Update: Additional records. */ + ns_s_max = 4 +} ns_sect; + +/*% + * This is a message handle. It is caller allocated and has no dynamic data. + * This structure is intended to be opaque to all but ns_parse.c, thus the + * leading _'s on the member names. Use the accessor functions, not the _'s. + */ +typedef struct __ns_msg { + 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. */ +struct _ns_flagdata { int mask, shift; }; +extern const struct _ns_flagdata _ns_flagdata[]; + +/* Accessor macros - this is part of the public interface. */ + +#define ns_msg_id(handle) ((handle)._id + 0) +#define ns_msg_base(handle) ((handle)._msg + 0) +#define ns_msg_end(handle) ((handle)._eom + 0) +#define ns_msg_size(handle) ((handle)._eom - (handle)._msg) +#define ns_msg_count(handle, section) ((handle)._counts[section] + 0) + +/*% + * This is a parsed record. It is caller allocated and has no dynamic data. + */ +typedef struct __ns_rr { + 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. */ +#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".") +#define ns_rr_type(rr) ((ns_type)((rr).type + 0)) +#define ns_rr_class(rr) ((ns_class)((rr).rr_class + 0)) +#define ns_rr_ttl(rr) ((rr).ttl + 0) +#define ns_rr_rdlen(rr) ((rr).rdlength + 0) +#define ns_rr_rdata(rr) ((rr).rdata + 0) + +/*% + * These don't have to be in the same order as in the packet flags word, + * and they can even overlap in some cases, but they will need to be kept + * in synch with ns_parse.c:ns_flagdata[]. + */ +typedef enum __ns_flag { + ns_f_qr, /*%< Question/Response. */ + ns_f_opcode, /*%< Operation code. */ + ns_f_aa, /*%< Authoritative Answer. */ + ns_f_tc, /*%< Truncation occurred. */ + ns_f_rd, /*%< Recursion Desired. */ + ns_f_ra, /*%< Recursion Available. */ + ns_f_z, /*%< MBZ. */ + ns_f_ad, /*%< Authentic Data (DNSSEC). */ + ns_f_cd, /*%< Checking Disabled (DNSSEC). */ + ns_f_rcode, /*%< Response code. */ + ns_f_max +} ns_flag; + +/*% + * Currently defined opcodes. + */ +typedef enum __ns_opcode { + ns_o_query = 0, /*%< Standard query. */ + ns_o_iquery = 1, /*%< Inverse query (deprecated/unsupported). */ + ns_o_status = 2, /*%< Name server status query (unsupported). */ + /* Opcode 3 is undefined/reserved. */ + ns_o_notify = 4, /*%< Zone change notification. */ + ns_o_update = 5, /*%< Zone update message. */ + ns_o_max = 6 +} ns_opcode; + +/*% + * Currently defined response codes. + */ +typedef enum __ns_rcode { + ns_r_noerror = 0, /*%< No error occurred. */ + ns_r_formerr = 1, /*%< Format error. */ + ns_r_servfail = 2, /*%< Server failure. */ + ns_r_nxdomain = 3, /*%< Name error. */ + ns_r_notimpl = 4, /*%< Unimplemented. */ + ns_r_refused = 5, /*%< Operation refused. */ + /* these are for BIND_UPDATE */ + ns_r_yxdomain = 6, /*%< Name exists */ + ns_r_yxrrset = 7, /*%< RRset exists */ + ns_r_nxrrset = 8, /*%< RRset does not exist */ + ns_r_notauth = 9, /*%< Not authoritative for zone */ + ns_r_notzone = 10, /*%< Zone of record different from zone section */ + ns_r_max = 11, + /* The following are EDNS extended rcodes */ + ns_r_badvers = 16, + /* The following are TSIG errors */ + ns_r_badsig = 16, + ns_r_badkey = 17, + ns_r_badtime = 18 +} ns_rcode; + +/* BIND_UPDATE */ +typedef enum __ns_update_operation { + ns_uop_delete = 0, + ns_uop_add = 1, + ns_uop_max = 2 +} ns_update_operation; + +/*% + * This structure is used for TSIG authenticated messages + */ +struct ns_tsig_key { + char name[NS_MAXDNAME], alg[NS_MAXDNAME]; + unsigned char *data; + int len; +}; +typedef struct ns_tsig_key ns_tsig_key; + +/*% + * This structure is used for TSIG authenticated TCP messages + */ +struct ns_tcp_tsig_state { + int counter; + struct dst_key *key; + void *ctx; + unsigned char sig[NS_PACKETSZ]; + int siglen; +}; +typedef struct ns_tcp_tsig_state ns_tcp_tsig_state; + +#define NS_TSIG_FUDGE 300 +#define NS_TSIG_TCP_COUNT 100 +#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT" + +#define NS_TSIG_ERROR_NO_TSIG -10 +#define NS_TSIG_ERROR_NO_SPACE -11 +#define NS_TSIG_ERROR_FORMERR -12 + +/*% + * Currently defined type values for resources and queries. + */ +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 + */ +typedef enum __ns_class { + ns_c_invalid = 0, /*%< Cookie. */ + ns_c_in = 1, /*%< Internet. */ + ns_c_2 = 2, /*%< unallocated/unsupported. */ + ns_c_chaos = 3, /*%< MIT Chaos-net. */ + ns_c_hs = 4, /*%< MIT Hesiod. */ + /* Query class values which do not appear in resource records */ + ns_c_none = 254, /*%< for prereq. sections in update requests */ + ns_c_any = 255, /*%< Wildcard match. */ + ns_c_max = 65536 +} ns_class; + +/* Certificate type values in CERT resource records. */ +typedef enum __ns_cert_types { + cert_t_pkix = 1, /*%< PKIX (X.509v3) */ + cert_t_spki = 2, /*%< SPKI */ + cert_t_pgp = 3, /*%< PGP */ + cert_t_url = 253, /*%< URL private type */ + cert_t_oid = 254 /*%< OID private type */ +} ns_cert_types; + +/*% + * EDNS0 extended flags and option codes, host order. + */ +#define NS_OPT_DNSSEC_OK 0x8000U +#define NS_OPT_NSID 3 + +/*% + * Inline versions of get/put short/long. Pointer is advanced. + */ +#define NS_GET16(s, cp) do { \ + 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 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 { \ + 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 { \ + 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; \ + *t_cp = t_l; \ + (cp) += NS_INT32SZ; \ +} while (0) + +__BEGIN_DECLS +int ns_msg_getflag (ns_msg, 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 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; +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 + +#include <arpa/nameser_compat.h> + +#endif /* !_ARPA_NAMESER_H_ */ +/*! \file */ diff --git a/REORG.TODO/resolv/arpa/nameser_compat.h b/REORG.TODO/resolv/arpa/nameser_compat.h new file mode 100644 index 0000000000..f1c390f3b9 --- /dev/null +++ b/REORG.TODO/resolv/arpa/nameser_compat.h @@ -0,0 +1,221 @@ +/* Copyright (c) 1983, 1989 + * 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. + */ + +#ifndef _ARPA_NAMESER_COMPAT_ +#define _ARPA_NAMESER_COMPAT_ + +#include <endian.h> + +/*% + * Structure for query header. The order of the fields is machine- and + * compiler-dependent, depending on the byte/bit order and the layout + * of bit fields. We use bit fields only in int variables, as this + * is all ANSI requires. This requires a somewhat confusing rearrangement. + */ + +typedef struct { + unsigned id :16; /*%< query identification number */ +#if __BYTE_ORDER == __BIG_ENDIAN + /* fields in third byte */ + unsigned qr: 1; /*%< response flag */ + unsigned opcode: 4; /*%< purpose of message */ + unsigned aa: 1; /*%< authoritive answer */ + unsigned tc: 1; /*%< truncated message */ + unsigned rd: 1; /*%< recursion desired */ + /* fields in fourth byte */ + unsigned ra: 1; /*%< recursion available */ + unsigned unused :1; /*%< unused bits (MBZ as of 4.9.3a3) */ + unsigned ad: 1; /*%< authentic data from named */ + unsigned cd: 1; /*%< checking disabled by resolver */ + unsigned rcode :4; /*%< response code */ +#endif +#if __BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __PDP_ENDIAN + /* fields in third byte */ + unsigned rd :1; /*%< recursion desired */ + unsigned tc :1; /*%< truncated message */ + unsigned aa :1; /*%< authoritive answer */ + unsigned opcode :4; /*%< purpose of message */ + unsigned qr :1; /*%< response flag */ + /* fields in fourth byte */ + unsigned rcode :4; /*%< response code */ + unsigned cd: 1; /*%< checking disabled by resolver */ + unsigned ad: 1; /*%< authentic data from named */ + unsigned unused :1; /*%< unused bits (MBZ as of 4.9.3a3) */ + unsigned ra :1; /*%< recursion available */ +#endif + /* remaining bytes */ + unsigned qdcount :16; /*%< number of question entries */ + unsigned ancount :16; /*%< number of answer entries */ + unsigned nscount :16; /*%< number of authority entries */ + unsigned arcount :16; /*%< number of resource entries */ +} HEADER; + +#define PACKETSZ NS_PACKETSZ +#define MAXDNAME NS_MAXDNAME +#define MAXCDNAME NS_MAXCDNAME +#define MAXLABEL NS_MAXLABEL +#define HFIXEDSZ NS_HFIXEDSZ +#define QFIXEDSZ NS_QFIXEDSZ +#define RRFIXEDSZ NS_RRFIXEDSZ +#define INT32SZ NS_INT32SZ +#define INT16SZ NS_INT16SZ +#define INT8SZ NS_INT8SZ +#define INADDRSZ NS_INADDRSZ +#define IN6ADDRSZ NS_IN6ADDRSZ +#define INDIR_MASK NS_CMPRSFLGS +#define NAMESERVER_PORT NS_DEFAULTPORT + +#define S_ZONE ns_s_zn +#define S_PREREQ ns_s_pr +#define S_UPDATE ns_s_ud +#define S_ADDT ns_s_ar + +#define QUERY ns_o_query +#define IQUERY ns_o_iquery +#define STATUS ns_o_status +#define NS_NOTIFY_OP ns_o_notify +#define NS_UPDATE_OP ns_o_update + +#define NOERROR ns_r_noerror +#define FORMERR ns_r_formerr +#define SERVFAIL ns_r_servfail +#define NXDOMAIN ns_r_nxdomain +#define NOTIMP ns_r_notimpl +#define REFUSED ns_r_refused +#define YXDOMAIN ns_r_yxdomain +#define YXRRSET ns_r_yxrrset +#define NXRRSET ns_r_nxrrset +#define NOTAUTH ns_r_notauth +#define NOTZONE ns_r_notzone +/*#define BADSIG ns_r_badsig*/ +/*#define BADKEY ns_r_badkey*/ +/*#define BADTIME ns_r_badtime*/ + + +#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_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 +#define C_HS ns_c_hs +/* BIND_UPDATE */ +#define C_NONE ns_c_none +#define C_ANY ns_c_any + +#define GETSHORT NS_GET16 +#define GETLONG NS_GET32 +#define PUTSHORT NS_PUT16 +#define PUTLONG NS_PUT32 + +#endif /* _ARPA_NAMESER_COMPAT_ */ +/*! \file */ diff --git a/REORG.TODO/resolv/base64.c b/REORG.TODO/resolv/base64.c new file mode 100644 index 0000000000..fedc086b0c --- /dev/null +++ b/REORG.TODO/resolv/base64.c @@ -0,0 +1,310 @@ +/* + * 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. + */ + +/* + * Portions Copyright (c) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +#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 <ctype.h> +#include <resolv.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define Assert(Cond) if (!(Cond)) abort() + +static const char Base64[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +static const char Pad64 = '='; + +/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt) + The following encoding technique is taken from RFC 1521 by Borenstein + and Freed. It is reproduced here in a slightly edited form for + convenience. + + A 65-character subset of US-ASCII is used, enabling 6 bits to be + represented per printable character. (The extra 65th character, "=", + is used to signify a special processing function.) + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8-bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + + Each 6-bit group is used as an index into an array of 64 printable + characters. The character referenced by the index is placed in the + output string. + + Table 1: The Base64 Alphabet + + Value Encoding Value Encoding Value Encoding Value Encoding + 0 A 17 R 34 i 51 z + 1 B 18 S 35 j 52 0 + 2 C 19 T 36 k 53 1 + 3 D 20 U 37 l 54 2 + 4 E 21 V 38 m 55 3 + 5 F 22 W 39 n 56 4 + 6 G 23 X 40 o 57 5 + 7 H 24 Y 41 p 58 6 + 8 I 25 Z 42 q 59 7 + 9 J 26 a 43 r 60 8 + 10 K 27 b 44 s 61 9 + 11 L 28 c 45 t 62 + + 12 M 29 d 46 u 63 / + 13 N 30 e 47 v + 14 O 31 f 48 w (pad) = + 15 P 32 g 49 x + 16 Q 33 h 50 y + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a quantity. When fewer than 24 input + bits are available in an input group, zero bits are added (on the + right) to form an integral number of 6-bit groups. Padding at the + end of the data is performed using the '=' character. + + Since all base64 input is an integral number of octets, only the + ------------------------------------------------- + following cases can arise: + + (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded + output will be an integral multiple of 4 characters + with no "=" padding, + (2) the final quantum of encoding input is exactly 8 bits; + here, the final unit of encoded output will be two + characters followed by two "=" padding characters, or + (3) the final quantum of encoding input is exactly 16 bits; + here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + +int +b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) { + size_t datalength = 0; + u_char input[3]; + u_char output[4]; + size_t i; + + while (2 < srclength) { + input[0] = *src++; + input[1] = *src++; + input[2] = *src++; + srclength -= 3; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + output[3] = input[2] & 0x3f; + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + Assert(output[3] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + target[datalength++] = Base64[output[2]]; + target[datalength++] = Base64[output[3]]; + } + + /* Now we worry about padding. */ + if (0 != srclength) { + /* Get what's left. */ + input[0] = input[1] = input[2] = '\0'; + for (i = 0; i < srclength; i++) + input[i] = *src++; + + output[0] = input[0] >> 2; + output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4); + output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6); + Assert(output[0] < 64); + Assert(output[1] < 64); + Assert(output[2] < 64); + + if (datalength + 4 > targsize) + return (-1); + target[datalength++] = Base64[output[0]]; + target[datalength++] = Base64[output[1]]; + if (srclength == 1) + target[datalength++] = Pad64; + else + target[datalength++] = Base64[output[2]]; + target[datalength++] = Pad64; + } + if (datalength >= targsize) + return (-1); + target[datalength] = '\0'; /* Returned value doesn't count \0. */ + return (datalength); +} +libresolv_hidden_def (b64_ntop) + +/* skips all whitespace anywhere. + converts characters, four at a time, starting at (or after) + src from base - 64 numbers into three 8 bit bytes in the target area. + it returns the number of data bytes stored at the target, or -1 on error. + */ + +int +b64_pton (char const *src, u_char *target, size_t targsize) +{ + int tarindex, state, ch; + char *pos; + + state = 0; + tarindex = 0; + + while ((ch = *src++) != '\0') { + if (isspace(ch)) /* Skip whitespace anywhere. */ + continue; + + if (ch == Pad64) + break; + + pos = strchr(Base64, ch); + if (pos == 0) /* A non-base64 character. */ + return (-1); + + switch (state) { + case 0: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] = (pos - Base64) << 2; + } + state = 1; + break; + case 1: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 4; + target[tarindex+1] = ((pos - Base64) & 0x0f) + << 4 ; + } + tarindex++; + state = 2; + break; + case 2: + if (target) { + if ((size_t)tarindex + 1 >= targsize) + return (-1); + target[tarindex] |= (pos - Base64) >> 2; + target[tarindex+1] = ((pos - Base64) & 0x03) + << 6; + } + tarindex++; + state = 3; + break; + case 3: + if (target) { + if ((size_t)tarindex >= targsize) + return (-1); + target[tarindex] |= (pos - Base64); + } + tarindex++; + state = 0; + break; + default: + abort(); + } + } + + /* + * We are done decoding Base-64 chars. Let's see if we ended + * on a byte boundary, and/or with erroneous trailing characters. + */ + + if (ch == Pad64) { /* We got a pad char. */ + ch = *src++; /* Skip it, get next. */ + switch (state) { + case 0: /* Invalid = in first position */ + case 1: /* Invalid = in second position */ + return (-1); + + case 2: /* Valid, means one byte of info */ + /* Skip any number of spaces. */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace(ch)) + break; + /* Make sure there is another trailing = sign. */ + if (ch != Pad64) + return (-1); + ch = *src++; /* Skip the = */ + /* Fall through to "single trailing =" case. */ + /* FALLTHROUGH */ + + case 3: /* Valid, means two bytes of info */ + /* + * We know this char is an =. Is there anything but + * whitespace after it? + */ + for ((void)NULL; ch != '\0'; ch = *src++) + if (!isspace(ch)) + return (-1); + + /* + * Now make sure for cases 2 and 3 that the "extra" + * bits that slopped past the last full byte were + * zeros. If we don't check them, they become a + * subliminal channel. + */ + if (target && target[tarindex] != 0) + return (-1); + } + } else { + /* + * We ended by seeing the end of the string. Make sure we + * have no partial bytes lying around. + */ + if (state != 0) + return (-1); + } + + return (tarindex); +} diff --git a/REORG.TODO/resolv/bits/types/res_state.h b/REORG.TODO/resolv/bits/types/res_state.h new file mode 100644 index 0000000000..cee4b6ddd0 --- /dev/null +++ b/REORG.TODO/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 initstamp + __attribute__((packed)); +#else + unsigned int _initstamp[2]; +#endif + } _ext; + } _u; +}; + +typedef struct __res_state *res_state; + +#endif /* __res_state_defined */ diff --git a/REORG.TODO/resolv/compat-gethnamaddr.c b/REORG.TODO/resolv/compat-gethnamaddr.c new file mode 100644 index 0000000000..813c7d4e85 --- /dev/null +++ b/REORG.TODO/resolv/compat-gethnamaddr.c @@ -0,0 +1,903 @@ +/* + * ++Copyright++ 1985, 1988, 1993 + * - + * Copyright (c) 1985, 1988, 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. + * - + * --Copyright-- + */ + +/* XXX This file is not used by any of the resolver functions implemented by + glibc (i.e. get*info and gethostby*). It cannot be removed however because + it exports symbols in the libresolv ABI. The file is not maintained any + more, nor are these functions. */ + +#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 <ctype.h> +# include <errno.h> +# include <stdlib.h> +# include <string.h> + +# define MAXALIASES 35 +# define MAXADDRS 35 + +static char *h_addr_ptrs[MAXADDRS + 1]; + +static struct hostent host; +static char *host_aliases[MAXALIASES]; +static char hostbuf[8*1024]; +static u_char host_addr[16]; /* IPv4 or IPv6 */ +static FILE *hostf = NULL; +static int stayopen = 0; + +static void map_v4v6_address (const char *src, char *dst) __THROW; +static void map_v4v6_hostent (struct hostent *hp, char **bp, int *len) __THROW; + +extern void addrsort (char **, int) __THROW; + +# 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 + +typedef union { + HEADER hdr; + u_char buf[MAXPACKET]; +} querybuf; + +typedef union { + int32_t al; + char ac; +} align; + +# ifndef h_errno +extern int h_errno; +# endif + +# ifdef DEBUG +static void +Dprintf (char *msg, int num) +{ + if (_res.options & RES_DEBUG) { + int save = errno; + + printf(msg, num); + __set_errno (save); + } +} +# else +# define Dprintf(msg, num) /*nada*/ +# endif + +# define BOUNDED_INCR(x) \ + do { \ + cp += x; \ + if (cp > eom) { \ + __set_h_errno (NO_RECOVERY); \ + return (NULL); \ + } \ + } while (0) + +# define BOUNDS_CHECK(ptr, count) \ + do { \ + if ((ptr) + (count) > eom) { \ + __set_h_errno (NO_RECOVERY); \ + return (NULL); \ + } \ + } while (0) + + +static struct hostent * +getanswer (const querybuf *answer, int anslen, const char *qname, int qtype) +{ + const HEADER *hp; + const u_char *cp; + int n; + const u_char *eom, *erdata; + char *bp, **ap, **hap; + int type, class, buflen, ancount, qdcount; + int haveanswer, had_error; + int toobig = 0; + char tbuf[MAXDNAME]; + const char *tname; + int (*name_ok) (const char *); + + tname = qname; + host.h_name = NULL; + eom = answer->buf + anslen; + switch (qtype) { + case T_A: + case T_AAAA: + name_ok = res_hnok; + break; + case T_PTR: + name_ok = res_dnok; + break; + default: + return (NULL); /* XXX should be abort(); */ + } + /* + * find first satisfactory answer + */ + hp = &answer->hdr; + ancount = ntohs(hp->ancount); + qdcount = ntohs(hp->qdcount); + bp = hostbuf; + buflen = sizeof hostbuf; + cp = answer->buf; + BOUNDED_INCR(HFIXEDSZ); + if (qdcount != 1) { + __set_h_errno (NO_RECOVERY); + return (NULL); + } + n = dn_expand(answer->buf, eom, cp, bp, buflen); + if ((n < 0) || !(*name_ok)(bp)) { + __set_h_errno (NO_RECOVERY); + return (NULL); + } + BOUNDED_INCR(n + QFIXEDSZ); + if (qtype == T_A || qtype == T_AAAA) { + /* res_send() has already verified that the query name is the + * same as the one we sent; this just gets the expanded name + * (i.e., with the succeeding search-domain tacked on). + */ + n = strlen(bp) + 1; /* for the \0 */ + if (n >= MAXHOSTNAMELEN) { + __set_h_errno (NO_RECOVERY); + return (NULL); + } + host.h_name = bp; + bp += n; + buflen -= n; + /* The qname can be abbreviated, but h_name is now absolute. */ + qname = host.h_name; + } + ap = host_aliases; + *ap = NULL; + host.h_aliases = host_aliases; + hap = h_addr_ptrs; + *hap = NULL; + host.h_addr_list = h_addr_ptrs; + haveanswer = 0; + had_error = 0; + while (ancount-- > 0 && cp < eom && !had_error) { + n = dn_expand(answer->buf, eom, cp, bp, buflen); + if ((n < 0) || !(*name_ok)(bp)) { + had_error++; + continue; + } + cp += n; /* name */ + BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ); + type = ns_get16(cp); + cp += INT16SZ; /* type */ + class = ns_get16(cp); + cp += INT16SZ + INT32SZ; /* class, TTL */ + n = ns_get16(cp); + cp += INT16SZ; /* len */ + BOUNDS_CHECK(cp, n); + erdata = cp + n; + if (class != C_IN) { + /* XXX - debug? syslog? */ + cp += n; + continue; /* XXX - had_error++ ? */ + } + if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) { + if (ap >= &host_aliases[MAXALIASES-1]) + continue; + n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); + if ((n < 0) || !(*name_ok)(tbuf)) { + had_error++; + continue; + } + cp += n; + if (cp != erdata) { + __set_h_errno (NO_RECOVERY); + return (NULL); + } + /* Store alias. */ + *ap++ = bp; + n = strlen(bp) + 1; /* for the \0 */ + if (n >= MAXHOSTNAMELEN) { + had_error++; + continue; + } + bp += n; + buflen -= n; + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > buflen || n >= MAXHOSTNAMELEN) { + had_error++; + continue; + } + strcpy(bp, tbuf); + host.h_name = bp; + bp += n; + buflen -= n; + continue; + } + if (qtype == T_PTR && type == T_CNAME) { + n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf); + if (n < 0 || !res_dnok(tbuf)) { + had_error++; + continue; + } + cp += n; + if (cp != erdata) { + __set_h_errno (NO_RECOVERY); + return (NULL); + } + /* Get canonical name. */ + n = strlen(tbuf) + 1; /* for the \0 */ + if (n > buflen || n >= MAXHOSTNAMELEN) { + had_error++; + continue; + } + strcpy(bp, tbuf); + tname = bp; + bp += n; + buflen -= n; + continue; + } + if (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. + */ + cp += n; + continue; /* XXX - had_error++ ? */ + } + switch (type) { + case T_PTR: + if (strcasecmp(tname, bp) != 0) { + cp += n; + continue; /* XXX - had_error++ ? */ + } + n = dn_expand(answer->buf, eom, cp, bp, buflen); + if ((n < 0) || !res_hnok(bp)) { + had_error++; + break; + } + cp += n; + if (cp != erdata) { + __set_h_errno (NO_RECOVERY); + return (NULL); + } + if (!haveanswer) + host.h_name = bp; + else if (ap < &host_aliases[MAXALIASES-1]) + *ap++ = bp; + else + n = -1; + if (n != -1) { + n = strlen(bp) + 1; /* for the \0 */ + if (n >= MAXHOSTNAMELEN) { + had_error++; + break; + } + bp += n; + buflen -= n; + } + break; + case T_A: + case T_AAAA: + if (strcasecmp(host.h_name, bp) != 0) { + cp += n; + continue; /* XXX - had_error++ ? */ + } + if (n != host.h_length) { + cp += n; + continue; + } + if (!haveanswer) { + int nn; + + host.h_name = bp; + nn = strlen(bp) + 1; /* for the \0 */ + bp += nn; + buflen -= nn; + } + + /* XXX: when incrementing bp, we have to decrement + * buflen by the same amount --okir */ + buflen -= sizeof(align) - ((u_long)bp % sizeof(align)); + + bp += sizeof(align) - ((u_long)bp % sizeof(align)); + + if (bp + n >= &hostbuf[sizeof hostbuf]) { + Dprintf("size (%d) too big\n", n); + had_error++; + continue; + } + if (hap >= &h_addr_ptrs[MAXADDRS-1]) { + if (!toobig++) { + Dprintf("Too many addresses (%d)\n", + MAXADDRS); + } + cp += n; + continue; + } + memmove(*hap++ = bp, cp, n); + bp += n; + buflen -= n; + cp += n; + if (cp != erdata) { + __set_h_errno (NO_RECOVERY); + return (NULL); + } + break; + default: + abort(); + } + if (!had_error) + haveanswer++; + } + if (haveanswer) { + *ap = NULL; + *hap = NULL; + /* + * 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(h_addr_ptrs, haveanswer); + if (!host.h_name) { + n = strlen(qname) + 1; /* for the \0 */ + if (n > buflen || n >= MAXHOSTNAMELEN) + goto no_recovery; + strcpy(bp, qname); + host.h_name = bp; + bp += n; + buflen -= n; + } + if (res_use_inet6 ()) + map_v4v6_hostent(&host, &bp, &buflen); + __set_h_errno (NETDB_SUCCESS); + return (&host); + } + no_recovery: + __set_h_errno (NO_RECOVERY); + return (NULL); +} + +extern struct hostent *res_gethostbyname2(const char *name, int af); +libresolv_hidden_proto (res_gethostbyname2) + +struct hostent * +res_gethostbyname (const char *name) +{ + struct hostent *hp; + + if (__res_maybe_init (&_res, 0) == -1) { + __set_h_errno (NETDB_INTERNAL); + return (NULL); + } + if (res_use_inet6 ()) { + hp = res_gethostbyname2(name, AF_INET6); + if (hp) + return (hp); + } + return (res_gethostbyname2(name, AF_INET)); +} +compat_symbol (libresolv, res_gethostbyname, res_gethostbyname, GLIBC_2_0); + +struct hostent * +res_gethostbyname2 (const char *name, int af) +{ + union + { + querybuf *buf; + u_char *ptr; + } buf; + querybuf *origbuf; + const char *cp; + char *bp; + 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; + type = T_A; + break; + case AF_INET6: + size = IN6ADDRSZ; + type = T_AAAA; + break; + default: + __set_h_errno (NETDB_INTERNAL); + __set_errno (EAFNOSUPPORT); + return (NULL); + } + + host.h_addrtype = af; + host.h_length = size; + + /* + * if there aren't any dots, it could be a user-level alias. + * 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; + + /* + * disallow names consisting only of digits/dots, unless + * they end in a dot. + */ + if (isdigit(name[0])) + for (cp = name;; ++cp) { + if (!*cp) { + if (*--cp == '.') + break; + /* + * All-numeric, no dot at the end. + * Fake up a hostent as if we'd actually + * done a lookup. + */ + if (inet_pton(af, name, host_addr) <= 0) { + __set_h_errno (HOST_NOT_FOUND); + return (NULL); + } + strncpy(hostbuf, name, MAXDNAME); + hostbuf[MAXDNAME] = '\0'; + bp = hostbuf + MAXDNAME; + len = sizeof hostbuf - MAXDNAME; + host.h_name = hostbuf; + host.h_aliases = host_aliases; + host_aliases[0] = NULL; + h_addr_ptrs[0] = (char *)host_addr; + h_addr_ptrs[1] = NULL; + host.h_addr_list = h_addr_ptrs; + if (res_use_inet6 ()) + map_v4v6_hostent(&host, &bp, &len); + __set_h_errno (NETDB_SUCCESS); + return (&host); + } + if (!isdigit(*cp) && *cp != '.') + break; + } + if ((isxdigit(name[0]) && strchr(name, ':') != NULL) || + name[0] == ':') + for (cp = name;; ++cp) { + if (!*cp) { + if (*--cp == '.') + break; + /* + * All-IPv6-legal, no dot at the end. + * Fake up a hostent as if we'd actually + * done a lookup. + */ + if (inet_pton(af, name, host_addr) <= 0) { + __set_h_errno (HOST_NOT_FOUND); + return (NULL); + } + strncpy(hostbuf, name, MAXDNAME); + hostbuf[MAXDNAME] = '\0'; + bp = hostbuf + MAXDNAME; + len = sizeof hostbuf - MAXDNAME; + host.h_name = hostbuf; + host.h_aliases = host_aliases; + host_aliases[0] = NULL; + h_addr_ptrs[0] = (char *)host_addr; + h_addr_ptrs[1] = NULL; + host.h_addr_list = h_addr_ptrs; + __set_h_errno (NETDB_SUCCESS); + return (&host); + } + if (!isxdigit(*cp) && *cp != ':' && *cp != '.') + break; + } + + 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 (buf.buf != origbuf) + free (buf.buf); + Dprintf("res_nsearch failed (%d)\n", n); + if (errno == ECONNREFUSED) + return (_gethtbyname2(name, af)); + return (NULL); + } + ret = getanswer(buf.buf, n, name, type); + if (buf.buf != origbuf) + free (buf.buf); + return ret; +} +libresolv_hidden_def (res_gethostbyname2) +compat_symbol (libresolv, res_gethostbyname2, res_gethostbyname2, GLIBC_2_0); + +struct hostent * +res_gethostbyaddr (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 }; + static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; + int n; + socklen_t size; + union + { + querybuf *buf; + u_char *ptr; + } buf; + querybuf *orig_buf; + struct hostent *hp; + char qbuf[MAXDNAME+1], *qp = NULL; + + 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))) { + /* Unmap. */ + addr += sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + switch (af) { + case AF_INET: + size = INADDRSZ; + break; + case AF_INET6: + size = IN6ADDRSZ; + break; + default: + __set_errno (EAFNOSUPPORT); + __set_h_errno (NETDB_INTERNAL); + return (NULL); + } + if (size != len) { + __set_errno (EINVAL); + __set_h_errno (NETDB_INTERNAL); + return (NULL); + } + switch (af) { + case AF_INET: + (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", + (uaddr[3] & 0xff), + (uaddr[2] & 0xff), + (uaddr[1] & 0xff), + (uaddr[0] & 0xff)); + break; + case AF_INET6: + qp = qbuf; + for (n = IN6ADDRSZ - 1; n >= 0; n--) { + qp += sprintf(qp, "%x.%x.", + uaddr[n] & 0xf, + (uaddr[n] >> 4) & 0xf); + } + strcpy(qp, "ip6.arpa"); + break; + default: + abort(); + } + + 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) { + if (buf.buf != orig_buf) + free (buf.buf); + Dprintf("res_nquery failed (%d)\n", n); + if (errno == ECONNREFUSED) + return (_gethtbyaddr(addr, len, af)); + return (NULL); + } + hp = getanswer(buf.buf, n, qbuf, T_PTR); + if (buf.buf != orig_buf) + free (buf.buf); + if (!hp) + return (NULL); /* h_errno was set by getanswer() */ + 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_use_inet6 ()) { + map_v4v6_address((char*)host_addr, (char*)host_addr); + hp->h_addrtype = AF_INET6; + hp->h_length = IN6ADDRSZ; + } + __set_h_errno (NETDB_SUCCESS); + return (hp); +} +compat_symbol (libresolv, res_gethostbyaddr, res_gethostbyaddr, GLIBC_2_0); + +void +_sethtent (int f) +{ + if (!hostf) + hostf = fopen(_PATH_HOSTS, "rce" ); + else + rewind(hostf); + stayopen = f; +} +libresolv_hidden_def (_sethtent) +compat_symbol (libresolv, _sethtent, _sethtent, GLIBC_2_0); + +static void +_endhtent (void) +{ + if (hostf && !stayopen) { + (void) fclose(hostf); + hostf = NULL; + } +} + +struct hostent * +_gethtent (void) +{ + char *p; + char *cp, **q; + int af, len; + + if (!hostf && !(hostf = fopen(_PATH_HOSTS, "rce" ))) { + __set_h_errno (NETDB_INTERNAL); + return (NULL); + } + again: + if (!(p = fgets(hostbuf, sizeof hostbuf, hostf))) { + __set_h_errno (HOST_NOT_FOUND); + return (NULL); + } + if (*p == '#') + goto again; + if (!(cp = strpbrk(p, "#\n"))) + goto again; + *cp = '\0'; + if (!(cp = strpbrk(p, " \t"))) + goto again; + *cp++ = '\0'; + if (inet_pton(AF_INET6, p, host_addr) > 0) { + af = AF_INET6; + len = IN6ADDRSZ; + } else if (inet_pton(AF_INET, p, host_addr) > 0) { + if (res_use_inet6 ()) { + map_v4v6_address((char*)host_addr, (char*)host_addr); + af = AF_INET6; + len = IN6ADDRSZ; + } else { + af = AF_INET; + len = INADDRSZ; + } + } else { + goto again; + } + h_addr_ptrs[0] = (char *)host_addr; + h_addr_ptrs[1] = NULL; + host.h_addr_list = h_addr_ptrs; + host.h_length = len; + host.h_addrtype = af; + while (*cp == ' ' || *cp == '\t') + cp++; + host.h_name = cp; + q = host.h_aliases = host_aliases; + if ((cp = strpbrk(cp, " \t"))) + *cp++ = '\0'; + while (cp && *cp) { + if (*cp == ' ' || *cp == '\t') { + cp++; + continue; + } + if (q < &host_aliases[MAXALIASES - 1]) + *q++ = cp; + if ((cp = strpbrk(cp, " \t"))) + *cp++ = '\0'; + } + *q = NULL; + __set_h_errno (NETDB_SUCCESS); + 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_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) +{ + struct hostent *p; + char **cp; + + _sethtent(0); + while ((p = _gethtent())) { + if (p->h_addrtype != af) + continue; + if (strcasecmp(p->h_name, name) == 0) + break; + for (cp = p->h_aliases; *cp != 0; cp++) + if (strcasecmp(*cp, name) == 0) + goto found; + } + found: + _endhtent(); + 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) +{ + struct hostent *p; + + _sethtent(0); + while ((p = _gethtent())) + if (p->h_addrtype == af && !memcmp(p->h_addr, addr, len)) + break; + _endhtent(); + return (p); +} +libresolv_hidden_def (_gethtbyaddr) +compat_symbol (libresolv, _gethtbyaddr, _gethtbyaddr, GLIBC_2_0); + +static void +map_v4v6_address (const char *src, char *dst) +{ + u_char *p = (u_char *)dst; + char tmp[INADDRSZ]; + int i; + + /* Stash a temporary copy so our caller can update in place. */ + memcpy(tmp, src, INADDRSZ); + /* Mark this ipv6 addr as a mapped ipv4. */ + for (i = 0; i < 10; i++) + *p++ = 0x00; + *p++ = 0xff; + *p++ = 0xff; + /* Retrieve the saved copy and we're done. */ + memcpy((void*)p, tmp, INADDRSZ); +} + +static void +map_v4v6_hostent (struct hostent *hp, char **bpp, int *lenp) +{ + char **ap; + + if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) + return; + hp->h_addrtype = AF_INET6; + hp->h_length = IN6ADDRSZ; + for (ap = hp->h_addr_list; *ap; ap++) { + int i = sizeof(align) - ((u_long)*bpp % sizeof(align)); + + if (*lenp < (i + IN6ADDRSZ)) { + /* Out of memory. Truncate address list here. XXX */ + *ap = NULL; + return; + } + *bpp += i; + *lenp -= i; + map_v4v6_address(*ap, *bpp); + *ap = *bpp; + *bpp += IN6ADDRSZ; + *lenp -= IN6ADDRSZ; + } +} + +extern void +addrsort (char **ap, int num) +{ + int i, j; + char **p; + short aval[MAXADDRS]; + int needsort = 0; + + p = ap; + 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; + aval[i] = j; + if (needsort == 0 && i > 0 && j < aval[i-1]) + needsort = i; + } + if (!needsort) + return; + + while (needsort < num) { + for (j = needsort - 1; j >= 0; j--) { + if (aval[j] > aval[j+1]) { + char *hp; + + i = aval[j]; + aval[j] = aval[j+1]; + aval[j+1] = i; + + hp = ap[j]; + ap[j] = ap[j+1]; + ap[j+1] = hp; + + } else + break; + } + needsort++; + } +} + +#endif /* SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_25) */ diff --git a/REORG.TODO/resolv/compat-hooks.c b/REORG.TODO/resolv/compat-hooks.c new file mode 100644 index 0000000000..e36a370f04 --- /dev/null +++ b/REORG.TODO/resolv/compat-hooks.c @@ -0,0 +1,56 @@ +/* Compatibility functions for obsolete libresolv hooks. + Copyright (C) 1999-2017 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/REORG.TODO/resolv/ga_test.c b/REORG.TODO/resolv/ga_test.c new file mode 100644 index 0000000000..673162f015 --- /dev/null +++ b/REORG.TODO/resolv/ga_test.c @@ -0,0 +1,99 @@ +#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/REORG.TODO/resolv/gai_cancel.c b/REORG.TODO/resolv/gai_cancel.c new file mode 100644 index 0000000000..4409327ed7 --- /dev/null +++ b/REORG.TODO/resolv/gai_cancel.c @@ -0,0 +1,47 @@ +/* Copyright (C) 2001-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + + 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 <pthread.h> + +#include <gai_misc.h> + + +int +gai_cancel (struct gaicb *gaicbp) +{ + int result = 0; + int status; + + /* Request the mutex. */ + pthread_mutex_lock (&__gai_requests_mutex); + + /* Find the request among those queued but not yet running. */ + status = __gai_remove_request (gaicbp); + if (status == 0) + result = EAI_CANCELED; + else if (status > 0) + result = EAI_NOTCANCELED; + else + result = EAI_ALLDONE; + + /* Release the mutex. */ + pthread_mutex_unlock (&__gai_requests_mutex); + + return result; +} diff --git a/REORG.TODO/resolv/gai_error.c b/REORG.TODO/resolv/gai_error.c new file mode 100644 index 0000000000..32b0620474 --- /dev/null +++ b/REORG.TODO/resolv/gai_error.c @@ -0,0 +1,27 @@ +/* Copyright (C) 2001-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + + 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 <gai_misc.h> + +int +gai_error (struct gaicb *req) +{ + return req->__return; +} diff --git a/REORG.TODO/resolv/gai_misc.c b/REORG.TODO/resolv/gai_misc.c new file mode 100644 index 0000000000..fd9aa356be --- /dev/null +++ b/REORG.TODO/resolv/gai_misc.c @@ -0,0 +1,436 @@ +/* Copyright (C) 2001-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + + 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 <assert.h> +#include <errno.h> +#include <pthread.h> +#include <stdlib.h> +#include <sys/time.h> + +#include <gai_misc.h> + + + +#ifndef gai_create_helper_thread +# define gai_create_helper_thread __gai_create_helper_thread + +extern inline int +__gai_create_helper_thread (pthread_t *threadp, void *(*tf) (void *), + void *arg) +{ + pthread_attr_t attr; + + /* Make sure the thread is created detached. */ + pthread_attr_init (&attr); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + + int ret = pthread_create (threadp, &attr, tf, arg); + + (void) pthread_attr_destroy (&attr); + return ret; +} +#endif + + +/* Pool of request list entries. */ +static struct requestlist **pool; + +/* Number of total and allocated pool entries. */ +static size_t pool_max_size; +static size_t pool_size; + +/* We implement a two dimensional array but allocate each row separately. + The macro below determines how many entries should be used per row. + It should better be a power of two. */ +#define ENTRIES_PER_ROW 32 + +/* How many rows we allocate at once. */ +#define ROWS_STEP 8 + +/* List of available entries. */ +static struct requestlist *freelist; + +/* Structure list of all currently processed requests. */ +static struct requestlist *requests; +static struct requestlist *requests_tail; + +/* Number of threads currently running. */ +static int nthreads; + +/* Number of threads waiting for work to arrive. */ +static int idle_thread_count; + + +/* These are the values used for optimization. We will probably + create a funcion to set these values. */ +static struct gaiinit optim = +{ + 20, /* int gai_threads; Maximal number of threads. */ + 64, /* int gai_num; Number of expected simultanious requests. */ + 0, + 0, + 0, + 0, + 1, + 0 +}; + + +/* Since the list is global we need a mutex protecting it. */ +pthread_mutex_t __gai_requests_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; + +/* When you add a request to the list and there are idle threads present, + you signal this condition variable. When a thread finishes work, it waits + on this condition variable for a time before it actually exits. */ +pthread_cond_t __gai_new_request_notification = PTHREAD_COND_INITIALIZER; + + +/* Functions to handle request list pool. */ +static struct requestlist * +get_elem (void) +{ + struct requestlist *result; + + if (freelist == NULL) + { + struct requestlist *new_row; + int cnt; + + if (pool_size + 1 >= pool_max_size) + { + size_t new_max_size = pool_max_size + ROWS_STEP; + struct requestlist **new_tab; + + new_tab = (struct requestlist **) + realloc (pool, new_max_size * sizeof (struct requestlist *)); + + if (new_tab == NULL) + return NULL; + + pool_max_size = new_max_size; + pool = new_tab; + } + + /* Allocate the new row. */ + cnt = pool_size == 0 ? optim.gai_num : ENTRIES_PER_ROW; + new_row = (struct requestlist *) calloc (cnt, + sizeof (struct requestlist)); + if (new_row == NULL) + return NULL; + + pool[pool_size++] = new_row; + + /* Put all the new entries in the freelist. */ + do + { + new_row->next = freelist; + freelist = new_row++; + } + while (--cnt > 0); + } + + result = freelist; + freelist = freelist->next; + + return result; +} + + +struct requestlist * +internal_function +__gai_find_request (const struct gaicb *gaicbp) +{ + struct requestlist *runp; + + runp = requests; + while (runp != NULL) + if (runp->gaicbp == gaicbp) + return runp; + else + runp = runp->next; + + return NULL; +} + + +int +internal_function +__gai_remove_request (struct gaicb *gaicbp) +{ + struct requestlist *runp; + struct requestlist *lastp; + + runp = requests; + lastp = NULL; + while (runp != NULL) + if (runp->gaicbp == gaicbp) + break; + else + { + lastp = runp; + runp = runp->next; + } + + if (runp == NULL) + /* Not known. */ + return -1; + if (runp->running != 0) + /* Currently handled. */ + return 1; + + /* Dequeue the request. */ + if (lastp == NULL) + requests = runp->next; + else + lastp->next = runp->next; + if (runp == requests_tail) + requests_tail = lastp; + + return 0; +} + + +/* The thread handler. */ +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; + struct requestlist *lastp; + + /* Get the mutex. */ + pthread_mutex_lock (&__gai_requests_mutex); + + /* Get a new element for the waiting list. */ + newp = get_elem (); + if (newp == NULL) + { + pthread_mutex_unlock (&__gai_requests_mutex); + __set_errno (EAGAIN); + return NULL; + } + newp->running = 0; + newp->gaicbp = gaicbp; + newp->waiting = NULL; + newp->next = NULL; + + lastp = requests_tail; + if (requests_tail == NULL) + requests = requests_tail = newp; + else + { + requests_tail->next = newp; + requests_tail = newp; + } + + gaicbp->__return = EAI_INPROGRESS; + + /* See if we need to and are able to create a thread. */ + if (nthreads < optim.gai_threads && idle_thread_count == 0) + { + pthread_t thid; + + newp->running = 1; + + /* Now try to start a thread. */ + if (gai_create_helper_thread (&thid, handle_requests, newp) == 0) + /* We managed to enqueue the request. All errors which can + happen now can be recognized by calls to `gai_error'. */ + ++nthreads; + else + { + if (nthreads == 0) + { + /* We cannot create a thread in the moment and there is + also no thread running. This is a problem. `errno' is + set to EAGAIN if this is only a temporary problem. */ + assert (lastp->next == newp); + lastp->next = NULL; + requests_tail = lastp; + + newp->next = freelist; + freelist = newp; + + newp = NULL; + } + else + /* We are not handling the request after all. */ + newp->running = 0; + } + } + + /* Enqueue the request in the request queue. */ + if (newp != NULL) + { + /* If there is a thread waiting for work, then let it know that we + have just given it something to do. */ + if (idle_thread_count > 0) + pthread_cond_signal (&__gai_new_request_notification); + } + + /* Release the mutex. */ + pthread_mutex_unlock (&__gai_requests_mutex); + + return newp; +} + + +static void * +__attribute__ ((noreturn)) +handle_requests (void *arg) +{ + struct requestlist *runp = (struct requestlist *) arg; + + do + { + /* If runp is NULL, then we were created to service the work queue + in general, not to handle any particular request. In that case we + skip the "do work" stuff on the first pass, and go directly to the + "get work off the work queue" part of this loop, which is near the + end. */ + if (runp == NULL) + pthread_mutex_lock (&__gai_requests_mutex); + else + { + /* Make the request. */ + struct gaicb *req = runp->gaicbp; + struct requestlist *srchp; + struct requestlist *lastp; + + req->__return = getaddrinfo (req->ar_name, req->ar_service, + req->ar_request, &req->ar_result); + + /* Get the mutex. */ + pthread_mutex_lock (&__gai_requests_mutex); + + /* Send the signal to notify about finished processing of the + request. */ + __gai_notify (runp); + + /* Now dequeue the current request. */ + lastp = NULL; + srchp = requests; + while (srchp != runp) + { + lastp = srchp; + srchp = srchp->next; + } + assert (runp->running == 1); + + if (requests_tail == runp) + requests_tail = lastp; + if (lastp == NULL) + requests = requests->next; + else + lastp->next = runp->next; + + /* Free the old element. */ + runp->next = freelist; + freelist = runp; + } + + runp = requests; + while (runp != NULL && runp->running != 0) + runp = runp->next; + + /* If the runlist is empty, then we sleep for a while, waiting for + something to arrive in it. */ + if (runp == NULL && optim.gai_idle_time >= 0) + { + struct timeval now; + struct timespec wakeup_time; + + ++idle_thread_count; + gettimeofday (&now, NULL); + wakeup_time.tv_sec = now.tv_sec + optim.gai_idle_time; + wakeup_time.tv_nsec = now.tv_usec * 1000; + if (wakeup_time.tv_nsec >= 1000000000) + { + wakeup_time.tv_nsec -= 1000000000; + ++wakeup_time.tv_sec; + } + pthread_cond_timedwait (&__gai_new_request_notification, + &__gai_requests_mutex, &wakeup_time); + --idle_thread_count; + runp = requests; + while (runp != NULL && runp->running != 0) + runp = runp->next; + } + + if (runp == NULL) + --nthreads; + else + { + /* Mark the request as being worked on. */ + assert (runp->running == 0); + runp->running = 1; + + /* If we have a request to process, and there's still another in + the run list, then we need to either wake up or create a new + thread to service the request that is still in the run list. */ + if (requests != NULL) + { + /* There are at least two items in the work queue to work on. + If there are other idle threads, then we should wake them + up for these other work elements; otherwise, we should try + to create a new thread. */ + if (idle_thread_count > 0) + pthread_cond_signal (&__gai_new_request_notification); + else if (nthreads < optim.gai_threads) + { + pthread_t thid; + pthread_attr_t attr; + + /* Make sure the thread is created detached. */ + pthread_attr_init (&attr); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + + /* Now try to start a thread. If we fail, no big deal, + because we know that there is at least one thread (us) + that is working on lookup operations. */ + if (pthread_create (&thid, &attr, handle_requests, NULL) + == 0) + ++nthreads; + } + } + } + + /* Release the mutex. */ + pthread_mutex_unlock (&__gai_requests_mutex); + } + while (runp != NULL); + + pthread_exit (NULL); +} + + +/* Free allocated resources. */ +libc_freeres_fn (free_res) +{ + size_t row; + + for (row = 0; row < pool_max_size; ++row) + free (pool[row]); + + free (pool); +} diff --git a/REORG.TODO/resolv/gai_misc.h b/REORG.TODO/resolv/gai_misc.h new file mode 100644 index 0000000000..6679d2b7d5 --- /dev/null +++ b/REORG.TODO/resolv/gai_misc.h @@ -0,0 +1,101 @@ +/* Copyright (C) 2001-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + + 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 _GAI_MISC_H +#define _GAI_MISC_H 1 + +#include <netdb.h> +#include <signal.h> + + +/* Used to synchronize. */ +struct waitlist + { + struct waitlist *next; + +#ifndef DONT_NEED_GAI_MISC_COND + pthread_cond_t *cond; +#endif + volatile unsigned int *counterp; + /* The next field is used in asynchronous `lio_listio' operations. */ + struct sigevent *sigevp; + /* XXX See requestlist, it's used to work around the broken signal + handling in Linux. */ + pid_t caller_pid; + }; + + +/* Used to queue requests.. */ +struct requestlist + { + int running; + + struct requestlist *next; + + /* Pointer to the actual data. */ + struct gaicb *gaicbp; + + /* List of waiting processes. */ + struct waitlist *waiting; + }; + +/* To customize the implementation one can use the following struct. + This implementation follows the one in Irix. */ +struct gaiinit + { + int gai_threads; /* Maximal number of threads. */ + int gai_num; /* Number of expected simultanious requests. */ + int gai_locks; /* Not used. */ + int gai_usedba; /* Not used. */ + int gai_debug; /* Not used. */ + int gai_numusers; /* Not used. */ + int gai_idle_time; /* Number of seconds before idle thread + terminates. */ + int gai_reserved; + }; + + +/* Lock for global I/O list of requests. */ +extern pthread_mutex_t __gai_requests_mutex; + + +/* Enqueue request. */ +extern struct requestlist *__gai_enqueue_request (struct gaicb *gaicbp) + internal_function; + +/* Find request on wait list. */ +extern struct requestlist *__gai_find_request (const struct gaicb *gaicbp) + internal_function; + +/* Remove request from waitlist. */ +extern int __gai_remove_request (struct gaicb *gaicbp) + internal_function; + +/* Notify initiator of request and tell this everybody listening. */ +extern void __gai_notify (struct requestlist *req) + internal_function; + +/* Notify initiator of request. */ +extern int __gai_notify_only (struct sigevent *sigev, pid_t caller_pid) + internal_function; + +/* Send the signal. */ +extern int __gai_sigqueue (int sig, const union sigval val, pid_t caller_pid) + internal_function; + +#endif /* gai_misc.h */ diff --git a/REORG.TODO/resolv/gai_notify.c b/REORG.TODO/resolv/gai_notify.c new file mode 100644 index 0000000000..2056aee5e8 --- /dev/null +++ b/REORG.TODO/resolv/gai_notify.c @@ -0,0 +1,132 @@ +/* Copyright (C) 2001-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + + 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 <pthread.h> +#include <stdlib.h> +#include <gai_misc.h> + + +struct notify_func + { + void (*func) (sigval_t); + sigval_t value; + }; + +static void * +notify_func_wrapper (void *arg) +{ + gai_start_notify_thread (); + struct notify_func *const n = arg; + void (*func) (sigval_t) = n->func; + sigval_t value = n->value; + free (n); + (*func) (value); + return NULL; +} + + +int +internal_function +__gai_notify_only (struct sigevent *sigev, pid_t caller_pid) +{ + int result = 0; + + /* Send the signal to notify about finished processing of the request. */ + if (sigev->sigev_notify == SIGEV_THREAD) + { + /* We have to start a thread. */ + pthread_t tid; + pthread_attr_t attr, *pattr; + + pattr = (pthread_attr_t *) sigev->sigev_notify_attributes; + if (pattr == NULL) + { + pthread_attr_init (&attr); + pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED); + pattr = &attr; + } + + /* SIGEV may be freed as soon as we return, so we cannot let the + notification thread use that pointer. Even though a sigval_t is + only one word and the same size as a void *, we cannot just pass + the value through pthread_create as the argument and have the new + thread run the user's function directly, because on some machines + the calling convention for a union like sigval_t is different from + that for a pointer type like void *. */ + struct notify_func *nf = malloc (sizeof *nf); + if (nf == NULL) + result = -1; + else + { + nf->func = sigev->sigev_notify_function; + nf->value = sigev->sigev_value; + if (pthread_create (&tid, pattr, notify_func_wrapper, nf) < 0) + { + free (nf); + result = -1; + } + } + } + else if (sigev->sigev_notify == SIGEV_SIGNAL) + /* We have to send a signal. */ + if (__gai_sigqueue (sigev->sigev_signo, sigev->sigev_value, caller_pid) + < 0) + result = -1; + + return result; +} + + +void +internal_function +__gai_notify (struct requestlist *req) +{ + struct waitlist *waitlist; + + /* Now also notify possibly waiting threads. */ + waitlist = req->waiting; + while (waitlist != NULL) + { + struct waitlist *next = waitlist->next; + + if (waitlist->sigevp == NULL) + { +#ifdef DONT_NEED_GAI_MISC_COND + GAI_MISC_NOTIFY (waitlist); +#else + /* Decrement the counter. */ + --*waitlist->counterp; + + pthread_cond_signal (waitlist->cond); +#endif + } + else + /* This is part of an asynchronous `getaddrinfo_a' operation. If + this request is the last one, send the signal. */ + if (--*waitlist->counterp == 0) + { + __gai_notify_only (waitlist->sigevp, waitlist->caller_pid); + /* This is tricky. See getaddrinfo_a.c for the reason why + this works. */ + free ((void *) waitlist->counterp); + } + + waitlist = next; + } +} diff --git a/REORG.TODO/resolv/gai_sigqueue.c b/REORG.TODO/resolv/gai_sigqueue.c new file mode 100644 index 0000000000..ebc1e5ed46 --- /dev/null +++ b/REORG.TODO/resolv/gai_sigqueue.c @@ -0,0 +1,32 @@ +/* Copyright (C) 2001-2017 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 <aio.h> +#include <errno.h> +#include <signal.h> + +#include <gai_misc.h> + +int +internal_function +__gai_sigqueue (int sig, const union sigval val, pid_t caller_pid) +{ + __set_errno (ENOSYS); + return -1; +} + +stub_warning (__gai_sigqueue) diff --git a/REORG.TODO/resolv/gai_suspend.c b/REORG.TODO/resolv/gai_suspend.c new file mode 100644 index 0000000000..a86bd4360d --- /dev/null +++ b/REORG.TODO/resolv/gai_suspend.c @@ -0,0 +1,157 @@ +/* Copyright (C) 2001-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + + 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 <pthread.h> +#include <stdlib.h> +#include <sys/time.h> + +#include <gai_misc.h> + + +int +gai_suspend (const struct gaicb *const list[], int ent, + const struct timespec *timeout) +{ + struct waitlist waitlist[ent]; + struct requestlist *requestlist[ent]; +#ifndef DONT_NEED_GAI_MISC_COND + pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +#endif + int cnt; + unsigned int cntr = 1; + int none = 1; + int result; + + /* Request the mutex. */ + pthread_mutex_lock (&__gai_requests_mutex); + + /* There is not yet a finished request. Signal the request that + we are working for it. */ + for (cnt = 0; cnt < ent; ++cnt) + if (list[cnt] != NULL && list[cnt]->__return == EAI_INPROGRESS) + { + requestlist[cnt] = __gai_find_request (list[cnt]); + + if (requestlist[cnt] != NULL) + { +#ifndef DONT_NEED_GAI_MISC_COND + waitlist[cnt].cond = &cond; +#endif + waitlist[cnt].next = requestlist[cnt]->waiting; + waitlist[cnt].counterp = &cntr; + waitlist[cnt].sigevp = NULL; + waitlist[cnt].caller_pid = 0; /* Not needed. */ + requestlist[cnt]->waiting = &waitlist[cnt]; + none = 0; + } + } + + if (none) + { + if (cnt < ent) + /* There is an entry which is finished. */ + result = 0; + else + result = EAI_ALLDONE; + } + else + { + /* There is no request done but some are still being worked on. */ + int oldstate; + + /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancelation + points we must be careful. We added entries to the waiting lists + which we must remove. So defer cancelation for now. */ + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate); + +#ifdef DONT_NEED_GAI_MISC_COND + result = 0; + GAI_MISC_WAIT (result, cntr, timeout, 1); +#else + if (timeout == NULL) + result = pthread_cond_wait (&cond, &__gai_requests_mutex); + else + { + /* We have to convert the relative timeout value into an + absolute time value with pthread_cond_timedwait expects. */ + struct timeval now; + struct timespec abstime; + + __gettimeofday (&now, NULL); + abstime.tv_nsec = timeout->tv_nsec + now.tv_usec * 1000; + abstime.tv_sec = timeout->tv_sec + now.tv_sec; + if (abstime.tv_nsec >= 1000000000) + { + abstime.tv_nsec -= 1000000000; + abstime.tv_sec += 1; + } + + result = pthread_cond_timedwait (&cond, &__gai_requests_mutex, + &abstime); + } +#endif + + /* Now remove the entry in the waiting list for all requests + which didn't terminate. */ + for (cnt = 0; cnt < ent; ++cnt) + if (list[cnt] != NULL && list[cnt]->__return == EAI_INPROGRESS + && requestlist[cnt] != NULL) + { + struct waitlist **listp = &requestlist[cnt]->waiting; + + /* There is the chance that we cannot find our entry anymore. + This could happen if the request terminated and restarted + again. */ + while (*listp != NULL && *listp != &waitlist[cnt]) + listp = &(*listp)->next; + + if (*listp != NULL) + *listp = (*listp)->next; + } + + /* Now it's time to restore the cancelation state. */ + pthread_setcancelstate (oldstate, NULL); + +#ifndef DONT_NEED_GAI_MISC_COND + /* Release the conditional variable. */ + if (pthread_cond_destroy (&cond) != 0) + /* This must never happen. */ + abort (); +#endif + + if (result != 0) + { + /* 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 (__glibc_likely (result == ETIMEDOUT)) + result = EAI_AGAIN; + else if (result == EINTR) + result = EAI_INTR; + else + result = EAI_SYSTEM; + } + } + + /* Release the mutex. */ + pthread_mutex_unlock (&__gai_requests_mutex); + + return result; +} diff --git a/REORG.TODO/resolv/getaddrinfo_a.c b/REORG.TODO/resolv/getaddrinfo_a.c new file mode 100644 index 0000000000..d63dc2e398 --- /dev/null +++ b/REORG.TODO/resolv/getaddrinfo_a.c @@ -0,0 +1,182 @@ +/* Copyright (C) 2001-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2001. + + 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 <pthread.h> +#include <stdlib.h> +#include <unistd.h> + +#include <gai_misc.h> + + +/* We need this special structure to handle asynchronous I/O. */ +struct async_waitlist + { + unsigned int counter; + struct sigevent sigev; + struct waitlist list[0]; + }; + + +int +getaddrinfo_a (int mode, struct gaicb *list[], int ent, struct sigevent *sig) +{ + struct sigevent defsigev; + struct requestlist *requests[ent]; + int cnt; + volatile unsigned int total = 0; + int result = 0; + + /* Check arguments. */ + if (mode != GAI_WAIT && mode != GAI_NOWAIT) + { + __set_errno (EINVAL); + return EAI_SYSTEM; + } + + if (sig == NULL) + { + defsigev.sigev_notify = SIGEV_NONE; + sig = &defsigev; + } + + /* Request the mutex. */ + pthread_mutex_lock (&__gai_requests_mutex); + + /* Now we can enqueue all requests. Since we already acquired the + mutex the enqueue function need not do this. */ + for (cnt = 0; cnt < ent; ++cnt) + if (list[cnt] != NULL) + { + requests[cnt] = __gai_enqueue_request (list[cnt]); + + if (requests[cnt] != NULL) + /* Successfully enqueued. */ + ++total; + else + /* Signal that we've seen an error. `errno' and the error code + of the gaicb will tell more. */ + result = EAI_SYSTEM; + } + else + requests[cnt] = NULL; + + if (total == 0) + { + /* We don't have anything to do except signalling if we work + asynchronously. */ + + /* Release the mutex. We do this before raising a signal since the + signal handler might do a `siglongjmp' and then the mutex is + locked forever. */ + pthread_mutex_unlock (&__gai_requests_mutex); + + if (mode == GAI_NOWAIT) + __gai_notify_only (sig, + sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0); + + return result; + } + else if (mode == GAI_WAIT) + { +#ifndef DONT_NEED_GAI_MISC_COND + pthread_cond_t cond = PTHREAD_COND_INITIALIZER; +#endif + struct waitlist waitlist[ent]; + int oldstate; + + total = 0; + for (cnt = 0; cnt < ent; ++cnt) + if (requests[cnt] != NULL) + { +#ifndef DONT_NEED_GAI_MISC_COND + waitlist[cnt].cond = &cond; +#endif + waitlist[cnt].next = requests[cnt]->waiting; + waitlist[cnt].counterp = &total; + waitlist[cnt].sigevp = NULL; + waitlist[cnt].caller_pid = 0; /* Not needed. */ + requests[cnt]->waiting = &waitlist[cnt]; + ++total; + } + + /* Since `pthread_cond_wait'/`pthread_cond_timedwait' are cancelation + points we must be careful. We added entries to the waiting lists + which we must remove. So defer cancelation for now. */ + pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, &oldstate); + + while (total > 0) + { +#ifdef DONT_NEED_GAI_MISC_COND + int not_used __attribute__ ((unused)); + GAI_MISC_WAIT (not_used, total, NULL, 1); +#else + pthread_cond_wait (&cond, &__gai_requests_mutex); +#endif + } + + /* Now it's time to restore the cancelation state. */ + pthread_setcancelstate (oldstate, NULL); + +#ifndef DONT_NEED_GAI_MISC_COND + /* Release the conditional variable. */ + if (pthread_cond_destroy (&cond) != 0) + /* This must never happen. */ + abort (); +#endif + } + else + { + struct async_waitlist *waitlist; + + waitlist = (struct async_waitlist *) + malloc (sizeof (struct async_waitlist) + + (ent * sizeof (struct waitlist))); + + if (waitlist == NULL) + result = EAI_AGAIN; + else + { + pid_t caller_pid = sig->sigev_notify == SIGEV_SIGNAL ? getpid () : 0; + total = 0; + + for (cnt = 0; cnt < ent; ++cnt) + if (requests[cnt] != NULL) + { +#ifndef DONT_NEED_GAI_MISC_COND + waitlist->list[cnt].cond = NULL; +#endif + waitlist->list[cnt].next = requests[cnt]->waiting; + waitlist->list[cnt].counterp = &waitlist->counter; + waitlist->list[cnt].sigevp = &waitlist->sigev; + waitlist->list[cnt].caller_pid = caller_pid; + requests[cnt]->waiting = &waitlist->list[cnt]; + ++total; + } + + waitlist->counter = total; + waitlist->sigev = *sig; + } + } + + /* Release the mutex. */ + pthread_mutex_unlock (&__gai_requests_mutex); + + return result; +} diff --git a/REORG.TODO/resolv/herror.c b/REORG.TODO/resolv/herror.c new file mode 100644 index 0000000000..b3df236bc9 --- /dev/null +++ b/REORG.TODO/resolv/herror.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 1987, 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) 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 <sys/types.h> +#include <sys/param.h> +#include <sys/uio.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <netdb.h> +#include <resolv.h> +#include <string.h> +#include <unistd.h> + +#include <libintl.h> +#include <not-cancel.h> + +const char *const h_errlist[] = { + N_("Resolver Error 0 (no error)"), + N_("Unknown host"), /* 1 HOST_NOT_FOUND */ + N_("Host name lookup failure"), /* 2 TRY_AGAIN */ + N_("Unknown server error"), /* 3 NO_RECOVERY */ + N_("No address associated with name"), /* 4 NO_ADDRESS */ +}; +const int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] }; + +/* + * herror -- + * print the error indicated by the h_errno value. + */ +void +herror(const char *s) { + struct iovec iov[4], *v = iov; + + if (s != NULL && *s != '\0') { + v->iov_base = (/*noconst*/ char *)s; + v->iov_len = strlen(s); + v++; + 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 = (char *) "\n"; + v->iov_len = 1; + writev_not_cancel_no_status(STDERR_FILENO, iov, (v - iov) + 1); +} + +/* + * hstrerror -- + * return the string associated with a given "host" errno value. + */ +const char * +hstrerror(int err) { + if (err < 0) + return _("Resolver internal error"); + else if (err < h_nerr) + return _(h_errlist[err]); + return _("Unknown resolver error"); +} +libc_hidden_def (hstrerror) diff --git a/REORG.TODO/resolv/inet_addr.c b/REORG.TODO/resolv/inet_addr.c new file mode 100644 index 0000000000..022f7ea084 --- /dev/null +++ b/REORG.TODO/resolv/inet_addr.c @@ -0,0 +1,183 @@ +/* + * Copyright (c) 1983, 1990, 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 <sys/types.h> +#include <sys/param.h> + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <ctype.h> + +#include <endian.h> +#include <stdint.h> +#include <stdlib.h> +#include <limits.h> +#include <errno.h> + +/* + * Ascii internet address interpretation routine. + * The value returned is in network order. + */ +in_addr_t +__inet_addr(const char *cp) { + struct in_addr val; + + if (__inet_aton(cp, &val)) + return (val.s_addr); + return (INADDR_NONE); +} +weak_alias (__inet_addr, inet_addr) + +/* + * Check whether "cp" is a valid ascii representation + * of an Internet address and convert to a binary address. + * Returns 1 if the address is valid, 0 if not. + * This replaces inet_addr, the return value from which + * cannot distinguish between failure and a local broadcast address. + */ +int +__inet_aton(const char *cp, struct in_addr *addr) +{ + static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff }; + in_addr_t val; + char c; + union iaddr { + uint8_t bytes[4]; + uint32_t word; + } res; + uint8_t *pp = res.bytes; + int digit; + + int saved_errno = errno; + __set_errno (0); + + res.word = 0; + + c = *cp; + for (;;) { + /* + * Collect number up to ``.''. + * Values are specified as for C: + * 0x=hex, 0=octal, isdigit=decimal. + */ + if (!isdigit(c)) + goto ret_0; + { + char *endp; + unsigned long ul = strtoul (cp, (char **) &endp, 0); + if (ul == ULONG_MAX && errno == ERANGE) + goto ret_0; + if (ul > 0xfffffffful) + goto ret_0; + val = ul; + digit = cp != endp; + cp = endp; + } + c = *cp; + if (c == '.') { + /* + * Internet format: + * a.b.c.d + * a.b.c (with c treated as 16 bits) + * a.b (with b treated as 24 bits) + */ + if (pp > res.bytes + 2 || val > 0xff) + goto ret_0; + *pp++ = val; + c = *++cp; + } else + break; + } + /* + * Check for trailing characters. + */ + if (c != '\0' && (!isascii(c) || !isspace(c))) + goto ret_0; + /* + * Did we get a valid digit? + */ + if (!digit) + goto ret_0; + + /* Check whether the last part is in its limits depending on + the number of parts in total. */ + if (val > max[pp - res.bytes]) + goto ret_0; + + if (addr != NULL) + addr->s_addr = res.word | htonl (val); + + __set_errno (saved_errno); + return (1); + +ret_0: + __set_errno (saved_errno); + return (0); +} +weak_alias (__inet_aton, inet_aton) +libc_hidden_def (__inet_aton) +libc_hidden_weak (inet_aton) diff --git a/REORG.TODO/resolv/inet_net_ntop.c b/REORG.TODO/resolv/inet_net_ntop.c new file mode 100644 index 0000000000..aaa78f664b --- /dev/null +++ b/REORG.TODO/resolv/inet_net_ntop.c @@ -0,0 +1,127 @@ +/* + * 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 <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static char * inet_net_ntop_ipv4 (const u_char *src, int bits, + char *dst, size_t size) __THROW; + +/* + * char * + * inet_net_ntop(af, src, bits, dst, size) + * convert network number from network to presentation format. + * generates CIDR style result always. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * author: + * Paul Vixie (ISC), July 1996 + */ +char * +inet_net_ntop (int af, const void *src, int bits, char *dst, size_t size) +{ + switch (af) { + case AF_INET: + return (inet_net_ntop_ipv4(src, bits, dst, size)); + default: + __set_errno (EAFNOSUPPORT); + return (NULL); + } +} + +/* + * static char * + * inet_net_ntop_ipv4(src, bits, dst, size) + * convert IPv4 network number from network to presentation format. + * generates CIDR style result always. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0b11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), July 1996 + */ +static char * +inet_net_ntop_ipv4 (const u_char *src, int bits, char *dst, size_t size) +{ + char *odst = dst; + char *t; + u_int m; + int b; + + if (bits < 0 || bits > 32) { + __set_errno (EINVAL); + return (NULL); + } + if (bits == 0) { + if (size < sizeof "0") + goto emsgsize; + *dst++ = '0'; + size--; + *dst = '\0'; + } + + /* Format whole octets. */ + for (b = bits / 8; b > 0; b--) { + if (size < sizeof "255.") + goto emsgsize; + t = dst; + dst += SPRINTF((dst, "%u", *src++)); + if (b > 1) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - t); + } + + /* Format partial octet. */ + b = bits % 8; + if (b > 0) { + if (size < sizeof ".255") + goto emsgsize; + t = dst; + if (dst != odst) + *dst++ = '.'; + m = ((1 << b) - 1) << (8 - b); + dst += SPRINTF((dst, "%u", *src & m)); + size -= (size_t)(dst - t); + } + + /* Format CIDR /width. */ + if (size < sizeof "/32") + goto emsgsize; + dst += SPRINTF((dst, "/%u", bits)); + return (odst); + + emsgsize: + __set_errno (EMSGSIZE); + return (NULL); +} diff --git a/REORG.TODO/resolv/inet_net_pton.c b/REORG.TODO/resolv/inet_net_pton.c new file mode 100644 index 0000000000..aab9b7b582 --- /dev/null +++ b/REORG.TODO/resolv/inet_net_pton.c @@ -0,0 +1,198 @@ +/* + * 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 <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +static int inet_net_pton_ipv4 (const char *src, u_char *dst, + size_t size) __THROW; + +/* + * static int + * inet_net_pton(af, src, dst, size) + * convert network number from presentation to network format. + * accepts hex octets, hex strings, decimal octets, and /CIDR. + * "size" is in bytes and describes "dst". + * return: + * number of bits, either imputed classfully or specified with /CIDR, + * or -1 if some failure occurred (check errno). ENOENT means it was + * not a valid network specification. + * author: + * Paul Vixie (ISC), June 1996 + */ +int +inet_net_pton (int af, const char *src, void *dst, size_t size) +{ + switch (af) { + case AF_INET: + return (inet_net_pton_ipv4(src, dst, size)); + default: + __set_errno (EAFNOSUPPORT); + return (-1); + } +} + +/* + * static int + * inet_net_pton_ipv4(src, dst, size) + * convert IPv4 network number from presentation to network format. + * accepts hex octets, hex strings, decimal octets, and /CIDR. + * "size" is in bytes and describes "dst". + * return: + * number of bits, either imputed classfully or specified with /CIDR, + * or -1 if some failure occurred (check errno). ENOENT means it was + * not an IPv4 network specification. + * note: + * network byte order assumed. this means 192.5.5.240/28 has + * 0b11110000 in its fourth octet. + * author: + * Paul Vixie (ISC), June 1996 + */ +static int +inet_net_pton_ipv4 (const char *src, u_char *dst, size_t size) +{ + static const char xdigits[] = "0123456789abcdef"; + int n, ch, tmp, dirty, bits; + const u_char *odst = dst; + + ch = *src++; + if (ch == '0' && (src[0] == 'x' || src[0] == 'X') + && isascii(src[1]) && isxdigit(src[1])) { + /* Hexadecimal: Eat nybble string. */ + if (size <= 0) + goto emsgsize; + dirty = 0; + tmp = 0; /* To calm down gcc. */ + src++; /* skip x or X. */ + while (isxdigit((ch = *src++))) { + ch = _tolower(ch); + n = (const char *) __rawmemchr(xdigits, ch) - xdigits; + assert(n >= 0 && n <= 15); + if (dirty == 0) + tmp = n; + else + tmp = (tmp << 4) | n; + if (++dirty == 2) { + if (size-- <= 0) + goto emsgsize; + *dst++ = (u_char) tmp; + dirty = 0; + } + } + if (dirty) { /* Odd trailing nybble? */ + if (size-- <= 0) + goto emsgsize; + *dst++ = (u_char) (tmp << 4); + } + } else if (isascii(ch) && isdigit(ch)) { + /* Decimal: eat dotted digit string. */ + for (;;) { + tmp = 0; + do { + n = ((const char *) __rawmemchr(xdigits, ch) + - xdigits); + assert(n >= 0 && n <= 9); + tmp *= 10; + tmp += n; + if (tmp > 255) + goto enoent; + } while (isascii((ch = *src++)) && isdigit(ch)); + if (size-- <= 0) + goto emsgsize; + *dst++ = (u_char) tmp; + if (ch == '\0' || ch == '/') + break; + if (ch != '.') + goto enoent; + ch = *src++; + if (!isascii(ch) || !isdigit(ch)) + goto enoent; + } + } else + goto enoent; + + bits = -1; + if (ch == '/' && isascii(src[0]) && isdigit(src[0]) && dst > odst) { + /* CIDR width specifier. Nothing can follow it. */ + ch = *src++; /* Skip over the /. */ + bits = 0; + do { + n = (const char *) __rawmemchr(xdigits, ch) - xdigits; + assert(n >= 0 && n <= 9); + bits *= 10; + bits += n; + } while (isascii((ch = *src++)) && isdigit(ch)); + if (ch != '\0') + goto enoent; + if (bits > 32) + goto emsgsize; + } + + /* Firey death and destruction unless we prefetched EOS. */ + if (ch != '\0') + goto enoent; + + /* If nothing was written to the destination, we found no address. */ + if (dst == odst) + goto enoent; + /* If no CIDR spec was given, infer width from net class. */ + if (bits == -1) { + if (*odst >= 240) /* Class E */ + bits = 32; + else if (*odst >= 224) /* Class D */ + bits = 4; + else if (*odst >= 192) /* Class C */ + bits = 24; + else if (*odst >= 128) /* Class B */ + bits = 16; + else /* Class A */ + bits = 8; + /* If imputed mask is narrower than specified octets, widen. */ + if (bits >= 8 && bits < ((dst - odst) * 8)) + bits = (dst - odst) * 8; + } + /* Extend network to cover the actual mask. */ + while (bits > ((dst - odst) * 8)) { + if (size-- <= 0) + goto emsgsize; + *dst++ = '\0'; + } + return (bits); + + enoent: + __set_errno (ENOENT); + return (-1); + + emsgsize: + __set_errno (EMSGSIZE); + return (-1); +} diff --git a/REORG.TODO/resolv/inet_neta.c b/REORG.TODO/resolv/inet_neta.c new file mode 100644 index 0000000000..348ff4784f --- /dev/null +++ b/REORG.TODO/resolv/inet_neta.c @@ -0,0 +1,76 @@ +/* + * 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 <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* + * char * + * inet_neta(src, dst, size) + * format a u_long network number into presentation format. + * return: + * pointer to dst, or NULL if an error occurred (check errno). + * note: + * format of ``src'' is as for inet_network(). + * author: + * Paul Vixie (ISC), July 1996 + */ +char * +inet_neta (u_int32_t src, char *dst, size_t size) +{ + char *odst = dst; + char *tp; + + while (src & 0xffffffff) { + u_char b = (src & 0xff000000) >> 24; + + src <<= 8; + if (b) { + if (size < sizeof "255.") + goto emsgsize; + tp = dst; + dst += SPRINTF((dst, "%u", b)); + if (src != 0L) { + *dst++ = '.'; + *dst = '\0'; + } + size -= (size_t)(dst - tp); + } + } + if (dst == odst) { + if (size < sizeof "0.0.0.0") + goto emsgsize; + strcpy(dst, "0.0.0.0"); + } + return (odst); + + emsgsize: + __set_errno (EMSGSIZE); + return (NULL); +} diff --git a/REORG.TODO/resolv/inet_ntop.c b/REORG.TODO/resolv/inet_ntop.c new file mode 100644 index 0000000000..01c45ce8b7 --- /dev/null +++ b/REORG.TODO/resolv/inet_ntop.c @@ -0,0 +1,189 @@ +/* + * 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 <sys/param.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* + * 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 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; + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ +const char * +inet_ntop (int af, const void *src, char *dst, socklen_t size) +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); + case AF_INET6: + return (inet_ntop6(src, dst, size)); + default: + __set_errno (EAFNOSUPPORT); + return (NULL); + } + /* NOTREACHED */ +} +libc_hidden_def (inet_ntop) + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * 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"; + char tmp[sizeof "255.255.255.255"]; + + if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) >= size) { + __set_errno (ENOSPC); + return (NULL); + } + return strcpy(dst, tmp); +} + +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +static const char * +internal_function +inet_ntop6 (const u_char *src, char *dst, socklen_t size) +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best, cur; + u_int words[NS_IN6ADDRSZ / NS_INT16SZ]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < NS_IN6ADDRSZ; i += 2) + words[i / 2] = (src[i] << 8) | src[i + 1]; + best.base = -1; + cur.base = -1; + best.len = 0; + cur.len = 0; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) + return (NULL); + tp += strlen(tp); + break; + } + tp += SPRINTF((tp, "%x", words[i])); + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == + (NS_IN6ADDRSZ / NS_INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((socklen_t)(tp - tmp) > size) { + __set_errno (ENOSPC); + return (NULL); + } + return strcpy(dst, tmp); +} diff --git a/REORG.TODO/resolv/inet_pton.c b/REORG.TODO/resolv/inet_pton.c new file mode 100644 index 0000000000..68f0fa5402 --- /dev/null +++ b/REORG.TODO/resolv/inet_pton.c @@ -0,0 +1,216 @@ +/* + * 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 <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> + +static int inet_pton4 (const char *src, unsigned char *dst); +static int inet_pton6 (const char *src, unsigned char *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 (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; + } +} +libc_hidden_def (__inet_pton) +weak_alias (__inet_pton, inet_pton) +libc_hidden_weak (inet_pton) + +/* Like inet_atonbut without all the hexadecimal, octal 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. + */ +static int +inet_pton4 (const char *src, unsigned char *dst) +{ + int saw_digit, octets, ch; + unsigned char tmp[NS_INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') + { + 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; +} + +/* Cconvert 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. + */ +static int +inet_pton6 (const char *src, unsigned char *dst) +{ + static const char xdigits[] = "0123456789abcdef"; + unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp; + const char *curtok; + int ch, saw_xdigit; + unsigned 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++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned 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; + } + if (saw_xdigit) + { + if (tp + NS_INT16SZ > endp) + return 0; + *tp++ = (unsigned char) (val >> 8) & 0xff; + *tp++ = (unsigned char) val & 0xff; + } + 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 (tp != endp) + return 0; + memcpy (dst, tmp, NS_IN6ADDRSZ); + return 1; +} diff --git a/REORG.TODO/resolv/mapv4v6addr.h b/REORG.TODO/resolv/mapv4v6addr.h new file mode 100644 index 0000000000..7f85f7d5e3 --- /dev/null +++ b/REORG.TODO/resolv/mapv4v6addr.h @@ -0,0 +1,69 @@ +/* + * ++Copyright++ 1985, 1988, 1993 + * - + * Copyright (c) 1985, 1988, 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. + * - + * --Copyright-- + */ + +#include <string.h> +#include <arpa/nameser.h> + +static void +map_v4v6_address (const char *src, char *dst) +{ + u_char *p = (u_char *) dst; + int i; + + /* Move the IPv4 part to the right position. */ + memcpy (dst + 12, src, INADDRSZ); + + /* Mark this ipv6 addr as a mapped ipv4. */ + for (i = 0; i < 10; i++) + *p++ = 0x00; + *p++ = 0xff; + *p = 0xff; +} diff --git a/REORG.TODO/resolv/mapv4v6hostent.h b/REORG.TODO/resolv/mapv4v6hostent.h new file mode 100644 index 0000000000..c11038adf3 --- /dev/null +++ b/REORG.TODO/resolv/mapv4v6hostent.h @@ -0,0 +1,84 @@ +/* + * ++Copyright++ 1985, 1988, 1993 + * - + * Copyright (c) 1985, 1988, 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. + * - + * --Copyright-- + */ + +#include <arpa/nameser.h> +#include <sys/socket.h> + +typedef union { + int32_t al; + char ac; +} align; + +static int +map_v4v6_hostent (struct hostent *hp, char **bpp, int *lenp) +{ + char **ap; + + if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ) + return 0; + hp->h_addrtype = AF_INET6; + hp->h_length = IN6ADDRSZ; + for (ap = hp->h_addr_list; *ap; ap++) + { + int i = sizeof (align) - ((u_long) *bpp % sizeof (align)); + + if (*lenp < (i + IN6ADDRSZ)) + /* Out of memory. */ + return 1; + *bpp += i; + *lenp -= i; + map_v4v6_address (*ap, *bpp); + *ap = *bpp; + *bpp += IN6ADDRSZ; + *lenp -= IN6ADDRSZ; + } + return 0; +} diff --git a/REORG.TODO/resolv/netdb.h b/REORG.TODO/resolv/netdb.h new file mode 100644 index 0000000000..f76ccf123e --- /dev/null +++ b/REORG.TODO/resolv/netdb.h @@ -0,0 +1,713 @@ + /* Copyright (C) 1996-2017 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/>. */ + +/* All data returned by the network data base library are supplied in + host order and returned in network order (suitable for use in + system calls). */ + +#ifndef _NETDB_H +#define _NETDB_H 1 + +#include <features.h> + +#include <netinet/in.h> +#include <bits/stdint-uintn.h> +#ifdef __USE_MISC +/* This is necessary to make this include file properly replace the + Sun version. */ +# include <rpc/netdb.h> +#endif + +#ifdef __USE_GNU +# include <bits/types/sigevent_t.h> +# include <bits/types/struct_timespec.h> +#endif + +#include <bits/netdb.h> + +/* Absolute file name for network data base files. */ +#define _PATH_HEQUIV "/etc/hosts.equiv" +#define _PATH_HOSTS "/etc/hosts" +#define _PATH_NETWORKS "/etc/networks" +#define _PATH_NSSWITCH_CONF "/etc/nsswitch.conf" +#define _PATH_PROTOCOLS "/etc/protocols" +#define _PATH_SERVICES "/etc/services" + + +__BEGIN_DECLS + +#if defined __USE_MISC || !defined __USE_XOPEN2K8 +/* Error status for non-reentrant lookup functions. + We use a macro to access always the thread-specific `h_errno' variable. */ +# define h_errno (*__h_errno_location ()) + +/* Function to get address of global `h_errno' variable. */ +extern int *__h_errno_location (void) __THROW __attribute__ ((__const__)); + + +/* Possible values left in `h_errno'. */ +# define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found. */ +# define TRY_AGAIN 2 /* Non-Authoritative Host not found, + or SERVERFAIL. */ +# define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, + NOTIMP. */ +# define NO_DATA 4 /* Valid name, no data record of requested + type. */ +#endif +#ifdef __USE_MISC +# define NETDB_INTERNAL -1 /* See errno. */ +# define NETDB_SUCCESS 0 /* No problem. */ +# define NO_ADDRESS NO_DATA /* No address, look for MX record. */ +#endif + +#if defined __USE_XOPEN2K || defined __USE_XOPEN_EXTENDED +/* Highest reserved Internet port number. */ +# define IPPORT_RESERVED 1024 +#endif + +#ifdef __USE_GNU +/* Scope delimiter for getaddrinfo(), getnameinfo(). */ +# define SCOPE_DELIMITER '%' +#endif + +#ifdef __USE_MISC +/* Print error indicated by `h_errno' variable on standard error. STR + if non-null is printed before the error string. */ +extern void herror (const char *__str) __THROW; + +/* Return string associated with error ERR_NUM. */ +extern const char *hstrerror (int __err_num) __THROW; +#endif + + +/* Description of data base entry for a single host. */ +struct hostent +{ + char *h_name; /* Official name of host. */ + char **h_aliases; /* Alias list. */ + int h_addrtype; /* Host address type. */ + int h_length; /* Length of address. */ + char **h_addr_list; /* List of addresses from name server. */ +#ifdef __USE_MISC +# define h_addr h_addr_list[0] /* Address, for backward compatibility.*/ +#endif +}; + +/* Open host data base files and mark them as staying open even after + a later search if STAY_OPEN is non-zero. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void sethostent (int __stay_open); + +/* Close host data base files and clear `stay open' flag. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endhostent (void); + +/* Get next entry from host data base file. Open data base if + necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct hostent *gethostent (void); + +/* Return entry from host data base which address match ADDR with + length LEN and type TYPE. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct hostent *gethostbyaddr (const void *__addr, __socklen_t __len, + int __type); + +/* Return entry from host data base for host with NAME. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct hostent *gethostbyname (const char *__name); + +#ifdef __USE_MISC +/* Return entry from host data base for host with NAME. AF must be + set to the address type which is `AF_INET' for IPv4 or `AF_INET6' + for IPv6. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern struct hostent *gethostbyname2 (const char *__name, int __af); + +/* Reentrant versions of the functions above. The additional + arguments specify a buffer of BUFLEN starting at BUF. The last + argument is a pointer to a variable which gets the value which + would be stored in the global variable `herrno' by the + non-reentrant functions. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int gethostent_r (struct hostent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct hostent **__restrict __result, + int *__restrict __h_errnop); + +extern int gethostbyaddr_r (const void *__restrict __addr, __socklen_t __len, + int __type, + struct hostent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct hostent **__restrict __result, + int *__restrict __h_errnop); + +extern int gethostbyname_r (const char *__restrict __name, + struct hostent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct hostent **__restrict __result, + int *__restrict __h_errnop); + +extern int gethostbyname2_r (const char *__restrict __name, int __af, + struct hostent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct hostent **__restrict __result, + int *__restrict __h_errnop); +#endif /* misc */ + + +/* Open network data base files and mark them as staying open even + after a later search if STAY_OPEN is non-zero. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void setnetent (int __stay_open); + +/* Close network data base files and clear `stay open' flag. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endnetent (void); + +/* Get next entry from network data base file. Open data base if + necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct netent *getnetent (void); + +/* Return entry from network data base which address match NET and + type TYPE. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct netent *getnetbyaddr (uint32_t __net, int __type); + +/* Return entry from network data base for network with NAME. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct netent *getnetbyname (const char *__name); + +#ifdef __USE_MISC +/* Reentrant versions of the functions above. The additional + arguments specify a buffer of BUFLEN starting at BUF. The last + argument is a pointer to a variable which gets the value which + would be stored in the global variable `herrno' by the + non-reentrant functions. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int getnetent_r (struct netent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct netent **__restrict __result, + int *__restrict __h_errnop); + +extern int getnetbyaddr_r (uint32_t __net, int __type, + struct netent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct netent **__restrict __result, + int *__restrict __h_errnop); + +extern int getnetbyname_r (const char *__restrict __name, + struct netent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct netent **__restrict __result, + int *__restrict __h_errnop); +#endif /* misc */ + + +/* Description of data base entry for a single service. */ +struct servent +{ + char *s_name; /* Official service name. */ + char **s_aliases; /* Alias list. */ + int s_port; /* Port number. */ + char *s_proto; /* Protocol to use. */ +}; + +/* Open service data base files and mark them as staying open even + after a later search if STAY_OPEN is non-zero. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void setservent (int __stay_open); + +/* Close service data base files and clear `stay open' flag. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endservent (void); + +/* Get next entry from service data base file. Open data base if + necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct servent *getservent (void); + +/* Return entry from network data base for network with NAME and + protocol PROTO. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct servent *getservbyname (const char *__name, const char *__proto); + +/* Return entry from service data base which matches port PORT and + protocol PROTO. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct servent *getservbyport (int __port, const char *__proto); + + +#ifdef __USE_MISC +/* Reentrant versions of the functions above. The additional + arguments specify a buffer of BUFLEN starting at BUF. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int getservent_r (struct servent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct servent **__restrict __result); + +extern int getservbyname_r (const char *__restrict __name, + const char *__restrict __proto, + struct servent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct servent **__restrict __result); + +extern int getservbyport_r (int __port, const char *__restrict __proto, + struct servent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct servent **__restrict __result); +#endif /* misc */ + + +/* Description of data base entry for a single service. */ +struct protoent +{ + char *p_name; /* Official protocol name. */ + char **p_aliases; /* Alias list. */ + int p_proto; /* Protocol number. */ +}; + +/* Open protocol data base files and mark them as staying open even + after a later search if STAY_OPEN is non-zero. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void setprotoent (int __stay_open); + +/* Close protocol data base files and clear `stay open' flag. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern void endprotoent (void); + +/* Get next entry from protocol data base file. Open data base if + necessary. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct protoent *getprotoent (void); + +/* Return entry from protocol data base for network with NAME. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct protoent *getprotobyname (const char *__name); + +/* Return entry from protocol data base which number is PROTO. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern struct protoent *getprotobynumber (int __proto); + + +#ifdef __USE_MISC +/* Reentrant versions of the functions above. The additional + arguments specify a buffer of BUFLEN starting at BUF. + + These functions are not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation they are cancellation points and + therefore not marked with __THROW. */ +extern int getprotoent_r (struct protoent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct protoent **__restrict __result); + +extern int getprotobyname_r (const char *__restrict __name, + struct protoent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct protoent **__restrict __result); + +extern int getprotobynumber_r (int __proto, + struct protoent *__restrict __result_buf, + char *__restrict __buf, size_t __buflen, + struct protoent **__restrict __result); + + +/* Establish network group NETGROUP for enumeration. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int setnetgrent (const char *__netgroup); + +/* Free all space allocated by previous `setnetgrent' call. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern void endnetgrent (void); + +/* Get next member of netgroup established by last `setnetgrent' call + and return pointers to elements in HOSTP, USERP, and DOMAINP. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int getnetgrent (char **__restrict __hostp, + char **__restrict __userp, + char **__restrict __domainp); + + +/* Test whether NETGROUP contains the triple (HOST,USER,DOMAIN). + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int innetgr (const char *__netgroup, const char *__host, + const char *__user, const char *__domain); + +/* Reentrant version of `getnetgrent' where result is placed in BUFFER. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int getnetgrent_r (char **__restrict __hostp, + char **__restrict __userp, + char **__restrict __domainp, + char *__restrict __buffer, size_t __buflen); +#endif /* misc */ + + +#ifdef __USE_MISC +/* Call `rshd' at port RPORT on remote machine *AHOST to execute CMD. + The local user is LOCUSER, on the remote machine the command is + executed as REMUSER. In *FD2P the descriptor to the socket for the + connection is returned. The caller must have the right to use a + reserved port. When the function returns *AHOST contains the + official host name. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rcmd (char **__restrict __ahost, unsigned short int __rport, + const char *__restrict __locuser, + const char *__restrict __remuser, + const char *__restrict __cmd, int *__restrict __fd2p); + +/* This is the equivalent function where the protocol can be selected + and which therefore can be used for IPv6. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rcmd_af (char **__restrict __ahost, unsigned short int __rport, + const char *__restrict __locuser, + const char *__restrict __remuser, + const char *__restrict __cmd, int *__restrict __fd2p, + sa_family_t __af); + +/* Call `rexecd' at port RPORT on remote machine *AHOST to execute + CMD. The process runs at the remote machine using the ID of user + NAME whose cleartext password is PASSWD. In *FD2P the descriptor + to the socket for the connection is returned. When the function + returns *AHOST contains the official host name. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rexec (char **__restrict __ahost, int __rport, + const char *__restrict __name, + const char *__restrict __pass, + const char *__restrict __cmd, int *__restrict __fd2p); + +/* This is the equivalent function where the protocol can be selected + and which therefore can be used for IPv6. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rexec_af (char **__restrict __ahost, int __rport, + const char *__restrict __name, + const char *__restrict __pass, + const char *__restrict __cmd, int *__restrict __fd2p, + sa_family_t __af); + +/* Check whether user REMUSER on system RHOST is allowed to login as LOCUSER. + If SUSER is not zero the user tries to become superuser. Return 0 if + it is possible. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int ruserok (const char *__rhost, int __suser, + const char *__remuser, const char *__locuser); + +/* This is the equivalent function where the protocol can be selected + and which therefore can be used for IPv6. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int ruserok_af (const char *__rhost, int __suser, + const char *__remuser, const char *__locuser, + sa_family_t __af); + +/* Check whether user REMUSER on system indicated by IPv4 address + RADDR is allowed to login as LOCUSER. Non-IPv4 (e.g., IPv6) are + not supported. If SUSER is not zero the user tries to become + superuser. Return 0 if it is possible. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int iruserok (uint32_t __raddr, int __suser, + const char *__remuser, const char *__locuser); + +/* This is the equivalent function where the pfamiliy if the address + pointed to by RADDR is determined by the value of AF. It therefore + can be used for IPv6 + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int iruserok_af (const void *__raddr, int __suser, + const char *__remuser, const char *__locuser, + sa_family_t __af); + +/* Try to allocate reserved port, returning a descriptor for a socket opened + at this port or -1 if unsuccessful. The search for an available port + will start at ALPORT and continues with lower numbers. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rresvport (int *__alport); + +/* This is the equivalent function where the protocol can be selected + and which therefore can be used for IPv6. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int rresvport_af (int *__alport, sa_family_t __af); +#endif + + +/* Extension from POSIX.1:2001. */ +#ifdef __USE_XOPEN2K +/* Structure to contain information about address of a service provider. */ +struct addrinfo +{ + int ai_flags; /* Input flags. */ + int ai_family; /* Protocol family for socket. */ + int ai_socktype; /* Socket type. */ + int ai_protocol; /* Protocol for socket. */ + socklen_t ai_addrlen; /* Length of socket address. */ + struct sockaddr *ai_addr; /* Socket address for socket. */ + char *ai_canonname; /* Canonical name for service location. */ + struct addrinfo *ai_next; /* Pointer to next in list. */ +}; + +# ifdef __USE_GNU +/* Structure used as control block for asynchronous lookup. */ +struct gaicb +{ + const char *ar_name; /* Name to look up. */ + const char *ar_service; /* Service name. */ + const struct addrinfo *ar_request; /* Additional request specification. */ + struct addrinfo *ar_result; /* Pointer to result. */ + /* The following are internal elements. */ + int __return; + int __glibc_reserved[5]; +}; + +/* Lookup mode. */ +# define GAI_WAIT 0 +# define GAI_NOWAIT 1 +# endif + +/* Possible values for `ai_flags' field in `addrinfo' structure. */ +# define AI_PASSIVE 0x0001 /* Socket address is intended for `bind'. */ +# define AI_CANONNAME 0x0002 /* Request for canonical name. */ +# define AI_NUMERICHOST 0x0004 /* Don't use name resolution. */ +# define AI_V4MAPPED 0x0008 /* IPv4 mapped addresses are acceptable. */ +# define AI_ALL 0x0010 /* Return IPv4 mapped and IPv6 addresses. */ +# define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose + returned address type.. */ +# ifdef __USE_GNU +# define AI_IDN 0x0040 /* IDN encode input (assuming it is encoded + 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. */ +# endif +# define AI_NUMERICSERV 0x0400 /* Don't use name resolution. */ + +/* Error values for `getaddrinfo' function. */ +# define EAI_BADFLAGS -1 /* Invalid value for `ai_flags' field. */ +# define EAI_NONAME -2 /* NAME or SERVICE is unknown. */ +# define EAI_AGAIN -3 /* Temporary failure in name resolution. */ +# define EAI_FAIL -4 /* Non-recoverable failure in name res. */ +# define EAI_FAMILY -6 /* `ai_family' not supported. */ +# define EAI_SOCKTYPE -7 /* `ai_socktype' not supported. */ +# define EAI_SERVICE -8 /* SERVICE not supported for `ai_socktype'. */ +# define EAI_MEMORY -10 /* Memory allocation failure. */ +# define EAI_SYSTEM -11 /* System error returned in `errno'. */ +# define EAI_OVERFLOW -12 /* Argument buffer overflow. */ +# ifdef __USE_GNU +# define EAI_NODATA -5 /* No address associated with NAME. */ +# define EAI_ADDRFAMILY -9 /* Address family for NAME not supported. */ +# define EAI_INPROGRESS -100 /* Processing request in progress. */ +# define EAI_CANCELED -101 /* Request canceled. */ +# define EAI_NOTCANCELED -102 /* Request not canceled. */ +# define EAI_ALLDONE -103 /* All requests done. */ +# define EAI_INTR -104 /* Interrupted by a signal. */ +# define EAI_IDN_ENCODE -105 /* IDN encoding failed. */ +# endif + +# ifdef __USE_MISC +# define NI_MAXHOST 1025 +# define NI_MAXSERV 32 +# endif + +# define NI_NUMERICHOST 1 /* Don't try to look up hostname. */ +# define NI_NUMERICSERV 2 /* Don't convert port number to name. */ +# define NI_NOFQDN 4 /* Only return nodename portion. */ +# define NI_NAMEREQD 8 /* Don't return numeric addresses. */ +# 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. */ +# endif + +/* Translate name of a service location and/or a service name to set of + socket addresses. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int getaddrinfo (const char *__restrict __name, + const char *__restrict __service, + const struct addrinfo *__restrict __req, + struct addrinfo **__restrict __pai); + +/* Free `addrinfo' structure AI including associated storage. */ +extern void freeaddrinfo (struct addrinfo *__ai) __THROW; + +/* Convert error return from getaddrinfo() to a string. */ +extern const char *gai_strerror (int __ecode) __THROW; + +/* Translate a socket address to a location and service name. + + This function is a possible cancellation point and therefore not + marked with __THROW. */ +extern int getnameinfo (const struct sockaddr *__restrict __sa, + socklen_t __salen, char *__restrict __host, + socklen_t __hostlen, char *__restrict __serv, + socklen_t __servlen, int __flags); +#endif /* POSIX */ + +#ifdef __USE_GNU +/* Enqueue ENT requests from the LIST. If MODE is GAI_WAIT wait until all + requests are handled. If WAIT is GAI_NOWAIT return immediately after + queueing the requests and signal completion according to SIG. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int getaddrinfo_a (int __mode, struct gaicb *__list[__restrict_arr], + int __ent, struct sigevent *__restrict __sig); + +/* Suspend execution of the thread until at least one of the ENT requests + in LIST is handled. If TIMEOUT is not a null pointer it specifies the + longest time the function keeps waiting before returning with an error. + + This function is not part of POSIX and therefore no official + cancellation point. But due to similarity with an POSIX interface + or due to the implementation it is a cancellation point and + therefore not marked with __THROW. */ +extern int gai_suspend (const struct gaicb *const __list[], int __ent, + const struct timespec *__timeout); + +/* Get the error status of the request REQ. */ +extern int gai_error (struct gaicb *__req) __THROW; + +/* Cancel the requests associated with GAICBP. */ +extern int gai_cancel (struct gaicb *__gaicbp) __THROW; +#endif /* GNU */ + +__END_DECLS + +#endif /* netdb.h */ diff --git a/REORG.TODO/resolv/ns_date.c b/REORG.TODO/resolv/ns_date.c new file mode 100644 index 0000000000..31cef74c92 --- /dev/null +++ b/REORG.TODO/resolv/ns_date.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* Import. */ + +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <time.h> + +#define SPRINTF(x) ((size_t)sprintf x) + +/* Forward. */ + +static int datepart(const char *, int, int, int, int *); + +/* Public. */ + +/*% + * Convert a date in ASCII into the number of seconds since + * 1 January 1970 (GMT assumed). Format is yyyymmddhhmmss, all + * digits required, no spaces allowed. + */ + +u_int32_t +ns_datetosecs(const char *cp, int *errp) { + struct tm time; + u_int32_t result; + int mdays, i; + static const int days_per_month[12] = + {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + if (strlen(cp) != 14U) { + *errp = 1; + return (0); + } + *errp = 0; + + memset(&time, 0, sizeof time); + time.tm_year = datepart(cp + 0, 4, 1990, 9999, errp) - 1900; + time.tm_mon = datepart(cp + 4, 2, 01, 12, errp) - 1; + time.tm_mday = datepart(cp + 6, 2, 01, 31, errp); + time.tm_hour = datepart(cp + 8, 2, 00, 23, errp); + time.tm_min = datepart(cp + 10, 2, 00, 59, errp); + time.tm_sec = datepart(cp + 12, 2, 00, 59, errp); + if (*errp) /*%< Any parse errors? */ + return (0); + + /* + * OK, now because timegm() is not available in all environments, + * we will do it by hand. Roll up sleeves, curse the gods, begin! + */ + +#define SECS_PER_DAY ((u_int32_t)24*60*60) +#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0) + + result = time.tm_sec; /*%< Seconds */ + result += time.tm_min * 60; /*%< Minutes */ + result += time.tm_hour * (60*60); /*%< Hours */ + result += (time.tm_mday - 1) * SECS_PER_DAY; /*%< Days */ + /* Months are trickier. Look without leaping, then leap */ + mdays = 0; + for (i = 0; i < time.tm_mon; i++) + mdays += days_per_month[i]; + result += mdays * SECS_PER_DAY; /*%< Months */ + if (time.tm_mon > 1 && isleap(1900+time.tm_year)) + result += SECS_PER_DAY; /*%< Add leapday for this year */ + /* First figure years without leapdays, then add them in. */ + /* The loop is slow, FIXME, but simple and accurate. */ + result += (time.tm_year - 70) * (SECS_PER_DAY*365); /*%< Years */ + for (i = 70; i < time.tm_year; i++) + if (isleap(1900+i)) + result += SECS_PER_DAY; /*%< Add leapday for prev year */ + return (result); +} + +/* Private. */ + +/*% + * Parse part of a date. Set error flag if any error. + * Don't reset the flag if there is no error. + */ +static int +datepart(const char *buf, int size, int min, int max, int *errp) { + int result = 0; + int i; + + for (i = 0; i < size; i++) { + if (!isdigit((unsigned char)(buf[i]))) + *errp = 1; + result = (result * 10) + buf[i] - '0'; + } + if (result < min) + *errp = 1; + if (result > max) + *errp = 1; + return (result); +} + +/*! \file */ diff --git a/REORG.TODO/resolv/ns_name.c b/REORG.TODO/resolv/ns_name.c new file mode 100644 index 0000000000..08a75e2fe0 --- /dev/null +++ b/REORG.TODO/resolv/ns_name.c @@ -0,0 +1,730 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv.h> +#include <string.h> +#include <ctype.h> +#include <stdlib.h> +#include <limits.h> + +# define SPRINTF(x) ((size_t)sprintf x) + +/* Data. */ + +static const char digits[] = "0123456789"; + +/* Forward. */ + +static int special(int); +static int printable(int); +static int dn_find(const u_char *, const u_char *, + const u_char * const *, + const u_char * const *); +static int labellen(const u_char *); + +/* Public. */ + +/*% + * Convert an encoded domain name to printable ascii as per RFC1035. + + * return: + *\li Number of bytes written to buffer, or -1 (with errno set) + * + * notes: + *\li The root is returned as "." + *\li All other domains are returned in non absolute form + */ +int +ns_name_ntop(const u_char *src, char *dst, size_t dstsiz) +{ + const u_char *cp; + char *dn, *eom; + u_char c; + u_int n; + int l; + + cp = src; + dn = dst; + eom = dst + dstsiz; + + while ((n = *cp++) != 0) { + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Some kind of compression pointer. */ + __set_errno (EMSGSIZE); + return (-1); + } + if (dn != dst) { + if (dn >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + *dn++ = '.'; + } + if ((l = labellen(cp - 1)) < 0) { + __set_errno (EMSGSIZE); + return(-1); + } + if (dn + l >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + for ((void)NULL; l > 0; l--) { + c = *cp++; + if (special(c)) { + if (dn + 1 >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + *dn++ = '\\'; + *dn++ = (char)c; + } else if (!printable(c)) { + if (dn + 3 >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + *dn++ = '\\'; + *dn++ = digits[c / 100]; + *dn++ = digits[(c % 100) / 10]; + *dn++ = digits[c % 10]; + } else { + if (dn >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + *dn++ = (char)c; + } + } + } + if (dn == dst) { + if (dn >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + *dn++ = '.'; + } + if (dn >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + *dn++ = '\0'; + return (dn - dst); +} +libresolv_hidden_def (ns_name_ntop) +strong_alias (ns_name_ntop, __ns_name_ntop) + +/*% + * Convert an ascii string into an encoded domain name as per RFC1035. + * + * return: + * + *\li -1 if it fails + *\li 1 if string was fully qualified + *\li 0 is string was not fully qualified + * + * notes: + *\li Enforces label and domain length limits. + */ + +int +ns_name_pton(const char *src, u_char *dst, size_t dstsiz) +{ + u_char *label, *bp, *eom; + int c, n, escaped; + char *cp; + + escaped = 0; + bp = dst; + eom = dst + dstsiz; + label = bp++; + + while ((c = *src++) != 0) { + if (escaped) { + if ((cp = strchr(digits, c)) != NULL) { + n = (cp - digits) * 100; + if ((c = *src++) == 0 || + (cp = strchr(digits, c)) == NULL) { + __set_errno (EMSGSIZE); + return (-1); + } + n += (cp - digits) * 10; + if ((c = *src++) == 0 || + (cp = strchr(digits, c)) == NULL) { + __set_errno (EMSGSIZE); + return (-1); + } + n += (cp - digits); + if (n > 255) { + __set_errno (EMSGSIZE); + return (-1); + } + c = n; + } + escaped = 0; + } else if (c == '\\') { + escaped = 1; + continue; + } else if (c == '.') { + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */ + __set_errno (EMSGSIZE); + return (-1); + } + if (label >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + *label = c; + /* Fully qualified ? */ + if (*src == '\0') { + if (c != 0) { + if (bp >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + *bp++ = '\0'; + } + if ((bp - dst) > MAXCDNAME) { + __set_errno (EMSGSIZE); + return (-1); + } + return (1); + } + if (c == 0 || *src == '.') { + __set_errno (EMSGSIZE); + return (-1); + } + label = bp++; + continue; + } + if (bp >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + *bp++ = (u_char)c; + } + c = (bp - label - 1); + if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */ + __set_errno (EMSGSIZE); + return (-1); + } + if (label >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + *label = c; + if (c != 0) { + if (bp >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + *bp++ = 0; + } + if ((bp - dst) > MAXCDNAME) { /*%< src too big */ + __set_errno (EMSGSIZE); + return (-1); + } + return (0); +} +libresolv_hidden_def (ns_name_pton) + +/*% + * Convert a network strings labels into all lowercase. + * + * return: + *\li Number of bytes written to buffer, or -1 (with errno set) + * + * notes: + *\li Enforces label and domain length limits. + */ + +int +ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz) +{ + const u_char *cp; + u_char *dn, *eom; + u_char c; + u_int n; + int l; + + cp = src; + dn = dst; + eom = dst + dstsiz; + + if (dn >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + while ((n = *cp++) != 0) { + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Some kind of compression pointer. */ + __set_errno (EMSGSIZE); + return (-1); + } + *dn++ = n; + if ((l = labellen(cp - 1)) < 0) { + __set_errno (EMSGSIZE); + return (-1); + } + if (dn + l >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + for ((void)NULL; l > 0; l--) { + c = *cp++; + if (isupper(c)) + *dn++ = tolower(c); + else + *dn++ = c; + } + } + *dn++ = '\0'; + return (dn - dst); +} + +/*% + * Unpack a domain name from a message, source may be compressed. + * + * return: + *\li -1 if it fails, or consumed octets if it succeeds. + */ +int +ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src, + u_char *dst, size_t dstsiz) +{ + const u_char *srcp, *dstlim; + u_char *dstp; + int n, len, checked, l; + + len = -1; + checked = 0; + dstp = dst; + srcp = src; + dstlim = dst + dstsiz; + if (srcp < msg || srcp >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + /* Fetch next label in domain name. */ + while ((n = *srcp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { + case 0: + /* Limit checks. */ + if ((l = labellen(srcp - 1)) < 0) { + __set_errno (EMSGSIZE); + return(-1); + } + if (dstp + l + 1 >= dstlim || srcp + l >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + checked += l + 1; + *dstp++ = n; + memcpy(dstp, srcp, l); + dstp += l; + srcp += l; + break; + + case NS_CMPRSFLGS: + if (srcp >= eom) { + __set_errno (EMSGSIZE); + return (-1); + } + if (len < 0) + len = srcp - src + 1; + srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff)); + if (srcp < msg || srcp >= eom) { /*%< Out of range. */ + __set_errno (EMSGSIZE); + return (-1); + } + checked += 2; + /* + * Check for loops in the compressed name; + * if we've looked at the whole message, + * there must be a loop. + */ + if (checked >= eom - msg) { + __set_errno (EMSGSIZE); + return (-1); + } + break; + + default: + __set_errno (EMSGSIZE); + return (-1); /*%< flag error */ + } + } + *dstp = '\0'; + if (len < 0) + len = srcp - src; + return (len); +} +libresolv_hidden_def (ns_name_unpack) +strong_alias (ns_name_unpack, __ns_name_unpack) + +/*% + * Pack domain name 'domain' into 'comp_dn'. + * + * return: + *\li Size of the compressed name, or -1. + * + * notes: + *\li 'dnptrs' is an array of pointers to previous compressed names. + *\li dnptrs[0] is a pointer to the beginning of the message. The array + * ends with NULL. + *\li 'lastdnptr' is a pointer to the end of the array pointed to + * by 'dnptrs'. + * + * Side effects: + *\li The list of pointers in dnptrs is updated for labels inserted into + * the message as we compress the name. If 'dnptr' is NULL, we don't + * try to compress names. If 'lastdnptr' is NULL, we don't update the + * list. + */ +int +ns_name_pack(const u_char *src, u_char *dst, int dstsiz, + const u_char **dnptrs, const u_char **lastdnptr) +{ + u_char *dstp; + const u_char **cpp, **lpp, *eob, *msg; + const u_char *srcp; + int n, l, first = 1; + + srcp = src; + dstp = dst; + eob = dstp + dstsiz; + lpp = cpp = NULL; + if (dnptrs != NULL) { + if ((msg = *dnptrs++) != NULL) { + for (cpp = dnptrs; *cpp != NULL; cpp++) + (void)NULL; + lpp = cpp; /*%< end of list to search */ + } + } else + msg = NULL; + + /* make sure the domain we are about to add is legal */ + l = 0; + do { + int l0; + + n = *srcp; + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + __set_errno (EMSGSIZE); + return (-1); + } + if ((l0 = labellen(srcp)) < 0) { + __set_errno (EINVAL); + return(-1); + } + l += l0 + 1; + if (l > MAXCDNAME) { + __set_errno (EMSGSIZE); + return (-1); + } + srcp += l0 + 1; + } while (n != 0); + + /* from here on we need to reset compression pointer array on error */ + srcp = src; + do { + /* Look to see if we can use pointers. */ + n = *srcp; + if (n != 0 && msg != NULL) { + l = dn_find(srcp, msg, (const u_char * const *)dnptrs, + (const u_char * const *)lpp); + if (l >= 0) { + if (dstp + 1 >= eob) { + goto cleanup; + } + *dstp++ = (l >> 8) | NS_CMPRSFLGS; + *dstp++ = l % 256; + return (dstp - dst); + } + /* Not found, save it. */ + if (lastdnptr != NULL && cpp < lastdnptr - 1 && + (dstp - msg) < 0x4000 && first) { + *cpp++ = dstp; + *cpp = NULL; + first = 0; + } + } + /* copy label to buffer */ + if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) { + /* Should not happen. */ + goto cleanup; + } + n = labellen(srcp); + if (n + 1 > eob - dstp) { + goto cleanup; + } + memcpy(dstp, srcp, n + 1); + srcp += n + 1; + dstp += n + 1; + } while (n != 0); + + if (dstp > eob) { +cleanup: + if (msg != NULL) + *lpp = NULL; + __set_errno (EMSGSIZE); + return (-1); + } + return (dstp - dst); +} +libresolv_hidden_def (ns_name_pack) + +/*% + * Expand compressed domain name to presentation format. + * + * return: + *\li Number of bytes read out of `src', or -1 (with errno set). + * + * note: + *\li Root domain returns as "." not "". + */ +int +ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src, + char *dst, size_t dstsiz) +{ + u_char tmp[NS_MAXCDNAME]; + int n; + + if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1) + return (-1); + if (ns_name_ntop(tmp, dst, dstsiz) == -1) + return (-1); + return (n); +} +libresolv_hidden_def (ns_name_uncompress) + +/*% + * Compress a domain name into wire format, using compression pointers. + * + * return: + *\li Number of bytes consumed in `dst' or -1 (with errno set). + * + * notes: + *\li 'dnptrs' is an array of pointers to previous compressed names. + *\li dnptrs[0] is a pointer to the beginning of the message. + *\li The list ends with NULL. 'lastdnptr' is a pointer to the end of the + * array pointed to by 'dnptrs'. Side effect is to update the list of + * pointers for labels inserted into the message as we compress the name. + *\li If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr' + * is NULL, we don't update the list. + */ +int +ns_name_compress(const char *src, u_char *dst, size_t dstsiz, + const u_char **dnptrs, const u_char **lastdnptr) +{ + u_char tmp[NS_MAXCDNAME]; + + if (ns_name_pton(src, tmp, sizeof tmp) == -1) + return (-1); + return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr)); +} +libresolv_hidden_def (ns_name_compress) + +/*% + * Reset dnptrs so that there are no active references to pointers at or + * after src. + */ +void +ns_name_rollback(const u_char *src, const u_char **dnptrs, + const u_char **lastdnptr) +{ + while (dnptrs < lastdnptr && *dnptrs != NULL) { + if (*dnptrs >= src) { + *dnptrs = NULL; + break; + } + dnptrs++; + } +} + +/*% + * Advance *ptrptr to skip over the compressed name it points at. + * + * return: + *\li 0 on success, -1 (with errno set) on failure. + */ +int +ns_name_skip(const u_char **ptrptr, const u_char *eom) +{ + const u_char *cp; + u_int n; + + cp = *ptrptr; + while (cp < eom && (n = *cp++) != 0) { + /* Check for indirection. */ + switch (n & NS_CMPRSFLGS) { + case 0: /*%< normal case, n == len */ + cp += n; + continue; + case NS_CMPRSFLGS: /*%< indirection */ + cp++; + break; + default: /*%< illegal type */ + __set_errno (EMSGSIZE); + return (-1); + } + break; + } + if (cp > eom) { + __set_errno (EMSGSIZE); + return (-1); + } + *ptrptr = cp; + return (0); +} +libresolv_hidden_def (ns_name_skip) + +/* Private. */ + +/*% + * Thinking in noninternationalized USASCII (per the DNS spec), + * is this character special ("in need of quoting") ? + * + * return: + *\li boolean. + */ +static int +special(int ch) { + switch (ch) { + case 0x22: /*%< '"' */ + case 0x2E: /*%< '.' */ + case 0x3B: /*%< ';' */ + case 0x5C: /*%< '\\' */ + case 0x28: /*%< '(' */ + case 0x29: /*%< ')' */ + /* Special modifiers in zone files. */ + case 0x40: /*%< '@' */ + case 0x24: /*%< '$' */ + return (1); + default: + return (0); + } +} + +/*% + * Thinking in noninternationalized USASCII (per the DNS spec), + * is this character visible and not a space when printed ? + * + * return: + *\li boolean. + */ +static int +printable(int ch) { + return (ch > 0x20 && ch < 0x7f); +} + +/*% + * Thinking in noninternationalized USASCII (per the DNS spec), + * convert this character to lower case if it's upper case. + */ +static int +mklower(int ch) { + if (ch >= 0x41 && ch <= 0x5A) + return (ch + 0x20); + return (ch); +} + +/*% + * Search for the counted-label name in an array of compressed names. + * + * return: + *\li offset from msg if found, or -1. + * + * notes: + *\li dnptrs is the pointer to the first name on the list, + *\li not the pointer to the start of the message. + */ +static int +dn_find(const u_char *domain, const u_char *msg, + const u_char * const *dnptrs, + const u_char * const *lastdnptr) +{ + const u_char *dn, *cp, *sp; + const u_char * const *cpp; + u_int n; + + for (cpp = dnptrs; cpp < lastdnptr; cpp++) { + sp = *cpp; + /* + * terminate search on: + * root label + * compression pointer + * unusable offset + */ + while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 && + (sp - msg) < 0x4000) { + dn = domain; + cp = sp; + while ((n = *cp++) != 0) { + /* + * check for indirection + */ + switch (n & NS_CMPRSFLGS) { + case 0: /*%< normal case, n == len */ + n = labellen(cp - 1); /*%< XXX */ + if (n != *dn++) + goto next; + + for ((void)NULL; n > 0; n--) + if (mklower(*dn++) != + mklower(*cp++)) + goto next; + /* Is next root for both ? */ + if (*dn == '\0' && *cp == '\0') + return (sp - msg); + if (*dn) + continue; + goto next; + case NS_CMPRSFLGS: /*%< indirection */ + cp = msg + (((n & 0x3f) << 8) | *cp); + break; + + default: /*%< illegal type */ + __set_errno (EMSGSIZE); + return (-1); + } + } + next: ; + sp += *sp + 1; + } + } + __set_errno (ENOENT); + return (-1); +} + +/* Return the length of the encoded label starting at LP, or -1 for + compression references and extended label types. */ +static int +labellen (const unsigned char *lp) +{ + if (*lp <= 63) + return *lp; + return -1; +} + +/*! \file */ diff --git a/REORG.TODO/resolv/ns_netint.c b/REORG.TODO/resolv/ns_netint.c new file mode 100644 index 0000000000..6a365a3b8c --- /dev/null +++ b/REORG.TODO/resolv/ns_netint.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* Import. */ + +#include <arpa/nameser.h> +#include <resolv.h> + +/* Public. */ + +u_int +ns_get16(const u_char *src) { + u_int dst; + + NS_GET16(dst, src); + return (dst); +} +libresolv_hidden_def (ns_get16) +strong_alias (ns_get16, __ns_get16) + +u_long +ns_get32(const u_char *src) { + u_long dst; + + NS_GET32(dst, src); + return (dst); +} +libresolv_hidden_def (ns_get32) +strong_alias (ns_get32, __ns_get32) + +void +ns_put16(u_int src, u_char *dst) { + NS_PUT16(src, dst); +} +libresolv_hidden_def (ns_put16) + +void +ns_put32(u_long src, u_char *dst) { + NS_PUT32(src, dst); +} +libresolv_hidden_def (ns_put32) + +/*! \file */ diff --git a/REORG.TODO/resolv/ns_parse.c b/REORG.TODO/resolv/ns_parse.c new file mode 100644 index 0000000000..863b20a9f7 --- /dev/null +++ b/REORG.TODO/resolv/ns_parse.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * 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 ISC DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC 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. + */ + +/* Import. */ + +#include <sys/types.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> + +#include <errno.h> +#include <resolv.h> +#include <string.h> + +/* Forward. */ + +static void setsection(ns_msg *msg, ns_sect sect); + +/* Macros. */ + +#define RETERR(err) do { __set_errno (err); return (-1); } while (0) + +/* Public. */ + +/* These need to be in the same order as the nres.h:ns_flag enum. */ +const struct _ns_flagdata _ns_flagdata[16] = { + { 0x8000, 15 }, /*%< qr. */ + { 0x7800, 11 }, /*%< opcode. */ + { 0x0400, 10 }, /*%< aa. */ + { 0x0200, 9 }, /*%< tc. */ + { 0x0100, 8 }, /*%< rd. */ + { 0x0080, 7 }, /*%< ra. */ + { 0x0040, 6 }, /*%< z. */ + { 0x0020, 5 }, /*%< ad. */ + { 0x0010, 4 }, /*%< cd. */ + { 0x000f, 0 }, /*%< rcode. */ + { 0x0000, 0 }, /*%< expansion (1/6). */ + { 0x0000, 0 }, /*%< expansion (2/6). */ + { 0x0000, 0 }, /*%< expansion (3/6). */ + { 0x0000, 0 }, /*%< expansion (4/6). */ + { 0x0000, 0 }, /*%< expansion (5/6). */ + { 0x0000, 0 }, /*%< expansion (6/6). */ +}; + +#undef ns_msg_getflag +int ns_msg_getflag(ns_msg handle, int flag) { + return(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift); +} + +int +ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) { + const u_char *optr = ptr; + + for ((void)NULL; count > 0; count--) { + int b, rdlength; + + b = dn_skipname(ptr, eom); + if (b < 0) + RETERR(EMSGSIZE); + ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/; + if (section != ns_s_qd) { + if (ptr + NS_INT32SZ + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + ptr += NS_INT32SZ/*TTL*/; + NS_GET16(rdlength, ptr); + ptr += rdlength/*RData*/; + } + } + if (ptr > eom) + RETERR(EMSGSIZE); + return (ptr - optr); +} +libresolv_hidden_def (ns_skiprr) + +int +ns_initparse(const u_char *msg, int msglen, ns_msg *handle) { + const u_char *eom = msg + msglen; + int i; + + memset(handle, 0x5e, sizeof *handle); + handle->_msg = msg; + handle->_eom = eom; + if (msg + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + NS_GET16(handle->_id, msg); + if (msg + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + NS_GET16(handle->_flags, msg); + for (i = 0; i < ns_s_max; i++) { + if (msg + NS_INT16SZ > eom) + RETERR(EMSGSIZE); + NS_GET16(handle->_counts[i], msg); + } + for (i = 0; i < ns_s_max; i++) + if (handle->_counts[i] == 0) + handle->_sections[i] = NULL; + else { + int b = ns_skiprr(msg, eom, (ns_sect)i, + handle->_counts[i]); + + if (b < 0) + return (-1); + handle->_sections[i] = msg; + msg += b; + } + if (msg != eom) + RETERR(EMSGSIZE); + setsection(handle, ns_s_max); + return (0); +} +libresolv_hidden_def (ns_initparse) + +int +ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) { + int b; + int tmp; + + /* Make section right. */ + tmp = section; + if (tmp < 0 || section >= ns_s_max) + RETERR(ENODEV); + if (section != handle->_sect) + setsection(handle, section); + + /* Make rrnum right. */ + if (rrnum == -1) + rrnum = handle->_rrnum; + if (rrnum < 0 || rrnum >= handle->_counts[(int)section]) + RETERR(ENODEV); + if (rrnum < handle->_rrnum) + setsection(handle, section); + if (rrnum > handle->_rrnum) { + b = ns_skiprr(handle->_msg_ptr, handle->_eom, section, + rrnum - handle->_rrnum); + + if (b < 0) + return (-1); + handle->_msg_ptr += b; + handle->_rrnum = rrnum; + } + + /* Do the parse. */ + b = dn_expand(handle->_msg, handle->_eom, + handle->_msg_ptr, rr->name, NS_MAXDNAME); + if (b < 0) + return (-1); + handle->_msg_ptr += b; + if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom) + RETERR(EMSGSIZE); + NS_GET16(rr->type, handle->_msg_ptr); + NS_GET16(rr->rr_class, handle->_msg_ptr); + if (section == ns_s_qd) { + rr->ttl = 0; + rr->rdlength = 0; + rr->rdata = NULL; + } else { + if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom) + RETERR(EMSGSIZE); + NS_GET32(rr->ttl, handle->_msg_ptr); + NS_GET16(rr->rdlength, handle->_msg_ptr); + if (handle->_msg_ptr + rr->rdlength > handle->_eom) + RETERR(EMSGSIZE); + rr->rdata = handle->_msg_ptr; + handle->_msg_ptr += rr->rdlength; + } + if (++handle->_rrnum > handle->_counts[(int)section]) + setsection(handle, (ns_sect)((int)section + 1)); + + /* All done. */ + return (0); +} +libresolv_hidden_def (ns_parserr) + +/* Private. */ + +static void +setsection(ns_msg *msg, ns_sect sect) { + msg->_sect = sect; + if (sect == ns_s_max) { + msg->_rrnum = -1; + msg->_msg_ptr = NULL; + } else { + msg->_rrnum = 0; + msg->_msg_ptr = msg->_sections[(int)sect]; + } +} + +/*! \file */ diff --git a/REORG.TODO/resolv/ns_print.c b/REORG.TODO/resolv/ns_print.c new file mode 100644 index 0000000000..f55680c311 --- /dev/null +++ b/REORG.TODO/resolv/ns_print.c @@ -0,0 +1,769 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * 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. + */ + +/* Import. */ + +#include <sys/types.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> + +#include <assert.h> +#include <errno.h> +#include <resolv.h> +#include <string.h> +#include <ctype.h> + +#define SPRINTF(x) ((size_t)sprintf x) + +/* Forward. */ + +static size_t prune_origin(const char *name, const char *origin); +static int charstr(const u_char *rdata, const u_char *edata, + char **buf, size_t *buflen); +static int addname(const u_char *msg, size_t msglen, + const u_char **p, const char *origin, + char **buf, size_t *buflen); +static void addlen(size_t len, char **buf, size_t *buflen); +static int addstr(const char *src, size_t len, + char **buf, size_t *buflen); +static int addtab(size_t len, size_t target, int spaced, + char **buf, size_t *buflen); + +/* Macros. */ + +#define T(x) \ + do { \ + if ((x) < 0) \ + return (-1); \ + } while (0) + +/* Public. */ + +/*% + * Convert an RR to presentation format. + * + * return: + *\li Number of characters written to buf, or -1 (check errno). + */ +int +ns_sprintrr(const ns_msg *handle, const ns_rr *rr, + const char *name_ctx, const char *origin, + char *buf, size_t buflen) +{ + int n; + + n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle), + ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr), + ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr), + name_ctx, origin, buf, buflen); + return (n); +} +libresolv_hidden_def (ns_sprintrr) + +/*% + * Convert the fields of an RR into presentation format. + * + * return: + *\li Number of characters written to buf, or -1 (check errno). + */ +int +ns_sprintrrf(const u_char *msg, size_t msglen, + const char *name, ns_class class, ns_type type, + u_long ttl, const u_char *rdata, size_t rdlen, + const char *name_ctx, const char *origin, + char *buf, size_t buflen) +{ + const char *obuf = buf; + const u_char *edata = rdata + rdlen; + int spaced = 0; + + const char *comment; + char tmp[100]; + char errbuf[40]; + int len, x; + + /* + * Owner. + */ + if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) { + T(addstr("\t\t\t", 3, &buf, &buflen)); + } else { + len = prune_origin(name, origin); + if (*name == '\0') { + goto root; + } else if (len == 0) { + T(addstr("@\t\t\t", 4, &buf, &buflen)); + } else { + T(addstr(name, len, &buf, &buflen)); + /* Origin not used or not root, and no trailing dot? */ + if (((origin == NULL || origin[0] == '\0') || + (origin[0] != '.' && origin[1] != '\0' && + name[len] == '\0')) && name[len - 1] != '.') { + root: + T(addstr(".", 1, &buf, &buflen)); + len++; + } + T(spaced = addtab(len, 24, spaced, &buf, &buflen)); + } + } + + /* + * TTL, Class, Type. + */ + T(x = ns_format_ttl(ttl, buf, buflen)); + addlen(x, &buf, &buflen); + len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type))); + T(addstr(tmp, len, &buf, &buflen)); + T(spaced = addtab(x + len, 16, spaced, &buf, &buflen)); + + /* + * RData. + */ + switch (type) { + case ns_t_a: + if (rdlen != (size_t)NS_INADDRSZ) + goto formerr; + (void) inet_ntop(AF_INET, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + break; + + case ns_t_cname: + case ns_t_mb: + case ns_t_mg: + case ns_t_mr: + case ns_t_ns: + case ns_t_ptr: + case ns_t_dname: + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + + case ns_t_hinfo: + case ns_t_isdn: + /* First word. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + + /* Second word, optional in ISDN records. */ + if (type == ns_t_isdn && rdata == edata) + break; + + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + break; + + case ns_t_soa: { + u_long t; + + /* Server name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Administrator name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" (\n", 3, &buf, &buflen)); + spaced = 0; + + if ((edata - rdata) != 5*NS_INT32SZ) + goto formerr; + + /* Serial number. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + len = SPRINTF((tmp, "%lu", t)); + T(addstr(tmp, len, &buf, &buflen)); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; serial\n", 9, &buf, &buflen)); + spaced = 0; + + /* Refresh interval. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; refresh\n", 10, &buf, &buflen)); + spaced = 0; + + /* Retry interval. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; retry\n", 8, &buf, &buflen)); + spaced = 0; + + /* Expiry. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; expiry\n", 9, &buf, &buflen)); + spaced = 0; + + /* Minimum TTL. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + T(addstr("\t\t\t\t\t", 5, &buf, &buflen)); + T(len = ns_format_ttl(t, buf, buflen)); + addlen(len, &buf, &buflen); + T(addstr(" )", 2, &buf, &buflen)); + T(spaced = addtab(len, 16, spaced, &buf, &buflen)); + T(addstr("; minimum\n", 10, &buf, &buflen)); + + break; + } + + case ns_t_mx: + case ns_t_afsdb: + case ns_t_rt: { + u_int t; + + if (rdlen < (size_t)NS_INT16SZ) + goto formerr; + + /* Priority. */ + t = ns_get16(rdata); + rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", t)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Target. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_px: { + u_int t; + + if (rdlen < (size_t)NS_INT16SZ) + goto formerr; + + /* Priority. */ + t = ns_get16(rdata); + rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u ", t)); + T(addstr(tmp, len, &buf, &buflen)); + + /* Name1. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Name2. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_x25: + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + break; + + case ns_t_txt: + while (rdata < edata) { + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + if (rdata < edata) + T(addstr(" ", 1, &buf, &buflen)); + } + break; + + case ns_t_nsap: { + char t[2+255*3]; + + (void) inet_nsap_ntoa(rdlen, rdata, t); + T(addstr(t, strlen(t), &buf, &buflen)); + break; + } + + case ns_t_aaaa: + if (rdlen != (size_t)NS_IN6ADDRSZ) + goto formerr; + (void) inet_ntop(AF_INET6, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + break; + + case ns_t_loc: { + char t[255]; + + /* XXX protocol format checking? */ + (void) loc_ntoa(rdata, t); + T(addstr(t, strlen(t), &buf, &buflen)); + break; + } + + case ns_t_naptr: { + u_int order, preference; + char t[50]; + + if (rdlen < 2U*NS_INT16SZ) + goto formerr; + + /* Order, Precedence. */ + order = ns_get16(rdata); rdata += NS_INT16SZ; + preference = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((t, "%u %u ", order, preference)); + T(addstr(t, len, &buf, &buflen)); + + /* Flags. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Service. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Regexp. */ + T(len = charstr(rdata, edata, &buf, &buflen)); + if (len < 0) + return (-1); + if (len == 0) + goto formerr; + rdata += len; + T(addstr(" ", 1, &buf, &buflen)); + + /* Server. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + } + + case ns_t_srv: { + u_int priority, weight, port; + char t[50]; + + if (rdlen < 3U*NS_INT16SZ) + goto formerr; + + /* Priority, Weight, Port. */ + priority = ns_get16(rdata); rdata += NS_INT16SZ; + weight = ns_get16(rdata); rdata += NS_INT16SZ; + port = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((t, "%u %u %u ", priority, weight, port)); + T(addstr(t, len, &buf, &buflen)); + + /* Server. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + break; + } + + case ns_t_minfo: + case ns_t_rp: + /* Name1. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Name2. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + + case ns_t_wks: { + int n, lcnt; + + if (rdlen < 1U + NS_INT32SZ) + goto formerr; + + /* Address. */ + (void) inet_ntop(AF_INET, rdata, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + rdata += NS_INADDRSZ; + + /* Protocol. */ + len = SPRINTF((tmp, " %u ( ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + rdata += NS_INT8SZ; + + /* Bit map. */ + n = 0; + lcnt = 0; + while (rdata < edata) { + u_int c = *rdata++; + do { + if (c & 0200) { + if (lcnt == 0) { + T(addstr("\n\t\t\t\t", 5, + &buf, &buflen)); + lcnt = 10; + spaced = 0; + } + len = SPRINTF((tmp, "%d ", n)); + T(addstr(tmp, len, &buf, &buflen)); + lcnt--; + } + c <<= 1; + } while (++n & 07); + } + T(addstr(")", 1, &buf, &buflen)); + + break; + } + + case ns_t_cert: { + u_int c_type, key_tag, alg; + int n; + unsigned int siz; + char base64_cert[8192], tmp[40]; + const char *leader; + + c_type = ns_get16(rdata); rdata += NS_INT16SZ; + key_tag = ns_get16(rdata); rdata += NS_INT16SZ; + alg = (u_int) *rdata++; + + len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg)); + T(addstr(tmp, len, &buf, &buflen)); + siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */ + if (siz > sizeof(base64_cert) * 3/4) { + const char *str = "record too long to print"; + T(addstr(str, strlen(str), &buf, &buflen)); + } + else { + len = b64_ntop(rdata, edata-rdata, base64_cert, siz); + + if (len < 0) + goto formerr; + else 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_cert + n, MIN(len - n, 48), + &buf, &buflen)); + } + if (len > 15) + T(addstr(" )", 2, &buf, &buflen)); + } + break; + } + + case ns_t_tkey: { + /* KJD - need to complete this */ + u_long t; + int mode, err, keysize; + + /* Algorithm name. */ + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + + /* Inception. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Experation. */ + t = ns_get32(rdata); rdata += NS_INT32SZ; + len = SPRINTF((tmp, "%s ", p_secstodate(t))); + T(addstr(tmp, len, &buf, &buflen)); + + /* Mode , Error, Key Size. */ + /* Priority, Weight, Port. */ + mode = ns_get16(rdata); rdata += NS_INT16SZ; + err = ns_get16(rdata); rdata += NS_INT16SZ; + keysize = ns_get16(rdata); rdata += NS_INT16SZ; + len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize)); + T(addstr(tmp, len, &buf, &buflen)); + + /* XXX need to dump key, print otherdata length & other data */ + break; + } + + case ns_t_tsig: { + /* BEW - need to complete this */ + int n; + + T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen)); + T(addstr(" ", 1, &buf, &buflen)); + rdata += 8; /*%< time */ + n = ns_get16(rdata); rdata += INT16SZ; + rdata += n; /*%< sig */ + n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */ + sprintf(buf, "%d", ns_get16(rdata)); + rdata += INT16SZ; + addlen(strlen(buf), &buf, &buflen); + break; + } + + case ns_t_a6: { + struct in6_addr a; + int pbyte, pbit; + + /* prefix length */ + if (rdlen == 0U) goto formerr; + len = SPRINTF((tmp, "%d ", *rdata)); + T(addstr(tmp, len, &buf, &buflen)); + pbit = *rdata; + if (pbit > 128) goto formerr; + pbyte = (pbit & ~7) / 8; + rdata++; + + /* address suffix: provided only when prefix len != 128 */ + if (pbit < 128) { + if (rdata + pbyte >= edata) goto formerr; + memset(&a, 0, sizeof(a)); + memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte); + (void) inet_ntop(AF_INET6, &a, buf, buflen); + addlen(strlen(buf), &buf, &buflen); + rdata += sizeof(a) - pbyte; + } + + /* prefix name: provided only when prefix len > 0 */ + if (pbit == 0) + break; + if (rdata >= edata) goto formerr; + T(addstr(" ", 1, &buf, &buflen)); + T(addname(msg, msglen, &rdata, origin, &buf, &buflen)); + + break; + } + + case ns_t_opt: { + len = SPRINTF((tmp, "%u bytes", class)); + T(addstr(tmp, len, &buf, &buflen)); + break; + } + + default: + snprintf (errbuf, sizeof (errbuf), "unknown RR type %d", type); + comment = errbuf; + goto hexify; + } + return (buf - obuf); + formerr: + comment = "RR format error"; + hexify: { + int n, m; + char *p; + + len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata), + rdlen != 0U ? " (" : "", comment)); + T(addstr(tmp, len, &buf, &buflen)); + while (rdata < edata) { + p = tmp; + p += SPRINTF((p, "\n\t")); + spaced = 0; + n = MIN(16, edata - rdata); + for (m = 0; m < n; m++) + p += SPRINTF((p, "%02x ", rdata[m])); + T(addstr(tmp, p - tmp, &buf, &buflen)); + if (n < 16) { + T(addstr(")", 1, &buf, &buflen)); + T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen)); + } + p = tmp; + p += SPRINTF((p, "; ")); + for (m = 0; m < n; m++) + *p++ = (isascii(rdata[m]) && isprint(rdata[m])) + ? rdata[m] + : '.'; + T(addstr(tmp, p - tmp, &buf, &buflen)); + rdata += n; + } + return (buf - obuf); + } +} +libresolv_hidden_def (ns_sprintrrf) + +/* Private. */ + +/*% + * size_t + * prune_origin(name, origin) + * Find out if the name is at or under the current origin. + * return: + * Number of characters in name before start of origin, + * or length of name if origin does not match. + * notes: + * This function should share code with samedomain(). + */ +static size_t +prune_origin(const char *name, const char *origin) { + const char *oname = name; + + while (*name != '\0') { + if (origin != NULL && ns_samename(name, origin) == 1) + return (name - oname - (name > oname)); + while (*name != '\0') { + if (*name == '\\') { + name++; + /* XXX need to handle \nnn form. */ + if (*name == '\0') + break; + } else if (*name == '.') { + name++; + break; + } + name++; + } + } + return (name - oname); +} + +/*% + * int + * charstr(rdata, edata, buf, buflen) + * Format a <character-string> into the presentation buffer. + * return: + * Number of rdata octets consumed + * 0 for protocol format error + * -1 for output buffer error + * side effects: + * buffer is advanced on success. + */ +static int +charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) { + const u_char *odata = rdata; + size_t save_buflen = *buflen; + char *save_buf = *buf; + + if (addstr("\"", 1, buf, buflen) < 0) + goto enospc; + if (rdata < edata) { + int n = *rdata; + + if (rdata + 1 + n <= edata) { + rdata++; + while (n-- > 0) { + if (strchr("\n\"\\", *rdata) != NULL) + if (addstr("\\", 1, buf, buflen) < 0) + goto enospc; + if (addstr((const char *)rdata, 1, + buf, buflen) < 0) + goto enospc; + rdata++; + } + } + } + if (addstr("\"", 1, buf, buflen) < 0) + goto enospc; + return (rdata - odata); + enospc: + __set_errno (ENOSPC); + *buf = save_buf; + *buflen = save_buflen; + return (-1); +} + +static int +addname(const u_char *msg, size_t msglen, + const u_char **pp, const char *origin, + char **buf, size_t *buflen) +{ + size_t newlen, save_buflen = *buflen; + char *save_buf = *buf; + int n; + + n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen); + if (n < 0) + goto enospc; /*%< Guess. */ + newlen = prune_origin(*buf, origin); + if (**buf == '\0') { + goto root; + } else if (newlen == 0U) { + /* Use "@" instead of name. */ + if (newlen + 2 > *buflen) + goto enospc; /* No room for "@\0". */ + (*buf)[newlen++] = '@'; + (*buf)[newlen] = '\0'; + } else { + if (((origin == NULL || origin[0] == '\0') || + (origin[0] != '.' && origin[1] != '\0' && + (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') { + /* No trailing dot. */ + root: + if (newlen + 2 > *buflen) + goto enospc; /* No room for ".\0". */ + (*buf)[newlen++] = '.'; + (*buf)[newlen] = '\0'; + } + } + *pp += n; + addlen(newlen, buf, buflen); + **buf = '\0'; + return (newlen); + enospc: + __set_errno (ENOSPC); + *buf = save_buf; + *buflen = save_buflen; + return (-1); +} + +static void +addlen(size_t len, char **buf, size_t *buflen) { + assert(len <= *buflen); + *buf += len; + *buflen -= len; +} + +static int +addstr(const char *src, size_t len, char **buf, size_t *buflen) { + if (len >= *buflen) { + __set_errno (ENOSPC); + return (-1); + } + memcpy(*buf, src, len); + addlen(len, buf, buflen); + **buf = '\0'; + return (0); +} + +static int +addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) { + size_t save_buflen = *buflen; + char *save_buf = *buf; + int t; + + if (spaced || len >= target - 1) { + T(addstr(" ", 2, buf, buflen)); + spaced = 1; + } else { + for (t = (target - len - 1) / 8; t >= 0; t--) + if (addstr("\t", 1, buf, buflen) < 0) { + *buflen = save_buflen; + *buf = save_buf; + return (-1); + } + spaced = 0; + } + return (spaced); +} diff --git a/REORG.TODO/resolv/ns_samedomain.c b/REORG.TODO/resolv/ns_samedomain.c new file mode 100644 index 0000000000..5d1bf39fc7 --- /dev/null +++ b/REORG.TODO/resolv/ns_samedomain.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * 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 <sys/types.h> +#include <arpa/nameser.h> +#include <errno.h> +#include <string.h> + +/*% + * Check whether a name belongs to a domain. + * + * Inputs: + *\li a - the domain whose ancestry is being verified + *\li b - the potential ancestor we're checking against + * + * Return: + *\li boolean - is a at or below b? + * + * Notes: + *\li Trailing dots are first removed from name and domain. + * Always compare complete subdomains, not only whether the + * domain name is the trailing string of the given name. + * + *\li "host.foobar.top" lies in "foobar.top" and in "top" and in "" + * but NOT in "bar.top" + */ + +int +ns_samedomain(const char *a, const char *b) { + size_t la, lb; + int diff, i, escaped; + const char *cp; + + la = strlen(a); + lb = strlen(b); + + /* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */ + if (la != 0U && a[la - 1] == '.') { + escaped = 0; + /* Note this loop doesn't get executed if la==1. */ + for (i = la - 2; i >= 0; i--) + if (a[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else + break; + if (!escaped) + la--; + } + + /* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */ + if (lb != 0U && b[lb - 1] == '.') { + escaped = 0; + /* note this loop doesn't get executed if lb==1 */ + for (i = lb - 2; i >= 0; i--) + if (b[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else + break; + if (!escaped) + lb--; + } + + /* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */ + if (lb == 0U) + return (1); + + /* 'b' longer than 'a' means 'a' can't be in 'b'. */ + if (lb > la) + return (0); + + /* 'a' and 'b' being equal at this point indicates sameness. */ + if (lb == la) + return (strncasecmp(a, b, lb) == 0); + + /* Ok, we know la > lb. */ + + diff = la - lb; + + /* + * If 'a' is only 1 character longer than 'b', then it can't be + * a subdomain of 'b' (because of the need for the '.' label + * separator). + */ + if (diff < 2) + return (0); + + /* + * If the character before the last 'lb' characters of 'b' + * isn't '.', then it can't be a match (this lets us avoid + * having "foobar.com" match "bar.com"). + */ + if (a[diff - 1] != '.') + return (0); + + /* + * We're not sure about that '.', however. It could be escaped + * and thus not a really a label separator. + */ + escaped = 0; + for (i = diff - 2; i >= 0; i--) + if (a[i] == '\\') { + if (escaped) + escaped = 0; + else + escaped = 1; + } else + break; + if (escaped) + return (0); + + /* Now compare aligned trailing substring. */ + cp = a + diff; + return (strncasecmp(cp, b, lb) == 0); +} +libresolv_hidden_def (ns_samedomain) + +/*% + * is "a" a subdomain of "b"? + */ +int +ns_subdomain(const char *a, const char *b) { + return (ns_samename(a, b) != 1 && ns_samedomain(a, b)); +} + +/*% + * make a canonical copy of domain name "src" + * + * notes: + * \code + * foo -> foo. + * foo. -> foo. + * foo.. -> foo. + * foo\. -> foo\.. + * foo\\. -> foo\\. + * \endcode + */ + +int +ns_makecanon(const char *src, char *dst, size_t dstsize) { + size_t n = strlen(src); + + if (n + sizeof "." > dstsize) { /*%< Note: sizeof == 2 */ + __set_errno (EMSGSIZE); + return (-1); + } + strcpy(dst, src); + while (n >= 1U && dst[n - 1] == '.') /*%< Ends in "." */ + if (n >= 2U && dst[n - 2] == '\\' && /*%< Ends in "\." */ + (n < 3U || dst[n - 3] != '\\')) /*%< But not "\\." */ + break; + else + dst[--n] = '\0'; + dst[n++] = '.'; + dst[n] = '\0'; + return (0); +} +libresolv_hidden_def (ns_makecanon) + +/*% + * determine whether domain name "a" is the same as domain name "b" + * + * return: + *\li -1 on error + *\li 0 if names differ + *\li 1 if names are the same + */ + +int +ns_samename(const char *a, const char *b) { + char ta[NS_MAXDNAME], tb[NS_MAXDNAME]; + + if (ns_makecanon(a, ta, sizeof ta) < 0 || + ns_makecanon(b, tb, sizeof tb) < 0) + return (-1); + if (strcasecmp(ta, tb) == 0) + return (1); + else + return (0); +} +libresolv_hidden_def (ns_samename) + +/*! \file */ diff --git a/REORG.TODO/resolv/ns_ttl.c b/REORG.TODO/resolv/ns_ttl.c new file mode 100644 index 0000000000..079948790b --- /dev/null +++ b/REORG.TODO/resolv/ns_ttl.c @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") + * 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. + */ + +/* Import. */ + +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) ((size_t)sprintf x) +#endif + +/* Forward. */ + +static int fmt1(int t, char s, char **buf, size_t *buflen); + +/* Macros. */ + +#define T(x) if ((x) < 0) return (-1); else (void)NULL + +/* Public. */ + +int +ns_format_ttl(u_long src, char *dst, size_t dstlen) { + char *odst = dst; + int secs, mins, hours, days, weeks, x; + char *p; + + secs = src % 60; src /= 60; + mins = src % 60; src /= 60; + hours = src % 24; src /= 24; + days = src % 7; src /= 7; + weeks = src; src = 0; + + x = 0; + if (weeks) { + T(fmt1(weeks, 'W', &dst, &dstlen)); + x++; + } + if (days) { + T(fmt1(days, 'D', &dst, &dstlen)); + x++; + } + if (hours) { + T(fmt1(hours, 'H', &dst, &dstlen)); + x++; + } + if (mins) { + T(fmt1(mins, 'M', &dst, &dstlen)); + x++; + } + if (secs || !(weeks || days || hours || mins)) { + T(fmt1(secs, 'S', &dst, &dstlen)); + x++; + } + + if (x > 1) { + int ch; + + for (p = odst; (ch = *p) != '\0'; p++) + if (isascii(ch) && isupper(ch)) + *p = tolower(ch); + } + + return (dst - odst); +} +libresolv_hidden_def (ns_format_ttl) + +// Seems not to be needed. It's not exported from the DSO. Some libresolv.a +// might depend on it so we let it in. +int +ns_parse_ttl(const char *src, u_long *dst) { + u_long ttl, tmp; + int ch, digits, dirty; + + ttl = 0; + tmp = 0; + digits = 0; + dirty = 0; + while ((ch = *src++) != '\0') { + if (!isascii(ch) || !isprint(ch)) + goto einval; + if (isdigit(ch)) { + tmp *= 10; + tmp += (ch - '0'); + digits++; + continue; + } + if (digits == 0) + goto einval; + if (islower(ch)) + ch = toupper(ch); + switch (ch) { + case 'W': tmp *= 7; + case 'D': tmp *= 24; + case 'H': tmp *= 60; + case 'M': tmp *= 60; + case 'S': break; + default: goto einval; + } + ttl += tmp; + tmp = 0; + digits = 0; + dirty = 1; + } + if (digits > 0) { + if (dirty) + goto einval; + else + ttl += tmp; + } else if (!dirty) + goto einval; + *dst = ttl; + return (0); + + einval: + __set_errno (EINVAL); + return (-1); +} + +/* Private. */ + +static int +fmt1(int t, char s, char **buf, size_t *buflen) { + char tmp[50]; + size_t len; + + len = SPRINTF((tmp, "%d%c", t, s)); + if (len + 1 > *buflen) + return (-1); + strcpy(*buf, tmp); + *buf += len; + *buflen -= len; + return (0); +} + +/*! \file */ diff --git a/REORG.TODO/resolv/nsap_addr.c b/REORG.TODO/resolv/nsap_addr.c new file mode 100644 index 0000000000..9a1d3f7fdc --- /dev/null +++ b/REORG.TODO/resolv/nsap_addr.c @@ -0,0 +1,92 @@ +/* + * 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 <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <resolv.h> + +static char +xtob(int c) { + return (c - (((c >= '0') && (c <= '9')) ? '0' : '7')); +} + +u_int +inet_nsap_addr(const char *ascii, u_char *binary, int maxlen) { + u_char c, nib; + u_int len = 0; + + while ((c = *ascii++) != '\0' && len < (u_int)maxlen) { + if (c == '.' || c == '+' || c == '/') + continue; + if (!isascii(c)) + return (0); + c = toupper(c); + if (isxdigit(c)) { + nib = xtob(c); + c = *ascii++; + if (c != '\0') { + c = toupper(c); + if (isxdigit(c)) { + *binary++ = (nib << 4) | xtob(c); + len++; + } else + return (0); + } + else + return (0); + } + else + return (0); + } + return (len); +} + +char * +inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) { + int nib; + int i; + static char tmpbuf[255*2 + 128]; + char *start; + + if (ascii) + start = ascii; + else { + ascii = tmpbuf; + start = tmpbuf; + } + + if (binlen > 255) + binlen = 255; + + for (i = 0; i < binlen; i++) { + nib = *binary >> 4; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + nib = *binary++ & 0x0f; + *ascii++ = nib + (nib < 10 ? '0' : '7'); + if (((i % 2) == 0 && (i + 1) < binlen)) + *ascii++ = '.'; + } + *ascii = '\0'; + return (start); +} diff --git a/REORG.TODO/resolv/nss_dns/dns-canon.c b/REORG.TODO/resolv/nss_dns/dns-canon.c new file mode 100644 index 0000000000..4276eb6542 --- /dev/null +++ b/REORG.TODO/resolv/nss_dns/dns-canon.c @@ -0,0 +1,173 @@ +/* Copyright (C) 2004-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@redhat.com>, 2004. + + 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 <stdlib.h> +#include <stdint.h> +#include <arpa/nameser.h> +#include <nsswitch.h> + + +#if PACKETSZ > 65536 +# define MAXPACKET PACKETSZ +#else +# define MAXPACKET 65536 +#endif + + +/* We need this time later. */ +typedef union querybuf +{ + HEADER hdr; + unsigned char buf[MAXPACKET]; +} querybuf; + + +static const short int qtypes[] = { ns_t_a, ns_t_aaaa }; +#define nqtypes (sizeof (qtypes) / sizeof (qtypes[0])) + + +enum nss_status +_nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen, + char **result,int *errnop, int *h_errnop) +{ + /* Just an alibi buffer, res_nquery will allocate a real buffer for + us. */ + unsigned char buf[20]; + union + { + querybuf *buf; + unsigned char *ptr; + } ansp = { .ptr = buf }; + enum nss_status status = 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); + if (r > 0) + { + /* We need to decode the response. Just one question record. + And if we got no answers we bail out, too. */ + if (ansp.buf->hdr.qdcount != htons (1)) + continue; + + /* Number of answers. */ + unsigned int ancount = ntohs (ansp.buf->hdr.ancount); + + /* Beginning and end of the buffer with query, answer, and the + rest. */ + unsigned char *ptr = &ansp.buf->buf[sizeof (HEADER)]; + unsigned char *endptr = ansp.ptr + r; + + /* Skip over the query. This is the name, type, and class. */ + int s = __dn_skipname (ptr, endptr); + if (s < 0) + { + unavail: + status = NSS_STATUS_UNAVAIL; + break; + } + + /* Skip over the name and the two 16-bit values containing type + and class. */ + ptr += s + 2 * sizeof (uint16_t); + + while (ancount-- > 0) + { + /* Now the reply. First again the name from the query, + then type, class, TTL, and the length of the RDATA. + We remember the name start. */ + unsigned char *namestart = ptr; + s = __dn_skipname (ptr, endptr); + if (s < 0) + goto unavail; + + 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); + if (type == qtypes[i]) + { + /* We found the record. */ + s = __dn_expand (ansp.buf->buf, endptr, namestart, + buffer, buflen); + if (s < 0) + { + if (errno != EMSGSIZE) + goto unavail; + + /* The buffer is too small. */ + *errnop = ERANGE; + status = NSS_STATUS_TRYAGAIN; + h_errno = NETDB_INTERNAL; + } + else + { + /* Success. */ + *result = buffer; + status = NSS_STATUS_SUCCESS; + } + + goto out; + } + + if (type != ns_t_cname) + goto unavail; + + if (__ns_get16 (ptr) != ns_c_in) + goto unavail; + + /* Also skip over class and TTL. */ + ptr += sizeof (uint16_t) + sizeof (uint32_t); + + /* 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: + *h_errnop = h_errno; + + if (ansp.ptr != buf) + free (ansp.ptr); + + return status; +} diff --git a/REORG.TODO/resolv/nss_dns/dns-host.c b/REORG.TODO/resolv/nss_dns/dns-host.c new file mode 100644 index 0000000000..f121aa3de7 --- /dev/null +++ b/REORG.TODO/resolv/nss_dns/dns-host.c @@ -0,0 +1,1333 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996. + + 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/>. */ + +/* Parts of this file are plain copies of the file `gethtnamadr.c' from + the bind package and it has the following copyright. */ + +/* + * ++Copyright++ 1985, 1988, 1993 + * - + * Copyright (c) 1985, 1988, 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. + * - + * --Copyright-- + */ + +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> + +#include "nsswitch.h" +#include <arpa/nameser.h> + +/* Get implementeation for some internal functions. */ +#include <resolv/resolv-internal.h> +#include <resolv/mapv4v6addr.h> +#include <resolv/mapv4v6hostent.h> + +#define RESOLVSORT + +#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 + +/* We need this time later. */ +typedef union querybuf +{ + HEADER hdr; + u_char buf[MAXPACKET]; +} querybuf; + +static enum nss_status getanswer_r (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); + +static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1, + const querybuf *answer2, int anslen2, + const char *qname, + struct gaih_addrtuple **pat, + char *buffer, size_t buflen, + 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) + +/* 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) +{ + union + { + querybuf *buf; + u_char *ptr; + } host_buffer; + querybuf *orig_host_buffer; + char tmp[NS_MAXDNAME]; + int size, type, n; + const char *cp; + int map = 0; + 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; + type = T_A; + break; + case AF_INET6: + size = IN6ADDRSZ; + type = T_AAAA; + break; + default: + *h_errnop = NO_DATA; + *errnop = EAFNOSUPPORT; + return NSS_STATUS_UNAVAIL; + } + + result->h_addrtype = af; + result->h_length = size; + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_query() since we are not the only + * function that looks up host names. + */ + if (strchr (name, '.') == NULL + && (cp = res_hostalias (&_res, 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); + if (n < 0) + { + switch (errno) + { + case ESRCH: + status = NSS_STATUS_TRYAGAIN; + h_errno = TRY_AGAIN; + break; + /* System has run out of file descriptors. */ + case EMFILE: + case ENFILE: + h_errno = NETDB_INTERNAL; + /* Fall through. */ + case ECONNREFUSED: + case ETIMEDOUT: + status = NSS_STATUS_UNAVAIL; + break; + default: + status = NSS_STATUS_NOTFOUND; + break; + } + *h_errnop = h_errno; + if (h_errno == TRY_AGAIN) + *errnop = EAGAIN; + else + __set_errno (olderr); + + /* 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_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 (n < 0) + { + if (host_buffer.buf != orig_host_buffer) + free (host_buffer.buf); + return status; + } + + map = 1; + + result->h_addrtype = AF_INET; + result->h_length = INADDRSZ; + } + + status = getanswer_r (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, + char *buffer, size_t buflen, int *errnop, + int *h_errnop) +{ + return _nss_dns_gethostbyname3_r (name, af, result, buffer, buflen, errnop, + h_errnop, NULL, NULL); +} + + +enum nss_status +_nss_dns_gethostbyname_r (const char *name, struct hostent *result, + char *buffer, size_t buflen, int *errnop, + int *h_errnop) +{ + enum nss_status status = NSS_STATUS_NOTFOUND; + + if (res_use_inet6 ()) + status = _nss_dns_gethostbyname3_r (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); + + return status; +} + + +enum nss_status +_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; + + /* + * if there aren't any dots, it could be a user-level alias. + * this is also done in res_query() since we are not the only + * function that looks up host names. + */ + if (strchr (name, '.') == NULL) + { + char *tmp = alloca (NS_MAXDNAME); + const char *cp = res_hostalias (&_res, name, tmp, NS_MAXDNAME); + if (cp != NULL) + name = cp; + } + + union + { + querybuf *buf; + u_char *ptr; + } host_buffer; + querybuf *orig_host_buffer; + host_buffer.buf = orig_host_buffer = (querybuf *) alloca (2048); + u_char *ans2p = NULL; + int nans2p = 0; + int resplen2 = 0; + int ans2p_malloced = 0; + + int olderr = errno; + enum nss_status status; + int n = __libc_res_nsearch (&_res, 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, + resplen2, name, pat, buffer, buflen, + errnop, herrnop, ttlp); + } + else + { + switch (errno) + { + case ESRCH: + status = NSS_STATUS_TRYAGAIN; + h_errno = TRY_AGAIN; + break; + /* System has run out of file descriptors. */ + case EMFILE: + case ENFILE: + h_errno = NETDB_INTERNAL; + /* Fall through. */ + case ECONNREFUSED: + case ETIMEDOUT: + status = NSS_STATUS_UNAVAIL; + break; + default: + status = NSS_STATUS_NOTFOUND; + break; + } + + *herrnop = h_errno; + if (h_errno == TRY_AGAIN) + *errnop = EAGAIN; + else + __set_errno (olderr); + } + + /* Check whether ans2p was separately allocated. */ + if (ans2p_malloced) + free (ans2p); + + if (host_buffer.buf != orig_host_buffer) + free (host_buffer.buf); + + return status; +} + + +extern enum nss_status _nss_dns_gethostbyaddr2_r (const void *addr, + socklen_t len, int af, + struct hostent *result, + char *buffer, size_t buflen, + int *errnop, int *h_errnop, + int32_t *ttlp); +hidden_proto (_nss_dns_gethostbyaddr2_r) + +enum nss_status +_nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af, + struct hostent *result, char *buffer, size_t buflen, + int *errnop, int *h_errnop, int32_t *ttlp) +{ + static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff }; + static const u_char tunnelled[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0,0 }; + static const u_char v6local[] = { 0,0, 0,1 }; + const u_char *uaddr = (const u_char *)addr; + struct host_data + { + char *aliases[MAX_NR_ALIASES]; + unsigned char host_addr[16]; /* IPv4 or IPv6 */ + char *h_addr_ptrs[MAX_NR_ADDRS + 1]; + char linebuffer[0]; + } *host_data = (struct host_data *) buffer; + union + { + querybuf *buf; + u_char *ptr; + } host_buffer; + querybuf *orig_host_buffer; + char qbuf[MAXDNAME+1], *qp = NULL; + size_t size; + int n, status; + int olderr = errno; + + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); + buffer += pad; + buflen = buflen > pad ? buflen - pad : 0; + + if (__glibc_unlikely (buflen < sizeof (struct host_data))) + { + *errnop = ERANGE; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + host_data = (struct host_data *) buffer; + + if (__res_maybe_init (&_res, 0) == -1) + return NSS_STATUS_UNAVAIL; + + if (af == AF_INET6 && len == IN6ADDRSZ + && (memcmp (uaddr, mapped, sizeof mapped) == 0 + || (memcmp (uaddr, tunnelled, sizeof tunnelled) == 0 + && memcmp (&uaddr[sizeof tunnelled], v6local, sizeof v6local)))) + { + /* Unmap. */ + addr += sizeof mapped; + uaddr += sizeof mapped; + af = AF_INET; + len = INADDRSZ; + } + + switch (af) + { + case AF_INET: + size = INADDRSZ; + break; + case AF_INET6: + size = IN6ADDRSZ; + break; + default: + *errnop = EAFNOSUPPORT; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } + if (size > len) + { + *errnop = EAFNOSUPPORT; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_UNAVAIL; + } + + host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024); + + switch (af) + { + case AF_INET: + sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", (uaddr[3] & 0xff), + (uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff)); + break; + case AF_INET6: + qp = qbuf; + for (n = IN6ADDRSZ - 1; n >= 0; n--) + { + static const char nibblechar[16] = "0123456789abcdef"; + *qp++ = nibblechar[uaddr[n] & 0xf]; + *qp++ = '.'; + *qp++ = nibblechar[(uaddr[n] >> 4) & 0xf]; + *qp++ = '.'; + } + strcpy(qp, "ip6.arpa"); + break; + default: + /* Cannot happen. */ + 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) + { + *h_errnop = h_errno; + __set_errno (olderr); + if (host_buffer.buf != orig_host_buffer) + free (host_buffer.buf); + return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND; + } + + status = getanswer_r (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; + + 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; + *h_errnop = NETDB_SUCCESS; + return NSS_STATUS_SUCCESS; +} +hidden_def (_nss_dns_gethostbyaddr2_r) + + +enum nss_status +_nss_dns_gethostbyaddr_r (const void *addr, socklen_t len, int af, + struct hostent *result, char *buffer, size_t buflen, + int *errnop, int *h_errnop) +{ + return _nss_dns_gethostbyaddr2_r (addr, len, af, result, buffer, buflen, + errnop, h_errnop, NULL); +} + +static void addrsort (char **ap, int num); + +static void +addrsort (char **ap, int num) +{ + int i, j; + char **p; + short aval[MAX_NR_ADDRS]; + int needsort = 0; + + 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; + aval[i] = j; + if (needsort == 0 && i > 0 && j < aval[i-1]) + needsort = i; + } + if (!needsort) + return; + + while (needsort++ < num) + for (j = needsort - 2; j >= 0; j--) + if (aval[j] > aval[j+1]) + { + char *hp; + + i = aval[j]; + aval[j] = aval[j+1]; + aval[j+1] = i; + + hp = ap[j]; + ap[j] = ap[j+1]; + ap[j+1] = hp; + } + else + break; +} + +static enum nss_status +getanswer_r (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) +{ + struct host_data + { + char *aliases[MAX_NR_ALIASES]; + unsigned char host_addr[16]; /* IPv4 or IPv6 */ + char *h_addr_ptrs[0]; + } *host_data; + int linebuflen; + const HEADER *hp; + const u_char *end_of_message, *cp; + int n, ancount, qdcount; + int haveanswer, had_error; + char *bp, **ap, **hap; + char tbuf[MAXDNAME]; + const char *tname; + int (*name_ok) (const char *); + u_char packtmp[NS_MAXCDNAME]; + int have_to_map = 0; + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data); + buffer += pad; + buflen = buflen > pad ? buflen - pad : 0; + if (__glibc_unlikely (buflen < sizeof (struct host_data))) + { + /* The buffer is too small. */ + too_small: + *errnop = ERANGE; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + host_data = (struct host_data *) buffer; + linebuflen = buflen - sizeof (struct host_data); + if (buflen - sizeof (struct host_data) != linebuflen) + linebuflen = INT_MAX; + + tname = qname; + result->h_name = NULL; + end_of_message = answer->buf + anslen; + switch (qtype) + { + case T_A: + case T_AAAA: + name_ok = res_hnok; + break; + case T_PTR: + name_ok = res_dnok; + break; + default: + *errnop = ENOENT; + return NSS_STATUS_UNAVAIL; /* XXX should be abort(); */ + } + + /* + * find first satisfactory answer + */ + hp = &answer->hdr; + ancount = ntohs (hp->ancount); + qdcount = ntohs (hp->qdcount); + cp = answer->buf + HFIXEDSZ; + if (__glibc_unlikely (qdcount != 1)) + { + *h_errnop = NO_RECOVERY; + return NSS_STATUS_UNAVAIL; + } + if (sizeof (struct host_data) + (ancount + 1) * sizeof (char *) >= buflen) + goto too_small; + bp = (char *) &host_data->h_addr_ptrs[ancount + 1]; + linebuflen -= (ancount + 1) * sizeof (char *); + + n = __ns_name_unpack (answer->buf, end_of_message, cp, + packtmp, sizeof packtmp); + if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1) + { + if (__glibc_unlikely (errno == EMSGSIZE)) + goto too_small; + + n = -1; + } + + if (n > 0 && bp[0] == '.') + bp[0] = '\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) + { + /* res_send() has already verified that the query name is the + * same as the one we sent; this just gets the expanded name + * (i.e., with the succeeding search-domain tacked on). + */ + n = strlen (bp) + 1; /* for the \0 */ + if (n >= MAXHOSTNAMELEN) + { + *h_errnop = NO_RECOVERY; + *errnop = ENOENT; + return NSS_STATUS_TRYAGAIN; + } + result->h_name = bp; + bp += n; + linebuflen -= n; + if (linebuflen < 0) + goto too_small; + /* The qname can be abbreviated, but h_name is now absolute. */ + qname = result->h_name; + } + + ap = host_data->aliases; + *ap = NULL; + result->h_aliases = host_data->aliases; + hap = host_data->h_addr_ptrs; + *hap = NULL; + result->h_addr_list = host_data->h_addr_ptrs; + haveanswer = 0; + had_error = 0; + + while (ancount-- > 0 && cp < end_of_message && had_error == 0) + { + int type, class; + + n = __ns_name_unpack (answer->buf, end_of_message, cp, + packtmp, sizeof packtmp); + if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1) + { + if (__glibc_unlikely (errno == EMSGSIZE)) + goto too_small; + + n = -1; + } + + if (__glibc_unlikely (n < 0 || (*name_ok) (bp) == 0)) + { + ++had_error; + continue; + } + cp += n; /* name */ + + if (__glibc_unlikely (cp + 10 > end_of_message)) + { + ++had_error; + continue; + } + + type = __ns_get16 (cp); + cp += INT16SZ; /* type */ + class = __ns_get16 (cp); + cp += INT16SZ; /* class */ + int32_t ttl = __ns_get32 (cp); + 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? */ + cp += n; + continue; /* XXX - had_error++ ? */ + } + + if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) + { + /* A CNAME could also have a TTL entry. */ + if (ttlp != NULL && ttl < *ttlp) + *ttlp = ttl; + + if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1]) + continue; + n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf); + if (__glibc_unlikely (n < 0 || (*name_ok) (tbuf) == 0)) + { + ++had_error; + continue; + } + cp += n; + /* Store alias. */ + *ap++ = bp; + n = strlen (bp) + 1; /* For the \0. */ + if (__glibc_unlikely (n >= MAXHOSTNAMELEN)) + { + ++had_error; + continue; + } + bp += n; + linebuflen -= n; + /* Get canonical name. */ + n = strlen (tbuf) + 1; /* For the \0. */ + if (__glibc_unlikely (n > linebuflen)) + goto too_small; + if (__glibc_unlikely (n >= MAXHOSTNAMELEN)) + { + ++had_error; + continue; + } + result->h_name = bp; + bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */ + linebuflen -= n; + continue; + } + + if (qtype == T_PTR && type == T_CNAME) + { + /* A CNAME could also have a TTL entry. */ + if (ttlp != NULL && ttl < *ttlp) + *ttlp = ttl; + + n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf); + if (__glibc_unlikely (n < 0 || res_dnok (tbuf) == 0)) + { + ++had_error; + continue; + } + cp += n; + /* Get canonical name. */ + n = strlen (tbuf) + 1; /* For the \0. */ + if (__glibc_unlikely (n > linebuflen)) + goto too_small; + if (__glibc_unlikely (n >= MAXHOSTNAMELEN)) + { + ++had_error; + continue; + } + tname = bp; + bp = __mempcpy (bp, tbuf, n); /* Cannot overflow. */ + linebuflen -= n; + continue; + } + + if (type == T_A && qtype == T_AAAA && map) + have_to_map = 1; + else if (__glibc_unlikely (type != qtype)) + { + cp += n; + continue; /* XXX - had_error++ ? */ + } + + switch (type) + { + case T_PTR: + if (__glibc_unlikely (strcasecmp (tname, bp) != 0)) + { + cp += n; + continue; /* XXX - had_error++ ? */ + } + + n = __ns_name_unpack (answer->buf, end_of_message, cp, + packtmp, sizeof packtmp); + if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1) + { + if (__glibc_unlikely (errno == EMSGSIZE)) + goto too_small; + + n = -1; + } + + if (__glibc_unlikely (n < 0 || res_hnok (bp) == 0)) + { + ++had_error; + break; + } + if (ttlp != NULL && ttl < *ttlp) + *ttlp = ttl; + /* 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 (__glibc_unlikely (strcasecmp (result->h_name, bp) != 0)) + { + 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; + continue; + } + if (!haveanswer) + { + int nn; + + /* We compose a single hostent out of the entire chain of + entries, so the TTL of the hostent is essentially the lowest + TTL in the chain. */ + if (ttlp != NULL && ttl < *ttlp) + *ttlp = ttl; + if (canonp != NULL) + *canonp = bp; + result->h_name = bp; + nn = strlen (bp) + 1; /* for the \0 */ + bp += nn; + linebuflen -= nn; + } + + linebuflen -= sizeof (align) - ((u_long) bp % sizeof (align)); + bp += sizeof (align) - ((u_long) bp % sizeof (align)); + + if (__glibc_unlikely (n > linebuflen)) + goto too_small; + bp = __mempcpy (*hap++ = bp, cp, n); + cp += n; + linebuflen -= n; + break; + default: + abort (); + } + if (had_error == 0) + ++haveanswer; + } + + if (haveanswer > 0) + { + *ap = NULL; + *hap = NULL; + /* + * 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); + + if (result->h_name == NULL) + { + n = strlen (qname) + 1; /* For the \0. */ + if (n > linebuflen) + goto too_small; + if (n >= MAXHOSTNAMELEN) + goto no_recovery; + result->h_name = bp; + bp = __mempcpy (bp, qname, n); /* Cannot overflow. */ + linebuflen -= n; + } + + if (have_to_map) + if (map_v4v6_hostent (result, &bp, &linebuflen)) + goto too_small; + *h_errnop = NETDB_SUCCESS; + return NSS_STATUS_SUCCESS; + } + no_recovery: + *h_errnop = NO_RECOVERY; + *errnop = ENOENT; + /* Special case here: if the resolver sent a result but it only + contains a CNAME while we are looking for a T_A or T_AAAA record, + we fail with NOTFOUND instead of TRYAGAIN. */ + return ((qtype == T_A || qtype == T_AAAA) && ap != host_data->aliases + ? NSS_STATUS_NOTFOUND : NSS_STATUS_TRYAGAIN); +} + + +static enum nss_status +gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname, + struct gaih_addrtuple ***patp, + char **bufferp, size_t *buflenp, + int *errnop, int *h_errnop, int32_t *ttlp, int *firstp) +{ + char *buffer = *bufferp; + size_t buflen = *buflenp; + + struct gaih_addrtuple **pat = *patp; + const HEADER *hp = &answer->hdr; + int ancount = ntohs (hp->ancount); + int qdcount = ntohs (hp->qdcount); + const u_char *cp = answer->buf + HFIXEDSZ; + const u_char *end_of_message = answer->buf + anslen; + if (__glibc_unlikely (qdcount != 1)) + { + *h_errnop = NO_RECOVERY; + return NSS_STATUS_UNAVAIL; + } + + u_char packtmp[NS_MAXCDNAME]; + int n = __ns_name_unpack (answer->buf, end_of_message, cp, + packtmp, sizeof packtmp); + /* We unpack the name to check it for validity. But we do not need + it later. */ + if (n != -1 && __ns_name_ntop (packtmp, buffer, buflen) == -1) + { + if (__glibc_unlikely (errno == EMSGSIZE)) + { + too_small: + *errnop = ERANGE; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + + n = -1; + } + + 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; + int had_error = 0; + char *canon = NULL; + char *h_name = NULL; + int h_namelen = 0; + + if (ancount == 0) + { + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; + } + + while (ancount-- > 0 && cp < end_of_message && had_error == 0) + { + n = __ns_name_unpack (answer->buf, end_of_message, cp, + packtmp, sizeof packtmp); + if (n != -1 && + (h_namelen = __ns_name_ntop (packtmp, buffer, buflen)) == -1) + { + if (__glibc_unlikely (errno == EMSGSIZE)) + goto too_small; + + n = -1; + } + if (__glibc_unlikely (n < 0 || res_hnok (buffer) == 0)) + { + ++had_error; + continue; + } + if (*firstp && canon == NULL) + { + h_name = buffer; + buffer += h_namelen; + buflen -= h_namelen; + } + + cp += n; /* name */ + + if (__glibc_unlikely (cp + 10 > end_of_message)) + { + ++had_error; + continue; + } + + int type = __ns_get16 (cp); + cp += INT16SZ; /* type */ + int class = __ns_get16 (cp); + cp += INT16SZ; /* class */ + int32_t ttl = __ns_get32 (cp); + 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 (class != C_IN) + { + cp += n; + continue; + } + + if (type == T_CNAME) + { + char tbuf[MAXDNAME]; + + /* A CNAME could also have a TTL entry. */ + if (ttlp != NULL && ttl < *ttlp) + *ttlp = ttl; + + n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf); + if (__glibc_unlikely (n < 0 || res_hnok (tbuf) == 0)) + { + ++had_error; + continue; + } + cp += n; + + if (*firstp) + { + /* Reclaim buffer space. */ + if (h_name + h_namelen == buffer) + { + buffer = h_name; + buflen += h_namelen; + } + + n = strlen (tbuf) + 1; + if (__glibc_unlikely (n > buflen)) + goto too_small; + if (__glibc_unlikely (n >= MAXHOSTNAMELEN)) + { + ++had_error; + continue; + } + + canon = buffer; + buffer = __mempcpy (buffer, tbuf, n); + buflen -= n; + h_namelen = 0; + } + continue; + } + + /* 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; + } + + assert (type == T_A || type == T_AAAA); + if (*pat == NULL) + { + uintptr_t pad = (-(uintptr_t) buffer + % __alignof__ (struct gaih_addrtuple)); + buffer += pad; + buflen = buflen > pad ? buflen - pad : 0; + + if (__glibc_unlikely (buflen < sizeof (struct gaih_addrtuple))) + goto too_small; + + *pat = (struct gaih_addrtuple *) buffer; + buffer += sizeof (struct gaih_addrtuple); + buflen -= sizeof (struct gaih_addrtuple); + } + + (*pat)->name = NULL; + (*pat)->next = NULL; + + if (*firstp) + { + /* We compose a single hostent out of the entire chain of + entries, so the TTL of the hostent is essentially the lowest + TTL in the chain. */ + if (ttlp != NULL && ttl < *ttlp) + *ttlp = ttl; + + (*pat)->name = canon ?: h_name; + + *firstp = 0; + } + + (*pat)->family = type == T_A ? AF_INET : AF_INET6; + memcpy ((*pat)->addr, cp, n); + cp += n; + (*pat)->scopeid = 0; + + pat = &((*pat)->next); + + haveanswer = 1; + } + + if (haveanswer) + { + *patp = pat; + *bufferp = buffer; + *buflenp = buflen; + + *h_errnop = NETDB_SUCCESS; + return NSS_STATUS_SUCCESS; + } + + /* Special case here: if the resolver sent a result but it only + contains a CNAME while we are looking for a T_A or T_AAAA record, + we fail with NOTFOUND instead of TRYAGAIN. */ + if (canon != NULL) + { + *h_errnop = HOST_NOT_FOUND; + return NSS_STATUS_NOTFOUND; + } + + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; +} + + +static enum nss_status +gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2, + int anslen2, const char *qname, + struct gaih_addrtuple **pat, char *buffer, size_t buflen, + int *errnop, int *h_errnop, int32_t *ttlp) +{ + int first = 1; + + enum nss_status status = NSS_STATUS_NOTFOUND; + + /* Combining the NSS status of two distinct queries requires some + compromise and attention to symmetry (A or AAAA queries can be + returned in any order). What follows is a breakdown of how this + code is expected to work and why. We discuss only SUCCESS, + TRYAGAIN, NOTFOUND and UNAVAIL, since they are the only returns + that apply (though RETURN and MERGE exist). We make a distinction + between TRYAGAIN (recoverable) and TRYAGAIN' (not-recoverable). + A recoverable TRYAGAIN is almost always due to buffer size issues + and returns ERANGE in errno and the caller is expected to retry + with a larger buffer. + + Lastly, you may be tempted to make significant changes to the + conditions in this code to bring about symmetry between responses. + Please don't change anything without due consideration for + expected application behaviour. Some of the synthesized responses + aren't very well thought out and sometimes appear to imply that + IPv4 responses are always answer 1, and IPv6 responses are always + answer 2, but that's not true (see the implementation of send_dg + and send_vc to see response can arrive in any order, particularly + for UDP). However, we expect it holds roughly enough of the time + that this code works, but certainly needs to be fixed to make this + a more robust implementation. + + ---------------------------------------------- + | Answer 1 Status / | Synthesized | Reason | + | Answer 2 Status | Status | | + |--------------------------------------------| + | SUCCESS/SUCCESS | SUCCESS | [1] | + | SUCCESS/TRYAGAIN | TRYAGAIN | [5] | + | SUCCESS/TRYAGAIN' | SUCCESS | [1] | + | SUCCESS/NOTFOUND | SUCCESS | [1] | + | SUCCESS/UNAVAIL | SUCCESS | [1] | + | TRYAGAIN/SUCCESS | TRYAGAIN | [2] | + | TRYAGAIN/TRYAGAIN | TRYAGAIN | [2] | + | TRYAGAIN/TRYAGAIN' | TRYAGAIN | [2] | + | TRYAGAIN/NOTFOUND | TRYAGAIN | [2] | + | TRYAGAIN/UNAVAIL | TRYAGAIN | [2] | + | TRYAGAIN'/SUCCESS | SUCCESS | [3] | + | TRYAGAIN'/TRYAGAIN | TRYAGAIN | [3] | + | TRYAGAIN'/TRYAGAIN' | TRYAGAIN' | [3] | + | TRYAGAIN'/NOTFOUND | TRYAGAIN' | [3] | + | TRYAGAIN'/UNAVAIL | UNAVAIL | [3] | + | NOTFOUND/SUCCESS | SUCCESS | [3] | + | NOTFOUND/TRYAGAIN | TRYAGAIN | [3] | + | NOTFOUND/TRYAGAIN' | TRYAGAIN' | [3] | + | NOTFOUND/NOTFOUND | NOTFOUND | [3] | + | NOTFOUND/UNAVAIL | UNAVAIL | [3] | + | UNAVAIL/SUCCESS | UNAVAIL | [4] | + | UNAVAIL/TRYAGAIN | UNAVAIL | [4] | + | UNAVAIL/TRYAGAIN' | UNAVAIL | [4] | + | UNAVAIL/NOTFOUND | UNAVAIL | [4] | + | UNAVAIL/UNAVAIL | UNAVAIL | [4] | + ---------------------------------------------- + + [1] If the first response is a success we return success. + This ignores the state of the second answer and in fact + incorrectly sets errno and h_errno to that of the second + answer. However because the response is a success we ignore + *errnop and *h_errnop (though that means you touched errno on + success). We are being conservative here and returning the + likely IPv4 response in the first answer as a success. + + [2] If the first response is a recoverable TRYAGAIN we return + that instead of looking at the second response. The + expectation here is that we have failed to get an IPv4 response + and should retry both queries. + + [3] If the first response was not a SUCCESS and the second + response is not NOTFOUND (had a SUCCESS, need to TRYAGAIN, + or failed entirely e.g. TRYAGAIN' and UNAVAIL) then use the + result from the second response, otherwise the first responses + status is used. Again we have some odd side-effects when the + second response is NOTFOUND because we overwrite *errnop and + *h_errnop that means that a first answer of NOTFOUND might see + its *errnop and *h_errnop values altered. Whether it matters + in practice that a first response NOTFOUND has the wrong + *errnop and *h_errnop is undecided. + + [4] If the first response is UNAVAIL we return that instead of + looking at the second response. The expectation here is that + it will have failed similarly e.g. configuration failure. + + [5] Testing this code is complicated by the fact that truncated + second response buffers might be returned as SUCCESS if the + first answer is a SUCCESS. To fix this we add symmetry to + TRYAGAIN with the second response. If the second response + is a recoverable error we now return TRYAGIN even if the first + response was SUCCESS. */ + + if (anslen1 > 0) + status = gaih_getanswer_slice(answer1, anslen1, qname, + &pat, &buffer, &buflen, + errnop, h_errnop, ttlp, + &first); + + if ((status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND + || (status == NSS_STATUS_TRYAGAIN + /* We want to look at the second answer in case of an + NSS_STATUS_TRYAGAIN only if the error is non-recoverable, i.e. + *h_errnop is NO_RECOVERY. If not, and if the failure was due to + an insufficient buffer (ERANGE), then we need to drop the results + and pass on the NSS_STATUS_TRYAGAIN to the caller so that it can + repeat the query with a larger buffer. */ + && (*errnop != ERANGE || *h_errnop == NO_RECOVERY))) + && answer2 != NULL && anslen2 > 0) + { + enum nss_status status2 = gaih_getanswer_slice(answer2, anslen2, qname, + &pat, &buffer, &buflen, + errnop, h_errnop, ttlp, + &first); + /* Use the second response status in some cases. */ + if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND) + status = status2; + /* Do not return a truncated second response (unless it was + unavoidable e.g. unrecoverable TRYAGAIN). */ + if (status == NSS_STATUS_SUCCESS + && (status2 == NSS_STATUS_TRYAGAIN + && *errnop == ERANGE && *h_errnop != NO_RECOVERY)) + status = NSS_STATUS_TRYAGAIN; + } + + return status; +} diff --git a/REORG.TODO/resolv/nss_dns/dns-network.c b/REORG.TODO/resolv/nss_dns/dns-network.c new file mode 100644 index 0000000000..2be72d33a3 --- /dev/null +++ b/REORG.TODO/resolv/nss_dns/dns-network.c @@ -0,0 +1,472 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996. + + 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/>. */ + +/* Parts of this file are plain copies of the file `getnetnamadr.c' from + the bind package and it has the following copyright. */ + +/* Copyright (c) 1993 Carlos Leandro and Rui Salgueiro + * Dep. Matematica Universidade de Coimbra, Portugal, Europe + * + * 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. + */ +/* + * Copyright (c) 1983, 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. + */ + +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include <stddef.h> + +#include "nsswitch.h" +#include <arpa/inet.h> +#include <arpa/nameser.h> + +/* Maximum number of aliases we allow. */ +#define MAX_NR_ALIASES 48 + + +#if PACKETSZ > 65536 +# define MAXPACKET PACKETSZ +#else +# define MAXPACKET 65536 +#endif + + +typedef enum +{ + BYADDR, + BYNAME +} lookup_method; + + +/* We need this time later. */ +typedef union querybuf +{ + HEADER hdr; + u_char buf[MAXPACKET]; +} querybuf; + +/* Prototypes for local functions. */ +static enum nss_status getanswer_r (const querybuf *answer, int anslen, + struct netent *result, char *buffer, + size_t buflen, int *errnop, int *h_errnop, + lookup_method net_i); + + +enum nss_status +_nss_dns_getnetbyname_r (const char *name, struct netent *result, + char *buffer, size_t buflen, int *errnop, + int *herrnop) +{ + /* Return entry for network with NAME. */ + union + { + querybuf *buf; + u_char *ptr; + } net_buffer; + querybuf *orig_net_buffer; + int anslen; + enum nss_status status; + + if (__res_maybe_init (&_res, 0) == -1) + return NSS_STATUS_UNAVAIL; + + net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024); + + anslen = __libc_res_nsearch (&_res, 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); + return (errno == ECONNREFUSED + || errno == EPFNOSUPPORT + || errno == EAFNOSUPPORT) + ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND; + } + + status = getanswer_r (net_buffer.buf, anslen, result, buffer, buflen, + errnop, herrnop, BYNAME); + if (net_buffer.buf != orig_net_buffer) + free (net_buffer.buf); + return status; +} + + +enum nss_status +_nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result, + char *buffer, size_t buflen, int *errnop, + int *herrnop) +{ + /* Return entry for network with NAME. */ + enum nss_status status; + union + { + querybuf *buf; + u_char *ptr; + } net_buffer; + querybuf *orig_net_buffer; + unsigned int net_bytes[4]; + char qbuf[MAXDNAME]; + int cnt, anslen; + u_int32_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; + + net2 = (u_int32_t) net; + for (cnt = 4; net2 != 0; net2 >>= 8) + net_bytes[--cnt] = net2 & 0xff; + + switch (cnt) + { + case 3: + /* Class A network. */ + sprintf (qbuf, "0.0.0.%u.in-addr.arpa", net_bytes[3]); + break; + case 2: + /* Class B network. */ + sprintf (qbuf, "0.0.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2]); + break; + case 1: + /* Class C network. */ + sprintf (qbuf, "0.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2], + net_bytes[1]); + break; + case 0: + /* Class D - E network. */ + sprintf (qbuf, "%u.%u.%u.%u.in-addr.arpa", net_bytes[3], net_bytes[2], + net_bytes[1], net_bytes[0]); + break; + } + + 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); + if (anslen < 0) + { + /* Nothing found. */ + int err = errno; + __set_errno (olderr); + if (net_buffer.buf != orig_net_buffer) + free (net_buffer.buf); + return (err == ECONNREFUSED + || err == EPFNOSUPPORT + || err == EAFNOSUPPORT) + ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND; + } + + status = getanswer_r (net_buffer.buf, anslen, result, buffer, buflen, + errnop, herrnop, BYADDR); + if (net_buffer.buf != orig_net_buffer) + free (net_buffer.buf); + if (status == NSS_STATUS_SUCCESS) + { + /* Strip trailing zeros. */ + unsigned int u_net = net; /* Maybe net should be unsigned? */ + + while ((u_net & 0xff) == 0 && u_net != 0) + u_net >>= 8; + result->n_net = u_net; + } + + return status; +} + + +static enum nss_status +getanswer_r (const querybuf *answer, int anslen, struct netent *result, + char *buffer, size_t buflen, int *errnop, int *h_errnop, + lookup_method net_i) +{ + /* + * Find first satisfactory answer + * + * answer --> +------------+ ( MESSAGE ) + * | Header | + * +------------+ + * | Question | the question for the name server + * +------------+ + * | Answer | RRs answering the question + * +------------+ + * | Authority | RRs pointing toward an authority + * | Additional | RRs holding additional information + * +------------+ + */ + struct net_data + { + char *aliases[MAX_NR_ALIASES]; + char linebuffer[0]; + } *net_data; + + uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct net_data); + buffer += pad; + + if (__glibc_unlikely (buflen < sizeof (*net_data) + pad)) + { + /* The buffer is too small. */ + too_small: + *errnop = ERANGE; + *h_errnop = NETDB_INTERNAL; + return NSS_STATUS_TRYAGAIN; + } + buflen -= pad; + + net_data = (struct net_data *) buffer; + int linebuflen = buflen - offsetof (struct net_data, linebuffer); + if (buflen - offsetof (struct net_data, linebuffer) != linebuflen) + linebuflen = INT_MAX; + const unsigned char *end_of_message = &answer->buf[anslen]; + const HEADER *header_pointer = &answer->hdr; + /* #/records in the answer section. */ + int answer_count = ntohs (header_pointer->ancount); + /* #/entries in the question section. */ + int question_count = ntohs (header_pointer->qdcount); + char *bp = net_data->linebuffer; + const unsigned char *cp = &answer->buf[HFIXEDSZ]; + char **alias_pointer; + int have_answer; + u_char packtmp[NS_MAXCDNAME]; + + if (question_count == 0) + { + /* FIXME: the Sun version uses for host name lookup an additional + parameter for pointing to h_errno. this is missing here. + OSF/1 has a per-thread h_errno variable. */ + if (header_pointer->aa != 0) + { + __set_h_errno (HOST_NOT_FOUND); + return NSS_STATUS_NOTFOUND; + } + else + { + __set_h_errno (TRY_AGAIN); + return NSS_STATUS_TRYAGAIN; + } + } + + /* Skip the question part. */ + while (question_count-- > 0) + { + int n = __dn_skipname (cp, end_of_message); + if (n < 0 || end_of_message - (cp + n) < QFIXEDSZ) + { + __set_h_errno (NO_RECOVERY); + return NSS_STATUS_UNAVAIL; + } + cp += n + QFIXEDSZ; + } + + alias_pointer = result->n_aliases = &net_data->aliases[0]; + *alias_pointer = NULL; + have_answer = 0; + + while (--answer_count >= 0 && cp < end_of_message) + { + 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) + goto too_small; + + n = -1; + } + + if (n > 0 && bp[0] == '.') + bp[0] = '\0'; + + 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 */ + 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) + { + 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) + goto too_small; + + n = -1; + } + + if (n < 0 || !res_hnok (bp)) + { + /* XXX What does this mean? The original form from bind + returns NULL. Incrementing cp has no effect in any case. + What should I return here. ??? */ + cp += n; + return NSS_STATUS_UNAVAIL; + } + cp += rdatalen; + if (alias_pointer + 2 < &net_data->aliases[MAX_NR_ALIASES]) + { + *alias_pointer++ = bp; + n = strlen (bp) + 1; + bp += n; + linebuflen -= n; + result->n_addrtype = class == C_IN ? AF_INET : AF_UNSPEC; + ++have_answer; + } + } + else + /* Skip over unknown record data. */ + cp += rdatalen; + } + + if (have_answer) + { + *alias_pointer = NULL; + switch (net_i) + { + case BYADDR: + result->n_name = *result->n_aliases++; + result->n_net = 0L; + return NSS_STATUS_SUCCESS; + + case BYNAME: + { + char **ap; + for (ap = result->n_aliases; *ap != NULL; ++ap) + { + /* Check each alias name for being of the forms: + 4.3.2.1.in-addr.arpa = net 1.2.3.4 + 3.2.1.in-addr.arpa = net 0.1.2.3 + 2.1.in-addr.arpa = net 0.0.1.2 + 1.in-addr.arpa = net 0.0.0.1 + */ + uint32_t val = 0; /* Accumulator for n_net value. */ + unsigned int shift = 0; /* Which part we are parsing now. */ + const char *p = *ap; /* Consuming the string. */ + do + { + /* Match the leading 0 or 0[xX] base indicator. */ + unsigned int base = 10; + if (*p == '0' && p[1] != '.') + { + base = 8; + ++p; + if (*p == 'x' || *p == 'X') + { + base = 16; + ++p; + if (*p == '.') + break; /* No digit here. Give up on alias. */ + } + if (*p == '\0') + break; + } + + uint32_t part = 0; /* Accumulates this part's number. */ + do + { + if (isdigit (*p) && (*p - '0' < base)) + part = (part * base) + (*p - '0'); + else if (base == 16 && isxdigit (*p)) + part = (part << 4) + 10 + (tolower (*p) - 'a'); + ++p; + } while (*p != '\0' && *p != '.'); + + if (*p != '.') + break; /* Bad form. Give up on this name. */ + + /* Install this as the next more significant byte. */ + val |= part << shift; + shift += 8; + ++p; + + /* If we are out of digits now, there are two cases: + 1. We are done with digits and now see "in-addr.arpa". + 2. This is not the droid we are looking for. */ + if (!isdigit (*p) && !strcasecmp (p, "in-addr.arpa")) + { + result->n_net = val; + return NSS_STATUS_SUCCESS; + } + + /* Keep going when we have seen fewer than 4 parts. */ + } while (shift < 32); + } + } + break; + } + } + + __set_h_errno (TRY_AGAIN); + return NSS_STATUS_TRYAGAIN; +} diff --git a/REORG.TODO/resolv/res-state.c b/REORG.TODO/resolv/res-state.c new file mode 100644 index 0000000000..4d4245459b --- /dev/null +++ b/REORG.TODO/resolv/res-state.c @@ -0,0 +1,27 @@ +/* Copyright (C) 1996-2017 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 <tls.h> + + +struct __res_state * +__res_state (void) +{ + return __resp; +} +libc_hidden_def (__res_state) diff --git a/REORG.TODO/resolv/res_comp.c b/REORG.TODO/resolv/res_comp.c new file mode 100644 index 0000000000..ffb2ed5914 --- /dev/null +++ b/REORG.TODO/resolv/res_comp.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 1985, 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 <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <ctype.h> +#include <resolv.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> + +/* + * Expand compressed domain name 'comp_dn' to full domain name. + * 'msg' is a pointer to the beginning of the message, + * 'eomorig' points to the first location after the message, + * 'exp_dn' is a pointer to a buffer of size 'length' for the result. + * Return size of compressed name or -1 if there was an error. + */ +int +dn_expand(const u_char *msg, const u_char *eom, const u_char *src, + char *dst, int dstsiz) +{ + int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz); + + if (n > 0 && dst[0] == '.') + dst[0] = '\0'; + return (n); +} +libresolv_hidden_def (dn_expand) + +/* + * Pack domain name 'exp_dn' in presentation form into 'comp_dn'. + * Return the size of the compressed name or -1. + * 'length' is the size of the array pointed to by 'comp_dn'. + */ +int +dn_comp(const char *src, u_char *dst, int dstsiz, + u_char **dnptrs, u_char **lastdnptr) +{ + return (ns_name_compress(src, dst, (size_t)dstsiz, + (const u_char **)dnptrs, + (const u_char **)lastdnptr)); +} +libresolv_hidden_def (dn_comp) + +/* + * Skip over a compressed domain name. Return the size or -1. + */ +int +dn_skipname(const u_char *ptr, const u_char *eom) { + const u_char *saveptr = ptr; + + if (ns_name_skip(&ptr, eom) == -1) + return (-1); + return (ptr - saveptr); +} +libresolv_hidden_def (dn_skipname) + +/* + * Verify that a domain name uses an acceptable character set. + */ + +/* + * 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) + +#define borderchar(c) (alphachar(c) || digitchar(c)) +#define middlechar(c) (borderchar(c) || hyphenchar(c) || underscorechar(c)) +#define domainchar(c) ((c) > 0x20 && (c) < 0x7f) + +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); +} +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. + */ +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)); +} + +/* + * 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. + */ +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); +} + +/* + * This function is quite liberal, since RFC 1034's character sets are only + * recommendations. + */ +int +res_dnok(const char *dn) { + int ch; + + while ((ch = *dn++) != '\0') + if (!domainchar(ch)) + return (0); + return (1); +} +libresolv_hidden_def (res_dnok) + +/* + * This module must export the following externally-visible symbols: + * ___putlong + * ___putshort + * __getlong + * __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); } +libresolv_hidden_def (__putlong) +void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); } +libresolv_hidden_def (__putshort) +u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); } +u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); } + + +#include <shlib-compat.h> + +#if SHLIB_COMPAT(libresolv, GLIBC_2_0, GLIBC_2_2) +# undef dn_expand +weak_alias (__dn_expand, dn_expand); +#endif diff --git a/REORG.TODO/resolv/res_data.c b/REORG.TODO/resolv/res_data.c new file mode 100644 index 0000000000..569ff4c0ea --- /dev/null +++ b/REORG.TODO/resolv/res_data.c @@ -0,0 +1,191 @@ +/* + * 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 <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> +#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) + +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 */ +{ + 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)); +} + +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)); +} + +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)); +} + + +void +res_close(void) { + /* + * 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; + /* 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); +} + +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) + + + +#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/REORG.TODO/resolv/res_debug.c b/REORG.TODO/resolv/res_debug.c new file mode 100644 index 0000000000..e23559bad3 --- /dev/null +++ b/REORG.TODO/resolv/res_debug.c @@ -0,0 +1,1024 @@ +/* + * Copyright (c) 1985 + * 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) 1995 by International Business Machines, Inc. + * + * International Business Machines, Inc. (hereinafter called IBM) grants + * permission under its copyrights to use, copy, modify, and distribute this + * Software with or without fee, provided that the above copyright notice and + * all paragraphs of this notice appear in all copies, and that the name of IBM + * not be used in connection with the marketing of any product incorporating + * the Software or modifications thereof, without specific, written prior + * permission. + * + * To the extent it has a right to do so, IBM grants an immunity from suit + * under its patents, if any, for the use, sale or manufacture of products to + * the extent that such products are used for performing Domain Name System + * dynamic updates in TCP/IP networks by means of the Software. No immunity is + * granted for any product per se or for any other function of any product. + * + * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, + * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING + * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN + * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES. + */ + +/* + * 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 <sys/types.h> +#include <sys/param.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> + +#include <ctype.h> +#include <errno.h> +#include <math.h> +#include <netdb.h> +#include <resolv/resolv-internal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +extern const char *_res_sectioncodes[] attribute_hidden; + +static const char *p_section(int section, int opcode); + +/* + * Print the current options. + */ +void +fp_resstat(const res_state statp, FILE *file) { + u_long mask; + + fprintf(file, ";; res options:"); + for (mask = 1; mask != 0; mask <<= 1) + if (statp->options & mask) + fprintf(file, " %s", p_option(mask)); + putc('\n', file); +} + +static void +do_section(const res_state statp, + ns_msg *handle, ns_sect section, + int pflag, FILE *file) +{ + int n, sflag, rrnum; + static int buflen = 2048; + char *buf; + ns_opcode opcode; + ns_rr rr; + + /* + * Print answer records. + */ + sflag = (statp->pfcode & pflag); + if (statp->pfcode && !sflag) + return; + + buf = malloc(buflen); + if (buf == NULL) { + fprintf(file, ";; memory allocation failure\n"); + return; + } + + opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode); + rrnum = 0; + for (;;) { + if (ns_parserr(handle, section, rrnum, &rr)) { + if (errno != ENODEV) + fprintf(file, ";; ns_parserr: %s\n", + strerror(errno)); + else if (rrnum > 0 && sflag != 0 && + (statp->pfcode & RES_PRF_HEAD1)) + putc('\n', file); + goto cleanup; + } + if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1)) + fprintf(file, ";; %s SECTION:\n", + p_section(section, opcode)); + if (section == ns_s_qd) + fprintf(file, ";;\t%s, type = %s, class = %s\n", + ns_rr_name(rr), + p_type(ns_rr_type(rr)), + p_class(ns_rr_class(rr))); + else { + n = ns_sprintrr(handle, &rr, NULL, NULL, + buf, buflen); + if (n < 0) { + if (errno == ENOSPC) { + free(buf); + buf = NULL; + if (buflen < 131072) + buf = malloc(buflen += 1024); + if (buf == NULL) { + fprintf(file, + ";; memory allocation failure\n"); + return; + } + continue; + } + fprintf(file, ";; ns_sprintrr: %s\n", + strerror(errno)); + goto cleanup; + } + fputs(buf, file); + fputc('\n', file); + } + rrnum++; + } + cleanup: + free(buf); +} + +/* + * Print the contents of a query. + * This is intended to be primarily a debugging routine. + */ +void +res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) { + ns_msg handle; + int qdcount, ancount, nscount, arcount; + u_int opcode, rcode, id; + + if (ns_initparse(msg, len, &handle) < 0) { + fprintf(file, ";; ns_initparse: %s\n", strerror(errno)); + return; + } + opcode = ns_msg_getflag(handle, ns_f_opcode); + rcode = ns_msg_getflag(handle, ns_f_rcode); + id = ns_msg_id(handle); + qdcount = ns_msg_count(handle, ns_s_qd); + ancount = ns_msg_count(handle, ns_s_an); + nscount = ns_msg_count(handle, ns_s_ns); + arcount = ns_msg_count(handle, ns_s_ar); + + /* + * Print header fields. + */ + if ((!statp->pfcode) || (statp->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)) + putc(';', file); + if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) { + fprintf(file, "; flags:"); + if (ns_msg_getflag(handle, ns_f_qr)) + fprintf(file, " qr"); + if (ns_msg_getflag(handle, ns_f_aa)) + fprintf(file, " aa"); + if (ns_msg_getflag(handle, ns_f_tc)) + fprintf(file, " tc"); + if (ns_msg_getflag(handle, ns_f_rd)) + fprintf(file, " rd"); + if (ns_msg_getflag(handle, ns_f_ra)) + fprintf(file, " ra"); + if (ns_msg_getflag(handle, ns_f_z)) + fprintf(file, " ??"); + if (ns_msg_getflag(handle, ns_f_ad)) + fprintf(file, " ad"); + if (ns_msg_getflag(handle, ns_f_cd)) + fprintf(file, " cd"); + } + if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) { + fprintf(file, "; %s: %d", + p_section(ns_s_qd, opcode), qdcount); + fprintf(file, ", %s: %d", + p_section(ns_s_an, opcode), ancount); + fprintf(file, ", %s: %d", + p_section(ns_s_ns, opcode), nscount); + fprintf(file, ", %s: %d", + p_section(ns_s_ar, opcode), arcount); + } + if ((!statp->pfcode) || (statp->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); + if (qdcount == 0 && ancount == 0 && + nscount == 0 && arcount == 0) + putc('\n', file); +} + +const u_char * +p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) { + char name[MAXDNAME]; + int n; + + if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0) + return (NULL); + if (name[0] == '\0') + putc('.', file); + else + fputs(name, file); + return (cp + n); +} +libresolv_hidden_def (p_cdnname) + +const u_char * +p_cdname(const u_char *cp, const u_char *msg, FILE *file) { + return (p_cdnname(cp, msg, PACKETSZ, file)); +} + +/* Return a fully-qualified domain name from a compressed name (with + length supplied). */ + +const u_char * +p_fqnname (const u_char *cp, const u_char *msg, int msglen, char *name, + int namelen) +{ + int n, newlen; + + if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0) + return (NULL); + newlen = strlen(name); + if (newlen == 0 || name[newlen - 1] != '.') { + if (newlen + 1 >= namelen) /* Lack space for final dot */ + return (NULL); + else + strcpy(name + newlen, "."); + } + return (cp + n); +} +libresolv_hidden_def (p_fqnname) + +/* XXX: the rest of these functions need to become length-limited, too. */ + +const u_char * +p_fqname(const u_char *cp, const u_char *msg, FILE *file) { + char name[MAXDNAME]; + const u_char *n; + + n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name); + if (n == NULL) + return (NULL); + fputs(name, file); + return (n); +} + +/* + * Names of RR classes and qclasses. Classes and qclasses are the same, except + * that C_ANY is a qclass but not a class. (You can ask for records of class + * C_ANY, but you can't have any records of that class in the database.) + */ +extern const struct res_sym __p_class_syms[]; +libresolv_hidden_proto (__p_class_syms) +const struct res_sym __p_class_syms[] = { + {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) + +/* + * Names of message sections. + */ +const struct res_sym __p_default_section_syms[] attribute_hidden = { + {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, (char *) "ZONE"}, + {S_PREREQ, (char *) "PREREQUISITE"}, + {S_UPDATE, (char *) "UPDATE"}, + {S_ADDT, (char *) "ADDITIONAL"}, + {0, NULL, NULL} +}; + +/* + * 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, (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) + +/* + * Names of DNS rcodes. + */ +const struct res_sym __p_rcode_syms[] attribute_hidden = { + {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 +sym_ston(const struct res_sym *syms, const char *name, int *success) { + for ((void)NULL; syms->name != 0; syms++) { + if (strcasecmp (name, syms->name) == 0) { + if (success) + *success = 1; + return (syms->number); + } + } + if (success) + *success = 0; + return (syms->number); /* The default value. */ +} + +const char * +sym_ntos(const struct res_sym *syms, int number, int *success) { + static char unname[20]; + + for ((void)NULL; syms->name != 0; syms++) { + if (number == syms->number) { + if (success) + *success = 1; + return (syms->name); + } + } + + sprintf(unname, "%d", number); /* XXX nonreentrant */ + if (success) + *success = 0; + return (unname); +} +libresolv_hidden_def (sym_ntos) + +const char * +sym_ntop(const struct res_sym *syms, int number, int *success) { + static char unname[20]; + + for ((void)NULL; syms->name != 0; syms++) { + if (number == syms->number) { + if (success) + *success = 1; + return (syms->humanname); + } + } + sprintf(unname, "%d", number); /* XXX nonreentrant */ + if (success) + *success = 0; + return (unname); +} + +/* + * Return a string for the type. + */ +const char * +p_type(int type) { + return (sym_ntos(__p_type_syms, type, (int *)0)); +} +libresolv_hidden_def (p_type) + +/* + * Return a string for the type. + */ +static const char * +p_section(int section, int opcode) { + const struct res_sym *symbols; + + switch (opcode) { + case ns_o_update: + symbols = __p_update_section_syms; + break; + default: + symbols = __p_default_section_syms; + break; + } + return (sym_ntos(symbols, section, (int *)0)); +} + +/* + * Return a mnemonic for class. + */ +const char * +p_class(int class) { + return (sym_ntos(__p_class_syms, class, (int *)0)); +} +libresolv_hidden_def (p_class) + +/* + * Return a mnemonic for an option + */ +const char * +p_option(u_long option) { + static char nbuf[40]; + + switch (option) { + case RES_INIT: return "init"; + case RES_DEBUG: return "debug"; + case RES_USEVC: return "use-vc"; + case RES_IGNTC: return "igntc"; + case RES_RECURSE: return "recurs"; + case RES_DEFNAMES: return "defnam"; + case RES_STAYOPEN: return "styopn"; + case RES_DNSRCH: return "dnsrch"; + case RES_INSECURE1: return "insecure1"; + case RES_INSECURE2: return "insecure2"; + case RES_NOALIASES: return "noaliases"; + case DEPRECATED_RES_USE_INET6: return "inet6"; + case RES_ROTATE: return "rotate"; + 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"; + /* XXX nonreentrant */ + default: sprintf(nbuf, "?0x%lx?", (u_long)option); + return (nbuf); + } +} +libresolv_hidden_def (p_option) + +/* + * Return a mnemonic for a time to live. + */ +const char * +p_time(u_int32_t value) { + static char nbuf[40]; /* XXX nonreentrant */ + + if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0) + sprintf(nbuf, "%u", value); + return (nbuf); +} + +/* + * Return a string for the rcode. + */ +const char * +p_rcode(int rcode) { + return (sym_ntos(__p_rcode_syms, rcode, (int *)0)); +} +libresolv_hidden_def (p_rcode) + +/* + * routines to convert between on-the-wire RR format and zone file format. + * Does not contain conversion to/from decimal degrees; divide or multiply + * by 60*60*1000 for that. + */ + +static const unsigned int poweroften[10]= + { 1, 10, 100, 1000, 10000, 100000, + 1000000,10000000,100000000,1000000000}; + +/* takes an XeY precision/size value, returns a string representation. */ +static const char * +precsize_ntoa (u_int8_t prec) +{ + static char retbuf[sizeof "90000000.00"]; /* XXX nonreentrant */ + unsigned long val; + int mantissa, exponent; + + mantissa = (int)((prec >> 4) & 0x0f) % 10; + exponent = (int)((prec >> 0) & 0x0f) % 10; + + val = mantissa * poweroften[exponent]; + + (void) sprintf(retbuf, "%ld.%.2ld", val/100, val%100); + return (retbuf); +} + +/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */ +static u_int8_t +precsize_aton (const char **strptr) +{ + unsigned int mval = 0, cmval = 0; + u_int8_t retval = 0; + const char *cp; + int exponent; + int mantissa; + + cp = *strptr; + + while (isdigit(*cp)) + mval = mval * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* centimeters */ + cp++; + if (isdigit(*cp)) { + cmval = (*cp++ - '0') * 10; + if (isdigit(*cp)) { + cmval += (*cp++ - '0'); + } + } + } + cmval = (mval * 100) + cmval; + + for (exponent = 0; exponent < 9; exponent++) + if (cmval < poweroften[exponent+1]) + break; + + mantissa = cmval / poweroften[exponent]; + if (mantissa > 9) + mantissa = 9; + + retval = (mantissa << 4) | exponent; + + *strptr = cp; + + return (retval); +} + +/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */ +static u_int32_t +latlon2ul (const char **latlonstrptr, int *which) +{ + const char *cp; + u_int32_t retval; + int deg = 0, min = 0, secs = 0, secsfrac = 0; + + cp = *latlonstrptr; + + while (isdigit(*cp)) + deg = deg * 10 + (*cp++ - '0'); + + while (isspace(*cp)) + cp++; + + if (!(isdigit(*cp))) + goto fndhemi; + + while (isdigit(*cp)) + min = min * 10 + (*cp++ - '0'); + + while (isspace(*cp)) + cp++; + + if (!(isdigit(*cp))) + goto fndhemi; + + while (isdigit(*cp)) + secs = secs * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* decimal seconds */ + cp++; + if (isdigit(*cp)) { + secsfrac = (*cp++ - '0') * 100; + if (isdigit(*cp)) { + secsfrac += (*cp++ - '0') * 10; + if (isdigit(*cp)) { + secsfrac += (*cp++ - '0'); + } + } + } + } + + while (!isspace(*cp)) /* if any trailing garbage */ + cp++; + + while (isspace(*cp)) + cp++; + + fndhemi: + switch (*cp) { + case 'N': case 'n': + case 'E': case 'e': + retval = ((unsigned)1<<31) + + (((((deg * 60) + min) * 60) + secs) * 1000) + + secsfrac; + break; + case 'S': case 's': + case 'W': case 'w': + retval = ((unsigned)1<<31) + - (((((deg * 60) + min) * 60) + secs) * 1000) + - secsfrac; + break; + default: + retval = 0; /* invalid value -- indicates error */ + break; + } + + switch (*cp) { + case 'N': case 'n': + case 'S': case 's': + *which = 1; /* latitude */ + break; + case 'E': case 'e': + case 'W': case 'w': + *which = 2; /* longitude */ + break; + default: + *which = 0; /* error */ + break; + } + + cp++; /* skip the hemisphere */ + + while (!isspace(*cp)) /* if any trailing garbage */ + cp++; + + while (isspace(*cp)) /* move to next field */ + cp++; + + *latlonstrptr = cp; + + return (retval); +} + +/* converts a zone file representation in a string to an RDATA on-the-wire + * representation. */ +int +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; + 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 */ + int which1 = 0, which2 = 0; + + cp = ascii; + maxcp = cp + strlen(ascii); + + lltemp1 = latlon2ul(&cp, &which1); + + lltemp2 = latlon2ul(&cp, &which2); + + switch (which1 + which2) { + case 3: /* 1 + 2, the only valid combination */ + if ((which1 == 1) && (which2 == 2)) { /* normal case */ + latit = lltemp1; + longit = lltemp2; + } else if ((which1 == 2) && (which2 == 1)) { /* reversed */ + longit = lltemp1; + latit = lltemp2; + } else { /* some kind of brokenness */ + return (0); + } + break; + default: /* we didn't get one of each */ + return (0); + } + + /* altitude */ + if (*cp == '-') { + altsign = -1; + cp++; + } + + if (*cp == '+') + cp++; + + while (isdigit(*cp)) + altmeters = altmeters * 10 + (*cp++ - '0'); + + if (*cp == '.') { /* decimal meters */ + cp++; + if (isdigit(*cp)) { + altfrac = (*cp++ - '0') * 10; + if (isdigit(*cp)) { + altfrac += (*cp++ - '0'); + } + } + } + + alt = (10000000 + (altsign * (altmeters * 100 + altfrac))); + + while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */ + cp++; + + while (isspace(*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + siz = precsize_aton(&cp); + + while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */ + cp++; + + while (isspace(*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + hp = precsize_aton(&cp); + + while (!isspace(*cp) && (cp < maxcp)) /* if trailing garbage or m */ + cp++; + + while (isspace(*cp) && (cp < maxcp)) + cp++; + + if (cp >= maxcp) + goto defaults; + + vp = precsize_aton(&cp); + + defaults: + + bcp = binary; + *bcp++ = (u_int8_t) 0; /* version byte */ + *bcp++ = siz; + *bcp++ = hp; + *bcp++ = vp; + PUTLONG(latit,bcp); + PUTLONG(longit,bcp); + PUTLONG(alt,bcp); + + return (16); /* size of RR in octets */ +} + +/* takes an on-the-wire LOC RR and formats it in a human readable format. */ +const char * +loc_ntoa (const u_char *binary, char *ascii) +{ + static const char error[] = "?"; + static char tmpbuf[sizeof +"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"]; + const u_char *cp = binary; + + int latdeg, latmin, latsec, latsecfrac; + int longdeg, longmin, longsec, longsecfrac; + char northsouth, eastwest; + int altmeters, altfrac, altsign; + + const u_int32_t referencealt = 100000 * 100; + + int32_t latval, longval, altval; + u_int32_t templ; + u_int8_t sizeval, hpval, vpval, versionval; + + char *sizestr, *hpstr, *vpstr; + + versionval = *cp++; + + if (ascii == NULL) + ascii = tmpbuf; + + if (versionval) { + (void) sprintf(ascii, "; error: unknown LOC RR version"); + return (ascii); + } + + sizeval = *cp++; + + hpval = *cp++; + vpval = *cp++; + + GETLONG(templ, cp); + latval = (templ - ((unsigned)1<<31)); + + GETLONG(templ, cp); + longval = (templ - ((unsigned)1<<31)); + + GETLONG(templ, cp); + if (templ < referencealt) { /* below WGS 84 spheroid */ + altval = referencealt - templ; + altsign = -1; + } else { + altval = templ - referencealt; + altsign = 1; + } + + if (latval < 0) { + northsouth = 'S'; + latval = -latval; + } else + northsouth = 'N'; + + latsecfrac = latval % 1000; + latval = latval / 1000; + latsec = latval % 60; + latval = latval / 60; + latmin = latval % 60; + latval = latval / 60; + latdeg = latval; + + if (longval < 0) { + eastwest = 'W'; + longval = -longval; + } else + eastwest = 'E'; + + longsecfrac = longval % 1000; + longval = longval / 1000; + longsec = longval % 60; + longval = longval / 60; + longmin = longval % 60; + longval = longval / 60; + longdeg = longval; + + altfrac = altval % 100; + altmeters = (altval / 100) * altsign; + + if ((sizestr = strdup(precsize_ntoa(sizeval))) == NULL) + sizestr = (char *) error; + if ((hpstr = strdup(precsize_ntoa(hpval))) == NULL) + hpstr = (char *) error; + if ((vpstr = strdup(precsize_ntoa(vpval))) == NULL) + vpstr = (char *) error; + + sprintf(ascii, + "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %d.%.2dm %sm %sm %sm", + latdeg, latmin, latsec, latsecfrac, northsouth, + longdeg, longmin, longsec, longsecfrac, eastwest, + altmeters, altfrac, sizestr, hpstr, vpstr); + + if (sizestr != (char *) error) + free(sizestr); + if (hpstr != (char *) error) + free(hpstr); + if (vpstr != (char *) error) + free(vpstr); + + return (ascii); +} +libresolv_hidden_def (loc_ntoa) + + +/* Return the number of DNS hierarchy levels in the name. */ +int +dn_count_labels(const char *name) { + int i, len, count; + + len = strlen(name); + for (i = 0, count = 0; i < len; i++) { + /* XXX need to check for \. or use named's nlabels(). */ + if (name[i] == '.') + count++; + } + + /* don't count initial wildcard */ + if (name[0] == '*') + if (count) + count--; + + /* don't count the null label for root. */ + /* if terminating '.' not found, must adjust */ + /* count to include last label */ + if (len > 0 && name[len-1] != '.') + count++; + return (count); +} +libresolv_hidden_def (__dn_count_labels) + + +/* + * 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. + */ +char * +p_secstodate (u_long secs) { + /* XXX nonreentrant */ + static char output[15]; /* YYYYMMDDHHMMSS and null */ + time_t clock = secs; + struct tm *time; + + struct tm timebuf; + time = __gmtime_r(&clock, &timebuf); + time->tm_year += 1900; + time->tm_mon += 1; + 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); + return (output); +} +libresolv_hidden_def (__p_secstodate) diff --git a/REORG.TODO/resolv/res_debug.h b/REORG.TODO/resolv/res_debug.h new file mode 100644 index 0000000000..2d8ad15d60 --- /dev/null +++ b/REORG.TODO/resolv/res_debug.h @@ -0,0 +1,34 @@ +/* + * 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/REORG.TODO/resolv/res_hconf.c b/REORG.TODO/resolv/res_hconf.c new file mode 100644 index 0000000000..8fc06e9abd --- /dev/null +++ b/REORG.TODO/resolv/res_hconf.c @@ -0,0 +1,572 @@ +/* Copyright (C) 1993-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger (davidm@azstarnet.com). + + 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 provides a Linux /etc/host.conf compatible front end to + the various name resolvers (/etc/hosts, named, NIS server, etc.). + Though mostly compatibly, the following differences exist compared + to the original implementation: + + - line comments can appear anywhere (not just at the beginning of + a line) +*/ + +#include <assert.h> +#include <errno.h> +#include <ctype.h> +#include <libintl.h> +#include <memory.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <stdlib.h> +#include <string.h> +#include <net/if.h> +#include <sys/ioctl.h> +#include <unistd.h> +#include <netinet/in.h> +#include <libc-lock.h> +#include "ifreq.h" +#include "res_hconf.h" +#include <wchar.h> +#include <atomic.h> + +#if IS_IN (libc) +# define fgets_unlocked __fgets_unlocked +#endif + +#define _PATH_HOSTCONF "/etc/host.conf" + +/* Environment vars that all user to override default behavior: */ +#define ENV_HOSTCONF "RESOLV_HOST_CONF" +#define ENV_TRIM_OVERR "RESOLV_OVERRIDE_TRIM_DOMAINS" +#define ENV_TRIM_ADD "RESOLV_ADD_TRIM_DOMAINS" +#define ENV_MULTI "RESOLV_MULTI" +#define ENV_REORDER "RESOLV_REORDER" + +enum parse_cbs + { + CB_none, + CB_arg_trimdomain_list, + CB_arg_bool + }; + +static const struct cmd +{ + const char name[11]; + uint8_t cb; + unsigned int arg; +} cmd[] = +{ + {"order", CB_none, 0}, + {"trim", CB_arg_trimdomain_list, 0}, + {"multi", CB_arg_bool, HCONF_FLAG_MULTI}, + {"reorder", CB_arg_bool, HCONF_FLAG_REORDER} +}; + +/* Structure containing the state. */ +struct hconf _res_hconf; + +/* Skip white space. */ +static const char * +skip_ws (const char *str) +{ + while (isspace (*str)) ++str; + return str; +} + + +/* Skip until whitespace, comma, end of line, or comment character. */ +static const char * +skip_string (const char *str) +{ + while (*str && !isspace (*str) && *str != '#' && *str != ',') + ++str; + return str; +} + + +static const char * +arg_trimdomain_list (const char *fname, int line_num, const char *args) +{ + const char * start; + size_t len; + + do + { + start = args; + args = skip_string (args); + len = args - start; + + if (_res_hconf.num_trimdomains >= TRIMDOMAINS_MAX) + { + char *buf; + + if (__asprintf (&buf, _("\ +%s: line %d: cannot specify more than %d trim domains"), + fname, line_num, TRIMDOMAINS_MAX) < 0) + return 0; + + __fxprintf (NULL, "%s", buf); + + free (buf); + return 0; + } + _res_hconf.trimdomain[_res_hconf.num_trimdomains++] = + __strndup (start, len); + args = skip_ws (args); + switch (*args) + { + case ',': case ';': case ':': + args = skip_ws (++args); + if (!*args || *args == '#') + { + char *buf; + + if (__asprintf (&buf, _("\ +%s: line %d: list delimiter not followed by domain"), + fname, line_num) < 0) + return 0; + + __fxprintf (NULL, "%s", buf); + + free (buf); + return 0; + } + default: + break; + } + } + while (*args && *args != '#'); + return args; +} + + +static const char * +arg_bool (const char *fname, int line_num, const char *args, unsigned flag) +{ + if (__strncasecmp (args, "on", 2) == 0) + { + args += 2; + _res_hconf.flags |= flag; + } + else if (__strncasecmp (args, "off", 3) == 0) + { + args += 3; + _res_hconf.flags &= ~flag; + } + else + { + char *buf; + + if (__asprintf (&buf, + _("%s: line %d: expected `on' or `off', found `%s'\n"), + fname, line_num, args) < 0) + return 0; + + __fxprintf (NULL, "%s", buf); + + free (buf); + return 0; + } + return args; +} + + +static void +parse_line (const char *fname, int line_num, const char *str) +{ + const char *start; + const struct cmd *c = 0; + size_t len; + size_t i; + + str = skip_ws (str); + + /* skip line comment and empty lines: */ + if (*str == '\0' || *str == '#') return; + + start = str; + str = skip_string (str); + len = str - start; + + for (i = 0; i < sizeof (cmd) / sizeof (cmd[0]); ++i) + { + if (__strncasecmp (start, cmd[i].name, len) == 0 + && strlen (cmd[i].name) == len) + { + c = &cmd[i]; + break; + } + } + if (c == NULL) + { + char *buf; + + if (__asprintf (&buf, _("%s: line %d: bad command `%s'\n"), + fname, line_num, start) < 0) + return; + + __fxprintf (NULL, "%s", buf); + + free (buf); + return; + } + + /* process args: */ + str = skip_ws (str); + + if (c->cb == CB_arg_trimdomain_list) + str = arg_trimdomain_list (fname, line_num, str); + else if (c->cb == CB_arg_bool) + str = arg_bool (fname, line_num, str, c->arg); + else + /* Ignore the line. */ + return; + + if (!str) + return; + + /* rest of line must contain white space or comment only: */ + while (*str) + { + if (!isspace (*str)) { + if (*str != '#') + { + char *buf; + + if (__asprintf (&buf, + _("%s: line %d: ignoring trailing garbage `%s'\n"), + fname, line_num, str) < 0) + break; + + __fxprintf (NULL, "%s", buf); + + free (buf); + } + break; + } + ++str; + } +} + + +static void +do_init (void) +{ + const char *hconf_name; + int line_num = 0; + char buf[256], *envval; + FILE *fp; + + memset (&_res_hconf, '\0', sizeof (_res_hconf)); + + hconf_name = getenv (ENV_HOSTCONF); + if (hconf_name == NULL) + hconf_name = _PATH_HOSTCONF; + + fp = fopen (hconf_name, "rce"); + if (fp) + { + /* No threads using this stream. */ + __fsetlocking (fp, FSETLOCKING_BYCALLER); + + while (fgets_unlocked (buf, sizeof (buf), fp)) + { + ++line_num; + *__strchrnul (buf, '\n') = '\0'; + parse_line (hconf_name, line_num, buf); + } + fclose (fp); + } + + envval = getenv (ENV_MULTI); + if (envval) + arg_bool (ENV_MULTI, 1, envval, HCONF_FLAG_MULTI); + + envval = getenv (ENV_REORDER); + if (envval) + arg_bool (ENV_REORDER, 1, envval, HCONF_FLAG_REORDER); + + envval = getenv (ENV_TRIM_ADD); + if (envval) + arg_trimdomain_list (ENV_TRIM_ADD, 1, envval); + + envval = getenv (ENV_TRIM_OVERR); + if (envval) + { + _res_hconf.num_trimdomains = 0; + arg_trimdomain_list (ENV_TRIM_OVERR, 1, envval); + } + + /* See comments on the declaration of _res_hconf. */ + atomic_store_release (&_res_hconf.initialized, 1); +} + + +/* Initialize hconf datastructure by reading host.conf file and + environment variables. */ +void +_res_hconf_init (void) +{ + __libc_once_define (static, once); + + __libc_once (once, do_init); +} + + +#if IS_IN (libc) +# if defined SIOCGIFCONF && defined SIOCGIFNETMASK +/* List of known interfaces. */ +libc_freeres_ptr ( +static struct netaddr +{ + int addrtype; + union + { + struct + { + u_int32_t addr; + u_int32_t mask; + } ipv4; + } u; +} *ifaddrs); +# endif + +/* Reorder addresses returned in a hostent such that the first address + is an address on the local subnet, if there is such an address. + Otherwise, nothing is changed. + + Note that this function currently only handles IPv4 addresses. */ + +void +_res_hconf_reorder_addrs (struct hostent *hp) +{ +#if defined SIOCGIFCONF && defined SIOCGIFNETMASK + int i, j; + /* Number of interfaces. Also serves as a flag for the + double-checked locking idiom. */ + static int num_ifs = -1; + /* Local copy of num_ifs, for non-atomic access. */ + int num_ifs_local; + /* We need to protect the dynamic buffer handling. The lock is only + acquired during initialization. Afterwards, a positive num_ifs + value indicates completed initialization. */ + __libc_lock_define_initialized (static, lock); + + /* Only reorder if we're supposed to. */ + if ((_res_hconf.flags & HCONF_FLAG_REORDER) == 0) + return; + + /* Can't deal with anything but IPv4 for now... */ + if (hp->h_addrtype != AF_INET) + return; + + /* This load synchronizes with the release MO store in the + initialization block below. */ + num_ifs_local = atomic_load_acquire (&num_ifs); + if (num_ifs_local <= 0) + { + struct ifreq *ifr, *cur_ifr; + int sd, num, i; + /* Save errno. */ + int save = errno; + + /* Initialize interface table. */ + + /* The SIOCGIFNETMASK ioctl will only work on an AF_INET socket. */ + sd = __socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (sd < 0) + return; + + /* Get lock. */ + __libc_lock_lock (lock); + + /* Recheck, somebody else might have done the work by now. No + ordering is required for the load because we have the lock, + and num_ifs is only updated under the lock. Also see (3) in + the analysis below. */ + num_ifs_local = atomic_load_relaxed (&num_ifs); + if (num_ifs_local <= 0) + { + /* This is the only block which writes to num_ifs. It can + be executed several times (sequentially) if + initialization does not yield any interfaces, and num_ifs + remains zero. However, once we stored a positive value + in num_ifs below, this block cannot be entered again due + to the condition above. */ + int new_num_ifs = 0; + + /* Get a list of interfaces. */ + __ifreq (&ifr, &num, sd); + if (!ifr) + goto cleanup; + + ifaddrs = malloc (num * sizeof (ifaddrs[0])); + if (!ifaddrs) + goto cleanup1; + + /* Copy usable interfaces in ifaddrs structure. */ + for (cur_ifr = ifr, i = 0; i < num; + cur_ifr = __if_nextreq (cur_ifr), ++i) + { + union + { + struct sockaddr sa; + struct sockaddr_in sin; + } ss; + + if (cur_ifr->ifr_addr.sa_family != AF_INET) + continue; + + ifaddrs[new_num_ifs].addrtype = AF_INET; + ss.sa = cur_ifr->ifr_addr; + ifaddrs[new_num_ifs].u.ipv4.addr = ss.sin.sin_addr.s_addr; + + if (__ioctl (sd, SIOCGIFNETMASK, cur_ifr) < 0) + continue; + + ss.sa = cur_ifr->ifr_netmask; + ifaddrs[new_num_ifs].u.ipv4.mask = ss.sin.sin_addr.s_addr; + + /* Now we're committed to this entry. */ + ++new_num_ifs; + } + /* Just keep enough memory to hold all the interfaces we want. */ + ifaddrs = realloc (ifaddrs, new_num_ifs * sizeof (ifaddrs[0])); + assert (ifaddrs != NULL); + + cleanup1: + __if_freereq (ifr, num); + + cleanup: + /* Release lock, preserve error value, and close socket. */ + errno = save; + + /* Advertise successful initialization if new_num_ifs is + positive (and no updates to ifaddrs are permitted after + that). Otherwise, num_ifs remains unchanged, at zero. + This store synchronizes with the initial acquire MO + load. */ + atomic_store_release (&num_ifs, new_num_ifs); + /* Keep the local copy current, to save another load. */ + num_ifs_local = new_num_ifs; + } + + __libc_lock_unlock (lock); + + __close (sd); + } + + /* num_ifs_local cannot be negative because the if statement above + covered this case. It can still be zero if we just performed + initialization, but could not find any interfaces. */ + if (num_ifs_local == 0) + return; + + /* The code below accesses ifaddrs, so we need to ensure that the + initialization happens-before this point. + + The actual initialization is sequenced-before the release store + to num_ifs, and sequenced-before the end of the critical section. + + This means there are three possible executions: + + (1) The thread that initialized the data also uses it, so + sequenced-before is sufficient to ensure happens-before. + + (2) The release MO store of num_ifs synchronizes-with the acquire + MO load, and the acquire MO load is sequenced before the use + of the initialized data below. + + (3) We enter the critical section, and the relaxed MO load of + num_ifs yields a positive value. The write to ifaddrs is + sequenced-before leaving the critical section. Leaving the + critical section happens-before we entered the critical + section ourselves, which means that the write to ifaddrs + happens-before this point. + + Consequently, all potential writes to ifaddrs (and the data it + points to) happens-before this point. */ + + /* Find an address for which we have a direct connection. */ + for (i = 0; hp->h_addr_list[i]; ++i) + { + struct in_addr *haddr = (struct in_addr *) hp->h_addr_list[i]; + + 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; + + if (((haddr->s_addr ^ if_addr) & if_netmask) == 0) + { + void *tmp; + + tmp = hp->h_addr_list[i]; + hp->h_addr_list[i] = hp->h_addr_list[0]; + hp->h_addr_list[0] = tmp; + return; + } + } + } +#endif /* defined(SIOCGIFCONF) && ... */ +} + + +/* If HOSTNAME has a postfix matching any of the trimdomains, trim away + that postfix. Notice that HOSTNAME is modified inplace. Also, the + original code applied all trimdomains in order, meaning that the + same domainname could be trimmed multiple times. I believe this + was unintentional. */ +void +_res_hconf_trim_domain (char *hostname) +{ + size_t hostname_len, trim_len; + int i; + + hostname_len = strlen (hostname); + + for (i = 0; i < _res_hconf.num_trimdomains; ++i) + { + const char *trim = _res_hconf.trimdomain[i]; + + trim_len = strlen (trim); + if (hostname_len > trim_len + && __strcasecmp (&hostname[hostname_len - trim_len], trim) == 0) + { + hostname[hostname_len - trim_len] = '\0'; + break; + } + } +} + + +/* Trim all hostnames/aliases in HP according to the trimdomain list. + Notice that HP is modified inplace! */ +void +_res_hconf_trim_domains (struct hostent *hp) +{ + int i; + + if (_res_hconf.num_trimdomains == 0) + return; + + _res_hconf_trim_domain (hp->h_name); + for (i = 0; hp->h_aliases[i]; ++i) + _res_hconf_trim_domain (hp->h_aliases[i]); +} +#endif diff --git a/REORG.TODO/resolv/res_hconf.h b/REORG.TODO/resolv/res_hconf.h new file mode 100644 index 0000000000..6eaf4039f3 --- /dev/null +++ b/REORG.TODO/resolv/res_hconf.h @@ -0,0 +1,54 @@ +/* Copyright (C) 1993-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by David Mosberger (davidm@azstarnet.com). + + 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_HCONF_H_ +#define _RES_HCONF_H_ + +#include <netdb.h> + +#define TRIMDOMAINS_MAX 4 + +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]; + int num_trimdomains; + const char *trimdomain[TRIMDOMAINS_MAX]; + unsigned int flags; +# define HCONF_FLAG_INITED (1 << 0) /* initialized? */ +# 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_trim_domain (char *domain); +extern void _res_hconf_trim_domains (struct hostent *hp); +extern void _res_hconf_reorder_addrs (struct hostent *hp); + +#endif /* _RES_HCONF_H_ */ diff --git a/REORG.TODO/resolv/res_init.c b/REORG.TODO/resolv/res_init.c new file mode 100644 index 0000000000..23676e994d --- /dev/null +++ b/REORG.TODO/resolv/res_init.c @@ -0,0 +1,542 @@ +/* + * 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 <ctype.h> +#include <netdb.h> +#include <resolv/resolv-internal.h> +#include <stdio.h> +#include <stdio_ext.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <stdint.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <net/if.h> +#include <netinet/in.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <sys/types.h> +#include <inet/net-internal.h> + +#include <not-cancel.h> + +/* Options. Should all be left alone. */ +/* #undef DEBUG */ + +static void res_setoptions (res_state, const char *, const char *) + internal_function; + +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; + +unsigned long long int __res_initstamp attribute_hidden; + +/* + * Resolver state default settings. + */ + +/* + * Set up default settings. If the 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. + * + * Return 0 if completes successfully, -1 on error + */ +int +res_ninit(res_state statp) { + extern int __res_vinit(res_state, int); + + return (__res_vinit(statp, 0)); +} +libc_hidden_def (__res_ninit) + +/* 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; + int nsort = 0; + char *net; + statp->_u._ext.initstamp = __res_initstamp; + + 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->__glibc_unused_qhook = NULL; + statp->__glibc_unused_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++; + } 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; + + sa6->sin6_scope_id = 0; + if (__glibc_likely (el != NULL)) { + /* Ignore errors, for backwards + compatibility. */ + (void) __inet6_scopeid_pton + (&a6, el + 1, &sa6->sin6_scope_id); + } + + statp->nsaddr_list[nserv].sin_family = 0; + statp->_u._ext.nsaddrs[nserv] = sa6; + statp->_u._ext.nssocks[nserv] = -1; + have_serv6 = 1; + nserv++; + } + } + } + continue; + } + 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; + } + if (MATCH(buf, "options")) { + res_setoptions(statp, buf + sizeof("options") - 1, "conf"); + continue; + } + } + statp->nscount = nserv; + if (have_serv6) { + /* We try IPv6 servers again. */ + statp->ipv6_unavail = false; + } + statp->nsort = nsort; + (void) fclose(fp); + } + if (__glibc_unlikely (statp->nscount == 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; + + } + + if ((cp = getenv("RES_OPTIONS")) != NULL) + res_setoptions(statp, cp, "env"); + statp->options |= RES_INIT; + return (0); +} + +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, 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 ("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++; + } +} + +/* 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) +{ + 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)); +} + +u_int +res_randomid(void) { + return 0xffff & __getpid(); +} +libc_hidden_def (__res_randomid) + + +/* + * 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->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; + } + } +} +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. */ +static void __attribute__ ((section ("__libc_thread_freeres_fn"))) +res_thread_freeres (void) +{ + 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; +} +text_set_element (__libc_thread_subfreeres, res_thread_freeres); +text_set_element (__libc_subfreeres, res_thread_freeres); diff --git a/REORG.TODO/resolv/res_libc.c b/REORG.TODO/resolv/res_libc.c new file mode 100644 index 0000000000..c8f158d94c --- /dev/null +++ b/REORG.TODO/resolv/res_libc.c @@ -0,0 +1,144 @@ +/* + * 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. + */ + +/* This file contains the definitions related to res_init which are + linked into libc instead of libresolv. */ + +#include <atomic.h> +#include <limits.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <libc-lock.h> + +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 + +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 = RES_DFLRETRY; + 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(); + + atomicinclock (lock); + /* Request all threads to re-initialize their resolver states, + resolv.conf might have changed. */ + atomicinc (__res_initstamp); + atomicincunlock (lock); + + return (__res_vinit(&_res, 1)); +} + +/* 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 = RES_DFLRETRY; + resp->options = RES_DEFAULT; + if (!resp->id) + resp->id = res_randomid (); + return __res_vinit (resp, 1); + } else + return __res_ninit (resp); +} +libc_hidden_def (__res_maybe_init) + +/* This needs to be after the use of _res in res_init, above. */ +#undef _res + +/* The resolver state for use by single-threaded programs. + This differs from plain `struct __res_state _res;' in that it doesn't + create a common definition, but a plain symbol that resides in .bss, + which can have an alias. */ +struct __res_state _res __attribute__ ((nocommon)); + +#undef __resp +__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 +compat_symbol (libc, _res, _res, GLIBC_2_0); +#endif + +#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2) +# undef res_init +extern int __res_init_weak (void); +weak_extern (__res_init_weak); +strong_alias (__res_init, __res_init_weak); +compat_symbol (libc, __res_init_weak, res_init, GLIBC_2_0); +#endif diff --git a/REORG.TODO/resolv/res_mkquery.c b/REORG.TODO/resolv/res_mkquery.c new file mode 100644 index 0000000000..8279d15de4 --- /dev/null +++ b/REORG.TODO/resolv/res_mkquery.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 1985, 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 <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <netdb.h> +#include <resolv/resolv-internal.h> +#include <stdio.h> +#include <string.h> +#include <sys/time.h> + +/* Options. Leave them on. */ +/* #define DEBUG */ + +#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 */ +{ + HEADER *hp; + u_char *cp; + int n; + u_char *dnptrs[20], **dpp, **lastdnptr; + + if (class < 0 || class > 65535 + || type < 0 || type > 65535) + return -1; + +#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 + { +#ifdef RANDOM_BITS + RANDOM_BITS (randombits); +#else + 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; + + default: + return (-1); + } + return (cp - buf); +} +libresolv_hidden_def (res_nmkquery) + + +/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */ +#ifndef T_OPT +#define T_OPT 41 +#endif + +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 */ +{ + u_int16_t flags = 0; + +#ifdef DEBUG + if ((statp->options & RES_DEBUG) != 0U) + printf(";; res_nopt()\n"); +#endif + + HEADER *hp = (HEADER *) buf; + u_char *cp = buf + n0; + u_char *ep = buf + buflen; + + if ((ep - cp) < 1 + RRFIXEDSZ) + return -1; + + *cp++ = 0; /* "." */ + + NS_PUT16(T_OPT, cp); /* 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); + } + + *cp++ = NOERROR; /* extended RCODE */ + *cp++ = 0; /* EDNS version */ + + 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(flags, cp); + NS_PUT16(0, cp); /* RDLEN */ + hp->arcount = htons(ntohs(hp->arcount) + 1); + + return cp - buf; +} diff --git a/REORG.TODO/resolv/res_query.c b/REORG.TODO/resolv/res_query.c new file mode 100644 index 0000000000..0ca3a65028 --- /dev/null +++ b/REORG.TODO/resolv/res_query.c @@ -0,0 +1,649 @@ +/* + * Copyright (c) 1988, 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 <assert.h> +#include <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <arpa/nameser.h> +#include <ctype.h> +#include <errno.h> +#include <netdb.h> +#include <resolv.h> +#include <resolv/resolv-internal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <resolv/resolv-internal.h> + +/* Options. Leave them on. */ +/* #undef DEBUG */ + +#if PACKETSZ > 65536 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 65536 +#endif + +#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. + */ +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) +{ + HEADER *hp = (HEADER *) answer; + HEADER *hp2; + int n, use_malloc = 0; + + size_t bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * QUERYSIZE; + u_char *buf = alloca (bufsize); + u_char *query1 = buf; + int nquery1 = -1; + u_char *query2 = NULL; + int nquery2 = 0; + + 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_QUERY_A_AND_AAAA) + { + n = res_nmkquery(statp, QUERY, name, class, T_A, NULL, 0, NULL, + query1, bufsize); + if (n > 0) + { + if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) + { + /* Use RESOLV_EDNS_BUFFER_SIZE because the receive + buffer can be reallocated. */ + n = __res_nopt (statp, n, query1, bufsize, + RESOLV_EDNS_BUFFER_SIZE); + if (n < 0) + goto unspec_nomem; + } + + nquery1 = n; + /* Align the buffer. */ + int npad = ((nquery1 + __alignof__ (HEADER) - 1) + & ~(__alignof__ (HEADER) - 1)) - nquery1; + if (n > bufsize - npad) + { + n = -1; + goto unspec_nomem; + } + int nused = n + npad; + query2 = buf + nused; + n = res_nmkquery(statp, QUERY, name, class, T_AAAA, NULL, 0, + NULL, query2, bufsize - nused); + if (n > 0 + && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) + /* Use RESOLV_EDNS_BUFFER_SIZE because the receive + buffer can be reallocated. */ + n = __res_nopt (statp, n, query2, bufsize, + RESOLV_EDNS_BUFFER_SIZE); + nquery2 = n; + } + + unspec_nomem:; + } + else + { + n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL, + query1, bufsize); + + if (n > 0 + && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0) + { + /* 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 (statp, n, query1, bufsize, advertise); + } + + nquery1 = n; + } + + 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_QUERY_A_AND_AAAA ? 2 : 1) * MAXPACKET; + buf = malloc (bufsize); + if (buf != NULL) { + query1 = buf; + use_malloc = 1; + goto again; + } + } + if (__glibc_unlikely (n <= 0)) { +#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); + 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. */ + hp = (HEADER *) *answerp; + + /* We simplify the following tests by assigning HP to HP2 or + vice versa. It is easy to verify that this is the same as + ignoring all tests of HP or HP2. */ + if (answerp2 == NULL || *resplen2 < (int) sizeof (HEADER)) + { + hp2 = hp; + } + else + { + hp2 = (HEADER *) *answerp2; + if (n < (int) sizeof (HEADER)) + { + hp = hp2; + } + } + + /* Make sure both hp and hp2 are defined */ + assert((hp != NULL) && (hp2 != NULL)); + + 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) + || (hp2->rcode == NOERROR + && ntohs (hp2->ancount) != 0)) + goto success; + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); + break; + case SERVFAIL: + RES_SET_H_ERRNO(statp, TRY_AGAIN); + break; + case NOERROR: + if (ntohs (hp->ancount) != 0 + || ntohs (hp2->ancount) != 0) + goto success; + RES_SET_H_ERRNO(statp, NO_DATA); + break; + case FORMERR: + case NOTIMP: + /* Servers must not reply to AAAA queries with + NOTIMP etc but some of them do. */ + if ((hp->rcode == NOERROR && ntohs (hp->ancount) != 0) + || (hp2->rcode == NOERROR + && ntohs (hp2->ancount) != 0)) + goto success; + /* FALLTHROUGH */ + case REFUSED: + default: + RES_SET_H_ERRNO(statp, NO_RECOVERY); + break; + } + return (-1); + } + success: + return (n); +} +libresolv_hidden_def (__libc_res_nquery) + +int +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 */ +{ + return __libc_res_nquery(statp, name, class, type, answer, anslen, + NULL, NULL, NULL, NULL, NULL); +} +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) +{ + const char *cp, * const *domain; + HEADER *hp = (HEADER *) answer; + char tmp[NS_MAXDNAME]; + u_int dots; + int trailing_dot, ret, saved_herrno; + int got_nodata = 0, got_servfail = 0, root_on_list = 0; + int tried_as_is = 0; + int searched = 0; + + __set_errno (0); + RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /* True if we never query. */ + + dots = 0; + for (cp = name; *cp != '\0'; cp++) + dots += (*cp == '.'); + trailing_dot = 0; + if (cp > name && *--cp == '.') + 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 there are enough dots in the name, let's just give it a + * try 'as is'. The threshold can be set with the "ndots" option. + * Also, query 'as is', if there is a trailing dot in the name. + */ + 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); + if (ret > 0 || trailing_dot + /* If the second response is valid then we use that. */ + || (ret == 0 && resplen2 != NULL && *resplen2 > 0)) + return (ret); + saved_herrno = h_errno; + tried_as_is++; + if (answerp && *answerp != answer) { + answer = *answerp; + anslen = MAXPACKET; + } + if (answerp2 && *answerp2_malloced) + { + free (*answerp2); + *answerp2 = NULL; + *nanswerp2 = 0; + *answerp2_malloced = 0; + } + } + + /* + * We do at least one level of search if + * - there is no dot and RES_DEFNAME is set, or + * - there is at least one dot, there is no trailing dot, + * and RES_DNSRCH is set. + */ + if ((!dots && (statp->options & RES_DEFNAMES) != 0) || + (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]; + searched = 1; + + /* __libc_res_nquerydoman 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 + up with "name..", which won't resolve. + OTOH, passing it "" will result in "name.", + which has the intended effect for both + possible representations of the root + domain. */ + if (dname[0] == '.') + dname++; + if (dname[0] == '\0') + root_on_list++; + + ret = __libc_res_nquerydomain(statp, name, dname, + class, type, + answer, anslen, answerp, + answerp2, nanswerp2, + resplen2, answerp2_malloced); + if (ret > 0 || (ret == 0 && resplen2 != NULL + && *resplen2 > 0)) + return (ret); + + if (answerp && *answerp != answer) { + answer = *answerp; + anslen = MAXPACKET; + } + if (answerp2 && *answerp2_malloced) + { + free (*answerp2); + *answerp2 = NULL; + *nanswerp2 = 0; + *answerp2_malloced = 0; + } + + /* + * If no server present, give up. + * If name isn't found in this domain, + * keep trying higher domains in the search list + * (if that's enabled). + * On a NO_DATA error, keep trying, otherwise + * a wildcard entry of another type could keep us + * from finding this entry higher in the domain. + * If we get some other error (negative answer or + * server failure), then stop searching up, + * but try the input name below in case it's + * fully-qualified. + */ + if (errno == ECONNREFUSED) { + RES_SET_H_ERRNO(statp, TRY_AGAIN); + return (-1); + } + + switch (statp->res_h_errno) { + case NO_DATA: + got_nodata++; + /* FALLTHROUGH */ + case HOST_NOT_FOUND: + /* keep trying */ + break; + case TRY_AGAIN: + if (hp->rcode == SERVFAIL) { + /* try next search element, if any */ + got_servfail++; + break; + } + /* FALLTHROUGH */ + default: + /* anything else implies that we're done */ + done++; + } + + /* if we got here for some reason other than DNSRCH, + * we only wanted one iteration of the loop, so stop. + */ + if ((statp->options & RES_DNSRCH) == 0) + done++; + } + } + + /* + * If the query has not already been tried as is then try it + * unless RES_NOTLDQUERY is set and there were no dots. + */ + 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); + if (ret > 0 || (ret == 0 && resplen2 != NULL + && *resplen2 > 0)) + return (ret); + } + + /* if we got here, we didn't satisfy the search. + * if we did an initial full query, return that query's H_ERRNO + * (note that we wouldn't be here if that query had succeeded). + * else if we ever got a nodata, send that back as the reason. + * else send back meaningless H_ERRNO, that being the one from + * the last DNSRCH we did. + */ + if (answerp2 && *answerp2_malloced) + { + free (*answerp2); + *answerp2 = NULL; + *nanswerp2 = 0; + *answerp2_malloced = 0; + } + if (saved_herrno != -1) + RES_SET_H_ERRNO(statp, saved_herrno); + else if (got_nodata) + RES_SET_H_ERRNO(statp, NO_DATA); + else if (got_servfail) + RES_SET_H_ERRNO(statp, TRY_AGAIN); + return (-1); +} +libresolv_hidden_def (__libc_res_nsearch) + +int +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 */ +{ + return __libc_res_nsearch(statp, name, class, type, answer, + anslen, NULL, NULL, NULL, NULL, NULL); +} +libresolv_hidden_def (res_nsearch) + +/* + * 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) +{ + 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); + + /* Decrement N prior to checking it against MAXDNAME + so that we detect a wrap to SIZE_MAX and return + a reasonable error. */ + n--; + if (n >= MAXDNAME - 1) { + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); + } + longname = name; + } else { + n = strlen(name); + d = strlen(domain); + if (n + d + 1 >= MAXDNAME) { + RES_SET_H_ERRNO(statp, NO_RECOVERY); + return (-1); + } + sprintf(nbuf, "%s.%s", name, domain); + } + return (__libc_res_nquery(statp, longname, class, type, answer, + anslen, answerp, answerp2, nanswerp2, + resplen2, answerp2_malloced)); +} + +int +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 */ +{ + return __libc_res_nquerydomain(statp, name, domain, class, type, + answer, anslen, NULL, NULL, NULL, NULL, + NULL); +} +libresolv_hidden_def (res_nquerydomain) + +const char * +res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) { + char *file, *cp1, *cp2; + char buf[BUFSIZ]; + FILE *fp; + + if (statp->options & RES_NOALIASES) + return (NULL); + file = getenv("HOSTALIASES"); + if (file == NULL || (fp = fopen(file, "rce")) == NULL) + return (NULL); + setbuf(fp, NULL); + buf[sizeof(buf) - 1] = '\0'; + while (fgets(buf, sizeof(buf), fp)) { + for (cp1 = buf; *cp1 && !isspace(*cp1); ++cp1) + ; + if (!*cp1) + break; + *cp1 = '\0'; + if (ns_samename(buf, name) == 1) { + while (isspace(*++cp1)) + ; + if (!*cp1) + break; + for (cp2 = cp1 + 1; *cp2 && !isspace(*cp2); ++cp2) + ; + *cp2 = '\0'; + strncpy(dst, cp1, siz - 1); + dst[siz - 1] = '\0'; + fclose(fp); + return (dst); + } + } + fclose(fp); + return (NULL); +} +libresolv_hidden_def (res_hostalias) diff --git a/REORG.TODO/resolv/res_send.c b/REORG.TODO/resolv/res_send.c new file mode 100644 index 0000000000..b7b8ecdfc4 --- /dev/null +++ b/REORG.TODO/resolv/res_send.c @@ -0,0 +1,1502 @@ +/* Copyright (C) 2016-2017 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. + */ + +/* + * Send query to name server and wait for reply. + */ + +#include <assert.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/time.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <sys/poll.h> + +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <arpa/inet.h> +#include <sys/ioctl.h> + +#include <errno.h> +#include <fcntl.h> +#include <netdb.h> +#include <resolv/resolv-internal.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <kernel-features.h> +#include <libc-diag.h> + +#if PACKETSZ > 65536 +#define MAXPACKET PACKETSZ +#else +#define MAXPACKET 65536 +#endif + +/* From ev_streams.c. */ + +static inline void +__attribute ((always_inline)) +evConsIovec(void *buf, size_t cnt, struct iovec *vec) { + memset(vec, 0xf5, sizeof (*vec)); + vec->iov_base = buf; + vec->iov_len = cnt; +} + +/* From ev_timers.c. */ + +#define BILLION 1000000000 + +static inline void +evConsTime(struct timespec *res, time_t sec, long nsec) { + res->tv_sec = sec; + res->tv_nsec = nsec; +} + +static inline void +evAddTime(struct timespec *res, const struct timespec *addend1, + const struct timespec *addend2) { + res->tv_sec = addend1->tv_sec + addend2->tv_sec; + res->tv_nsec = addend1->tv_nsec + addend2->tv_nsec; + if (res->tv_nsec >= BILLION) { + res->tv_sec++; + res->tv_nsec -= BILLION; + } +} + +static inline void +evSubTime(struct timespec *res, const struct timespec *minuend, + const struct timespec *subtrahend) { + res->tv_sec = minuend->tv_sec - subtrahend->tv_sec; + if (minuend->tv_nsec >= subtrahend->tv_nsec) + res->tv_nsec = minuend->tv_nsec - subtrahend->tv_nsec; + else { + res->tv_nsec = (BILLION + - subtrahend->tv_nsec + minuend->tv_nsec); + res->tv_sec--; + } +} + +static int +evCmpTime(struct timespec a, struct timespec b) { + long x = a.tv_sec - b.tv_sec; + + if (x == 0L) + x = a.tv_nsec - b.tv_nsec; + return (x < 0L ? (-1) : x > 0L ? (1) : (0)); +} + +static void +evNowTime(struct timespec *res) { + struct timeval now; + + if (gettimeofday(&now, NULL) < 0) + evConsTime(res, 0, 0); + else + TIMEVAL_TO_TIMESPEC (&now, 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 int send_vc(res_state, const u_char *, int, + const u_char *, int, + u_char **, int *, int *, int, u_char **, + u_char **, int *, int *, int *); +static int send_dg(res_state, const u_char *, int, + 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. */ + +/* int + * res_isourserver(ina) + * looks up "ina" in _res.ns_addr_list[] + * returns: + * 0 : not found + * >0 : found + * author: + * paul vixie, 29may94 + */ +int +res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp) +{ + int ns; + + if (inp->sin6_family == AF_INET) { + struct sockaddr_in *in4p = (struct sockaddr_in *) inp; + in_port_t port = in4p->sin_port; + in_addr_t addr = in4p->sin_addr.s_addr; + + for (ns = 0; ns < statp->nscount; ns++) { + const struct sockaddr_in *srv = + (struct sockaddr_in *) get_nsaddr (statp, ns); + + if ((srv->sin_family == AF_INET) && + (srv->sin_port == port) && + (srv->sin_addr.s_addr == INADDR_ANY || + srv->sin_addr.s_addr == addr)) + return (1); + } + } else if (inp->sin6_family == AF_INET6) { + for (ns = 0; ns < statp->nscount; ns++) { + const struct sockaddr_in6 *srv + = (struct sockaddr_in6 *) get_nsaddr (statp, ns); + if ((srv->sin6_family == AF_INET6) && + (srv->sin6_port == inp->sin6_port) && + !(memcmp(&srv->sin6_addr, &in6addr_any, + sizeof (struct in6_addr)) && + memcmp(&srv->sin6_addr, &inp->sin6_addr, + sizeof (struct in6_addr)))) + return (1); + } + } + return (0); +} + +/* int + * res_nameinquery(name, type, class, buf, eom) + * look for (name,type,class) in the query section of packet (buf,eom) + * requires: + * buf + HFIXEDSZ <= eom + * returns: + * -1 : format error + * 0 : not found + * >0 : found + * author: + * paul vixie, 29may94 + */ +int +res_nameinquery(const char *name, int type, int class, + const u_char *buf, const u_char *eom) +{ + const u_char *cp = buf + HFIXEDSZ; + int qdcount = ntohs(((HEADER*)buf)->qdcount); + + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + int n, ttype, tclass; + + n = dn_expand(buf, eom, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + if (cp + 2 * INT16SZ > eom) + return (-1); + NS_GET16(ttype, cp); + NS_GET16(tclass, cp); + if (ttype == type && tclass == class && + ns_samename(tname, name) == 1) + return (1); + } + return (0); +} +libresolv_hidden_def (res_nameinquery) + +/* int + * res_queriesmatch(buf1, eom1, buf2, eom2) + * is there a 1:1 mapping of (name,type,class) + * in (buf1,eom1) and (buf2,eom2)? + * returns: + * -1 : format error + * 0 : not a 1:1 mapping + * >0 : is a 1:1 mapping + * author: + * paul vixie, 29may94 + */ +int +res_queriesmatch(const u_char *buf1, const u_char *eom1, + const u_char *buf2, const u_char *eom2) +{ + if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2) + return (-1); + + /* + * Only header section present in replies to + * dynamic update packets. + */ + if ((((HEADER *)buf1)->opcode == ns_o_update) && + (((HEADER *)buf2)->opcode == ns_o_update)) + return (1); + + /* Note that we initially do not convert QDCOUNT to the host byte + order. We can compare it with the second buffer's QDCOUNT + value without doing this. */ + int qdcount = ((HEADER*)buf1)->qdcount; + if (qdcount != ((HEADER*)buf2)->qdcount) + return (0); + + qdcount = htons (qdcount); + const u_char *cp = buf1 + HFIXEDSZ; + + while (qdcount-- > 0) { + char tname[MAXDNAME+1]; + int n, ttype, tclass; + + n = dn_expand(buf1, eom1, cp, tname, sizeof tname); + if (n < 0) + return (-1); + cp += n; + if (cp + 2 * INT16SZ > eom1) + return (-1); + NS_GET16(ttype, cp); + NS_GET16(tclass, cp); + if (!res_nameinquery(tname, ttype, tclass, buf2, eom2)) + return (0); + } + return (1); +} +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) +{ + int gotsomewhere, terrno, try, v_circuit, resplen, ns, n; + + if (statp->nscount == 0) { + __set_errno (ESRCH); + return (-1); + } + + if (anssiz < (buf2 == NULL ? 1 : 2) * HFIXEDSZ) { + __set_errno (EINVAL); + return (-1); + } + + 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); + gotsomewhere = 0; + terrno = ETIMEDOUT; + + /* + * If the ns_addr_list in the resolver context has changed, then + * invalidate our cached copy and the associated timing data. + */ + if (EXT(statp).nscount != 0) { + int needclose = 0; + + if (EXT(statp).nscount != statp->nscount) + needclose++; + else + for (ns = 0; ns < statp->nscount; ns++) { + if (statp->nsaddr_list[ns].sin_family != 0 + && !sock_eq((struct sockaddr_in6 *) + &statp->nsaddr_list[ns], + EXT(statp).nsaddrs[ns])) + { + needclose++; + break; + } + } + if (needclose) { + __res_iclose(statp, false); + EXT(statp).nscount = 0; + } + } + + /* + * Maybe initialize our private copy of the ns_addr_list. + */ + if (EXT(statp).nscount == 0) { + for (ns = 0; ns < statp->nscount; ns++) { + EXT(statp).nssocks[ns] = -1; + if (statp->nsaddr_list[ns].sin_family == 0) + continue; + if (EXT(statp).nsaddrs[ns] == NULL) + EXT(statp).nsaddrs[ns] = + malloc(sizeof (struct sockaddr_in6)); + if (EXT(statp).nsaddrs[ns] != NULL) + memset (mempcpy(EXT(statp).nsaddrs[ns], + &statp->nsaddr_list[ns], + sizeof (struct sockaddr_in)), + '\0', + sizeof (struct sockaddr_in6) + - sizeof (struct sockaddr_in)); + } + EXT(statp).nscount = statp->nscount; + } + + /* + * Some resolvers want to even out the load on their nameservers. + * Note that RES_BLAST overrides RES_ROTATE. + */ + if (__glibc_unlikely ((statp->options & RES_ROTATE) != 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; + } + + /* + * Send request, RETRY times, or until successful. + */ + for (try = 0; try < statp->retry; try++) { + for (ns = 0; ns < statp->nscount; ns++) + { +#ifdef DEBUG + char tmpbuf[40]; + struct sockaddr *nsap = get_nsaddr (statp, ns); +#endif + + same_ns: + 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; + n = send_vc(statp, buf, buflen, buf2, buflen2, + &ans, &anssiz, &terrno, + ns, ansp, ansp2, nansp2, resplen2, + ansp2_malloced); + if (n < 0) + return (-1); + if (n == 0 && (buf2 == NULL || *resplen2 == 0)) + goto next_ns; + } else { + /* Use datagrams. */ + n = send_dg(statp, buf, buflen, buf2, buflen2, + &ans, &anssiz, &terrno, + ns, &v_circuit, &gotsomewhere, ansp, + ansp2, nansp2, resplen2, ansp2_malloced); + if (n < 0) + return (-1); + if (n == 0 && (buf2 == NULL || *resplen2 == 0)) + goto next_ns; + if (v_circuit) + // XXX Check whether both requests failed or + // XXX whether one has been answered successfully + goto same_ns; + } + + 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, + * close the socket. + */ + if ((v_circuit && (statp->options & RES_USEVC) == 0) || + (statp->options & RES_STAYOPEN) == 0) { + __res_iclose(statp, false); + } + return (resplen); + next_ns: ; + } /*foreach ns*/ + } /*foreach retry*/ + __res_iclose(statp, false); + if (!v_circuit) { + if (!gotsomewhere) + __set_errno (ECONNREFUSED); /* no nameservers found */ + else + __set_errno (ETIMEDOUT); /* no answer obtained */ + } else + __set_errno (terrno); + return (-1); +} + +int +res_nsend(res_state statp, + const u_char *buf, int buflen, u_char *ans, int anssiz) +{ + return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz, + NULL, NULL, NULL, NULL, NULL); +} +libresolv_hidden_def (res_nsend) + +/* Private */ + +static struct sockaddr * +get_nsaddr (res_state statp, int n) +{ + + if (statp->nsaddr_list[n].sin_family == 0 && EXT(statp).nsaddrs[n] != NULL) + /* EXT(statp).nsaddrs[n] holds an address that is larger than + struct sockaddr, and user code did not update + statp->nsaddr_list[n]. */ + return (struct sockaddr *) EXT(statp).nsaddrs[n]; + else + /* User code updated statp->nsaddr_list[n], or statp->nsaddr_list[n] + has the same content as EXT(statp).nsaddrs[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 + IPv6 queries at the same serially on the same socket. + + 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 implementation should be corrected to honour these + options. + + Please also note that for TCP we send both queries over the same + socket one after another. This technically violates best practice + since the server is allowed to read the first query, respond, and + then close the socket (to service another client). If the server + does this, then the remaining second query in the socket data buffer + will cause the server to send the client an RST which will arrive + asynchronously and the client's OS will likely tear down the socket + receive buffer resulting in a potentially short read and lost + response data. This will force the client to retry the query again, + and this process may repeat until all servers and connection resets + are exhausted and then the query will fail. It's not known if this + happens with any frequency in real DNS server implementations. This + implementation should be corrected to use two sockets by default for + parallel queries. + + The query stored in BUF of BUFLEN length is sent first followed by + the query stored in BUF2 of BUFLEN2 length. Queries are sent + serially on the same socket. + + Answers to the query are stored firstly in *ANSP up to a max of + *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP + is non-NULL (to indicate that modifying the answer buffer is allowed) + then malloc is used to allocate a new response buffer and ANSCP and + ANSP will both point to the new buffer. If more than *ANSSIZP bytes + are needed but ANSCP is NULL, then as much of the response as + possible is read into the buffer, but the results will be truncated. + When truncation happens because of a small answer buffer the DNS + packets header field TC will bet set to 1, indicating a truncated + message and the rest of the socket data will be read and discarded. + + Answers to the query are stored secondly in *ANSP2 up to a max of + *ANSSIZP2 bytes, with the actual response length stored in + *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2 + is non-NULL (required for a second query) then malloc is used to + allocate a new response buffer, *ANSSIZP2 is set to the new buffer + size and *ANSP2_MALLOCED is set to 1. + + The ANSP2_MALLOCED argument will eventually be removed as the + change in buffer pointer can be used to detect the buffer has + changed and that the caller should use free on the new buffer. + + Note that the answers may arrive in any order from the server and + therefore the first and second answer buffers may not correspond to + the first and second queries. + + It is not supported to call this function with a non-NULL ANSP2 + but a NULL ANSCP. Put another way, you can call send_vc with a + single unmodifiable buffer or two modifiable buffers, but no other + combination is supported. + + It is the caller's responsibility to free the malloc allocated + buffers by detecting that the pointers have changed from their + original values i.e. *ANSCP or *ANSP2 has changed. + + If errors are encountered then *TERRNO is set to an appropriate + errno value and a zero result is returned for a recoverable error, + and a less-than zero result is returned for a non-recoverable error. + + If no errors are encountered then *TERRNO is left unmodified and + a the length of the first response in bytes is returned. */ +static int +send_vc(res_state statp, + const u_char *buf, int buflen, const u_char *buf2, int buflen2, + u_char **ansp, int *anssizp, + int *terrno, int ns, u_char **anscp, u_char **ansp2, int *anssizp2, + int *resplen2, int *ansp2_malloced) +{ + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; + HEADER *anhp = (HEADER *) *ansp; + struct sockaddr *nsap = get_nsaddr (statp, ns); + int truncating, connreset, n; + /* On some architectures compiler might emit a warning indicating + 'resplen' may be used uninitialized. However if buf2 == NULL + then this code won't be executed; if buf2 != NULL, then first + time round the loop recvresp1 and recvresp2 will be 0 so this + code won't be executed but "thisresplenp = &resplen;" followed + by "*thisresplenp = rlen;" will be executed so that subsequent + times round the loop resplen has been initialized. So this is + a false-positive. + */ + DIAG_PUSH_NEEDS_COMMENT; + DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized"); + int resplen; + DIAG_POP_NEEDS_COMMENT; + struct iovec iov[4]; + u_short len; + u_short len2; + u_char *cp; + + connreset = 0; + same_ns: + truncating = 0; + + /* Are we still talking to whom we want to talk to? */ + if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) { + struct sockaddr_in6 peer; + socklen_t size = sizeof peer; + + if (getpeername(statp->_vcsock, + (struct sockaddr *)&peer, &size) < 0 || + !sock_eq(&peer, (struct sockaddr_in6 *) nsap)) { + __res_iclose(statp, false); + statp->_flags &= ~RES_F_VC; + } + } + + if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) { + if (statp->_vcsock >= 0) + __res_iclose(statp, false); + + 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); + if (connect(statp->_vcsock, nsap, + nsap->sa_family == AF_INET + ? sizeof (struct sockaddr_in) + : sizeof (struct sockaddr_in6)) < 0) { + *terrno = errno; + Aerror(statp, stderr, "connect/vc", errno, nsap); + return close_and_return_error (statp, resplen2); + } + statp->_flags |= RES_F_VC; + } + + /* + * Send length & message + */ + len = htons ((u_short) buflen); + evConsIovec(&len, INT16SZ, &iov[0]); + evConsIovec((void*)buf, buflen, &iov[1]); + int niov = 2; + ssize_t explen = INT16SZ + buflen; + if (buf2 != NULL) { + len2 = htons ((u_short) buflen2); + evConsIovec(&len2, INT16SZ, &iov[2]); + evConsIovec((void*)buf2, buflen2, &iov[3]); + niov = 4; + explen += INT16SZ + buflen2; + } + if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, niov)) != explen) { + *terrno = errno; + Perror(statp, stderr, "write failed", errno); + return close_and_return_error (statp, resplen2); + } + /* + * Receive length & response + */ + int recvresp1 = 0; + /* Skip the second response if there is no second query. + To do that we mark the second response as received. */ + int recvresp2 = buf2 == NULL; + uint16_t rlen16; + read_len: + cp = (u_char *)&rlen16; + len = sizeof(rlen16); + while ((n = TEMP_FAILURE_RETRY (read(statp->_vcsock, cp, + (int)len))) > 0) { + cp += n; + if ((len -= n) <= 0) + break; + } + if (n <= 0) { + *terrno = errno; + Perror(statp, stderr, "read failed", errno); + /* + * A long running process might get its TCP + * connection reset if the remote server was + * restarted. Requery the server instead of + * trying a new one. When there is only one + * server, this means that a query might work + * instead of failing. We only allow one reset + * per query to prevent looping. + */ + if (*terrno == ECONNRESET && !connreset) + { + __res_iclose (statp, false); + connreset = 1; + goto same_ns; + } + return close_and_return_error (statp, resplen2); + } + int rlen = ntohs (rlen16); + + int *thisanssizp; + u_char **thisansp; + int *thisresplenp; + if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) { + /* We have not received any responses + yet or we only have one response to + receive. */ + thisanssizp = anssizp; + thisansp = anscp ?: ansp; + assert (anscp != NULL || ansp2 == NULL); + thisresplenp = &resplen; + } else { + thisanssizp = anssizp2; + thisansp = ansp2; + thisresplenp = resplen2; + } + anhp = (HEADER *) *thisansp; + + *thisresplenp = rlen; + /* Is the answer buffer too small? */ + if (*thisanssizp < rlen) { + /* If the current buffer is not the the static + user-supplied buffer then we can reallocate + it. */ + if (thisansp != NULL && thisansp != ansp) { + /* Always allocate MAXPACKET, callers expect + this specific size. */ + u_char *newp = malloc (MAXPACKET); + if (newp == NULL) + { + *terrno = ENOMEM; + return close_and_return_error (statp, resplen2); + } + *thisanssizp = MAXPACKET; + *thisansp = newp; + if (thisansp == ansp2) + *ansp2_malloced = 1; + anhp = (HEADER *) newp; + /* A uint16_t can't be larger than MAXPACKET + thus it's safe to allocate MAXPACKET but + read RLEN bytes instead. */ + len = rlen; + } else { + Dprint(statp->options & RES_DEBUG, + (stdout, ";; response truncated\n") + ); + truncating = 1; + len = *thisanssizp; + } + } else + len = rlen; + + if (__glibc_unlikely (len < HFIXEDSZ)) { + /* + * Undersized message. + */ + Dprint(statp->options & RES_DEBUG, + (stdout, ";; undersized: %d\n", len)); + *terrno = EMSGSIZE; + return close_and_return_error (statp, resplen2); + } + + cp = *thisansp; + while (len != 0 && (n = read(statp->_vcsock, (char *)cp, (int)len)) > 0){ + cp += n; + len -= n; + } + if (__glibc_unlikely (n <= 0)) { + *terrno = errno; + Perror(statp, stderr, "read(vc)", errno); + return close_and_return_error (statp, resplen2); + } + if (__glibc_unlikely (truncating)) { + /* + * Flush rest of answer so connection stays in synch. + */ + anhp->tc = 1; + len = rlen - *thisanssizp; + while (len != 0) { + char junk[PACKETSZ]; + + n = read(statp->_vcsock, junk, + (len > sizeof junk) ? sizeof junk : len); + if (n > 0) + len -= n; + else + break; + } + } + /* + * If the calling application has bailed out of + * a previous call and failed to arrange to have + * the circuit closed or the server has got + * itself confused, then drop the packet and + * 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); + goto read_len; + } + + /* Mark which reply we received. */ + if (recvresp1 == 0 && hp->id == anhp->id) + recvresp1 = 1; + else + recvresp2 = 1; + /* Repeat waiting if we have a second answer to arrive. */ + if ((recvresp1 & recvresp2) == 0) + goto read_len; + + /* + * All is well, or the error is fatal. Signal that the + * next nameserver ought not be tried. + */ + return resplen; +} + +static int +reopen (res_state statp, int *terrno, int ns) +{ + if (EXT(statp).nssocks[ns] == -1) { + struct sockaddr *nsap = get_nsaddr (statp, ns); + socklen_t slen; + + /* 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 | 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 | SOCK_CLOEXEC, 0); + slen = sizeof (struct sockaddr_in); + } + if (EXT(statp).nssocks[ns] < 0) { + *terrno = errno; + Perror(statp, stderr, "socket(dg)", errno); + return (-1); + } + + /* + * On a 4.3BSD+ machine (client and server, + * actually), sending to a nameserver datagram + * port with no nameserver will cause an + * ICMP port unreachable message to be returned. + * If our datagram socket is "connected" to the + * server, we get an ECONNREFUSED error on the next + * socket operation, and select returns if the + * 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) { + DIAG_POP_NEEDS_COMMENT; + Aerror(statp, stderr, "connect(dg)", errno, nsap); + __res_iclose(statp, false); + return (0); + } + } + + return 1; +} + +/* The send_dg function is responsible for sending a DNS query over UDP + to the nameserver numbered NS from the res_state STATP i.e. + EXT(statp).nssocks[ns]. The function supports IPv4 and IPv6 queries + along with the ability to send the query in parallel for both stacks + (default) or serially (RES_SINGLKUP). It also supports serial lookup + with a close and reopen of the socket used to talk to the server + (RES_SNGLKUPREOP) to work around broken name servers. + + The query stored in BUF of BUFLEN length is sent first followed by + the query stored in BUF2 of BUFLEN2 length. Queries are sent + in parallel (default) or serially (RES_SINGLKUP or RES_SNGLKUPREOP). + + Answers to the query are stored firstly in *ANSP up to a max of + *ANSSIZP bytes. If more than *ANSSIZP bytes are needed and ANSCP + is non-NULL (to indicate that modifying the answer buffer is allowed) + then malloc is used to allocate a new response buffer and ANSCP and + ANSP will both point to the new buffer. If more than *ANSSIZP bytes + are needed but ANSCP is NULL, then as much of the response as + possible is read into the buffer, but the results will be truncated. + When truncation happens because of a small answer buffer the DNS + packets header field TC will bet set to 1, indicating a truncated + message, while the rest of the UDP packet is discarded. + + Answers to the query are stored secondly in *ANSP2 up to a max of + *ANSSIZP2 bytes, with the actual response length stored in + *RESPLEN2. If more than *ANSSIZP bytes are needed and ANSP2 + is non-NULL (required for a second query) then malloc is used to + allocate a new response buffer, *ANSSIZP2 is set to the new buffer + size and *ANSP2_MALLOCED is set to 1. + + The ANSP2_MALLOCED argument will eventually be removed as the + change in buffer pointer can be used to detect the buffer has + changed and that the caller should use free on the new buffer. + + Note that the answers may arrive in any order from the server and + therefore the first and second answer buffers may not correspond to + the first and second queries. + + It is not supported to call this function with a non-NULL ANSP2 + but a NULL ANSCP. Put another way, you can call send_vc with a + single unmodifiable buffer or two modifiable buffers, but no other + combination is supported. + + It is the caller's responsibility to free the malloc allocated + buffers by detecting that the pointers have changed from their + original values i.e. *ANSCP or *ANSP2 has changed. + + If an answer is truncated because of UDP datagram DNS limits then + *V_CIRCUIT is set to 1 and the return value non-zero to indicate to + the caller to retry with TCP. The value *GOTSOMEWHERE is set to 1 + if any progress was made reading a response from the nameserver and + is used by the caller to distinguish between ECONNREFUSED and + ETIMEDOUT (the latter if *GOTSOMEWHERE is 1). + + If errors are encountered then *TERRNO is set to an appropriate + errno value and a zero result is returned for a recoverable error, + and a less-than zero result is returned for a non-recoverable error. + + If no errors are encountered then *TERRNO is left unmodified and + a the length of the first response in bytes is returned. */ +static int +send_dg(res_state statp, + const u_char *buf, int buflen, const u_char *buf2, int buflen2, + u_char **ansp, int *anssizp, + int *terrno, int ns, int *v_circuit, int *gotsomewhere, u_char **anscp, + u_char **ansp2, int *anssizp2, int *resplen2, int *ansp2_malloced) +{ + const HEADER *hp = (HEADER *) buf; + const HEADER *hp2 = (HEADER *) buf2; + struct timespec now, timeout, finish; + struct pollfd pfd[1]; + int ptimeout; + struct sockaddr_in6 from; + int resplen = 0; + int n; + + /* + * Compute time for the total operation. + */ + int seconds = (statp->retrans << ns); + if (ns > 0) + seconds /= statp->nscount; + if (seconds <= 0) + seconds = 1; + bool single_request_reopen = (statp->options & RES_SNGLKUPREOP) != 0; + bool single_request = (((statp->options & RES_SNGLKUP) != 0) + | single_request_reopen); + int save_gotsomewhere = *gotsomewhere; + + int retval; + retry_reopen: + retval = reopen (statp, terrno, ns); + if (retval <= 0) + { + if (resplen2 != NULL) + *resplen2 = 0; + return retval; + } + retry: + evNowTime(&now); + evConsTime(&timeout, seconds, 0); + evAddTime(&finish, &now, &timeout); + int need_recompute = 0; + int nwritten = 0; + int recvresp1 = 0; + /* Skip the second response if there is no second query. + To do that we mark the second response as received. */ + int recvresp2 = buf2 == NULL; + pfd[0].fd = EXT(statp).nssocks[ns]; + pfd[0].events = POLLOUT; + wait: + if (need_recompute) { + recompute_resend: + evNowTime(&now); + if (evCmpTime(finish, now) <= 0) { + poll_err_out: + Perror(statp, stderr, "poll", errno); + return close_and_return_error (statp, resplen2); + } + evSubTime(&timeout, &finish, &now); + need_recompute = 0; + } + /* Convert struct timespec in milliseconds. */ + ptimeout = timeout.tv_sec * 1000 + timeout.tv_nsec / 1000000; + + n = 0; + if (nwritten == 0) + n = __poll (pfd, 1, 0); + if (__glibc_unlikely (n == 0)) { + n = __poll (pfd, 1, ptimeout); + 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 + there which don't handle two outstanding + requests from the same source. There are also + broken firewall settings. If we time out after + having received one answer switch to the mode + where we send the second request only once we + have received the first answer. */ + if (!single_request) + { + statp->options |= RES_SNGLKUP; + single_request = true; + *gotsomewhere = save_gotsomewhere; + goto retry; + } + else if (!single_request_reopen) + { + statp->options |= RES_SNGLKUPREOP; + single_request_reopen = true; + *gotsomewhere = save_gotsomewhere; + __res_iclose (statp, false); + goto retry_reopen; + } + + *resplen2 = 1; + return resplen; + } + + *gotsomewhere = 1; + if (resplen2 != NULL) + *resplen2 = 0; + return 0; + } + if (n < 0) { + if (errno == EINTR) + goto recompute_resend; + + goto poll_err_out; + } + __set_errno (0); + if (pfd[0].revents & POLLOUT) { +#ifndef __ASSUME_SENDMMSG + static int have_sendmmsg; +#else +# define have_sendmmsg 1 +#endif + 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; + + int ndg = __sendmmsg (pfd[0].fd, reqs, 2, MSG_NOSIGNAL); + if (__glibc_likely (ndg == 2)) + { + if (reqs[0].msg_len != buflen + || reqs[1].msg_len != buflen2) + goto fail_sendmmsg; + + pfd[0].events = POLLIN; + nwritten += 2; + } + else if (ndg == 1 && reqs[0].msg_len == buflen) + goto just_one; + else if (ndg < 0 && (errno == EINTR || errno == EAGAIN)) + goto recompute_resend; + else + { +#ifndef __ASSUME_SENDMMSG + if (__glibc_unlikely (have_sendmmsg == 0)) + { + if (ndg < 0 && errno == ENOSYS) + { + have_sendmmsg = -1; + goto try_send; + } + have_sendmmsg = 1; + } +#endif + + fail_sendmmsg: + Perror(statp, stderr, "sendmmsg", errno); + return close_and_return_error (statp, resplen2); + } + } + else + { + ssize_t sr; +#ifndef __ASSUME_SENDMMSG + try_send: +#endif + if (nwritten != 0) + sr = send (pfd[0].fd, buf2, buflen2, MSG_NOSIGNAL); + else + sr = send (pfd[0].fd, buf, buflen, MSG_NOSIGNAL); + + if (sr != (nwritten != 0 ? buflen2 : buflen)) { + if (errno == EINTR || errno == EAGAIN) + goto recompute_resend; + Perror(statp, stderr, "send", errno); + return close_and_return_error (statp, resplen2); + } + just_one: + if (nwritten != 0 || buf2 == NULL || single_request) + pfd[0].events = POLLIN; + else + pfd[0].events = POLLIN | POLLOUT; + ++nwritten; + } + goto wait; + } else if (pfd[0].revents & POLLIN) { + int *thisanssizp; + u_char **thisansp; + int *thisresplenp; + + if ((recvresp1 | recvresp2) == 0 || buf2 == NULL) { + /* We have not received any responses + yet or we only have one response to + receive. */ + thisanssizp = anssizp; + thisansp = anscp ?: ansp; + assert (anscp != NULL || ansp2 == NULL); + thisresplenp = &resplen; + } else { + thisanssizp = anssizp2; + thisansp = ansp2; + thisresplenp = resplen2; + } + + if (*thisanssizp < MAXPACKET + /* If the current buffer is not the the static + user-supplied buffer then we can reallocate + it. */ + && (thisansp != NULL && thisansp != ansp) +#ifdef FIONREAD + /* Is the size too small? */ + && (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0 + || *thisanssizp < *thisresplenp) +#endif + ) { + /* Always allocate MAXPACKET, callers expect + this specific size. */ + u_char *newp = malloc (MAXPACKET); + if (newp != NULL) { + *thisanssizp = MAXPACKET; + *thisansp = newp; + if (thisansp == ansp2) + *ansp2_malloced = 1; + } + } + /* We could end up with truncation if anscp was NULL + (not allowed to change caller's buffer) and the + response buffer size is too small. This isn't a + reliable way to detect truncation because the ioctl + may be an inaccurate report of the UDP message size. + Therefore we use this only to issue debug output. + To do truncation accurately with UDP we need + 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); + *thisresplenp = recvfrom(pfd[0].fd, (char*)*thisansp, + *thisanssizp, 0, + (struct sockaddr *)&from, &fromlen); + if (__glibc_unlikely (*thisresplenp <= 0)) { + if (errno == EINTR || errno == EAGAIN) { + need_recompute = 1; + goto wait; + } + Perror(statp, stderr, "recvfrom", errno); + 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; + return close_and_return_error (statp, resplen2); + } + if ((recvresp1 || hp->id != anhp->id) + && (recvresp2 || hp2->id != anhp->id)) { + /* + * response from old query, ignore it. + * 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) && + !res_ourserver_p(statp, &from)) { + /* + * response from wrong server? ignore it. + * 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; + } + if (!(statp->options & RES_INSECURE2) + && (recvresp1 || !res_queriesmatch(buf, buf + buflen, + *thisansp, + *thisansp + + *thisanssizp)) + && (recvresp2 || !res_queriesmatch(buf2, buf2 + buflen2, + *thisansp, + *thisansp + + *thisanssizp))) { + /* + * response contains wrong query? ignore it. + * 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; + return resplen; + } + if (buf2 != NULL) + { + /* No data from the first reply. */ + resplen = 0; + /* We are waiting for a possible second reply. */ + if (hp->id == anhp->id) + recvresp1 = 1; + else + recvresp2 = 1; + + goto wait; + } + + /* don't retry if called from dig */ + if (!statp->pfcode) + 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) { + /* + * 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. */ + if (recvresp1 == 0 && hp->id == anhp->id) + recvresp1 = 1; + else + recvresp2 = 1; + /* Repeat waiting if we have a second answer to arrive. */ + if ((recvresp1 & recvresp2) == 0) { + if (single_request) { + pfd[0].events = POLLOUT; + if (single_request_reopen) { + __res_iclose (statp, false); + retval = reopen (statp, terrno, ns); + if (retval <= 0) + { + if (resplen2 != NULL) + *resplen2 = 0; + return retval; + } + pfd[0].fd = EXT(statp).nssocks[ns]; + } + } + goto wait; + } + /* 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. */ + 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) { + if (a1->sin6_family == AF_INET) + return ((((struct sockaddr_in *)a1)->sin_port == + ((struct sockaddr_in *)a2)->sin_port) && + (((struct sockaddr_in *)a1)->sin_addr.s_addr == + ((struct sockaddr_in *)a2)->sin_addr.s_addr)); + else + return ((a1->sin6_port == a2->sin6_port) && + !memcmp(&a1->sin6_addr, &a2->sin6_addr, + sizeof (struct in6_addr))); + } + if (a1->sin6_family == AF_INET) { + struct sockaddr_in6 *sap = a1; + a1 = a2; + a2 = sap; + } /* assumes that AF_INET and AF_INET6 are the only possibilities */ + return ((a1->sin6_port == ((struct sockaddr_in *)a2)->sin_port) && + IN6_IS_ADDR_V4MAPPED(&a1->sin6_addr) && + (a1->sin6_addr.s6_addr32[3] == + ((struct sockaddr_in *)a2)->sin_addr.s_addr)); +} diff --git a/REORG.TODO/resolv/resolv-internal.h b/REORG.TODO/resolv/resolv-internal.h new file mode 100644 index 0000000000..0d69ce10d3 --- /dev/null +++ b/REORG.TODO/resolv/resolv-internal.h @@ -0,0 +1,59 @@ +/* libresolv interfaces for internal use across glibc. + Copyright (C) 2016-2017 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, + }; + +/* Add an OPT record to a DNS query. */ +int __res_nopt (res_state, int n0, unsigned char *buf, int buflen, + int anslen) attribute_hidden; + +#endif /* _RESOLV_INTERNAL_H */ diff --git a/REORG.TODO/resolv/resolv.h b/REORG.TODO/resolv/resolv.h new file mode 100644 index 0000000000..1fb0ad459c --- /dev/null +++ b/REORG.TODO/resolv/resolv.h @@ -0,0 +1,305 @@ +/* + * Copyright (c) 1983, 1987, 1989 + * 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) 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. + */ + +/* + * @(#)resolv.h 8.1 (Berkeley) 6/2/93 + * $BINDId: resolv.h,v 8.31 2000/03/30 20:16:50 vixie Exp $ + */ + +#ifndef _RESOLV_H_ +#define _RESOLV_H_ + +#include <sys/cdefs.h> +#include <sys/param.h> +#include <sys/types.h> +#include <stdio.h> +#include <netinet/in.h> +#include <arpa/nameser.h> +#include <bits/types/res_state.h> + +/* + * Global defines and variables for resolver stub. + */ +#define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */ + +#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. */ + +#define nsaddr nsaddr_list[0] /* for backward compatibility */ + +/* + * 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 (__RES > 19931104)". Do not + * compare for equality; rather, use it to determine whether your resolver + * is new enough to contain a certain feature. + */ + +#define __RES 19991006 + +/* + * Resolver configuration file. + * Normally not present, but may contain the address of the + * inital name server(s) to query and the domain search list. + */ + +#ifndef _PATH_RESCONF +#define _PATH_RESCONF "/etc/resolv.conf" +#endif + +struct res_sym { + int number; /* Identifying number, like T_MX */ + char * name; /* Its symbolic name, like "MX" */ + char * humanname; /* Its fun name, like "mail exchanger" */ +}; + +/* + * 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 \ + __glibc_macro_warning ("RES_AAONLY is deprecated") 0x00000004 +#define RES_USEVC 0x00000008 /* use virtual circuit */ +#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 */ +#define RES_STAYOPEN 0x00000100 /* Keep TCP socket open */ +#define RES_DNSRCH 0x00000200 /* search up local domain tree */ +#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 \ + __glibc_macro_warning ("RES_USE_INET6 is deprecated") 0x00002000 +#define RES_ROTATE 0x00004000 /* rotate ns list after each query */ +#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 + request */ +#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_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH) + +/* + * Resolver "pfcode" values. Used by dig. + */ +#define RES_PRF_STATS 0x00000001 +#define RES_PRF_UPDATE 0x00000002 +#define RES_PRF_CLASS 0x00000004 +#define RES_PRF_CMD 0x00000008 +#define RES_PRF_QUES 0x00000010 +#define RES_PRF_ANS 0x00000020 +#define RES_PRF_AUTH 0x00000040 +#define RES_PRF_ADD 0x00000080 +#define RES_PRF_HEAD1 0x00000100 +#define RES_PRF_HEAD2 0x00000200 +#define RES_PRF_TTLID 0x00000400 +#define RES_PRF_HEADX 0x00000800 +#define RES_PRF_QUERY 0x00001000 +#define RES_PRF_REPLY 0x00002000 +#define RES_PRF_INIT 0x00004000 +/* 0x00008000 */ + +/* Things involving an internal (static) resolver context. */ +__BEGIN_DECLS +extern struct __res_state *__res_state(void) __attribute__ ((__const__)); +__END_DECLS +#define _res (*__res_state()) + +#define fp_nquery __fp_nquery +#define fp_query __fp_query +#define hostalias __hostalias +#define p_query __p_query +#define res_close __res_close +#define res_init __res_init +#define res_isourserver __res_isourserver +#define res_mkquery __res_mkquery +#define res_query __res_query +#define res_querydomain __res_querydomain +#define res_search __res_search +#define res_send __res_send + +__BEGIN_DECLS +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 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 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, + 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 + +#define b64_ntop __b64_ntop +#define b64_pton __b64_pton +#define dn_comp __dn_comp +#define dn_count_labels __dn_count_labels +#define dn_expand __dn_expand +#define dn_skipname __dn_skipname +#define fp_resstat __fp_resstat +#define loc_aton __loc_aton +#define loc_ntoa __loc_ntoa +#define p_cdname __p_cdname +#define p_cdnname __p_cdnname +#define p_class __p_class +#define p_fqname __p_fqname +#define p_fqnname __p_fqnname +#define p_option __p_option +#define p_secstodate __p_secstodate +#define p_time __p_time +#define p_type __p_type +#define p_rcode __p_rcode +#define putlong __putlong +#define putshort __putshort +#define res_dnok __res_dnok +#define res_hnok __res_hnok +#define res_hostalias __res_hostalias +#define res_mailok __res_mailok +#define res_nameinquery __res_nameinquery +#define res_nclose __res_nclose +#define res_ninit __res_ninit +#define res_nmkquery __res_nmkquery +#define res_nquery __res_nquery +#define res_nquerydomain __res_nquerydomain +#define res_nsearch __res_nsearch +#define res_nsend __res_nsend +#define res_ownok __res_ownok +#define res_queriesmatch __res_queriesmatch +#define res_randomid __res_randomid +#define sym_ntop __sym_ntop +#define sym_ntos __sym_ntos +#define sym_ston __sym_ston +__BEGIN_DECLS +int res_hnok (const char *) __THROW; +int res_ownok (const char *) __THROW; +int res_mailok (const char *) __THROW; +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 (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 (uint32_t) __THROW; +const char * p_type (int) __THROW; +const char * p_rcode (int) __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; +char * p_secstodate (unsigned long) __THROW; +int dn_count_labels (const char *) __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 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; +void fp_resstat (const res_state, FILE *) __THROW; +const char * res_hostalias (const res_state, const char *, char *, size_t) + __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, unsigned char *, int) __THROW; +int res_nmkquery (res_state, int, const char *, int, 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 /* !_RESOLV_H_ */ diff --git a/REORG.TODO/resolv/rpc/netdb.h b/REORG.TODO/resolv/rpc/netdb.h new file mode 100644 index 0000000000..eecea3cb06 --- /dev/null +++ b/REORG.TODO/resolv/rpc/netdb.h @@ -0,0 +1,3 @@ +/* This is a dummy file for <rpc/netdb.h>, which is included by <netdb.h>. + This file is installed when the C library does not support the SunRPC + interfaces (including 'struct rpcent' et al) at all. */ diff --git a/REORG.TODO/resolv/sys/bitypes.h b/REORG.TODO/resolv/sys/bitypes.h new file mode 100644 index 0000000000..3a9860f713 --- /dev/null +++ b/REORG.TODO/resolv/sys/bitypes.h @@ -0,0 +1,3 @@ +/* The GNU <sys/types.h> defines all the necessary types. */ + +#include <sys/types.h> diff --git a/REORG.TODO/resolv/tst-aton.c b/REORG.TODO/resolv/tst-aton.c new file mode 100644 index 0000000000..08110a007a --- /dev/null +++ b/REORG.TODO/resolv/tst-aton.c @@ -0,0 +1,77 @@ +#include <stdio.h> +#include <stdint.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + + +static struct tests +{ + const char *input; + int valid; + uint32_t result; +} tests[] = +{ + { "", 0, 0 }, + { "-1", 0, 0 }, + { "256", 1, 0x00000100 }, + { "256.", 0, 0 }, + { "256a", 0, 0 }, + { "0x100", 1, 0x00000100 }, + { "0200.0x123456", 1, 0x80123456 }, + { "0300.0x89123456.", 0 ,0 }, + { "0100.-0xffff0000", 0, 0 }, + { "0.0xffffff", 1, 0x00ffffff }, + { "0.0x1000000", 0, 0 }, + { "0377.16777215", 1, 0xffffffff }, + { "0377.16777216", 0, 0 }, + { "0x87.077777777", 1, 0x87ffffff }, + { "0x87.0100000000", 0, 0 }, + { "0.1.3", 1, 0x00010003 }, + { "0.256.3", 0, 0 }, + { "256.1.3", 0, 0 }, + { "0.1.0x10000", 0, 0 }, + { "0.1.0xffff", 1, 0x0001ffff }, + { "0.1a.3", 0, 0 }, + { "0.1.a3", 0, 0 }, + { "1.2.3.4", 1, 0x01020304 }, + { "0400.2.3.4", 0, 0 }, + { "1.0x100.3.4", 0, 0 }, + { "1.2.256.4", 0, 0 }, + { "1.2.3.0x100", 0, 0 }, + { "323543357756889", 0, 0 }, + { "10.1.2.3.4", 0, 0}, +}; + + +static int +do_test (void) +{ + int result = 0; + size_t cnt; + + for (cnt = 0; cnt < sizeof (tests) / sizeof (tests[0]); ++cnt) + { + struct in_addr addr; + + if ((int) inet_aton (tests[cnt].input, &addr) != tests[cnt].valid) + { + if (tests[cnt].valid) + printf ("\"%s\" not seen as valid IP address\n", tests[cnt].input); + else + printf ("\"%s\" seen as valid IP address\n", tests[cnt].input); + result = 1; + } + else if (tests[cnt].valid && addr.s_addr != ntohl (tests[cnt].result)) + { + printf ("\"%s\" not converted correctly: is %08x, should be %08x\n", + tests[cnt].input, addr.s_addr, tests[cnt].result); + result = 1; + } + } + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/resolv/tst-bug18665-tcp.c b/REORG.TODO/resolv/tst-bug18665-tcp.c new file mode 100644 index 0000000000..4bc0c262b1 --- /dev/null +++ b/REORG.TODO/resolv/tst-bug18665-tcp.c @@ -0,0 +1,230 @@ +/* Test __libc_res_nsend buffer mismanagement, basic TCP coverage. + Copyright (C) 2016-2017 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/REORG.TODO/resolv/tst-bug18665.c b/REORG.TODO/resolv/tst-bug18665.c new file mode 100644 index 0000000000..3c699919fc --- /dev/null +++ b/REORG.TODO/resolv/tst-bug18665.c @@ -0,0 +1,138 @@ +/* Test for __libc_res_nsend buffer mismanagent (bug 18665), UDP case. + Copyright (C) 2016-2017 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/REORG.TODO/resolv/tst-inet_ntop.c b/REORG.TODO/resolv/tst-inet_ntop.c new file mode 100644 index 0000000000..f0de06306c --- /dev/null +++ b/REORG.TODO/resolv/tst-inet_ntop.c @@ -0,0 +1,114 @@ +#include <arpa/inet.h> +#include <errno.h> +#include <netinet/in.h> +#include <stdio.h> +#include <string.h> + +static int +do_test (void) +{ + struct in_addr addr4; + struct in6_addr addr6; + char buf[64]; + int result = 0; + + addr4.s_addr = 0xe0e0e0e0; + addr6.s6_addr16[0] = 0; + addr6.s6_addr16[1] = 0; + addr6.s6_addr16[2] = 0; + addr6.s6_addr16[3] = 0; + addr6.s6_addr16[4] = 0; + addr6.s6_addr16[5] = 0xffff; + addr6.s6_addr32[3] = 0xe0e0e0e0; + memset (buf, 'x', sizeof buf); + + if (inet_ntop (AF_INET, &addr4, buf, 15) != NULL) + { + puts ("1st inet_ntop returned non-NULL"); + result++; + } + else if (errno != ENOSPC) + { + puts ("1st inet_ntop didn't fail with ENOSPC"); + result++; + } + if (buf[15] != 'x') + { + puts ("1st inet_ntop wrote past the end of buffer"); + result++; + } + + if (inet_ntop (AF_INET, &addr4, buf, 16) != buf) + { + puts ("2nd inet_ntop did not return buf"); + result++; + } + if (memcmp (buf, "224.224.224.224\0" "xxxxxxxx", 24) != 0) + { + puts ("2nd inet_ntop wrote past the end of buffer"); + result++; + } + + if (inet_ntop (AF_INET6, &addr6, buf, 22) != NULL) + { + puts ("3rd inet_ntop returned non-NULL"); + result++; + } + else if (errno != ENOSPC) + { + puts ("3rd inet_ntop didn't fail with ENOSPC"); + result++; + } + if (buf[22] != 'x') + { + puts ("3rd inet_ntop wrote past the end of buffer"); + result++; + } + + if (inet_ntop (AF_INET6, &addr6, buf, 23) != buf) + { + puts ("4th inet_ntop did not return buf"); + result++; + } + if (memcmp (buf, "::ffff:224.224.224.224\0" "xxxxxxxx", 31) != 0) + { + puts ("4th inet_ntop wrote past the end of buffer"); + result++; + } + + memset (&addr6.s6_addr, 0xe0, sizeof (addr6.s6_addr)); + + if (inet_ntop (AF_INET6, &addr6, buf, 39) != NULL) + { + puts ("5th inet_ntop returned non-NULL"); + result++; + } + else if (errno != ENOSPC) + { + puts ("5th inet_ntop didn't fail with ENOSPC"); + result++; + } + if (buf[39] != 'x') + { + puts ("5th inet_ntop wrote past the end of buffer"); + result++; + } + + if (inet_ntop (AF_INET6, &addr6, buf, 40) != buf) + { + puts ("6th inet_ntop did not return buf"); + result++; + } + if (memcmp (buf, "e0e0:e0e0:e0e0:e0e0:e0e0:e0e0:e0e0:e0e0\0" + "xxxxxxxx", 48) != 0) + { + puts ("6th inet_ntop wrote past the end of buffer"); + result++; + } + + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/resolv/tst-leaks.c b/REORG.TODO/resolv/tst-leaks.c new file mode 100644 index 0000000000..4f6453517f --- /dev/null +++ b/REORG.TODO/resolv/tst-leaks.c @@ -0,0 +1,43 @@ +/* Tests for res_query in libresolv + Copyright (C) 2003-2017 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 <netinet/in.h> +#include <arpa/nameser.h> +#include <resolv.h> +#include <mcheck.h> + +/* Prototype for our test function. */ +extern int do_test (int argc, char *argv[]); + +/* This defines the `main' function and some more. */ +#define TIMEOUT 40 +#include <test-skeleton.c> + +int +do_test (int argc, char *argv[]) +{ + unsigned char buf[256]; + + mtrace(); + + /* This will allocate some memory, which should be automatically + freed at exit. */ + res_query ("1.0.0.127.in-addr.arpa.", C_ANY, T_ANY, buf, 256); + + return 0; +} diff --git a/REORG.TODO/resolv/tst-leaks2.c b/REORG.TODO/resolv/tst-leaks2.c new file mode 100644 index 0000000000..5a68a4c657 --- /dev/null +++ b/REORG.TODO/resolv/tst-leaks2.c @@ -0,0 +1,40 @@ +/* Tests for res_init in libresolv + Copyright (C) 2004-2017 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/>. */ + +#undef gethostbyname + +#include <mcheck.h> +#include <netdb.h> +#include <resolv.h> + +static int +do_test (void) +{ + mtrace (); + for (int i = 0; i < 20; ++i) + { + res_init (); + gethostbyname ("www.gnu.org"); + } + return 0; +} + +#define TEST_FUNCTION do_test () +#define TIMEOUT 30 +/* This defines the `main' function and some more. */ +#include <test-skeleton.c> diff --git a/REORG.TODO/resolv/tst-ns_name.c b/REORG.TODO/resolv/tst-ns_name.c new file mode 100644 index 0000000000..65eea4c827 --- /dev/null +++ b/REORG.TODO/resolv/tst-ns_name.c @@ -0,0 +1,438 @@ +/* Test ns_name-related functions. + Copyright (C) 2017 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/REORG.TODO/resolv/tst-ns_name.data b/REORG.TODO/resolv/tst-ns_name.data new file mode 100644 index 0000000000..0ff0dc3de7 --- /dev/null +++ b/REORG.TODO/resolv/tst-ns_name.data @@ -0,0 +1,548 @@ +# Test input for ns_name_unpack and ns_name_ntop. +# Copyright (C) 2017 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/REORG.TODO/resolv/tst-ns_name_compress.c b/REORG.TODO/resolv/tst-ns_name_compress.c new file mode 100644 index 0000000000..0c01b753e7 --- /dev/null +++ b/REORG.TODO/resolv/tst-ns_name_compress.c @@ -0,0 +1,76 @@ +/* Test ns_name_compress corner cases. + Copyright (C) 2017 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/REORG.TODO/resolv/tst-res_hconf_reorder.c b/REORG.TODO/resolv/tst-res_hconf_reorder.c new file mode 100644 index 0000000000..20e5a5a448 --- /dev/null +++ b/REORG.TODO/resolv/tst-res_hconf_reorder.c @@ -0,0 +1,113 @@ +/* BZ #17977 _res_hconf_reorder_addrs test. + + Copyright (C) 2015-2017 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 <time.h> +#include <dlfcn.h> +#include <pthread.h> +#include <netdb.h> +#include <netinet/in.h> +#include <sys/socket.h> + +static struct timespec ts; + +/* The first thread that gets a lock in _res_hconf_reorder_addrs() + should hold the lock long enough to make two other threads blocked. + This is achieved by slowing down realloc(3) that is called several times + by _res_hconf_reorder_addrs(). */ + +void * +realloc (void *ptr, size_t len) +{ + static void *(*fun) (void *, size_t); + + if (!fun) + fun = dlsym (RTLD_NEXT, "realloc"); + + if (ts.tv_nsec) + nanosleep (&ts, NULL); + + return (*fun) (ptr, len); +} + +static void * +resolve (void *arg) +{ + struct in_addr addr; + struct hostent ent; + struct hostent *result; + int err; + char buf[1024]; + + addr.s_addr = htonl (INADDR_LOOPBACK); + (void) gethostbyaddr_r ((void *) &addr, sizeof (addr), AF_INET, + &ent, buf, sizeof (buf), &result, &err); + return arg; +} + +static int +do_test (void) +{ + #define N 3 + pthread_t thr[N]; + unsigned int i; + int result = 0; + + /* turn on realloc slowdown */ + ts.tv_nsec = 100000000; + + for (i = 0; i < N; ++i) + { + int rc = pthread_create (&thr[i], NULL, resolve, NULL); + + if (rc) + { + printf ("pthread_create: %s\n", strerror(rc)); + exit (1); + } + } + + for (i = 0; i < N; ++i) + { + void *retval; + int rc = pthread_join (thr[i], &retval); + + if (rc) + { + printf ("pthread_join: %s\n", strerror(rc)); + exit (1); + } + if (retval) + { + printf ("thread %u exit status %p\n", i, retval); + result = 1; + } + } + + /* turn off realloc slowdown, no longer needed */ + ts.tv_nsec = 0; + + return result; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/resolv/tst-res_use_inet6.c b/REORG.TODO/resolv/tst-res_use_inet6.c new file mode 100644 index 0000000000..6f3db08892 --- /dev/null +++ b/REORG.TODO/resolv/tst-res_use_inet6.c @@ -0,0 +1,201 @@ +/* Basic functionality tests for inet6 option processing. + Copyright (C) 2016-2017 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 <string.h> +#include <support/check_nss.h> +#include <support/resolv_test.h> +#include <support/xthread.h> + +static void +response (const struct resolv_response_context *ctx, + struct resolv_response_builder *b, + const char *qname, uint16_t qclass, uint16_t qtype) +{ + bool include_both = strcmp (qname, "both.example") == 0; + bool include_a = qtype == T_A || include_both; + bool include_aaaa = qtype == T_AAAA || include_both; + + 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); + } +} + +/* 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 ("www1.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_UNSPEC www1.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 ("both.example", "80", &hints, &ai); + /* Combined A/AAAA responses currently result in address + duplication. */ + check_addrinfo ("getaddrinfo AF_UNSPEC both.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 ("www1.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_INET www1.example", ai, ret, + "address: STREAM/TCP 192.0.2.17 80\n"); + if (ret == 0) + freeaddrinfo (ai); + ret = getaddrinfo ("both.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_INET both.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 ("www1.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 ("both.example", "80", &hints, &ai); + check_addrinfo ("getaddrinfo AF_INET6 both.example", ai, ret, + "address: STREAM/TCP 2001:db8::1 80\n"); + if (ret == 0) + freeaddrinfo (ai); + } +} + +/* Test that gethostbyname2 is not influenced by RES_USE_INET6. */ +static void +test_get2 (void) +{ + check_hostent ("gethostbyname2 AF_INET www1.example", + gethostbyname2 ("www1.example", AF_INET), + "name: www1.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname2 AF_INET both.example", + gethostbyname2 ("both.example", AF_INET), + "name: both.example\n" + "address: 192.0.2.17\n"); + + check_hostent ("gethostbyname2 AF_INET6 www1.example", + gethostbyname2 ("www1.example", AF_INET6), + "name: www1.example\n" + "address: 2001:db8::1\n"); + check_hostent ("gethostbyname2 AF_INET6 both.example", + gethostbyname2 ("both.example", AF_INET6), + "name: both.example\n" + "address: 2001:db8::1\n"); +} + +static void * +threadfunc (void *ignored) +{ + struct resolv_test *obj = resolv_test_start + ((struct resolv_redirect_config) + { + .response_callback = response + }); + + check_hostent ("gethostbyname (\"www1.example\")", + gethostbyname ("www1.example"), + "name: www1.example\n" + "address: 192.0.2.17\n"); + check_hostent ("gethostbyname (\"both.example\")", + gethostbyname ("both.example"), + "name: both.example\n" + "address: 192.0.2.17\n"); + test_get2 (); + test_gai (); + + _res.options |= RES_USE_INET6; + check_hostent ("gethostbyname (\"www1.example\")", + gethostbyname ("www1.example"), + "name: www1.example\n" + "address: 2001:db8::1\n"); + check_hostent ("gethostbyname (\"both.example\")", + gethostbyname ("both.example"), + "name: both.example\n" + "address: 2001:db8::1\n"); + test_get2 (); + test_gai (); + + 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/REORG.TODO/resolv/tst-resolv-basic.c b/REORG.TODO/resolv/tst-resolv-basic.c new file mode 100644 index 0000000000..92f912beed --- /dev/null +++ b/REORG.TODO/resolv/tst-resolv-basic.c @@ -0,0 +1,406 @@ +/* Test basic nss_dns functionality and the resolver test harness itself. + Copyright (C) 2016-2017 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/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} 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 + { + 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 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); +} + +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"); + + check_h ("nxdomain.example", AF_INET, + "error: HOST_NOT_FOUND\n"); + check_h ("nxdomain.example", AF_INET6, + "error: HOST_NOT_FOUND\n"); + check_ai ("nxdomain.example", "80", AF_UNSPEC, + "error: Name or service not known\n"); + check_ai ("nxdomain.example", "80", AF_INET, + "error: Name or service not known\n"); + check_ai ("nxdomain.example", "80", AF_INET6, + "error: Name or service not known\n"); + + check_h ("t.nxdomain.example", AF_INET, + "error: HOST_NOT_FOUND\n"); + check_h ("t.nxdomain.example", AF_INET6, + "error: HOST_NOT_FOUND\n"); + check_ai ("t.nxdomain.example", "80", AF_UNSPEC, + "error: Name or service not known\n"); + check_ai ("t.nxdomain.example", "80", AF_INET, + "error: Name or service not known\n"); + check_ai ("t.nxdomain.example", "80", AF_INET6, + "error: Name or service not known\n"); + + resolv_test_end (aux); + + return 0; +} + +#include <support/test-driver.c> diff --git a/REORG.TODO/resolv/tst-resolv-canonname.c b/REORG.TODO/resolv/tst-resolv-canonname.c new file mode 100644 index 0000000000..5daac33882 --- /dev/null +++ b/REORG.TODO/resolv/tst-resolv-canonname.c @@ -0,0 +1,313 @@ +/* Test _nss_dns_getcanonname_r corner cases. + Copyright (C) 2017 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/REORG.TODO/resolv/tst-resolv-edns.c b/REORG.TODO/resolv/tst-resolv-edns.c new file mode 100644 index 0000000000..8945d79d09 --- /dev/null +++ b/REORG.TODO/resolv/tst-resolv-edns.c @@ -0,0 +1,532 @@ +/* Test EDNS handling in the stub resolver. + Copyright (C) 2016-2017 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/REORG.TODO/resolv/tst-resolv-network.c b/REORG.TODO/resolv/tst-resolv-network.c new file mode 100644 index 0000000000..df9daf8d58 --- /dev/null +++ b/REORG.TODO/resolv/tst-resolv-network.c @@ -0,0 +1,299 @@ +/* Test getnetbyname and getnetbyaddr. + Copyright (C) 2016-2017 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); +} + +int +main (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); +} diff --git a/REORG.TODO/resolv/tst-resolv-qtypes.c b/REORG.TODO/resolv/tst-resolv-qtypes.c new file mode 100644 index 0000000000..06ea3dbd14 --- /dev/null +++ b/REORG.TODO/resolv/tst-resolv-qtypes.c @@ -0,0 +1,185 @@ +/* Exercise low-level query functions with different QTYPEs. + Copyright (C) 2016-2017 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 * const 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/REORG.TODO/resolv/tst-resolv-res_init-skeleton.c b/REORG.TODO/resolv/tst-resolv-res_init-skeleton.c new file mode 100644 index 0000000000..1d2c475c4b --- /dev/null +++ b/REORG.TODO/resolv/tst-resolv-res_init-skeleton.c @@ -0,0 +1,601 @@ +/* Test parsing of /etc/resolv.conf. Genric version. + Copyright (C) 2017 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 <gnu/lib-names.h> +#include <netdb.h> +#include <resolv/resolv-internal.h> /* For DEPRECATED_RES_USE_INET6. */ +#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/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"; + +/* Path to the test root directory. */ +static char *path_chroot; + +/* Path to resolv.conf under path_chroot (outside the chroot). */ +static char *path_resolv_conf; + +static void +prepare (int argc, char **argv) +{ + path_chroot = xasprintf ("%s/tst-resolv-res_init-XXXXXX", test_dir); + if (mkdtemp (path_chroot) == NULL) + FAIL_EXIT1 ("mkdtemp (\"%s\"): %m", path_chroot); + add_temp_file (path_chroot); + + /* Create the /etc directory in the chroot environment. */ + char *path_etc = xasprintf ("%s/etc", path_chroot); + xmkdir (path_etc, 0777); + add_temp_file (path_etc); + + /* Create an empty resolv.conf file. */ + path_resolv_conf = xasprintf ("%s/resolv.conf", path_etc); + add_temp_file (path_resolv_conf); + support_write_file_string (path_resolv_conf, ""); + + free (path_etc); + + /* valgrind needs a temporary directory in the chroot. */ + { + char *path_tmp = xasprintf ("%s/tmp", path_chroot); + xmkdir (path_tmp, 0777); + add_temp_file (path_tmp); + free (path_tmp); + } +} + +/* Verify that the chroot environment has been set up. */ +static void +check_chroot_working (void *closure) +{ + xchroot (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) +{ + /* 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"); + 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 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); + } + } + + TEST_VERIFY (!ferror (fp)); +} + +/* 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; +}; + +enum test_init +{ + test_init, + test_ninit, + test_mkquery, + test_gethostbyname, + test_getaddrinfo, + test_init_method_last = test_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 (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); + + switch (ctx->init) + { + case test_init: + xchroot (path_chroot); + TEST_VERIFY (res_init () == 0); + print_resp (stdout, &_res); + return; + + case test_ninit: + xchroot (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 (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" + "nameserver 127.0.0.1\n" + }, + {.name = "empty file with LOCALDOMAIN", + .conf = "", + .expected = "search example.net\n" + "nameserver 127.0.0.1\n", + .localdomain = "example.net", + }, + {.name = "empty file with RES_OPTIONS", + .conf = "", + .expected = "options attempts:5 edns0\n" + "search example.com\n" + "nameserver 127.0.0.1\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" + "nameserver 127.0.0.1\n", + .localdomain = "example.org", + .res_options = "edns0 attempts:5", + }, + {.name = "basic", + .conf = "domain example.net\n" + "search corp.example.com example.com\n" + "nameserver 192.0.2.1\n", + .expected = "search corp.example.com example.com\n" + "nameserver 192.0.2.1\n" + }, + {.name = "whitespace", + .conf = "# This test covers comment and whitespace processing " + " (trailing whitespace,\n" + "# missing newline at end of file).\n" + "\n" + "domain example.net\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" + "nameserver 192.0.2.1\n" + "nameserver 192.0.2.2\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" + "nameserver 192.0.2.1\n" + "nameserver ::1\n" + "nameserver 192.0.2.2\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" + "nameserver 127.0.0.1\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" + "nameserver 127.0.0.1\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" + "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" + }, + {.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" + "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" + }, + {.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" + "nameserver 192.0.2.1\n" + "nameserver 192.0.2.3\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" + "nameserver 192.0.2.1\n", + .res_options = "attempts:5 ndots:3 edns0 ", + }, + { 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 %d\n", 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\n", t->name); + 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); + } +} + +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); + } + + 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 (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 (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", path_resolv_conf) == 0); + test_file_contents (&test_cases[i]); + TEST_VERIFY (unlink (path_resolv_conf) == 0); + + if (test_verbose > 0) + printf ("info: special test: unreadable file\n"); + support_write_file_string (path_resolv_conf, ""); + TEST_VERIFY (chmod (path_resolv_conf, 0) == 0); + test_file_contents (&test_cases[i]); + + /* Restore the empty file. */ + TEST_VERIFY (unlink (path_resolv_conf) == 0); + support_write_file_string (path_resolv_conf, ""); + } + } + + free (path_chroot); + path_chroot = NULL; + free (path_resolv_conf); + path_resolv_conf = NULL; + return 0; +} + +#define PREPARE prepare +#include <support/test-driver.c> diff --git a/REORG.TODO/resolv/tst-resolv-res_init-thread.c b/REORG.TODO/resolv/tst-resolv-res_init-thread.c new file mode 100644 index 0000000000..f47ac34f7f --- /dev/null +++ b/REORG.TODO/resolv/tst-resolv-res_init-thread.c @@ -0,0 +1,20 @@ +/* Test parsing of /etc/resolv.conf, threading version. + Copyright (C) 2017 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/REORG.TODO/resolv/tst-resolv-res_init.c b/REORG.TODO/resolv/tst-resolv-res_init.c new file mode 100644 index 0000000000..40c0154eca --- /dev/null +++ b/REORG.TODO/resolv/tst-resolv-res_init.c @@ -0,0 +1,20 @@ +/* Test parsing of /etc/resolv.conf, non-threading version. + Copyright (C) 2017 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/REORG.TODO/resolv/tst-resolv-search.c b/REORG.TODO/resolv/tst-resolv-search.c new file mode 100644 index 0000000000..a5406b3b0e --- /dev/null +++ b/REORG.TODO/resolv/tst-resolv-search.c @@ -0,0 +1,344 @@ +/* Test search/default domain name behavior. + Copyright (C) 2016-2017 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> |