summaryrefslogtreecommitdiff
path: root/resolv
diff options
context:
space:
mode:
authorSamuel Thibault <samuel.thibault@ens-lyon.org>2018-12-27 17:45:04 +0000
committerSamuel Thibault <samuel.thibault@ens-lyon.org>2018-12-27 17:45:04 +0000
commit6aa82888e61d3e2232926ee68e764f17eae2e7e1 (patch)
tree17b2fb350da15d1d097f22dc7e2e7d20db1bd486 /resolv
parentffbe9c552a1009167ec7a765c1543c7f3e4169d6 (diff)
parent963c37d5c0eb62b38f8764b23931c0dcdd497a13 (diff)
Merge commit 'refs/top-bases/t/sendmsg-SCM_RIGHTS' into t/sendmsg-SCM_RIGHTS
Diffstat (limited to 'resolv')
-rw-r--r--resolv/Banner1
-rw-r--r--resolv/Depend1
-rw-r--r--resolv/Makefile137
-rw-r--r--resolv/README14
-rw-r--r--resolv/Versions11
-rw-r--r--resolv/arpa/nameser.h404
-rw-r--r--resolv/arpa/nameser_compat.h138
-rw-r--r--resolv/bits/types/res_state.h61
-rw-r--r--resolv/compat-gethnamaddr.c (renamed from resolv/gethnamaddr.c)347
-rw-r--r--resolv/compat-hooks.c56
-rw-r--r--resolv/ga_test.c99
-rw-r--r--resolv/gai_cancel.c2
-rw-r--r--resolv/gai_error.c2
-rw-r--r--resolv/gai_misc.c5
-rw-r--r--resolv/gai_misc.h15
-rw-r--r--resolv/gai_notify.c4
-rw-r--r--resolv/gai_sigqueue.c2
-rw-r--r--resolv/gai_suspend.c4
-rw-r--r--resolv/getaddrinfo_a.c2
-rw-r--r--resolv/herror.c11
-rw-r--r--resolv/inet_addr.c54
-rw-r--r--resolv/inet_net_ntop.c4
-rw-r--r--resolv/inet_net_pton.c4
-rw-r--r--resolv/inet_neta.c6
-rw-r--r--resolv/inet_ntop.c12
-rw-r--r--resolv/inet_pton.c368
-rw-r--r--resolv/netdb.h26
-rw-r--r--resolv/ns_date.c10
-rw-r--r--resolv/ns_name.c267
-rw-r--r--resolv/ns_netint.c4
-rw-r--r--resolv/ns_parse.c4
-rw-r--r--resolv/ns_print.c206
-rw-r--r--resolv/ns_samedomain.c4
-rw-r--r--resolv/ns_ttl.c4
-rw-r--r--resolv/nsap_addr.c4
-rw-r--r--resolv/nss_dns/dns-canon.c44
-rw-r--r--resolv/nss_dns/dns-host.c361
-rw-r--r--resolv/nss_dns/dns-network.c82
-rw-r--r--resolv/res-close.c144
-rw-r--r--resolv/res-state.c2
-rw-r--r--resolv/res_comp.c223
-rw-r--r--resolv/res_data.c346
-rw-r--r--resolv/res_debug.c353
-rw-r--r--resolv/res_debug.h34
-rw-r--r--resolv/res_hconf.c51
-rw-r--r--resolv/res_hconf.h15
-rw-r--r--resolv/res_init.c1121
-rw-r--r--resolv/res_libc.c145
-rw-r--r--resolv/res_mkquery.c378
-rw-r--r--resolv/res_query.c403
-rw-r--r--resolv/res_randomid.c92
-rw-r--r--resolv/res_send.c579
-rw-r--r--resolv/res_use_inet6.h49
-rw-r--r--resolv/resolv-internal.h103
-rw-r--r--resolv/resolv.h249
-rw-r--r--resolv/resolv_conf.c700
-rw-r--r--resolv/resolv_conf.h103
-rw-r--r--resolv/resolv_context.c252
-rw-r--r--resolv/resolv_context.h182
-rw-r--r--resolv/tst-bug18665-tcp.c230
-rw-r--r--resolv/tst-bug18665.c138
-rw-r--r--resolv/tst-inet_pton.c492
-rw-r--r--resolv/tst-leaks.c2
-rw-r--r--resolv/tst-leaks2.c2
-rw-r--r--resolv/tst-no-libidn2.c2
-rw-r--r--resolv/tst-ns_name.c438
-rw-r--r--resolv/tst-ns_name.data548
-rw-r--r--resolv/tst-ns_name_compress.c76
-rw-r--r--resolv/tst-ns_name_pton.c210
-rw-r--r--resolv/tst-p_secstodate.c84
-rw-r--r--resolv/tst-res_hconf_reorder.c3
-rw-r--r--resolv/tst-res_hnok.c169
-rw-r--r--resolv/tst-res_use_inet6.c509
-rw-r--r--resolv/tst-resolv-ai_idn-common.c569
-rw-r--r--resolv/tst-resolv-ai_idn-latin1.c50
-rw-r--r--resolv/tst-resolv-ai_idn-nolibidn2.c151
-rw-r--r--resolv/tst-resolv-ai_idn.c49
-rw-r--r--resolv/tst-resolv-basic.c503
-rw-r--r--resolv/tst-resolv-binary.c120
-rw-r--r--resolv/tst-resolv-canonname.c313
-rw-r--r--resolv/tst-resolv-edns.c532
-rw-r--r--resolv/tst-resolv-network.c303
-rw-r--r--resolv/tst-resolv-qtypes.c185
-rw-r--r--resolv/tst-resolv-res_init-multi.c89
-rw-r--r--resolv/tst-resolv-res_init-skeleton.c1096
-rw-r--r--resolv/tst-resolv-res_init-thread.c20
-rw-r--r--resolv/tst-resolv-res_init.c20
-rw-r--r--resolv/tst-resolv-res_ninit.c75
-rw-r--r--resolv/tst-resolv-rotate.c263
-rw-r--r--resolv/tst-resolv-search.c344
-rw-r--r--resolv/tst-resolv-threads.c484
91 files changed, 12576 insertions, 3797 deletions
diff --git a/resolv/Banner b/resolv/Banner
deleted file mode 100644
index e585ed8532..0000000000
--- a/resolv/Banner
+++ /dev/null
@@ -1 +0,0 @@
-BIND-8.2.3-T5B
diff --git a/resolv/Depend b/resolv/Depend
index 6c1aa44e6e..ba64a2d899 100644
--- a/resolv/Depend
+++ b/resolv/Depend
@@ -1 +1,2 @@
nptl
+htl
diff --git a/resolv/Makefile b/resolv/Makefile
index 8be41d3ae1..ea395ac3eb 100644
--- a/resolv/Makefile
+++ b/resolv/Makefile
@@ -1,4 +1,4 @@
-# Copyright (C) 1994-2016 Free Software Foundation, Inc.
+# Copyright (C) 1994-2018 Free Software Foundation, Inc.
# This file is part of the GNU C Library.
# The GNU C Library is free software; you can redistribute it and/or
@@ -22,13 +22,14 @@ subdir := resolv
include ../Makeconfig
-headers := resolv.h \
+headers := resolv.h bits/types/res_state.h \
netdb.h bits/netdb.h \
arpa/nameser.h arpa/nameser_compat.h \
sys/bitypes.h
routines := herror inet_addr inet_ntop inet_pton nsap_addr res_init \
- res_hconf res_libc res-state
+ res_hconf res_libc res-state res_randomid res-close \
+ resolv_context resolv_conf
tests = tst-aton tst-leaks tst-inet_ntop
xtests = tst-leaks2
@@ -39,14 +40,68 @@ extra-libs := libresolv libnss_dns
ifeq ($(have-thread-library),yes)
extra-libs += libanl
routines += gai_sigqueue
-tests += tst-res_hconf_reorder
+
+tests += \
+ tst-bug18665 \
+ tst-bug18665-tcp \
+ tst-ns_name \
+ tst-ns_name_compress \
+ tst-ns_name_pton \
+ tst-res_hconf_reorder \
+ tst-res_hnok \
+ tst-res_use_inet6 \
+ tst-resolv-basic \
+ tst-resolv-binary \
+ tst-resolv-edns \
+ tst-resolv-network \
+ tst-resolv-res_init-multi \
+ tst-resolv-search \
+
+# These tests need libdl.
+ifeq (yes,$(build-shared))
+tests += \
+ tst-resolv-ai_idn \
+ tst-resolv-ai_idn-latin1 \
+ tst-resolv-ai_idn-nolibidn2 \
+ tst-resolv-canonname \
+
+# uses DEPRECATED_RES_USE_INET6 from <resolv-internal.h>.
+tests-internal += \
+ tst-resolv-res_init \
+ tst-resolv-res_init-thread \
+
+# Needs resolv_context.
+tests-internal += \
+ tst-resolv-res_ninit \
+ tst-resolv-threads \
+
+# Used by tst-resolv-ai_idn-nolibidn2 to disable libidn2 (by not
+# providing any functions in libidn2.so.0).
+modules-names += tst-no-libidn2
+extra-test-objs += tst-no-libidn2.os
+LDFLAGS-tst-no-libidn2.so = -Wl,-soname,libidn2.so.0
+
+endif # $(build-shared)
+
+# This test accesses __inet_ntop_length, an internal libc function.
+tests-internal += tst-inet_pton
+
+# This test accesses the __p_secstodate compat symbol.
+tests-internal += tst-p_secstodate
+
+# This test sends millions of packets and is rather slow.
+xtests += tst-resolv-qtypes
+
+# This test has dropped packet tests and runs for a long time.
+xtests += tst-resolv-rotate
endif
extra-libs-others = $(extra-libs)
-libresolv-routines := gethnamaddr res_comp res_debug \
+libresolv-routines := res_comp res_debug \
res_data res_mkquery res_query res_send \
inet_net_ntop inet_net_pton inet_neta base64 \
ns_parse ns_name ns_netint ns_ttl ns_print \
- ns_samedomain ns_date
+ ns_samedomain ns_date \
+ compat-hooks compat-gethnamaddr
libanl-routines := gai_cancel gai_error gai_misc gai_notify gai_suspend \
getaddrinfo_a
@@ -61,14 +116,11 @@ routines += $(libnss_dns-routines) $(libresolv-routines)
static-only-routines += $(libnss_dns-routines) $(libresolv-routines)
endif
-ifeq (yesyes,$(build-shared)$(have-thread-library))
-tests: $(objpfx)ga_test
-endif
-
ifeq ($(run-built-tests),yes)
ifneq (no,$(PERL))
tests-special += $(objpfx)mtrace-tst-leaks.out
xtests-special += $(objpfx)mtrace-tst-leaks2.out
+tests-special += $(objpfx)mtrace-tst-resolv-res_ninit.out
endif
endif
@@ -80,21 +132,15 @@ headers += rpc/netdb.h
endif
generated += mtrace-tst-leaks.out tst-leaks.mtrace \
- mtrace-tst-leaks2.out tst-leaks2.mtrace
+ mtrace-tst-leaks2.out tst-leaks2.mtrace \
+ mtrace-tst-resolv-res_ninit.out tst-resolv-res_ninit.mtrace \
include ../Rules
-CPPFLAGS += -Dgethostbyname=res_gethostbyname \
- -Dgethostbyname2=res_gethostbyname2 \
- -Dgethostbyaddr=res_gethostbyaddr \
- -Dgetnetbyname=res_getnetbyname \
- -Dgetnetbyaddr=res_getnetbyaddr
+LOCALES := en_US.UTF-8 en_US.ISO-8859-1
+include ../gen-locales.mk
-CFLAGS-libresolv += $(stack-protector)
-CFLAGS-res_hconf.c = -fexceptions
-
-# The BIND code elicits some harmless warnings.
-+cflags += -Wno-write-strings
+CFLAGS-res_hconf.c += -fexceptions
# The DNS NSS modules needs the resolver.
$(objpfx)libnss_dns.so: $(objpfx)libresolv.so
@@ -102,8 +148,6 @@ $(objpfx)libnss_dns.so: $(objpfx)libresolv.so
# The asynchronous name lookup code needs the thread library.
$(objpfx)libanl.so: $(shared-thread-library)
-$(objpfx)ga_test: $(objpfx)libanl.so $(shared-thread-library)
-
$(objpfx)tst-res_hconf_reorder: $(libdl) $(shared-thread-library)
tst-res_hconf_reorder-ENV = RESOLV_REORDER=on
@@ -117,3 +161,50 @@ tst-leaks2-ENV = MALLOC_TRACE=$(objpfx)tst-leaks2.mtrace
$(objpfx)mtrace-tst-leaks2.out: $(objpfx)tst-leaks2.out
$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@; \
$(evaluate-test)
+
+tst-resolv-res_ninit-ENV = MALLOC_TRACE=$(objpfx)tst-resolv-res_ninit.mtrace
+$(objpfx)mtrace-tst-resolv-res_ninit.out: $(objpfx)tst-resolv-res_ninit.out
+ $(common-objpfx)malloc/mtrace \
+ $(objpfx)tst-resolv-res_ninit.mtrace > $@; \
+ $(evaluate-test)
+
+$(objpfx)tst-bug18665-tcp: $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-bug18665: $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-res_use_inet6: $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-resolv-ai_idn: \
+ $(libdl) $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-resolv-ai_idn-latin1: \
+ $(libdl) $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-resolv-ai_idn-nolibidn2: \
+ $(libdl) $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-resolv-ai_idn.out: $(gen-locales)
+$(objpfx)tst-resolv-ai_idn-latin1.out: $(gen-locales)
+$(objpfx)tst-resolv-ai_idn-nolibidn2.out: \
+ $(gen-locales) $(objpfx)tst-no-libidn2.so
+$(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-resolv-binary: $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-resolv-res_init: $(libdl) $(objpfx)libresolv.so
+$(objpfx)tst-resolv-res_init-multi: $(objpfx)libresolv.so \
+ $(shared-thread-library)
+$(objpfx)tst-resolv-res_init-thread: $(libdl) $(objpfx)libresolv.so \
+ $(shared-thread-library)
+$(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-resolv-threads: \
+ $(libdl) $(objpfx)libresolv.so $(shared-thread-library)
+$(objpfx)tst-resolv-canonname: \
+ $(libdl) $(objpfx)libresolv.so $(shared-thread-library)
+
+$(objpfx)tst-ns_name: $(objpfx)libresolv.so
+$(objpfx)tst-ns_name.out: tst-ns_name.data
+$(objpfx)tst-ns_name_compress: $(objpfx)libresolv.so
+$(objpfx)tst-ns_name_pton: $(objpfx)libresolv.so
+$(objpfx)tst-res_hnok: $(objpfx)libresolv.so
+$(objpfx)tst-p_secstodate: $(objpfx)libresolv.so
+
+
+# This test case uses the deprecated RES_USE_INET6 resolver option.
+CFLAGS-tst-res_use_inet6.c += -Wno-error
diff --git a/resolv/README b/resolv/README
index dbb15108ae..514e9bb617 100644
--- a/resolv/README
+++ b/resolv/README
@@ -18,10 +18,6 @@ Differences
The resolver in the GNU C Library still differs from what's in BIND
8.2.3-T5B:
-* The resolver in glibc strictly adheres to the recommendations in RFC
- 1535. BIND 8.2.3-T5B seems to relax those rules a bit (see the code
- that's wrapped in `#ifndef RFC1535').
-
* The RES_DEBUG option (`options debug' in /etc/resolv.conf) has been
disabled.
@@ -84,11 +80,7 @@ code:
* In Multi-threaded that manipulate the _res structure, calls to
functions like `gethostbyname' in threads other than the "main"
- thread won't be influenced by the those changes anymore. So if you
- set RES_USE_INET6, a call to `gethostbyname' won't return any IPv6
- hosts anymore. If you recompile such programs, manipulating the
- _res structure will affect the thread in which you do so instead of
- the "main" thread.
+ thread won't be influenced by the those changes anymore.
We recommend to use the new thread-safe interfaces in new code, since
the traditional interfaces have been deprecated by the BIND folks.
@@ -122,7 +114,6 @@ src/lib/resolv/
res_comp.c
res_data.c
res_debug.c
- res_debug.h
res_init.c
res_mkquery.c
res_query.c
@@ -149,8 +140,7 @@ src/lib/isc/
base64.c
Some of these files have been optimised a bit, and adaptations have
-been made to make them fit in with the rest of glibc. The more
-non-obvious changes are wrapped in something like `#ifdef _LIBC'.
+been made to make them fit in with the rest of glibc.
res_libc.c is home-brewn, although parts of it are taken from res_data.c.
diff --git a/resolv/Versions b/resolv/Versions
index e561bce1a4..b05778d965 100644
--- a/resolv/Versions
+++ b/resolv/Versions
@@ -26,7 +26,12 @@ libc {
__h_errno; __resp;
- __res_maybe_init; __res_iclose;
+ __res_iclose;
+ __inet_pton_length;
+ __resolv_context_get;
+ __resolv_context_get_preinit;
+ __resolv_context_get_override;
+ __resolv_context_put;
}
}
@@ -78,7 +83,9 @@ libresolv {
# Needed in libnss_dns.
__ns_name_unpack; __ns_name_ntop;
__ns_get16; __ns_get32;
- __libc_res_nquery; __libc_res_nsearch;
+ __res_context_query;
+ __res_context_search;
+ __res_context_hostalias;
}
}
diff --git a/resolv/arpa/nameser.h b/resolv/arpa/nameser.h
index fb8513ba9b..a99d5ec508 100644
--- a/resolv/arpa/nameser.h
+++ b/resolv/arpa/nameser.h
@@ -45,34 +45,13 @@
* SOFTWARE.
*/
-/*
- * $BINDId: nameser.h,v 8.37 2000/03/30 21:16:49 vixie Exp $
- */
-
#ifndef _ARPA_NAMESER_H_
#define _ARPA_NAMESER_H_
-/*! \file */
-
-#define BIND_4_COMPAT
-
#include <sys/param.h>
-#if (!defined(BSD)) || (BSD < 199306)
-# include <sys/bitypes.h>
-#else
-# include <sys/types.h>
-#endif
-#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <stdint.h>
-/*%
- * Revision information. This is the release date in YYYYMMDD format.
- * It can change every day so the right thing to do with it is use it
- * in preprocessor commands such as "#if (__NAMESER > 19931104)". Do not
- * compare for equality; rather, use it to determine whether your libbind.a
- * contains a new enough lib/nameser/ to support the feature you need.
- */
-
-#define __NAMESER 19991006 /*%< New interface version stamp. */
/*
* Define constants based on RFC 883, RFC 1034, RFC 1035
*/
@@ -84,9 +63,9 @@
#define NS_HFIXEDSZ 12 /*%< #/bytes of fixed data in header */
#define NS_QFIXEDSZ 4 /*%< #/bytes of fixed data in query */
#define NS_RRFIXEDSZ 10 /*%< #/bytes of fixed data in r record */
-#define NS_INT32SZ 4 /*%< #/bytes of data in a u_int32_t */
-#define NS_INT16SZ 2 /*%< #/bytes of data in a u_int16_t */
-#define NS_INT8SZ 1 /*%< #/bytes of data in a u_int8_t */
+#define NS_INT32SZ 4 /*%< #/bytes of data in a uint32_t */
+#define NS_INT16SZ 2 /*%< #/bytes of data in a uint16_t */
+#define NS_INT8SZ 1 /*%< #/bytes of data in a uint8_t */
#define NS_INADDRSZ 4 /*%< IPv4 T_A */
#define NS_IN6ADDRSZ 16 /*%< IPv6 T_AAAA */
#define NS_CMPRSFLGS 0xc0 /*%< Flag bits indicating name compression. */
@@ -112,12 +91,12 @@ typedef enum __ns_sect {
* leading _'s on the member names. Use the accessor functions, not the _'s.
*/
typedef struct __ns_msg {
- const u_char *_msg, *_eom;
- u_int16_t _id, _flags, _counts[ns_s_max];
- const u_char *_sections[ns_s_max];
- ns_sect _sect;
- int _rrnum;
- const u_char *_msg_ptr;
+ const unsigned char *_msg, *_eom;
+ uint16_t _id, _flags, _counts[ns_s_max];
+ const unsigned char *_sections[ns_s_max];
+ ns_sect _sect;
+ int _rrnum;
+ const unsigned char *_msg_ptr;
} ns_msg;
/* Private data structure - do not use from outside library. */
@@ -136,12 +115,12 @@ extern const struct _ns_flagdata _ns_flagdata[];
* This is a parsed record. It is caller allocated and has no dynamic data.
*/
typedef struct __ns_rr {
- char name[NS_MAXDNAME];
- u_int16_t type;
- u_int16_t rr_class;
- u_int32_t ttl;
- u_int16_t rdlength;
- const u_char * rdata;
+ char name[NS_MAXDNAME];
+ uint16_t type;
+ uint16_t rr_class;
+ uint32_t ttl;
+ uint16_t rdlength;
+ const unsigned char * rdata;
} ns_rr;
/* Accessor macros - this is part of the public interface. */
@@ -249,71 +228,97 @@ typedef struct ns_tcp_tsig_state ns_tcp_tsig_state;
/*%
* Currently defined type values for resources and queries.
*/
-typedef enum __ns_type {
- ns_t_invalid = 0, /*%< Cookie. */
- ns_t_a = 1, /*%< Host address. */
- ns_t_ns = 2, /*%< Authoritative server. */
- ns_t_md = 3, /*%< Mail destination. */
- ns_t_mf = 4, /*%< Mail forwarder. */
- ns_t_cname = 5, /*%< Canonical name. */
- ns_t_soa = 6, /*%< Start of authority zone. */
- ns_t_mb = 7, /*%< Mailbox domain name. */
- ns_t_mg = 8, /*%< Mail group member. */
- ns_t_mr = 9, /*%< Mail rename name. */
- ns_t_null = 10, /*%< Null resource record. */
- ns_t_wks = 11, /*%< Well known service. */
- ns_t_ptr = 12, /*%< Domain name pointer. */
- ns_t_hinfo = 13, /*%< Host information. */
- ns_t_minfo = 14, /*%< Mailbox information. */
- ns_t_mx = 15, /*%< Mail routing information. */
- ns_t_txt = 16, /*%< Text strings. */
- ns_t_rp = 17, /*%< Responsible person. */
- ns_t_afsdb = 18, /*%< AFS cell database. */
- ns_t_x25 = 19, /*%< X_25 calling address. */
- ns_t_isdn = 20, /*%< ISDN calling address. */
- ns_t_rt = 21, /*%< Router. */
- ns_t_nsap = 22, /*%< NSAP address. */
- ns_t_nsap_ptr = 23, /*%< Reverse NSAP lookup (deprecated). */
- ns_t_sig = 24, /*%< Security signature. */
- ns_t_key = 25, /*%< Security key. */
- ns_t_px = 26, /*%< X.400 mail mapping. */
- ns_t_gpos = 27, /*%< Geographical position (withdrawn). */
- ns_t_aaaa = 28, /*%< Ip6 Address. */
- ns_t_loc = 29, /*%< Location Information. */
- ns_t_nxt = 30, /*%< Next domain (security). */
- ns_t_eid = 31, /*%< Endpoint identifier. */
- ns_t_nimloc = 32, /*%< Nimrod Locator. */
- ns_t_srv = 33, /*%< Server Selection. */
- ns_t_atma = 34, /*%< ATM Address */
- ns_t_naptr = 35, /*%< Naming Authority PoinTeR */
- ns_t_kx = 36, /*%< Key Exchange */
- ns_t_cert = 37, /*%< Certification record */
- ns_t_a6 = 38, /*%< IPv6 address (deprecated, use ns_t_aaaa) */
- ns_t_dname = 39, /*%< Non-terminal DNAME (for IPv6) */
- ns_t_sink = 40, /*%< Kitchen sink (experimentatl) */
- ns_t_opt = 41, /*%< EDNS0 option (meta-RR) */
- ns_t_apl = 42, /*%< Address prefix list (RFC3123) */
- ns_t_tkey = 249, /*%< Transaction key */
- ns_t_tsig = 250, /*%< Transaction signature. */
- ns_t_ixfr = 251, /*%< Incremental zone transfer. */
- ns_t_axfr = 252, /*%< Transfer zone of authority. */
- ns_t_mailb = 253, /*%< Transfer mailbox records. */
- ns_t_maila = 254, /*%< Transfer mail agent records. */
- ns_t_any = 255, /*%< Wildcard match. */
- ns_t_zxfr = 256, /*%< BIND-specific, nonstandard. */
- ns_t_max = 65536
-} ns_type;
-
-/* Exclusively a QTYPE? (not also an RTYPE) */
-#define ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \
- (t) == ns_t_mailb || (t) == ns_t_maila)
-/* Some kind of meta-RR? (not a QTYPE, but also not an RTYPE) */
-#define ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt)
-/* Exclusively an RTYPE? (not also a QTYPE or a meta-RR) */
-#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t))
-#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr)
-#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \
- (t) == ns_t_zxfr)
+typedef enum __ns_type
+ {
+ ns_t_invalid = 0,
+
+ ns_t_a = 1,
+ ns_t_ns = 2,
+ ns_t_md = 3,
+ ns_t_mf = 4,
+ ns_t_cname = 5,
+ ns_t_soa = 6,
+ ns_t_mb = 7,
+ ns_t_mg = 8,
+ ns_t_mr = 9,
+ ns_t_null = 10,
+ ns_t_wks = 11,
+ ns_t_ptr = 12,
+ ns_t_hinfo = 13,
+ ns_t_minfo = 14,
+ ns_t_mx = 15,
+ ns_t_txt = 16,
+ ns_t_rp = 17,
+ ns_t_afsdb = 18,
+ ns_t_x25 = 19,
+ ns_t_isdn = 20,
+ ns_t_rt = 21,
+ ns_t_nsap = 22,
+ ns_t_nsap_ptr = 23,
+ ns_t_sig = 24,
+ ns_t_key = 25,
+ ns_t_px = 26,
+ ns_t_gpos = 27,
+ ns_t_aaaa = 28,
+ ns_t_loc = 29,
+ ns_t_nxt = 30,
+ ns_t_eid = 31,
+ ns_t_nimloc = 32,
+ ns_t_srv = 33,
+ ns_t_atma = 34,
+ ns_t_naptr = 35,
+ ns_t_kx = 36,
+ ns_t_cert = 37,
+ ns_t_a6 = 38,
+ ns_t_dname = 39,
+ ns_t_sink = 40,
+ ns_t_opt = 41,
+ ns_t_apl = 42,
+ ns_t_ds = 43,
+ ns_t_sshfp = 44,
+ ns_t_ipseckey = 45,
+ ns_t_rrsig = 46,
+ ns_t_nsec = 47,
+ ns_t_dnskey = 48,
+ ns_t_dhcid = 49,
+ ns_t_nsec3 = 50,
+ ns_t_nsec3param = 51,
+ ns_t_tlsa = 52,
+ ns_t_smimea = 53,
+ ns_t_hip = 55,
+ ns_t_ninfo = 56,
+ ns_t_rkey = 57,
+ ns_t_talink = 58,
+ ns_t_cds = 59,
+ ns_t_cdnskey = 60,
+ ns_t_openpgpkey = 61,
+ ns_t_csync = 62,
+ ns_t_spf = 99,
+ ns_t_uinfo = 100,
+ ns_t_uid = 101,
+ ns_t_gid = 102,
+ ns_t_unspec = 103,
+ ns_t_nid = 104,
+ ns_t_l32 = 105,
+ ns_t_l64 = 106,
+ ns_t_lp = 107,
+ ns_t_eui48 = 108,
+ ns_t_eui64 = 109,
+ ns_t_tkey = 249,
+ ns_t_tsig = 250,
+ ns_t_ixfr = 251,
+ ns_t_axfr = 252,
+ ns_t_mailb = 253,
+ ns_t_maila = 254,
+ ns_t_any = 255,
+ ns_t_uri = 256,
+ ns_t_caa = 257,
+ ns_t_avc = 258,
+ ns_t_ta = 32768,
+ ns_t_dlv = 32769,
+
+ ns_t_max = 65536
+ } ns_type;
/*%
* Values for class field
@@ -330,15 +335,7 @@ typedef enum __ns_class {
ns_c_max = 65536
} ns_class;
-/* DNSSEC constants. */
-
-typedef enum __ns_key_types {
- ns_kt_rsa = 1, /*%< key type RSA/MD5 */
- ns_kt_dh = 2, /*%< Diffie Hellman */
- ns_kt_dsa = 3, /*%< Digital Signature Standard (MANDATORY) */
- ns_kt_private = 254 /*%< Private key type starts with OID */
-} ns_key_types;
-
+/* Certificate type values in CERT resource records. */
typedef enum __ns_cert_types {
cert_t_pkix = 1, /*%< PKIX (X.509v3) */
cert_t_spki = 2, /*%< SPKI */
@@ -347,82 +344,6 @@ typedef enum __ns_cert_types {
cert_t_oid = 254 /*%< OID private type */
} ns_cert_types;
-/* Flags field of the KEY RR rdata. */
-#define NS_KEY_TYPEMASK 0xC000 /*%< Mask for "type" bits */
-#define NS_KEY_TYPE_AUTH_CONF 0x0000 /*%< Key usable for both */
-#define NS_KEY_TYPE_CONF_ONLY 0x8000 /*%< Key usable for confidentiality */
-#define NS_KEY_TYPE_AUTH_ONLY 0x4000 /*%< Key usable for authentication */
-#define NS_KEY_TYPE_NO_KEY 0xC000 /*%< No key usable for either; no key */
-/* The type bits can also be interpreted independently, as single bits: */
-#define NS_KEY_NO_AUTH 0x8000 /*%< Key unusable for authentication */
-#define NS_KEY_NO_CONF 0x4000 /*%< Key unusable for confidentiality */
-#define NS_KEY_RESERVED2 0x2000 /* Security is *mandatory* if bit=0 */
-#define NS_KEY_EXTENDED_FLAGS 0x1000 /*%< reserved - must be zero */
-#define NS_KEY_RESERVED4 0x0800 /*%< reserved - must be zero */
-#define NS_KEY_RESERVED5 0x0400 /*%< reserved - must be zero */
-#define NS_KEY_NAME_TYPE 0x0300 /*%< these bits determine the type */
-#define NS_KEY_NAME_USER 0x0000 /*%< key is assoc. with user */
-#define NS_KEY_NAME_ENTITY 0x0200 /*%< key is assoc. with entity eg host */
-#define NS_KEY_NAME_ZONE 0x0100 /*%< key is zone key */
-#define NS_KEY_NAME_RESERVED 0x0300 /*%< reserved meaning */
-#define NS_KEY_RESERVED8 0x0080 /*%< reserved - must be zero */
-#define NS_KEY_RESERVED9 0x0040 /*%< reserved - must be zero */
-#define NS_KEY_RESERVED10 0x0020 /*%< reserved - must be zero */
-#define NS_KEY_RESERVED11 0x0010 /*%< reserved - must be zero */
-#define NS_KEY_SIGNATORYMASK 0x000F /*%< key can sign RR's of same name */
-#define NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \
- NS_KEY_RESERVED4 | \
- NS_KEY_RESERVED5 | \
- NS_KEY_RESERVED8 | \
- NS_KEY_RESERVED9 | \
- NS_KEY_RESERVED10 | \
- NS_KEY_RESERVED11 )
-#define NS_KEY_RESERVED_BITMASK2 0xFFFF /*%< no bits defined here */
-/* The Algorithm field of the KEY and SIG RR's is an integer, {1..254} */
-#define NS_ALG_MD5RSA 1 /*%< MD5 with RSA */
-#define NS_ALG_DH 2 /*%< Diffie Hellman KEY */
-#define NS_ALG_DSA 3 /*%< DSA KEY */
-#define NS_ALG_DSS NS_ALG_DSA
-#define NS_ALG_EXPIRE_ONLY 253 /*%< No alg, no security */
-#define NS_ALG_PRIVATE_OID 254 /*%< Key begins with OID giving alg */
-/* Protocol values */
-/* value 0 is reserved */
-#define NS_KEY_PROT_TLS 1
-#define NS_KEY_PROT_EMAIL 2
-#define NS_KEY_PROT_DNSSEC 3
-#define NS_KEY_PROT_IPSEC 4
-#define NS_KEY_PROT_ANY 255
-
-/* Signatures */
-#define NS_MD5RSA_MIN_BITS 512 /*%< Size of a mod or exp in bits */
-#define NS_MD5RSA_MAX_BITS 4096
- /* Total of binary mod and exp */
-#define NS_MD5RSA_MAX_BYTES ((NS_MD5RSA_MAX_BITS+7/8)*2+3)
- /* Max length of text sig block */
-#define NS_MD5RSA_MAX_BASE64 (((NS_MD5RSA_MAX_BYTES+2)/3)*4)
-#define NS_MD5RSA_MIN_SIZE ((NS_MD5RSA_MIN_BITS+7)/8)
-#define NS_MD5RSA_MAX_SIZE ((NS_MD5RSA_MAX_BITS+7)/8)
-
-#define NS_DSA_SIG_SIZE 41
-#define NS_DSA_MIN_SIZE 213
-#define NS_DSA_MAX_BYTES 405
-
-/* Offsets into SIG record rdata to find various values */
-#define NS_SIG_TYPE 0 /*%< Type flags */
-#define NS_SIG_ALG 2 /*%< Algorithm */
-#define NS_SIG_LABELS 3 /*%< How many labels in name */
-#define NS_SIG_OTTL 4 /*%< Original TTL */
-#define NS_SIG_EXPIR 8 /*%< Expiration time */
-#define NS_SIG_SIGNED 12 /*%< Signature time */
-#define NS_SIG_FOOT 16 /*%< Key footprint */
-#define NS_SIG_SIGNER 18 /*%< Domain name of who signed it */
-/* How RR types are represented as bit-flags in NXT records */
-#define NS_NXT_BITS 8
-#define NS_NXT_BIT_SET( n,p) (p[(n)/NS_NXT_BITS] |= (0x80>>((n)%NS_NXT_BITS)))
-#define NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS)))
-#define NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] & (0x80>>((n)%NS_NXT_BITS)))
-#define NS_NXT_MAX 127
-
/*%
* EDNS0 extended flags and option codes, host order.
*/
@@ -433,34 +354,34 @@ typedef enum __ns_cert_types {
* Inline versions of get/put short/long. Pointer is advanced.
*/
#define NS_GET16(s, cp) do { \
- const u_char *t_cp = (const u_char *)(cp); \
- (s) = ((u_int16_t)t_cp[0] << 8) \
- | ((u_int16_t)t_cp[1]) \
+ const unsigned char *t_cp = (const unsigned char *)(cp); \
+ (s) = ((uint16_t)t_cp[0] << 8) \
+ | ((uint16_t)t_cp[1]) \
; \
(cp) += NS_INT16SZ; \
} while (0)
#define NS_GET32(l, cp) do { \
- const u_char *t_cp = (const u_char *)(cp); \
- (l) = ((u_int32_t)t_cp[0] << 24) \
- | ((u_int32_t)t_cp[1] << 16) \
- | ((u_int32_t)t_cp[2] << 8) \
- | ((u_int32_t)t_cp[3]) \
+ const unsigned char *t_cp = (const unsigned char *)(cp); \
+ (l) = ((uint32_t)t_cp[0] << 24) \
+ | ((uint32_t)t_cp[1] << 16) \
+ | ((uint32_t)t_cp[2] << 8) \
+ | ((uint32_t)t_cp[3]) \
; \
(cp) += NS_INT32SZ; \
} while (0)
#define NS_PUT16(s, cp) do { \
- u_int16_t t_s = (u_int16_t)(s); \
- u_char *t_cp = (u_char *)(cp); \
+ uint16_t t_s = (uint16_t)(s); \
+ unsigned char *t_cp = (unsigned char *)(cp); \
*t_cp++ = t_s >> 8; \
*t_cp = t_s; \
(cp) += NS_INT16SZ; \
} while (0)
#define NS_PUT32(l, cp) do { \
- u_int32_t t_l = (u_int32_t)(l); \
- u_char *t_cp = (u_char *)(cp); \
+ uint32_t t_l = (uint32_t)(l); \
+ unsigned char *t_cp = (unsigned char *)(cp); \
*t_cp++ = t_l >> 24; \
*t_cp++ = t_l >> 16; \
*t_cp++ = t_l >> 8; \
@@ -470,66 +391,53 @@ typedef enum __ns_cert_types {
__BEGIN_DECLS
int ns_msg_getflag (ns_msg, int) __THROW;
-u_int ns_get16 (const u_char *) __THROW;
-u_long ns_get32 (const u_char *) __THROW;
-void ns_put16 (u_int, u_char *) __THROW;
-void ns_put32 (u_long, u_char *) __THROW;
-int ns_initparse (const u_char *, int, ns_msg *) __THROW;
-int ns_skiprr (const u_char *, const u_char *, ns_sect, int)
- __THROW;
+unsigned int ns_get16 (const unsigned char *) __THROW;
+unsigned long ns_get32 (const unsigned char *) __THROW;
+void ns_put16 (unsigned int, unsigned char *) __THROW;
+void ns_put32 (unsigned long, unsigned char *) __THROW;
+int ns_initparse (const unsigned char *, int, ns_msg *) __THROW;
+int ns_skiprr (const unsigned char *, const unsigned char *,
+ ns_sect, int) __THROW;
int ns_parserr (ns_msg *, ns_sect, int, ns_rr *) __THROW;
int ns_sprintrr (const ns_msg *, const ns_rr *,
const char *, const char *, char *, size_t)
__THROW;
-int ns_sprintrrf (const u_char *, size_t, const char *,
- ns_class, ns_type, u_long, const u_char *,
- size_t, const char *, const char *,
- char *, size_t) __THROW;
-int ns_format_ttl (u_long, char *, size_t) __THROW;
-int ns_parse_ttl (const char *, u_long *) __THROW;
-u_int32_t ns_datetosecs (const char *, int *) __THROW;
-int ns_name_ntol (const u_char *, u_char *, size_t) __THROW;
-int ns_name_ntop (const u_char *, char *, size_t) __THROW;
-int ns_name_pton (const char *, u_char *, size_t) __THROW;
-int ns_name_unpack (const u_char *, const u_char *,
- const u_char *, u_char *, size_t) __THROW;
-int ns_name_pack (const u_char *, u_char *, int,
- const u_char **, const u_char **) __THROW;
-int ns_name_uncompress (const u_char *, const u_char *,
- const u_char *, char *, size_t) __THROW;
-int ns_name_compress (const char *, u_char *, size_t,
- const u_char **, const u_char **) __THROW;
-int ns_name_skip (const u_char **, const u_char *) __THROW;
-void ns_name_rollback (const u_char *, const u_char **,
- const u_char **) __THROW;
-int ns_sign (u_char *, int *, int, int, void *,
- const u_char *, int, u_char *, int *, time_t) __THROW;
-int ns_sign2 (u_char *, int *, int, int, void *,
- const u_char *, int, u_char *, int *, time_t,
- u_char **, u_char **) __THROW;
-int ns_sign_tcp (u_char *, int *, int, int,
- ns_tcp_tsig_state *, int) __THROW;
-int ns_sign_tcp2 (u_char *, int *, int, int,
- ns_tcp_tsig_state *, int,
- u_char **, u_char **) __THROW;
-int ns_sign_tcp_init (void *, const u_char *, int,
- ns_tcp_tsig_state *) __THROW;
-u_char *ns_find_tsig (u_char *, u_char *) __THROW;
-int ns_verify (u_char *, int *, void *, const u_char *, int,
- u_char *, int *, time_t *, int) __THROW;
-int ns_verify_tcp (u_char *, int *, ns_tcp_tsig_state *, int)
+int ns_sprintrrf (const unsigned char *, size_t, const char *,
+ ns_class, ns_type, unsigned long,
+ const unsigned char *, size_t, const char *,
+ const char *, char *, size_t) __THROW;
+int ns_format_ttl (unsigned long, char *, size_t) __THROW;
+int ns_parse_ttl (const char *, unsigned long *) __THROW;
+uint32_t ns_datetosecs (const char *, int *) __THROW;
+int ns_name_ntol (const unsigned char *, unsigned char *, size_t)
+ __THROW;
+int ns_name_ntop (const unsigned char *, char *, size_t) __THROW;
+int ns_name_pton (const char *, unsigned char *, size_t) __THROW;
+int ns_name_unpack (const unsigned char *, const unsigned char *,
+ const unsigned char *, unsigned char *, size_t)
+ __THROW;
+int ns_name_pack (const unsigned char *, unsigned char *, int,
+ const unsigned char **, const unsigned char **)
+ __THROW;
+int ns_name_uncompress (const unsigned char *,
+ const unsigned char *,
+ const unsigned char *,
+ char *, size_t) __THROW;
+int ns_name_compress (const char *, unsigned char *, size_t,
+ const unsigned char **,
+ const unsigned char **) __THROW;
+int ns_name_skip (const unsigned char **, const unsigned char *)
__THROW;
-int ns_verify_tcp_init (void *, const u_char *, int,
- ns_tcp_tsig_state *) __THROW;
+void ns_name_rollback (const unsigned char *,
+ const unsigned char **,
+ const unsigned char **) __THROW;
int ns_samedomain (const char *, const char *) __THROW;
int ns_subdomain (const char *, const char *) __THROW;
int ns_makecanon (const char *, char *, size_t) __THROW;
int ns_samename (const char *, const char *) __THROW;
__END_DECLS
-#ifdef BIND_4_COMPAT
#include <arpa/nameser_compat.h>
-#endif
#endif /* !_ARPA_NAMESER_H_ */
/*! \file */
diff --git a/resolv/arpa/nameser_compat.h b/resolv/arpa/nameser_compat.h
index d59c9e41b3..f1c390f3b9 100644
--- a/resolv/arpa/nameser_compat.h
+++ b/resolv/arpa/nameser_compat.h
@@ -26,16 +26,9 @@
* SUCH DAMAGE.
*/
-/*%
- * from nameser.h 8.1 (Berkeley) 6/2/93
- * $BINDId: nameser_compat.h,v 8.11 1999/01/02 08:00:58 vixie Exp $
- */
-
#ifndef _ARPA_NAMESER_COMPAT_
#define _ARPA_NAMESER_COMPAT_
-#define __BIND 19950621 /*%< (DEAD) interface version stamp. */
-
#include <endian.h>
/*%
@@ -47,7 +40,7 @@
typedef struct {
unsigned id :16; /*%< query identification number */
-#if BYTE_ORDER == BIG_ENDIAN
+#if __BYTE_ORDER == __BIG_ENDIAN
/* fields in third byte */
unsigned qr: 1; /*%< response flag */
unsigned opcode: 4; /*%< purpose of message */
@@ -61,7 +54,7 @@ typedef struct {
unsigned cd: 1; /*%< checking disabled by resolver */
unsigned rcode :4; /*%< response code */
#endif
-#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN
+#if __BYTE_ORDER == __LITTLE_ENDIAN || __BYTE_ORDER == __PDP_ENDIAN
/* fields in third byte */
unsigned rd :1; /*%< recursion desired */
unsigned tc :1; /*%< truncated message */
@@ -127,49 +120,90 @@ typedef struct {
#define DELETE ns_uop_delete
#define ADD ns_uop_add
-#define T_A ns_t_a
-#define T_NS ns_t_ns
-#define T_MD ns_t_md
-#define T_MF ns_t_mf
-#define T_CNAME ns_t_cname
-#define T_SOA ns_t_soa
-#define T_MB ns_t_mb
-#define T_MG ns_t_mg
-#define T_MR ns_t_mr
-#define T_NULL ns_t_null
-#define T_WKS ns_t_wks
-#define T_PTR ns_t_ptr
-#define T_HINFO ns_t_hinfo
-#define T_MINFO ns_t_minfo
-#define T_MX ns_t_mx
-#define T_TXT ns_t_txt
-#define T_RP ns_t_rp
-#define T_AFSDB ns_t_afsdb
-#define T_X25 ns_t_x25
-#define T_ISDN ns_t_isdn
-#define T_RT ns_t_rt
-#define T_NSAP ns_t_nsap
-#define T_NSAP_PTR ns_t_nsap_ptr
-#define T_SIG ns_t_sig
-#define T_KEY ns_t_key
-#define T_PX ns_t_px
-#define T_GPOS ns_t_gpos
-#define T_AAAA ns_t_aaaa
-#define T_LOC ns_t_loc
-#define T_NXT ns_t_nxt
-#define T_EID ns_t_eid
-#define T_NIMLOC ns_t_nimloc
-#define T_SRV ns_t_srv
-#define T_ATMA ns_t_atma
-#define T_NAPTR ns_t_naptr
-#define T_A6 ns_t_a6
-#define T_DNAME ns_t_dname
-#define T_TSIG ns_t_tsig
-#define T_IXFR ns_t_ixfr
-#define T_AXFR ns_t_axfr
-#define T_MAILB ns_t_mailb
-#define T_MAILA ns_t_maila
-#define T_ANY ns_t_any
+#define T_A ns_t_a
+#define T_NS ns_t_ns
+#define T_MD ns_t_md
+#define T_MF ns_t_mf
+#define T_CNAME ns_t_cname
+#define T_SOA ns_t_soa
+#define T_MB ns_t_mb
+#define T_MG ns_t_mg
+#define T_MR ns_t_mr
+#define T_NULL ns_t_null
+#define T_WKS ns_t_wks
+#define T_PTR ns_t_ptr
+#define T_HINFO ns_t_hinfo
+#define T_MINFO ns_t_minfo
+#define T_MX ns_t_mx
+#define T_TXT ns_t_txt
+#define T_RP ns_t_rp
+#define T_AFSDB ns_t_afsdb
+#define T_X25 ns_t_x25
+#define T_ISDN ns_t_isdn
+#define T_RT ns_t_rt
+#define T_NSAP ns_t_nsap
+#define T_NSAP_PTR ns_t_nsap_ptr
+#define T_SIG ns_t_sig
+#define T_KEY ns_t_key
+#define T_PX ns_t_px
+#define T_GPOS ns_t_gpos
+#define T_AAAA ns_t_aaaa
+#define T_LOC ns_t_loc
+#define T_NXT ns_t_nxt
+#define T_EID ns_t_eid
+#define T_NIMLOC ns_t_nimloc
+#define T_SRV ns_t_srv
+#define T_ATMA ns_t_atma
+#define T_NAPTR ns_t_naptr
+#define T_KX ns_t_kx
+#define T_CERT ns_t_cert
+#define T_A6 ns_t_a6
+#define T_DNAME ns_t_dname
+#define T_SINK ns_t_sink
+#define T_OPT ns_t_opt
+#define T_APL ns_t_apl
+#define T_DS ns_t_ds
+#define T_SSHFP ns_t_sshfp
+#define T_IPSECKEY ns_t_ipseckey
+#define T_RRSIG ns_t_rrsig
+#define T_NSEC ns_t_nsec
+#define T_DNSKEY ns_t_dnskey
+#define T_DHCID ns_t_dhcid
+#define T_NSEC3 ns_t_nsec3
+#define T_NSEC3PARAM ns_t_nsec3param
+#define T_TLSA ns_t_tlsa
+#define T_SMIMEA ns_t_smimea
+#define T_HIP ns_t_hip
+#define T_NINFO ns_t_ninfo
+#define T_RKEY ns_t_rkey
+#define T_TALINK ns_t_talink
+#define T_CDS ns_t_cds
+#define T_CDNSKEY ns_t_cdnskey
+#define T_OPENPGPKEY ns_t_openpgpkey
+#define T_CSYNC ns_t_csync
+#define T_SPF ns_t_spf
+#define T_UINFO ns_t_uinfo
+#define T_UID ns_t_uid
+#define T_GID ns_t_gid
+#define T_UNSPEC ns_t_unspec
+#define T_NID ns_t_nid
+#define T_L32 ns_t_l32
+#define T_L64 ns_t_l64
+#define T_LP ns_t_lp
+#define T_EUI48 ns_t_eui48
+#define T_EUI64 ns_t_eui64
+#define T_TKEY ns_t_tkey
+#define T_TSIG ns_t_tsig
+#define T_IXFR ns_t_ixfr
+#define T_AXFR ns_t_axfr
+#define T_MAILB ns_t_mailb
+#define T_MAILA ns_t_maila
+#define T_ANY ns_t_any
+#define T_URI ns_t_uri
+#define T_CAA ns_t_caa
+#define T_AVC ns_t_avc
+#define T_TA ns_t_ta
+#define T_DLV ns_t_dlv
#define C_IN ns_c_in
#define C_CHAOS ns_c_chaos
diff --git a/resolv/bits/types/res_state.h b/resolv/bits/types/res_state.h
new file mode 100644
index 0000000000..2544a627f6
--- /dev/null
+++ b/resolv/bits/types/res_state.h
@@ -0,0 +1,61 @@
+#ifndef __res_state_defined
+#define __res_state_defined 1
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+/* res_state: the global state used by the resolver stub. */
+#define MAXNS 3 /* max # name servers we'll track */
+#define MAXDFLSRCH 3 /* # default domain levels to try */
+#define MAXDNSRCH 6 /* max # domains in search path */
+#define MAXRESOLVSORT 10 /* number of net to sort on */
+
+struct __res_state {
+ int retrans; /* retransmition time interval */
+ int retry; /* number of times to retransmit */
+ unsigned long options; /* option flags - see below. */
+ int nscount; /* number of name servers */
+ struct sockaddr_in
+ nsaddr_list[MAXNS]; /* address of name server */
+ unsigned short id; /* current message id */
+ /* 2 byte hole here. */
+ char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */
+ char defdname[256]; /* default domain (deprecated) */
+ unsigned long pfcode; /* RES_PRF_ flags - see below. */
+ unsigned ndots:4; /* threshold for initial abs. query */
+ unsigned nsort:4; /* number of elements in sort_list[] */
+ unsigned ipv6_unavail:1; /* connecting to IPv6 server failed */
+ unsigned unused:23;
+ struct {
+ struct in_addr addr;
+ uint32_t mask;
+ } sort_list[MAXRESOLVSORT];
+ /* 4 byte hole here on 64-bit architectures. */
+ void * __glibc_unused_qhook;
+ void * __glibc_unused_rhook;
+ int res_h_errno; /* last one set for this context */
+ int _vcsock; /* PRIVATE: for res_send VC i/o */
+ unsigned int _flags; /* PRIVATE: see below */
+ /* 4 byte hole here on 64-bit architectures. */
+ union {
+ char pad[52]; /* On an i386 this means 512b total. */
+ struct {
+ uint16_t nscount;
+ uint16_t nsmap[MAXNS];
+ int nssocks[MAXNS];
+ uint16_t nscount6;
+ uint16_t nsinit;
+ struct sockaddr_in6 *nsaddrs[MAXNS];
+#ifdef _LIBC
+ unsigned long long int __glibc_extension_index
+ __attribute__((packed));
+#else
+ unsigned int __glibc_reserved[2];
+#endif
+ } _ext;
+ } _u;
+};
+
+typedef struct __res_state *res_state;
+
+#endif /* __res_state_defined */
diff --git a/resolv/gethnamaddr.c b/resolv/compat-gethnamaddr.c
index 3a8e9b1490..259378b2be 100644
--- a/resolv/gethnamaddr.c
+++ b/resolv/compat-gethnamaddr.c
@@ -54,54 +54,27 @@
it exports symbols in the libresolv ABI. The file is not maintained any
more, nor are these functions. */
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-
-#include <stdio.h>
-#include <netdb.h>
-#include <resolv.h>
-#include <ctype.h>
-#include <errno.h>
-#include <syslog.h>
-
-#define RESOLVSORT
-
-#ifndef LOG_AUTH
-# define LOG_AUTH 0
-#endif
-
-#define MULTI_PTRS_ARE_ALIASES 1 /* XXX - experimental */
-
-#if defined(BSD) && (BSD >= 199103) && defined(AF_INET6)
+#include <shlib-compat.h>
+#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_25)
+
+# include <sys/types.h>
+# include <sys/param.h>
+# include <sys/socket.h>
+# include <netinet/in.h>
+# include <arpa/inet.h>
+# include <arpa/nameser.h>
+
+# include <stdio.h>
+# include <netdb.h>
+# include <resolv/resolv-internal.h>
+# include <resolv/resolv_context.h>
+# include <ctype.h>
+# include <errno.h>
# include <stdlib.h>
# include <string.h>
-#else
-# include "../conf/portability.h"
-#endif
-#if defined(USE_OPTIONS_H)
-# include <../conf/options.h>
-#endif
-
-#ifdef SPRINTF_CHAR
-# define SPRINTF(x) strlen(sprintf/**/x)
-#else
-# define SPRINTF(x) ((size_t)sprintf x)
-#endif
-
-#define MAXALIASES 35
-#define MAXADDRS 35
-
-static const char AskedForGot[] =
- "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
+# define MAXALIASES 35
+# define MAXADDRS 35
static char *h_addr_ptrs[MAXADDRS + 1];
@@ -112,24 +85,25 @@ static u_char host_addr[16]; /* IPv4 or IPv6 */
static FILE *hostf = NULL;
static int stayopen = 0;
+static struct hostent *res_gethostbyname2_context (struct resolv_context *,
+ const char *name, int af);
+
static void map_v4v6_address (const char *src, char *dst) __THROW;
static void map_v4v6_hostent (struct hostent *hp, char **bp, int *len) __THROW;
-#ifdef RESOLVSORT
extern void addrsort (char **, int) __THROW;
-#endif
-#if PACKETSZ > 65536
-#define MAXPACKET PACKETSZ
-#else
-#define MAXPACKET 65536
-#endif
+# if PACKETSZ > 65536
+# define MAXPACKET PACKETSZ
+# else
+# define MAXPACKET 65536
+# endif
/* As per RFC 1034 and 1035 a host name cannot exceed 255 octets in length. */
-#ifdef MAXHOSTNAMELEN
-# undef MAXHOSTNAMELEN
-#endif
-#define MAXHOSTNAMELEN 256
+# ifdef MAXHOSTNAMELEN
+# undef MAXHOSTNAMELEN
+# endif
+# define MAXHOSTNAMELEN 256
typedef union {
HEADER hdr;
@@ -141,11 +115,11 @@ typedef union {
char ac;
} align;
-#ifndef h_errno
+# ifndef h_errno
extern int h_errno;
-#endif
+# endif
-#ifdef DEBUG
+# ifdef DEBUG
static void
Dprintf (char *msg, int num)
{
@@ -156,11 +130,11 @@ Dprintf (char *msg, int num)
__set_errno (save);
}
}
-#else
-# define Dprintf(msg, num) /*nada*/
-#endif
+# else
+# define Dprintf(msg, num) /*nada*/
+# endif
-#define BOUNDED_INCR(x) \
+# define BOUNDED_INCR(x) \
do { \
cp += x; \
if (cp > eom) { \
@@ -169,7 +143,7 @@ Dprintf (char *msg, int num)
} \
} while (0)
-#define BOUNDS_CHECK(ptr, count) \
+# define BOUNDS_CHECK(ptr, count) \
do { \
if ((ptr) + (count) > eom) { \
__set_h_errno (NO_RECOVERY); \
@@ -335,20 +309,12 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
* uses many different types in responses that do not
* match QTYPE.
*/
- if ((_res.options & RES_USE_DNSSEC) == 0) {
- syslog(LOG_NOTICE|LOG_AUTH,
- "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
- qname, p_class(C_IN), p_type(qtype),
- p_type(type));
- }
cp += n;
continue; /* XXX - had_error++ ? */
}
switch (type) {
case T_PTR:
if (strcasecmp(tname, bp) != 0) {
- syslog(LOG_NOTICE|LOG_AUTH,
- AskedForGot, qname, bp);
cp += n;
continue; /* XXX - had_error++ ? */
}
@@ -357,7 +323,6 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
had_error++;
break;
}
-#if MULTI_PTRS_ARE_ALIASES
cp += n;
if (cp != erdata) {
__set_h_errno (NO_RECOVERY);
@@ -379,26 +344,9 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
buflen -= n;
}
break;
-#else
- host.h_name = bp;
- if (_res.options & RES_USE_INET6) {
- n = strlen(bp) + 1; /* for the \0 */
- if (n >= MAXHOSTNAMELEN) {
- had_error++;
- break;
- }
- bp += n;
- buflen -= n;
- map_v4v6_hostent(&host, &bp, &buflen);
- }
- __set_h_errno (NETDB_SUCCESS);
- return (&host);
-#endif
case T_A:
case T_AAAA:
if (strcasecmp(host.h_name, bp) != 0) {
- syslog(LOG_NOTICE|LOG_AUTH,
- AskedForGot, host.h_name, bp);
cp += n;
continue; /* XXX - had_error++ ? */
}
@@ -452,7 +400,6 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
if (haveanswer) {
*ap = NULL;
*hap = NULL;
-# if defined(RESOLVSORT)
/*
* Note: we sort even if host can take only one address
* in its return structures - should give it the "best"
@@ -460,7 +407,6 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
*/
if (_res.nsort && haveanswer > 1 && qtype == T_A)
addrsort(h_addr_ptrs, haveanswer);
-# endif /*RESOLVSORT*/
if (!host.h_name) {
n = strlen(qname) + 1; /* for the \0 */
if (n > buflen || n >= MAXHOSTNAMELEN)
@@ -470,7 +416,7 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
bp += n;
buflen -= n;
}
- if (_res.options & RES_USE_INET6)
+ if (res_use_inet6 ())
map_v4v6_hostent(&host, &bp, &buflen);
__set_h_errno (NETDB_SUCCESS);
return (&host);
@@ -480,28 +426,37 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
return (NULL);
}
-extern struct hostent *gethostbyname2(const char *name, int af);
-libresolv_hidden_proto (gethostbyname2)
+extern struct hostent *res_gethostbyname2(const char *name, int af);
+libresolv_hidden_proto (res_gethostbyname2)
struct hostent *
-gethostbyname (const char *name)
+res_gethostbyname (const char *name)
{
- struct hostent *hp;
-
- if (__res_maybe_init (&_res, 0) == -1) {
- __set_h_errno (NETDB_INTERNAL);
- return (NULL);
- }
- if (_res.options & RES_USE_INET6) {
- hp = gethostbyname2(name, AF_INET6);
- if (hp)
- return (hp);
+ struct resolv_context *ctx = __resolv_context_get ();
+ if (ctx == NULL)
+ {
+ __set_h_errno (NETDB_INTERNAL);
+ return NULL;
+ }
+
+ if (res_use_inet6 ())
+ {
+ struct hostent *hp = res_gethostbyname2_context (ctx, name, AF_INET6);
+ if (hp != NULL)
+ {
+ __resolv_context_put (ctx);
+ return hp;
}
- return (gethostbyname2(name, AF_INET));
+ }
+ struct hostent *hp = res_gethostbyname2_context (ctx, name, AF_INET);
+ __resolv_context_put (ctx);
+ return hp;
}
+compat_symbol (libresolv, res_gethostbyname, res_gethostbyname, GLIBC_2_0);
-struct hostent *
-gethostbyname2 (const char *name, int af)
+static struct hostent *
+res_gethostbyname2_context (struct resolv_context *ctx,
+ const char *name, int af)
{
union
{
@@ -514,11 +469,6 @@ gethostbyname2 (const char *name, int af)
int n, size, type, len;
struct hostent *ret;
- if (__res_maybe_init (&_res, 0) == -1) {
- __set_h_errno (NETDB_INTERNAL);
- return (NULL);
- }
-
switch (af) {
case AF_INET:
size = INADDRSZ;
@@ -542,8 +492,10 @@ gethostbyname2 (const char *name, int af)
* this is also done in res_query() since we are not the only
* function that looks up host names.
*/
- if (!strchr(name, '.') && (cp = __hostalias(name)))
- name = cp;
+ char abuf[MAXDNAME];
+ if (strchr (name, '.') != NULL
+ && (cp = __res_context_hostalias (ctx, name, abuf, sizeof (abuf))))
+ name = cp;
/*
* disallow names consisting only of digits/dots, unless
@@ -573,7 +525,7 @@ gethostbyname2 (const char *name, int af)
h_addr_ptrs[0] = (char *)host_addr;
h_addr_ptrs[1] = NULL;
host.h_addr_list = h_addr_ptrs;
- if (_res.options & RES_USE_INET6)
+ if (res_use_inet6 ())
map_v4v6_hostent(&host, &bp, &len);
__set_h_errno (NETDB_SUCCESS);
return (&host);
@@ -615,8 +567,9 @@ gethostbyname2 (const char *name, int af)
buf.buf = origbuf = (querybuf *) alloca (1024);
- if ((n = __libc_res_nsearch(&_res, name, C_IN, type, buf.buf->buf, 1024,
- &buf.ptr, NULL, NULL, NULL, NULL)) < 0) {
+ if ((n = __res_context_search
+ (ctx, name, C_IN, type, buf.buf->buf, 1024,
+ &buf.ptr, NULL, NULL, NULL, NULL)) < 0) {
if (buf.buf != origbuf)
free (buf.buf);
Dprintf("res_nsearch failed (%d)\n", n);
@@ -629,10 +582,26 @@ gethostbyname2 (const char *name, int af)
free (buf.buf);
return ret;
}
-libresolv_hidden_def (gethostbyname2)
struct hostent *
-gethostbyaddr (const void *addr, socklen_t len, int af)
+res_gethostbyname2 (const char *name, int af)
+{
+ struct resolv_context *ctx = __resolv_context_get ();
+ if (ctx == NULL)
+ {
+ __set_h_errno (NETDB_INTERNAL);
+ return NULL;
+ }
+ struct hostent *hp = res_gethostbyname2_context (ctx, name, AF_INET);
+ __resolv_context_put (ctx);
+ return hp;
+}
+libresolv_hidden_def (res_gethostbyname2)
+compat_symbol (libresolv, res_gethostbyname2, res_gethostbyname2, GLIBC_2_0);
+
+static struct hostent *
+res_gethostbyaddr_context (struct resolv_context *ctx,
+ const void *addr, socklen_t len, int af)
{
const u_char *uaddr = (const u_char *)addr;
static const u_char mapped[] = { 0,0, 0,0, 0,0, 0,0, 0,0, 0xff,0xff };
@@ -647,17 +616,7 @@ gethostbyaddr (const void *addr, socklen_t len, int af)
querybuf *orig_buf;
struct hostent *hp;
char qbuf[MAXDNAME+1], *qp = NULL;
-#ifdef SUNSECURITY
- struct hostent *rhp;
- char **haddr;
- u_long old_options;
- char hname2[MAXDNAME+1];
-#endif /*SUNSECURITY*/
-
- if (__res_maybe_init (&_res, 0) == -1) {
- __set_h_errno (NETDB_INTERNAL);
- return (NULL);
- }
+
if (af == AF_INET6 && len == IN6ADDRSZ &&
(!memcmp(uaddr, mapped, sizeof mapped) ||
!memcmp(uaddr, tunnelled, sizeof tunnelled))) {
@@ -695,9 +654,9 @@ gethostbyaddr (const void *addr, socklen_t len, int af)
case AF_INET6:
qp = qbuf;
for (n = IN6ADDRSZ - 1; n >= 0; n--) {
- qp += SPRINTF((qp, "%x.%x.",
- uaddr[n] & 0xf,
- (uaddr[n] >> 4) & 0xf));
+ qp += sprintf(qp, "%x.%x.",
+ uaddr[n] & 0xf,
+ (uaddr[n] >> 4) & 0xf);
}
strcpy(qp, "ip6.arpa");
break;
@@ -707,14 +666,8 @@ gethostbyaddr (const void *addr, socklen_t len, int af)
buf.buf = orig_buf = (querybuf *) alloca (1024);
- n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf, 1024,
- &buf.ptr, NULL, NULL, NULL, NULL);
- if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0) {
- strcpy(qp, "ip6.int");
- n = __libc_res_nquery(&_res, qbuf, C_IN, T_PTR, buf.buf->buf,
- buf.buf != orig_buf ? MAXPACKET : 1024,
- &buf.ptr, NULL, NULL, NULL, NULL);
- }
+ n = __res_context_query (ctx, qbuf, C_IN, T_PTR, buf.buf->buf, 1024,
+ &buf.ptr, NULL, NULL, NULL, NULL);
if (n < 0) {
if (buf.buf != orig_buf)
free (buf.buf);
@@ -728,44 +681,12 @@ gethostbyaddr (const void *addr, socklen_t len, int af)
free (buf.buf);
if (!hp)
return (NULL); /* h_errno was set by getanswer() */
-#ifdef SUNSECURITY
- if (af == AF_INET) {
- /*
- * turn off search as the name should be absolute,
- * 'localhost' should be matched by defnames
- */
- strncpy(hname2, hp->h_name, MAXDNAME);
- hname2[MAXDNAME] = '\0';
- old_options = _res.options;
- _res.options &= ~RES_DNSRCH;
- _res.options |= RES_DEFNAMES;
- if (!(rhp = gethostbyname(hname2))) {
- syslog(LOG_NOTICE|LOG_AUTH,
- "gethostbyaddr: No A record for %s (verifying [%s])",
- hname2, inet_ntoa(*((struct in_addr *)addr)));
- _res.options = old_options;
- __set_h_errno (HOST_NOT_FOUND);
- return (NULL);
- }
- _res.options = old_options;
- for (haddr = rhp->h_addr_list; *haddr; haddr++)
- if (!memcmp(*haddr, addr, INADDRSZ))
- break;
- if (!*haddr) {
- syslog(LOG_NOTICE|LOG_AUTH,
- "gethostbyaddr: A record of %s != PTR record [%s]",
- hname2, inet_ntoa(*((struct in_addr *)addr)));
- __set_h_errno (HOST_NOT_FOUND);
- return (NULL);
- }
- }
-#endif /*SUNSECURITY*/
hp->h_addrtype = af;
hp->h_length = len;
memmove(host_addr, addr, len);
h_addr_ptrs[0] = (char *)host_addr;
h_addr_ptrs[1] = NULL;
- if (af == AF_INET && (_res.options & RES_USE_INET6)) {
+ if (af == AF_INET && res_use_inet6 ()) {
map_v4v6_address((char*)host_addr, (char*)host_addr);
hp->h_addrtype = AF_INET6;
hp->h_length = IN6ADDRSZ;
@@ -774,6 +695,21 @@ gethostbyaddr (const void *addr, socklen_t len, int af)
return (hp);
}
+struct hostent *
+res_gethostbyaddr (const void *addr, socklen_t len, int af)
+{
+ struct resolv_context *ctx = __resolv_context_get ();
+ if (ctx == NULL)
+ {
+ __set_h_errno (NETDB_INTERNAL);
+ return NULL;
+ }
+ struct hostent *hp = res_gethostbyaddr_context (ctx, addr, len, af);
+ __resolv_context_put (ctx);
+ return hp;
+}
+compat_symbol (libresolv, res_gethostbyaddr, res_gethostbyaddr, GLIBC_2_0);
+
void
_sethtent (int f)
{
@@ -784,8 +720,9 @@ _sethtent (int f)
stayopen = f;
}
libresolv_hidden_def (_sethtent)
+compat_symbol (libresolv, _sethtent, _sethtent, GLIBC_2_0);
-void
+static void
_endhtent (void)
{
if (hostf && !stayopen) {
@@ -822,7 +759,7 @@ _gethtent (void)
af = AF_INET6;
len = IN6ADDRSZ;
} else if (inet_pton(AF_INET, p, host_addr) > 0) {
- if (_res.options & RES_USE_INET6) {
+ if (res_use_inet6 ()) {
map_v4v6_address((char*)host_addr, (char*)host_addr);
af = AF_INET6;
len = IN6ADDRSZ;
@@ -859,19 +796,21 @@ _gethtent (void)
return (&host);
}
libresolv_hidden_def (_gethtent)
+compat_symbol (libresolv, _gethtent, _gethtent, GLIBC_2_0);
struct hostent *
_gethtbyname (const char *name)
{
struct hostent *hp;
- if (_res.options & RES_USE_INET6) {
+ if (res_use_inet6 ()) {
hp = _gethtbyname2(name, AF_INET6);
if (hp)
return (hp);
}
return (_gethtbyname2(name, AF_INET));
}
+compat_symbol (libresolv, _gethtbyname, _gethtbyname, GLIBC_2_0);
struct hostent *
_gethtbyname2 (const char *name, int af)
@@ -894,6 +833,7 @@ _gethtbyname2 (const char *name, int af)
return (p);
}
libresolv_hidden_def (_gethtbyname2)
+compat_symbol (libresolv, _gethtbyname2, _gethtbyname2, GLIBC_2_0);
struct hostent *
_gethtbyaddr (const char *addr, size_t len, int af)
@@ -908,6 +848,7 @@ _gethtbyaddr (const char *addr, size_t len, int af)
return (p);
}
libresolv_hidden_def (_gethtbyaddr)
+compat_symbol (libresolv, _gethtbyaddr, _gethtbyaddr, GLIBC_2_0);
static void
map_v4v6_address (const char *src, char *dst)
@@ -953,7 +894,6 @@ map_v4v6_hostent (struct hostent *hp, char **bpp, int *lenp)
}
}
-#ifdef RESOLVSORT
extern void
addrsort (char **ap, int num)
{
@@ -994,50 +934,5 @@ addrsort (char **ap, int num)
needsort++;
}
}
-#endif
-
-#if defined(BSD43_BSD43_NFS) || defined(sun)
-/* some libc's out there are bound internally to these names (UMIPS) */
-void
-ht_sethostent (int stayopen)
-{
- _sethtent(stayopen);
-}
-
-void
-ht_endhostent (void)
-{
- _endhtent();
-}
-
-struct hostent *
-ht_gethostbyname (char *name)
-{
- return (_gethtbyname(name));
-}
-
-struct hostent *
-ht_gethostbyaddr (const char *addr, size_t len, int af)
-{
- return (_gethtbyaddr(addr, len, af));
-}
-struct hostent *
-gethostent (void)
-{
- return (_gethtent());
-}
-
-void
-dns_service (void)
-{
- return;
-}
-
-#undef dn_skipname
-dn_skipname(comp_dn, eom)
- const u_char *comp_dn, *eom;
-{
- return (__dn_skipname(comp_dn, eom));
-}
-#endif /*old-style libc with yp junk in it*/
+#endif /* SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_25) */
diff --git a/resolv/compat-hooks.c b/resolv/compat-hooks.c
new file mode 100644
index 0000000000..75228647ce
--- /dev/null
+++ b/resolv/compat-hooks.c
@@ -0,0 +1,56 @@
+/* Compatibility functions for obsolete libresolv hooks.
+ Copyright (C) 1999-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/*
+ * Copyright (c) 1995-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include <resolv.h>
+
+#include <shlib-compat.h>
+
+#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_25)
+
+void
+attribute_compat_text_section
+res_send_setqhook(void *hook) {
+ _res.__glibc_unused_qhook = hook;
+}
+compat_symbol (libresolv, res_send_setqhook, res_send_setqhook, GLIBC_2_0);
+
+void
+attribute_compat_text_section
+res_send_setrhook(void *hook) {
+ _res.__glibc_unused_rhook = hook;
+}
+compat_symbol (libresolv, res_send_setrhook, res_send_setrhook, GLIBC_2_0);
+
+#endif
diff --git a/resolv/ga_test.c b/resolv/ga_test.c
deleted file mode 100644
index 673162f015..0000000000
--- a/resolv/ga_test.c
+++ /dev/null
@@ -1,99 +0,0 @@
-#include <arpa/inet.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-
-int
-main (void)
-{
-#define N 10
- struct gaicb reqmem[N];
- struct gaicb *req[N];
- int n;
-
- for (n = 0; n < N; ++n)
- {
- asprintf (&reqmem[n].ar_name, "test%d.test.redhat.com", 140 + n);
- reqmem[n].ar_service = NULL;
- reqmem[n].ar_request = NULL;
- reqmem[n].ar_result = NULL;
- req[n] = &reqmem[n];
- }
-
- if (getaddrinfo_a (GAI_NOWAIT, req, N, NULL) != 0)
- {
- puts ("queue call failed");
- exit (1);
- }
- else
- puts ("queue call successful");
-
- while (1)
- {
- int any = 0;
-
- for (n = 0; n < N; ++n)
- if (req[n] != NULL && gai_error (req[n]) != EAI_INPROGRESS)
- {
- if (gai_error (req[n]) == 0)
- {
- struct addrinfo *runp = req[n]->ar_result;
-
- while (runp != NULL)
- {
- switch (runp->ai_family)
- {
- case PF_INET:
- {
- struct sockaddr_in *sinp;
-
- sinp = (struct sockaddr_in *) runp->ai_addr;
- printf ("%2d: %s = %s\n", n,
- req[n]->ar_name, inet_ntoa (sinp->sin_addr));
- }
- break;
- default:
- printf ("%2d: family %d\n", n, runp->ai_family);
- break;
- }
- runp = runp->ai_next;
- }
- }
- else
- printf ("error for %d: %s\n", n,
- gai_strerror (gai_error (req[n])));
- req[n] = NULL;
- break;
- }
- else if (req[n] != NULL)
- any = 1;
-
- if (n == N)
- {
- if (any)
- gai_suspend (req, N, NULL);
- else
- break;
- }
- }
-
- __libc_write(1,"got all\n", 8);
-
- for (n = 0; n < N; ++n)
- if (gai_error (&reqmem[n]) == 0)
- {
- struct addrinfo *runp = reqmem[n].ar_result;
-
- while (runp != NULL)
- {
- struct addrinfo *oldp = runp;
- runp = runp->ai_next;
- freeaddrinfo (oldp);
- }
- }
-
- return 0;
-}
diff --git a/resolv/gai_cancel.c b/resolv/gai_cancel.c
index a2b33f46cf..07e5dd97e6 100644
--- a/resolv/gai_cancel.c
+++ b/resolv/gai_cancel.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
diff --git a/resolv/gai_error.c b/resolv/gai_error.c
index 330426f11c..48fda59f89 100644
--- a/resolv/gai_error.c
+++ b/resolv/gai_error.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
diff --git a/resolv/gai_misc.c b/resolv/gai_misc.c
index 8b142f23bd..e7c3b63cc5 100644
--- a/resolv/gai_misc.c
+++ b/resolv/gai_misc.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
@@ -152,7 +152,6 @@ get_elem (void)
struct requestlist *
-internal_function
__gai_find_request (const struct gaicb *gaicbp)
{
struct requestlist *runp;
@@ -169,7 +168,6 @@ __gai_find_request (const struct gaicb *gaicbp)
int
-internal_function
__gai_remove_request (struct gaicb *gaicbp)
{
struct requestlist *runp;
@@ -212,7 +210,6 @@ static void *handle_requests (void *arg);
/* The main function of the async I/O handling. It enqueues requests
and if necessary starts and handles threads. */
struct requestlist *
-internal_function
__gai_enqueue_request (struct gaicb *gaicbp)
{
struct requestlist *newp;
diff --git a/resolv/gai_misc.h b/resolv/gai_misc.h
index a250c0262f..b788ffc483 100644
--- a/resolv/gai_misc.h
+++ b/resolv/gai_misc.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
@@ -76,26 +76,25 @@ extern pthread_mutex_t __gai_requests_mutex;
/* Enqueue request. */
extern struct requestlist *__gai_enqueue_request (struct gaicb *gaicbp)
- internal_function;
+ attribute_hidden;
/* Find request on wait list. */
extern struct requestlist *__gai_find_request (const struct gaicb *gaicbp)
- internal_function;
+ attribute_hidden;
/* Remove request from waitlist. */
extern int __gai_remove_request (struct gaicb *gaicbp)
- internal_function;
+ attribute_hidden;
/* Notify initiator of request and tell this everybody listening. */
extern void __gai_notify (struct requestlist *req)
- internal_function;
+ attribute_hidden;
/* Notify initiator of request. */
extern int __gai_notify_only (struct sigevent *sigev, pid_t caller_pid)
- internal_function;
+ attribute_hidden;
/* Send the signal. */
-extern int __gai_sigqueue (int sig, const union sigval val, pid_t caller_pid)
- internal_function;
+extern int __gai_sigqueue (int sig, const union sigval val, pid_t caller_pid);
#endif /* gai_misc.h */
diff --git a/resolv/gai_notify.c b/resolv/gai_notify.c
index db99bf7db0..dad2546802 100644
--- a/resolv/gai_notify.c
+++ b/resolv/gai_notify.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
@@ -42,7 +42,6 @@ notify_func_wrapper (void *arg)
int
-internal_function
__gai_notify_only (struct sigevent *sigev, pid_t caller_pid)
{
int result = 0;
@@ -94,7 +93,6 @@ __gai_notify_only (struct sigevent *sigev, pid_t caller_pid)
void
-internal_function
__gai_notify (struct requestlist *req)
{
struct waitlist *waitlist;
diff --git a/resolv/gai_sigqueue.c b/resolv/gai_sigqueue.c
index 4b0c08f6e5..f087e1cefa 100644
--- a/resolv/gai_sigqueue.c
+++ b/resolv/gai_sigqueue.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/resolv/gai_suspend.c b/resolv/gai_suspend.c
index accb8704c1..1da7108118 100644
--- a/resolv/gai_suspend.c
+++ b/resolv/gai_suspend.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
@@ -141,7 +141,7 @@ gai_suspend (const struct gaicb *const list[], int ent,
/* An error occurred. Possibly it's EINTR. We have to translate
the timeout error report of `pthread_cond_timedwait' to the
form expected from `gai_suspend'. */
- if (__builtin_expect (result, ETIMEDOUT) == ETIMEDOUT)
+ if (__glibc_likely (result == ETIMEDOUT))
result = EAI_AGAIN;
else if (result == EINTR)
result = EAI_INTR;
diff --git a/resolv/getaddrinfo_a.c b/resolv/getaddrinfo_a.c
index 4d147e6935..60e3140553 100644
--- a/resolv/getaddrinfo_a.c
+++ b/resolv/getaddrinfo_a.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2001-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
diff --git a/resolv/herror.c b/resolv/herror.c
index 0aaf29f9db..45c0a5dbda 100644
--- a/resolv/herror.c
+++ b/resolv/herror.c
@@ -44,11 +44,6 @@
* SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$BINDId: herror.c,v 8.11 1999/10/13 16:39:39 vixie Exp $";
-#endif /* LIBC_SCCS and not lint */
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/uio.h>
@@ -85,16 +80,16 @@ herror(const char *s) {
v->iov_base = (/*noconst*/ char *)s;
v->iov_len = strlen(s);
v++;
- v->iov_base = ": ";
+ v->iov_base = (char *) ": ";
v->iov_len = 2;
v++;
}
v->iov_base = (char *)hstrerror(h_errno);
v->iov_len = strlen(v->iov_base);
v++;
- v->iov_base = "\n";
+ v->iov_base = (char *) "\n";
v->iov_len = 1;
- writev_not_cancel_no_status(STDERR_FILENO, iov, (v - iov) + 1);
+ __writev_nocancel_nostatus(STDERR_FILENO, iov, (v - iov) + 1);
}
/*
diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c
index ee42093754..022f7ea084 100644
--- a/resolv/inet_addr.c
+++ b/resolv/inet_addr.c
@@ -64,11 +64,6 @@
* SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
-static const char rcsid[] = "$BINDId: inet_addr.c,v 8.11 1999/10/13 16:39:25 vixie Exp $";
-#endif /* LIBC_SCCS and not lint */
-
#include <sys/types.h>
#include <sys/param.h>
@@ -77,13 +72,11 @@ static const char rcsid[] = "$BINDId: inet_addr.c,v 8.11 1999/10/13 16:39:25 vix
#include <ctype.h>
-#ifdef _LIBC
-# include <endian.h>
-# include <stdint.h>
-# include <stdlib.h>
-# include <limits.h>
-# include <errno.h>
-#endif
+#include <endian.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <errno.h>
/*
* Ascii internet address interpretation routine.
@@ -111,9 +104,6 @@ __inet_aton(const char *cp, struct in_addr *addr)
{
static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
in_addr_t val;
-#ifndef _LIBC
- int base;
-#endif
char c;
union iaddr {
uint8_t bytes[4];
@@ -122,10 +112,8 @@ __inet_aton(const char *cp, struct in_addr *addr)
uint8_t *pp = res.bytes;
int digit;
-#ifdef _LIBC
int saved_errno = errno;
__set_errno (0);
-#endif
res.word = 0;
@@ -138,7 +126,6 @@ __inet_aton(const char *cp, struct in_addr *addr)
*/
if (!isdigit(c))
goto ret_0;
-#ifdef _LIBC
{
char *endp;
unsigned long ul = strtoul (cp, (char **) &endp, 0);
@@ -151,33 +138,6 @@ __inet_aton(const char *cp, struct in_addr *addr)
cp = endp;
}
c = *cp;
-#else
- val = 0; base = 10; digit = 0;
- if (c == '0') {
- c = *++cp;
- if (c == 'x' || c == 'X')
- base = 16, c = *++cp;
- else {
- base = 8;
- digit = 1 ;
- }
- }
- for (;;) {
- if (isascii(c) && isdigit(c)) {
- if (base == 8 && (c == '8' || c == '9'))
- return (0);
- val = (val * base) + (c - '0');
- c = *++cp;
- digit = 1;
- } else if (base == 16 && isascii(c) && isxdigit(c)) {
- val = (val << 4) |
- (c + 10 - (islower(c) ? 'a' : 'A'));
- c = *++cp;
- digit = 1;
- } else
- break;
- }
-#endif
if (c == '.') {
/*
* Internet format:
@@ -211,15 +171,11 @@ __inet_aton(const char *cp, struct in_addr *addr)
if (addr != NULL)
addr->s_addr = res.word | htonl (val);
-#ifdef _LIBC
__set_errno (saved_errno);
-#endif
return (1);
ret_0:
-#ifdef _LIBC
__set_errno (saved_errno);
-#endif
return (0);
}
weak_alias (__inet_aton, inet_aton)
diff --git a/resolv/inet_net_ntop.c b/resolv/inet_net_ntop.c
index 2d57ae3030..aaa78f664b 100644
--- a/resolv/inet_net_ntop.c
+++ b/resolv/inet_net_ntop.c
@@ -15,10 +15,6 @@
* SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$BINDId: inet_net_ntop.c,v 1.6 1999/01/08 19:23:42 vixie Exp $";
-#endif
-
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
diff --git a/resolv/inet_net_pton.c b/resolv/inet_net_pton.c
index 75a8515c15..aab9b7b582 100644
--- a/resolv/inet_net_pton.c
+++ b/resolv/inet_net_pton.c
@@ -15,10 +15,6 @@
* SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$BINDId: inet_net_pton.c,v 1.11 1999/01/08 19:23:44 vixie Exp $";
-#endif
-
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
diff --git a/resolv/inet_neta.c b/resolv/inet_neta.c
index b9f256b9e5..f26932cdee 100644
--- a/resolv/inet_neta.c
+++ b/resolv/inet_neta.c
@@ -15,10 +15,6 @@
* SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$BINDId: inet_neta.c,v 1.6 1999/01/08 19:23:45 vixie Exp $";
-#endif
-
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
@@ -46,7 +42,7 @@ static const char rcsid[] = "$BINDId: inet_neta.c,v 1.6 1999/01/08 19:23:45 vixi
* Paul Vixie (ISC), July 1996
*/
char *
-inet_neta (u_int32_t src, char *dst, size_t size)
+inet_neta (uint32_t src, char *dst, size_t size)
{
char *odst = dst;
char *tp;
diff --git a/resolv/inet_ntop.c b/resolv/inet_ntop.c
index 32338c58b0..c4d38c0f95 100644
--- a/resolv/inet_ntop.c
+++ b/resolv/inet_ntop.c
@@ -15,10 +15,6 @@
* SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$BINDId: inet_ntop.c,v 1.8 1999/10/13 16:39:28 vixie Exp $";
-#endif /* LIBC_SCCS and not lint */
-
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
@@ -42,10 +38,8 @@ static const char rcsid[] = "$BINDId: inet_ntop.c,v 1.8 1999/10/13 16:39:28 vixi
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
*/
-static const char *inet_ntop4 (const u_char *src, char *dst, socklen_t size)
- internal_function;
-static const char *inet_ntop6 (const u_char *src, char *dst, socklen_t size)
- internal_function;
+static const char *inet_ntop4 (const u_char *src, char *dst, socklen_t size);
+static const char *inet_ntop6 (const u_char *src, char *dst, socklen_t size);
/* char *
* inet_ntop(af, src, dst, size)
@@ -83,7 +77,6 @@ libc_hidden_def (inet_ntop)
* Paul Vixie, 1996.
*/
static const char *
-internal_function
inet_ntop4 (const u_char *src, char *dst, socklen_t size)
{
static const char fmt[] = "%u.%u.%u.%u";
@@ -103,7 +96,6 @@ inet_ntop4 (const u_char *src, char *dst, socklen_t size)
* Paul Vixie, 1996.
*/
static const char *
-internal_function
inet_ntop6 (const u_char *src, char *dst, socklen_t size)
{
/*
diff --git a/resolv/inet_pton.c b/resolv/inet_pton.c
index 0d18e9acb5..9cb21f9f82 100644
--- a/resolv/inet_pton.c
+++ b/resolv/inet_pton.c
@@ -1,3 +1,20 @@
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
/*
* Copyright (c) 1996,1999 by Internet Software Consortium.
*
@@ -15,202 +32,203 @@
* SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$BINDId: inet_pton.c,v 1.7 1999/10/13 16:39:28 vixie Exp $";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/param.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
#include <ctype.h>
-#include <string.h>
#include <errno.h>
+#include <netinet/in.h>
+#include <resolv/resolv-internal.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
-/*
- * WARNING: Don't even consider trying to compile this on a system where
- * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
- */
+static int inet_pton4 (const char *src, const char *src_end, u_char *dst);
+static int inet_pton6 (const char *src, const char *src_end, u_char *dst);
-static int inet_pton4 (const char *src, u_char *dst) internal_function;
-static int inet_pton6 (const char *src, u_char *dst) internal_function;
-
-/* int
- * inet_pton(af, src, dst)
- * convert from presentation format (which usually means ASCII printable)
- * to network format (which is usually some kind of binary format).
- * return:
- * 1 if the address was valid for the specified address family
- * 0 if the address wasn't valid (`dst' is untouched in this case)
- * -1 if some other error occurred (`dst' is untouched in this case, too)
- * author:
- * Paul Vixie, 1996.
- */
+int
+__inet_pton_length (int af, const char *src, size_t srclen, void *dst)
+{
+ switch (af)
+ {
+ case AF_INET:
+ return inet_pton4 (src, src + srclen, dst);
+ case AF_INET6:
+ return inet_pton6 (src, src + srclen, dst);
+ default:
+ __set_errno (EAFNOSUPPORT);
+ return -1;
+ }
+}
+libc_hidden_def (__inet_pton_length)
+
+/* Like __inet_pton_length, but use strlen (SRC) as the length of
+ SRC. */
int
__inet_pton (int af, const char *src, void *dst)
{
- switch (af) {
- case AF_INET:
- return (inet_pton4(src, dst));
- case AF_INET6:
- return (inet_pton6(src, dst));
- default:
- __set_errno (EAFNOSUPPORT);
- return (-1);
- }
- /* NOTREACHED */
+ return __inet_pton_length (af, src, strlen (src), dst);
}
libc_hidden_def (__inet_pton)
weak_alias (__inet_pton, inet_pton)
libc_hidden_weak (inet_pton)
-/* int
- * inet_pton4(src, dst)
- * like inet_aton() but without all the hexadecimal, octal (with the
- * exception of 0) and shorthand.
- * return:
- * 1 if `src' is a valid dotted quad, else 0.
- * notice:
- * does not touch `dst' unless it's returning 1.
- * author:
- * Paul Vixie, 1996.
- */
+/* Like inet_aton but without all the hexadecimal, octal and shorthand
+ (and trailing garbage is not ignored). Return 1 if SRC is a valid
+ dotted quad, else 0. This function does not touch DST unless it's
+ returning 1.
+ Author: Paul Vixie, 1996. */
static int
-internal_function
-inet_pton4 (const char *src, u_char *dst)
+inet_pton4 (const char *src, const char *end, unsigned char *dst)
{
- int saw_digit, octets, ch;
- u_char tmp[NS_INADDRSZ], *tp;
-
- saw_digit = 0;
- octets = 0;
- *(tp = tmp) = 0;
- while ((ch = *src++) != '\0') {
-
- if (ch >= '0' && ch <= '9') {
- u_int new = *tp * 10 + (ch - '0');
-
- if (saw_digit && *tp == 0)
- return (0);
- if (new > 255)
- return (0);
- *tp = new;
- if (! saw_digit) {
- if (++octets > 4)
- return (0);
- saw_digit = 1;
- }
- } else if (ch == '.' && saw_digit) {
- if (octets == 4)
- return (0);
- *++tp = 0;
- saw_digit = 0;
- } else
- return (0);
- }
- if (octets < 4)
- return (0);
- memcpy(dst, tmp, NS_INADDRSZ);
- return (1);
+ int saw_digit, octets, ch;
+ unsigned char tmp[NS_INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while (src < end)
+ {
+ ch = *src++;
+ if (ch >= '0' && ch <= '9')
+ {
+ unsigned int new = *tp * 10 + (ch - '0');
+
+ if (saw_digit && *tp == 0)
+ return 0;
+ if (new > 255)
+ return 0;
+ *tp = new;
+ if (! saw_digit)
+ {
+ if (++octets > 4)
+ return 0;
+ saw_digit = 1;
+ }
+ }
+ else if (ch == '.' && saw_digit)
+ {
+ if (octets == 4)
+ return 0;
+ *++tp = 0;
+ saw_digit = 0;
+ }
+ else
+ return 0;
+ }
+ if (octets < 4)
+ return 0;
+ memcpy (dst, tmp, NS_INADDRSZ);
+ return 1;
}
-/* int
- * inet_pton6(src, dst)
- * convert presentation level address to network order binary form.
- * return:
- * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
- * notice:
- * (1) does not touch `dst' unless it's returning 1.
- * (2) :: in a full address is silently ignored.
- * credit:
- * inspired by Mark Andrews.
- * author:
- * Paul Vixie, 1996.
- */
+/* Return the value of CH as a hexademical digit, or -1 if it is a
+ different type of character. */
+static int
+hex_digit_value (char ch)
+{
+ if ('0' <= ch && ch <= '9')
+ return ch - '0';
+ if ('a' <= ch && ch <= 'f')
+ return ch - 'a' + 10;
+ if ('A' <= ch && ch <= 'F')
+ return ch - 'A' + 10;
+ return -1;
+}
+
+/* Convert presentation-level IPv6 address to network order binary
+ form. Return 1 if SRC is a valid [RFC1884 2.2] address, else 0.
+ This function does not touch DST unless it's returning 1.
+ Author: Paul Vixie, 1996. Inspired by Mark Andrews. */
static int
-internal_function
-inet_pton6 (const char *src, u_char *dst)
+inet_pton6 (const char *src, const char *src_endp, unsigned char *dst)
{
- static const char xdigits[] = "0123456789abcdef";
- u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
- const char *curtok;
- int ch, saw_xdigit;
- u_int val;
-
- tp = memset(tmp, '\0', NS_IN6ADDRSZ);
- endp = tp + NS_IN6ADDRSZ;
- colonp = NULL;
- /* Leading :: requires some special handling. */
- if (*src == ':')
- if (*++src != ':')
- return (0);
- curtok = src;
- saw_xdigit = 0;
- val = 0;
- while ((ch = tolower (*src++)) != '\0') {
- const char *pch;
-
- pch = strchr(xdigits, ch);
- if (pch != NULL) {
- val <<= 4;
- val |= (pch - xdigits);
- if (val > 0xffff)
- return (0);
- saw_xdigit = 1;
- continue;
- }
- if (ch == ':') {
- curtok = src;
- if (!saw_xdigit) {
- if (colonp)
- return (0);
- colonp = tp;
- continue;
- } else if (*src == '\0') {
- return (0);
- }
- if (tp + NS_INT16SZ > endp)
- return (0);
- *tp++ = (u_char) (val >> 8) & 0xff;
- *tp++ = (u_char) val & 0xff;
- saw_xdigit = 0;
- val = 0;
- continue;
- }
- if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
- inet_pton4(curtok, tp) > 0) {
- tp += NS_INADDRSZ;
- saw_xdigit = 0;
- break; /* '\0' was seen by inet_pton4(). */
- }
- return (0);
+ unsigned char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *curtok;
+ int ch;
+ size_t xdigits_seen; /* Number of hex digits since colon. */
+ unsigned int val;
+
+ tp = memset (tmp, '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+
+ /* Leading :: requires some special handling. */
+ if (src == src_endp)
+ return 0;
+ if (*src == ':')
+ {
+ ++src;
+ if (src == src_endp || *src != ':')
+ return 0;
+ }
+
+ curtok = src;
+ xdigits_seen = 0;
+ val = 0;
+ while (src < src_endp)
+ {
+ ch = *src++;
+ int digit = hex_digit_value (ch);
+ if (digit >= 0)
+ {
+ if (xdigits_seen == 4)
+ return 0;
+ val <<= 4;
+ val |= digit;
+ if (val > 0xffff)
+ return 0;
+ ++xdigits_seen;
+ continue;
}
- if (saw_xdigit) {
- if (tp + NS_INT16SZ > endp)
- return (0);
- *tp++ = (u_char) (val >> 8) & 0xff;
- *tp++ = (u_char) val & 0xff;
+ if (ch == ':')
+ {
+ curtok = src;
+ if (xdigits_seen == 0)
+ {
+ if (colonp)
+ return 0;
+ colonp = tp;
+ continue;
+ }
+ else if (src == src_endp)
+ return 0;
+ if (tp + NS_INT16SZ > endp)
+ return 0;
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ xdigits_seen = 0;
+ val = 0;
+ continue;
}
- if (colonp != NULL) {
- /*
- * Since some memmove()'s erroneously fail to handle
- * overlapping regions, we'll do the shift by hand.
- */
- const int n = tp - colonp;
- int i;
-
- if (tp == endp)
- return (0);
- for (i = 1; i <= n; i++) {
- endp[- i] = colonp[n - i];
- colonp[n - i] = 0;
- }
- tp = endp;
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp)
+ && inet_pton4 (curtok, src_endp, tp) > 0)
+ {
+ tp += NS_INADDRSZ;
+ xdigits_seen = 0;
+ break; /* '\0' was seen by inet_pton4. */
}
- if (tp != endp)
- return (0);
- memcpy(dst, tmp, NS_IN6ADDRSZ);
- return (1);
+ return 0;
+ }
+ if (xdigits_seen > 0)
+ {
+ if (tp + NS_INT16SZ > endp)
+ return 0;
+ *tp++ = (unsigned char) (val >> 8) & 0xff;
+ *tp++ = (unsigned char) val & 0xff;
+ }
+ if (colonp != NULL)
+ {
+ /* Replace :: with zeros. */
+ if (tp == endp)
+ /* :: would expand to a zero-width field. */
+ return 0;
+ size_t n = tp - colonp;
+ memmove (endp - n, colonp, n);
+ memset (colonp, 0, endp - n - colonp);
+ tp = endp;
+ }
+ if (tp != endp)
+ return 0;
+ memcpy (dst, tmp, NS_IN6ADDRSZ);
+ return 1;
}
diff --git a/resolv/netdb.h b/resolv/netdb.h
index 3aba530932..003800e882 100644
--- a/resolv/netdb.h
+++ b/resolv/netdb.h
@@ -1,4 +1,4 @@
- /* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+ /* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -25,7 +25,7 @@
#include <features.h>
#include <netinet/in.h>
-#include <stdint.h>
+#include <bits/stdint-uintn.h>
#ifdef __USE_MISC
/* This is necessary to make this include file properly replace the
Sun version. */
@@ -33,10 +33,8 @@
#endif
#ifdef __USE_GNU
-# define __need_sigevent_t
-# include <bits/siginfo.h>
-# define __need_timespec
-# include <time.h>
+# include <bits/types/sigevent_t.h>
+# include <bits/types/struct_timespec.h>
#endif
#include <bits/netdb.h>
@@ -607,10 +605,10 @@ struct gaicb
in the current locale's character set)
before looking it up. */
# define AI_CANONIDN 0x0080 /* Translate canonical name from IDN format. */
-# define AI_IDN_ALLOW_UNASSIGNED 0x0100 /* Don't reject unassigned Unicode
- code points. */
-# define AI_IDN_USE_STD3_ASCII_RULES 0x0200 /* Validate strings according to
- STD3 rules. */
+# define AI_IDN_ALLOW_UNASSIGNED \
+ __glibc_macro_warning ("AI_IDN_ALLOW_UNASSIGNED is deprecated") 0x0100
+# define AI_IDN_USE_STD3_ASCII_RULES \
+ __glibc_macro_warning ("AI_IDN_USE_STD3_ASCII_RULES is deprecated") 0x0200
# endif
# define AI_NUMERICSERV 0x0400 /* Don't use name resolution. */
@@ -648,10 +646,10 @@ struct gaicb
# define NI_DGRAM 16 /* Look up UDP service rather than TCP. */
# ifdef __USE_GNU
# define NI_IDN 32 /* Convert name from IDN format. */
-# define NI_IDN_ALLOW_UNASSIGNED 64 /* Don't reject unassigned Unicode
- code points. */
-# define NI_IDN_USE_STD3_ASCII_RULES 128 /* Validate strings according to
- STD3 rules. */
+# define NI_IDN_ALLOW_UNASSIGNED \
+ __glibc_macro_warning ("NI_IDN_ALLOW_UNASSIGNED is deprecated") 64
+# define NI_IDN_USE_STD3_ASCII_RULES \
+ __glibc_macro_warning ("NI_IDN_USE_STD3_ASCII_RULES is deprecated") 128
# endif
/* Translate name of a service location and/or a service name to set of
diff --git a/resolv/ns_date.c b/resolv/ns_date.c
index 9801ac46d4..8e94d1c4e8 100644
--- a/resolv/ns_date.c
+++ b/resolv/ns_date.c
@@ -15,10 +15,6 @@
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#if !defined(_LIBC) && !defined(lint)
-static const char rcsid[] = "$Id$";
-#endif
-
/* Import. */
#include <arpa/nameser.h>
@@ -43,10 +39,10 @@ static int datepart(const char *, int, int, int, int *);
* digits required, no spaces allowed.
*/
-u_int32_t
+uint32_t
ns_datetosecs(const char *cp, int *errp) {
struct tm time;
- u_int32_t result;
+ uint32_t result;
int mdays, i;
static const int days_per_month[12] =
{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
@@ -72,7 +68,7 @@ ns_datetosecs(const char *cp, int *errp) {
* we will do it by hand. Roll up sleeves, curse the gods, begin!
*/
-#define SECS_PER_DAY ((u_int32_t)24*60*60)
+#define SECS_PER_DAY ((uint32_t)24*60*60)
#define isleap(y) ((((y) % 4) == 0 && ((y) % 100) != 0) || ((y) % 400) == 0)
result = time.tm_sec; /*%< Seconds */
diff --git a/resolv/ns_name.c b/resolv/ns_name.c
index f355cf3444..73213fee2d 100644
--- a/resolv/ns_name.c
+++ b/resolv/ns_name.c
@@ -15,10 +15,6 @@
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#if !defined(_LIBC) && !defined(lint)
-static const char rcsid[] = "$BINDId: ns_name.c,v 8.15 2000/03/30 22:53:46 vixie Exp $";
-#endif
-
#include <sys/types.h>
#include <netinet/in.h>
@@ -33,32 +29,10 @@ static const char rcsid[] = "$BINDId: ns_name.c,v 8.15 2000/03/30 22:53:46 vixie
# define SPRINTF(x) ((size_t)sprintf x)
-#define NS_TYPE_ELT 0x40 /*%< EDNS0 extended label type */
-#define DNS_LABELTYPE_BITSTRING 0x41
-
/* Data. */
static const char digits[] = "0123456789";
-static const char digitvalue[256] = {
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
- 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
- -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
- -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
-};
-
/* Forward. */
static int special(int);
@@ -66,12 +40,7 @@ static int printable(int);
static int dn_find(const u_char *, const u_char *,
const u_char * const *,
const u_char * const *);
-static int encode_bitstring(const char **, const char *,
- unsigned char **, unsigned char **,
- unsigned const char *);
static int labellen(const u_char *);
-static int decode_bitstring(const unsigned char **,
- char *, const char *);
/* Public. */
@@ -119,22 +88,6 @@ ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
__set_errno (EMSGSIZE);
return (-1);
}
- if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
- int m;
-
- if (n != DNS_LABELTYPE_BITSTRING) {
- /* XXX: labellen should reject this case */
- __set_errno (EINVAL);
- return(-1);
- }
- if ((m = decode_bitstring(&cp, dn, eom)) < 0)
- {
- __set_errno (EMSGSIZE);
- return(-1);
- }
- dn += m;
- continue;
- }
for ((void)NULL; l > 0; l--) {
c = *cp++;
if (special(c)) {
@@ -196,7 +149,7 @@ int
ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
{
u_char *label, *bp, *eom;
- int c, n, escaped, e = 0;
+ int c, n, escaped;
char *cp;
escaped = 0;
@@ -206,28 +159,7 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
while ((c = *src++) != 0) {
if (escaped) {
- if (c == '[') { /*%< start a bit string label */
- if ((cp = strchr(src, ']')) == NULL) {
- __set_errno (EINVAL);
- return(-1);
- }
- if ((e = encode_bitstring(&src, cp + 2,
- &label, &bp, eom))
- != 0) {
- __set_errno (e);
- return(-1);
- }
- escaped = 0;
- label = bp++;
- if ((c = *src++) == 0)
- goto done;
- else if (c != '.') {
- __set_errno (EINVAL);
- return(-1);
- }
- continue;
- }
- else if ((cp = strchr(digits, c)) != NULL) {
+ if ((cp = strchr(digits, c)) != NULL) {
n = (cp - digits) * 100;
if ((c = *src++) == 0 ||
(cp = strchr(digits, c)) == NULL) {
@@ -290,12 +222,16 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
}
*bp++ = (u_char)c;
}
+ if (escaped) {
+ /* Trailing backslash. */
+ __set_errno (EMSGSIZE);
+ return -1;
+ }
c = (bp - label - 1);
if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */
__set_errno (EMSGSIZE);
return (-1);
}
- done:
if (label >= eom) {
__set_errno (EMSGSIZE);
return (-1);
@@ -398,7 +334,6 @@ ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
/* Check for indirection. */
switch (n & NS_CMPRSFLGS) {
case 0:
- case NS_TYPE_ELT:
/* Limit checks. */
if ((l = labellen(srcp - 1)) < 0) {
__set_errno (EMSGSIZE);
@@ -545,7 +480,7 @@ ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
goto cleanup;
}
n = labellen(srcp);
- if (dstp + 1 + n >= eob) {
+ if (n + 1 > eob - dstp) {
goto cleanup;
}
memcpy(dstp, srcp, n + 1);
@@ -643,7 +578,6 @@ ns_name_skip(const u_char **ptrptr, const u_char *eom)
{
const u_char *cp;
u_int n;
- int l;
cp = *ptrptr;
while (cp < eom && (n = *cp++) != 0) {
@@ -652,13 +586,6 @@ ns_name_skip(const u_char **ptrptr, const u_char *eom)
case 0: /*%< normal case, n == len */
cp += n;
continue;
- case NS_TYPE_ELT: /*%< EDNS0 extended label */
- if ((l = labellen(cp - 1)) < 0) {
- __set_errno (EMSGSIZE);
- return(-1);
- }
- cp += l;
- continue;
case NS_CMPRSFLGS: /*%< indirection */
cp++;
break;
@@ -795,180 +722,14 @@ dn_find(const u_char *domain, const u_char *msg,
return (-1);
}
+/* Return the length of the encoded label starting at LP, or -1 for
+ compression references and extended label types. */
static int
-decode_bitstring(const unsigned char **cpp, char *dn, const char *eom)
-{
- const unsigned char *cp = *cpp;
- char *beg = dn, tc;
- int b, blen, plen, i;
-
- if ((blen = (*cp & 0xff)) == 0)
- blen = 256;
- plen = (blen + 3) / 4;
- plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
- if (dn + plen >= eom)
- return(-1);
-
- cp++;
- i = SPRINTF((dn, "\\[x"));
- if (i < 0)
- return (-1);
- dn += i;
- for (b = blen; b > 7; b -= 8, cp++) {
- i = SPRINTF((dn, "%02x", *cp & 0xff));
- if (i < 0)
- return (-1);
- dn += i;
- }
- if (b > 4) {
- tc = *cp++;
- i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b))));
- if (i < 0)
- return (-1);
- dn += i;
- } else if (b > 0) {
- tc = *cp++;
- i = SPRINTF((dn, "%1x",
- ((tc >> 4) & 0x0f) & (0x0f << (4 - b))));
- if (i < 0)
- return (-1);
- dn += i;
- }
- i = SPRINTF((dn, "/%d]", blen));
- if (i < 0)
- return (-1);
- dn += i;
-
- *cpp = cp;
- return(dn - beg);
-}
-
-static int
-encode_bitstring(const char **bp, const char *end, unsigned char **labelp,
- unsigned char ** dst, unsigned const char *eom)
+labellen (const unsigned char *lp)
{
- int afterslash = 0;
- const char *cp = *bp;
- unsigned char *tp;
- char c;
- const char *beg_blen;
- char *end_blen = NULL;
- int value = 0, count = 0, tbcount = 0, blen = 0;
-
- beg_blen = end_blen = NULL;
-
- /* a bitstring must contain at least 2 characters */
- if (end - cp < 2)
- return(EINVAL);
-
- /* XXX: currently, only hex strings are supported */
- if (*cp++ != 'x')
- return(EINVAL);
- if (!isxdigit((*cp) & 0xff)) /*%< reject '\[x/BLEN]' */
- return(EINVAL);
-
- for (tp = *dst + 1; cp < end && tp < eom; cp++) {
- switch((c = *cp)) {
- case ']': /*%< end of the bitstring */
- if (afterslash) {
- if (beg_blen == NULL)
- return(EINVAL);
- blen = (int)strtol(beg_blen, &end_blen, 10);
- if (*end_blen != ']')
- return(EINVAL);
- }
- if (count)
- *tp++ = ((value << 4) & 0xff);
- cp++; /*%< skip ']' */
- goto done;
- case '/':
- afterslash = 1;
- break;
- default:
- if (afterslash) {
- if (!isdigit(c&0xff))
- return(EINVAL);
- if (beg_blen == NULL) {
-
- if (c == '0') {
- /* blen never begings with 0 */
- return(EINVAL);
- }
- beg_blen = cp;
- }
- } else {
- if (!isxdigit(c&0xff))
- return(EINVAL);
- value <<= 4;
- value += digitvalue[(int)c];
- count += 4;
- tbcount += 4;
- if (tbcount > 256)
- return(EINVAL);
- if (count == 8) {
- *tp++ = value;
- count = 0;
- }
- }
- break;
- }
- }
- done:
- if (cp >= end || tp >= eom)
- return(EMSGSIZE);
-
- /*
- * bit length validation:
- * If a <length> is present, the number of digits in the <bit-data>
- * MUST be just sufficient to contain the number of bits specified
- * by the <length>. If there are insignificant bits in a final
- * hexadecimal or octal digit, they MUST be zero.
- * RFC2673, Section 3.2.
- */
- if (blen > 0) {
- int traillen;
-
- if (((blen + 3) & ~3) != tbcount)
- return(EINVAL);
- traillen = tbcount - blen; /*%< between 0 and 3 */
- if (((value << (8 - traillen)) & 0xff) != 0)
- return(EINVAL);
- }
- else
- blen = tbcount;
- if (blen == 256)
- blen = 0;
-
- /* encode the type and the significant bit fields */
- **labelp = DNS_LABELTYPE_BITSTRING;
- **dst = blen;
-
- *bp = cp;
- *dst = tp;
-
- return(0);
-}
-
-static int
-labellen(const u_char *lp)
-{
- int bitlen;
- u_char l = *lp;
-
- if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
- /* should be avoided by the caller */
- return(-1);
- }
-
- if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
- if (l == DNS_LABELTYPE_BITSTRING) {
- if ((bitlen = *(lp + 1)) == 0)
- bitlen = 256;
- return((bitlen + 7 ) / 8 + 1);
- }
- return(-1); /*%< unknwon ELT */
- }
- return(l);
+ if (*lp <= 63)
+ return *lp;
+ return -1;
}
/*! \file */
diff --git a/resolv/ns_netint.c b/resolv/ns_netint.c
index 4318f18879..6a365a3b8c 100644
--- a/resolv/ns_netint.c
+++ b/resolv/ns_netint.c
@@ -15,10 +15,6 @@
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#if !defined(_LIBC) && !defined(lint)
-static const char rcsid[] = "$BINDId: ns_netint.c,v 8.4 1999/10/13 16:39:35 vixie Exp $";
-#endif
-
/* Import. */
#include <arpa/nameser.h>
diff --git a/resolv/ns_parse.c b/resolv/ns_parse.c
index 712469be1d..863b20a9f7 100644
--- a/resolv/ns_parse.c
+++ b/resolv/ns_parse.c
@@ -15,10 +15,6 @@
* OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#if !defined(_LIBC) && !defined(lint)
-static const char rcsid[] = "$BINDId: ns_parse.c,v 8.13 1999/10/13 16:39:35 vixie Exp $";
-#endif
-
/* Import. */
#include <sys/types.h>
diff --git a/resolv/ns_print.c b/resolv/ns_print.c
index 800680d371..d61f5044b1 100644
--- a/resolv/ns_print.c
+++ b/resolv/ns_print.c
@@ -16,10 +16,6 @@
* SOFTWARE.
*/
-#if !defined(_LIBC) && !defined(lint)
-static const char rcsid[] = "$BINDId: ns_print.c,v 8.18 2000/02/29 05:48:12 vixie Exp $";
-#endif
-
/* Import. */
#include <sys/types.h>
@@ -51,8 +47,6 @@ static int addstr(const char *src, size_t len,
static int addtab(size_t len, size_t target, int spaced,
char **buf, size_t *buflen);
-static u_int16_t dst_s_dns_key_id(const u_char *, const int);
-
/* Macros. */
#define T(x) \
@@ -440,124 +434,6 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
break;
}
- case ns_t_key: {
- char base64_key[NS_MD5RSA_MAX_BASE64];
- u_int keyflags, protocol, algorithm, key_id;
- const char *leader;
- int n;
-
- if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
- goto formerr;
-
- /* Key flags, Protocol, Algorithm. */
- key_id = dst_s_dns_key_id(rdata, edata-rdata);
- keyflags = ns_get16(rdata); rdata += NS_INT16SZ;
- protocol = *rdata++;
- algorithm = *rdata++;
- len = SPRINTF((tmp, "0x%04x %u %u",
- keyflags, protocol, algorithm));
- T(addstr(tmp, len, &buf, &buflen));
-
- /* Public key data. */
- len = b64_ntop(rdata, edata - rdata,
- base64_key, sizeof base64_key);
- if (len < 0)
- goto formerr;
- if (len > 15) {
- T(addstr(" (", 2, &buf, &buflen));
- leader = "\n\t\t";
- spaced = 0;
- } else
- leader = " ";
- for (n = 0; n < len; n += 48) {
- T(addstr(leader, strlen(leader), &buf, &buflen));
- T(addstr(base64_key + n, MIN(len - n, 48),
- &buf, &buflen));
- }
- if (len > 15)
- T(addstr(" )", 2, &buf, &buflen));
- n = SPRINTF((tmp, " ; key_tag= %u", key_id));
- T(addstr(tmp, n, &buf, &buflen));
-
- break;
- }
-
- case ns_t_sig: {
- char base64_key[NS_MD5RSA_MAX_BASE64];
- u_int type, algorithm, labels, footprint;
- const char *leader;
- u_long t;
- int n;
-
- if (rdlen < 22U)
- goto formerr;
-
- /* Type covered, Algorithm, Label count, Original TTL. */
- type = ns_get16(rdata); rdata += NS_INT16SZ;
- algorithm = *rdata++;
- labels = *rdata++;
- t = ns_get32(rdata); rdata += NS_INT32SZ;
- len = SPRINTF((tmp, "%s %d %d %lu ",
- p_type(type), algorithm, labels, t));
- T(addstr(tmp, len, &buf, &buflen));
- if (labels > (u_int)dn_count_labels(name))
- goto formerr;
-
- /* Signature expiry. */
- t = ns_get32(rdata); rdata += NS_INT32SZ;
- len = SPRINTF((tmp, "%s ", p_secstodate(t)));
- T(addstr(tmp, len, &buf, &buflen));
-
- /* Time signed. */
- t = ns_get32(rdata); rdata += NS_INT32SZ;
- len = SPRINTF((tmp, "%s ", p_secstodate(t)));
- T(addstr(tmp, len, &buf, &buflen));
-
- /* Signature Footprint. */
- footprint = ns_get16(rdata); rdata += NS_INT16SZ;
- len = SPRINTF((tmp, "%u ", footprint));
- T(addstr(tmp, len, &buf, &buflen));
-
- /* Signer's name. */
- T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
-
- /* Signature. */
- len = b64_ntop(rdata, edata - rdata,
- base64_key, sizeof base64_key);
- if (len > 15) {
- T(addstr(" (", 2, &buf, &buflen));
- leader = "\n\t\t";
- spaced = 0;
- } else
- leader = " ";
- if (len < 0)
- goto formerr;
- for (n = 0; n < len; n += 48) {
- T(addstr(leader, strlen(leader), &buf, &buflen));
- T(addstr(base64_key + n, MIN(len - n, 48),
- &buf, &buflen));
- }
- if (len > 15)
- T(addstr(" )", 2, &buf, &buflen));
- break;
- }
-
- case ns_t_nxt: {
- int n, c;
-
- /* Next domain name. */
- T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
-
- /* Type bit map. */
- n = edata - rdata;
- for (c = 0; c < n*8; c++)
- if (NS_NXT_BIT_ISSET(c, rdata)) {
- len = SPRINTF((tmp, " %s", p_type(c)));
- T(addstr(tmp, len, &buf, &buflen));
- }
- break;
- }
-
case ns_t_cert: {
u_int c_type, key_tag, alg;
int n;
@@ -612,12 +488,12 @@ ns_sprintrrf(const u_char *msg, size_t msglen,
/* Inception. */
t = ns_get32(rdata); rdata += NS_INT32SZ;
- len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ len = SPRINTF((tmp, "%lu ", t));
T(addstr(tmp, len, &buf, &buflen));
/* Experation. */
t = ns_get32(rdata); rdata += NS_INT32SZ;
- len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ len = SPRINTF((tmp, "%lu ", t));
T(addstr(tmp, len, &buf, &buflen));
/* Mode , Error, Key Size. */
@@ -891,81 +767,3 @@ addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
}
return (spaced);
}
-
-/* DST algorithm codes */
-#define KEY_RSA 1
-#define KEY_HMAC_MD5 157
-
-/*%
- * calculates a checksum used in dst for an id.
- * takes an array of bytes and a length.
- * returns a 16 bit checksum.
- */
-static u_int16_t
-dst_s_id_calc(const u_char *key, const int keysize)
-{
- u_int32_t ac;
- const u_char *kp = key;
- int size = keysize;
-
- if (!key || (keysize <= 0))
- return (0xffffU);
-
- for (ac = 0; size > 1; size -= 2, kp += 2)
- ac += ((*kp) << 8) + *(kp + 1);
-
- if (size > 0)
- ac += ((*kp) << 8);
- ac += (ac >> 16) & 0xffff;
-
- return (ac & 0xffff);
-}
-
-/*%
- * dst_s_get_int16
- * This routine extracts a 16 bit integer from a two byte character
- * string. The character string is assumed to be in network byte
- * order and may be unaligned. The number returned is in host order.
- * Parameter
- * buf A two byte character string.
- * Return
- * The converted integer value.
- */
-
-static u_int16_t
-dst_s_get_int16(const u_char *buf)
-{
- u_int16_t a = 0;
- a = ((u_int16_t)(buf[0] << 8)) | ((u_int16_t)(buf[1]));
- return (a);
-}
-
-/*%
- * dst_s_dns_key_id() Function to calculate DNSSEC footprint from KEY record
- * rdata
- * Input:
- * dns_key_rdata: the raw data in wire format
- * rdata_len: the size of the input data
- * Output:
- * the key footprint/id calculated from the key data
- */
-static u_int16_t
-dst_s_dns_key_id(const u_char *dns_key_rdata, const int rdata_len)
-{
- if (!dns_key_rdata)
- return 0;
-
- /* compute id */
- if (dns_key_rdata[3] == KEY_RSA) /*%< Algorithm RSA */
- return dst_s_get_int16((const u_char *)
- &dns_key_rdata[rdata_len - 3]);
- else if (dns_key_rdata[3] == KEY_HMAC_MD5)
- /* compatibility */
- return 0;
- else
- /* compute a checksum on the key part of the key rr */
- return dst_s_id_calc(dns_key_rdata, rdata_len);
-}
-
-
-/*! \file */
diff --git a/resolv/ns_samedomain.c b/resolv/ns_samedomain.c
index df6a4a26fb..5d1bf39fc7 100644
--- a/resolv/ns_samedomain.c
+++ b/resolv/ns_samedomain.c
@@ -16,10 +16,6 @@
* SOFTWARE.
*/
-#if !defined(_LIBC) && !defined(lint)
-static const char rcsid[] = "$BINDId: ns_samedomain.c,v 8.9 1999/10/15 21:06:51 vixie Exp $";
-#endif
-
#include <sys/types.h>
#include <arpa/nameser.h>
#include <errno.h>
diff --git a/resolv/ns_ttl.c b/resolv/ns_ttl.c
index d4c98bcf3a..079948790b 100644
--- a/resolv/ns_ttl.c
+++ b/resolv/ns_ttl.c
@@ -16,10 +16,6 @@
* SOFTWARE.
*/
-#if !defined(_LIBC) && !defined(lint)
-static const char rcsid[] = "$BINDId: ns_ttl.c,v 8.8 1999/10/13 16:39:36 vixie Exp $";
-#endif
-
/* Import. */
#include <arpa/nameser.h>
diff --git a/resolv/nsap_addr.c b/resolv/nsap_addr.c
index 7041e5282e..9a1d3f7fdc 100644
--- a/resolv/nsap_addr.c
+++ b/resolv/nsap_addr.c
@@ -15,10 +15,6 @@
* SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$BINDId: nsap_addr.c,v 8.10 1999/10/13 16:39:28 vixie Exp $";
-#endif /* LIBC_SCCS and not lint */
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
diff --git a/resolv/nss_dns/dns-canon.c b/resolv/nss_dns/dns-canon.c
index 27255fda58..b9e32cae52 100644
--- a/resolv/nss_dns/dns-canon.c
+++ b/resolv/nss_dns/dns-canon.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2004-2016 Free Software Foundation, Inc.
+/* Copyright (C) 2004-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
@@ -23,7 +23,8 @@
#include <stdint.h>
#include <arpa/nameser.h>
#include <nsswitch.h>
-
+#include <resolv/resolv_context.h>
+#include <resolv/resolv-internal.h>
#if PACKETSZ > 65536
# define MAXPACKET PACKETSZ
@@ -58,11 +59,19 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
} ansp = { .ptr = buf };
enum nss_status status = NSS_STATUS_UNAVAIL;
+ struct resolv_context *ctx = __resolv_context_get ();
+ if (ctx == NULL)
+ {
+ *errnop = errno;
+ *h_errnop = NETDB_INTERNAL;
+ return NSS_STATUS_UNAVAIL;
+ }
+
for (int i = 0; i < nqtypes; ++i)
{
- int r = __libc_res_nquery (&_res, name, ns_c_in, qtypes[i],
- buf, sizeof (buf), &ansp.ptr, NULL, NULL,
- NULL, NULL);
+ int r = __res_context_query (ctx, name, ns_c_in, qtypes[i],
+ buf, sizeof (buf), &ansp.ptr, NULL, NULL,
+ NULL, NULL);
if (r > 0)
{
/* We need to decode the response. Just one question record.
@@ -103,6 +112,11 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
ptr += s;
+ /* Check that there are enough bytes for the RR
+ metadata. */
+ if (endptr - ptr < 10)
+ goto unavail;
+
/* Check whether type and class match. */
uint_fast16_t type;
NS_GET16 (type, ptr);
@@ -137,13 +151,25 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
if (__ns_get16 (ptr) != ns_c_in)
goto unavail;
- /* Also skip over the TTL. */
+ /* Also skip over class and TTL. */
ptr += sizeof (uint16_t) + sizeof (uint32_t);
- /* Skip over the data length and data. */
- ptr += sizeof (uint16_t) + __ns_get16 (ptr);
+ /* Skip over RDATA length and RDATA itself. */
+ uint16_t rdatalen = __ns_get16 (ptr);
+ ptr += sizeof (uint16_t);
+ /* Not enough room for RDATA. */
+ if (endptr - ptr < rdatalen)
+ goto unavail;
+ ptr += rdatalen;
}
}
+
+ /* Restore original buffer before retry. */
+ if (ansp.ptr != buf)
+ {
+ free (ansp.ptr);
+ ansp.ptr = buf;
+ }
}
out:
@@ -151,6 +177,6 @@ _nss_dns_getcanonname_r (const char *name, char *buffer, size_t buflen,
if (ansp.ptr != buf)
free (ansp.ptr);
-
+ __resolv_context_put (ctx);
return status;
}
diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
index 8599f4c6a6..5dc2829cd1 100644
--- a/resolv/nss_dns/dns-host.c
+++ b/resolv/nss_dns/dns-host.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996.
@@ -78,11 +78,14 @@
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
-#include <sys/syslog.h>
#include "nsswitch.h"
+#include <arpa/nameser.h>
-/* Get implementation for some internal functions. */
+#include <resolv/resolv-internal.h>
+#include <resolv/resolv_context.h>
+
+/* Get implementations of some internal functions. */
#include <resolv/mapv4v6addr.h>
#include <resolv/mapv4v6hostent.h>
@@ -99,10 +102,6 @@
#endif
#define MAXHOSTNAMELEN 256
-static const char AskedForGot[] = "\
-gethostby*.getanswer: asked for \"%s\", got \"%s\"";
-
-
/* We need this time later. */
typedef union querybuf
{
@@ -110,14 +109,8 @@ typedef union querybuf
u_char buf[MAXPACKET];
} querybuf;
-/* These functions are defined in res_comp.c. */
-#define NS_MAXCDNAME 255 /* maximum compressed domain name */
-extern int __ns_name_ntop (const u_char *, char *, size_t);
-extern int __ns_name_unpack (const u_char *, const u_char *,
- const u_char *, u_char *, size_t);
-
-
-static enum nss_status getanswer_r (const querybuf *answer, int anslen,
+static enum nss_status getanswer_r (struct resolv_context *ctx,
+ const querybuf *answer, int anslen,
const char *qname, int qtype,
struct hostent *result, char *buffer,
size_t buflen, int *errnop, int *h_errnop,
@@ -131,19 +124,55 @@ static enum nss_status gaih_getanswer (const querybuf *answer1, int anslen1,
int *errnop, int *h_errnop,
int32_t *ttlp);
-extern enum nss_status _nss_dns_gethostbyname3_r (const char *name, int af,
- struct hostent *result,
- char *buffer, size_t buflen,
- int *errnop, int *h_errnop,
- int32_t *ttlp,
- char **canonp);
-hidden_proto (_nss_dns_gethostbyname3_r)
+static enum nss_status gethostbyname3_context (struct resolv_context *ctx,
+ const char *name, int af,
+ struct hostent *result,
+ char *buffer, size_t buflen,
+ int *errnop, int *h_errnop,
+ int32_t *ttlp,
+ char **canonp);
+
+/* Return the expected RDATA length for an address record type (A or
+ AAAA). */
+static int
+rrtype_to_rdata_length (int type)
+{
+ switch (type)
+ {
+ case T_A:
+ return INADDRSZ;
+ case T_AAAA:
+ return IN6ADDRSZ;
+ default:
+ return -1;
+ }
+}
+
enum nss_status
_nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
char *buffer, size_t buflen, int *errnop,
int *h_errnop, int32_t *ttlp, char **canonp)
{
+ struct resolv_context *ctx = __resolv_context_get ();
+ if (ctx == NULL)
+ {
+ *errnop = errno;
+ *h_errnop = NETDB_INTERNAL;
+ return NSS_STATUS_UNAVAIL;
+ }
+ enum nss_status status = gethostbyname3_context
+ (ctx, name, af, result, buffer, buflen, errnop, h_errnop, ttlp, canonp);
+ __resolv_context_put (ctx);
+ return status;
+}
+
+static enum nss_status
+gethostbyname3_context (struct resolv_context *ctx,
+ const char *name, int af, struct hostent *result,
+ char *buffer, size_t buflen, int *errnop,
+ int *h_errnop, int32_t *ttlp, char **canonp)
+{
union
{
querybuf *buf;
@@ -157,9 +186,6 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
int olderr = errno;
enum nss_status status;
- if (__res_maybe_init (&_res, 0) == -1)
- return NSS_STATUS_UNAVAIL;
-
switch (af) {
case AF_INET:
size = INADDRSZ;
@@ -184,13 +210,13 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
* function that looks up host names.
*/
if (strchr (name, '.') == NULL
- && (cp = res_hostalias (&_res, name, tmp, sizeof (tmp))) != NULL)
+ && (cp = __res_context_hostalias (ctx, name, tmp, sizeof (tmp))) != NULL)
name = cp;
host_buffer.buf = orig_host_buffer = (querybuf *) alloca (1024);
- n = __libc_res_nsearch (&_res, name, C_IN, type, host_buffer.buf->buf,
- 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
+ n = __res_context_search (ctx, name, C_IN, type, host_buffer.buf->buf,
+ 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
if (n < 0)
{
switch (errno)
@@ -221,11 +247,11 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
/* If we are looking for an IPv6 address and mapping is enabled
by having the RES_USE_INET6 bit in _res.options set, we try
another lookup. */
- if (af == AF_INET6 && (_res.options & RES_USE_INET6))
- n = __libc_res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf->buf,
- host_buffer.buf != orig_host_buffer
- ? MAXPACKET : 1024, &host_buffer.ptr,
- NULL, NULL, NULL, NULL);
+ if (af == AF_INET6 && res_use_inet6 ())
+ n = __res_context_search (ctx, name, C_IN, T_A, host_buffer.buf->buf,
+ host_buffer.buf != orig_host_buffer
+ ? MAXPACKET : 1024, &host_buffer.ptr,
+ NULL, NULL, NULL, NULL);
if (n < 0)
{
@@ -240,14 +266,13 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
result->h_length = INADDRSZ;
}
- status = getanswer_r (host_buffer.buf, n, name, type, result, buffer, buflen,
- errnop, h_errnop, map, ttlp, canonp);
+ status = getanswer_r
+ (ctx, host_buffer.buf, n, name, type, result, buffer, buflen,
+ errnop, h_errnop, map, ttlp, canonp);
if (host_buffer.buf != orig_host_buffer)
free (host_buffer.buf);
return status;
}
-hidden_def (_nss_dns_gethostbyname3_r)
-
enum nss_status
_nss_dns_gethostbyname2_r (const char *name, int af, struct hostent *result,
@@ -264,15 +289,21 @@ _nss_dns_gethostbyname_r (const char *name, struct hostent *result,
char *buffer, size_t buflen, int *errnop,
int *h_errnop)
{
+ struct resolv_context *ctx = __resolv_context_get ();
+ if (ctx == NULL)
+ {
+ *errnop = errno;
+ *h_errnop = NETDB_INTERNAL;
+ return NSS_STATUS_UNAVAIL;
+ }
enum nss_status status = NSS_STATUS_NOTFOUND;
-
- if (_res.options & RES_USE_INET6)
- status = _nss_dns_gethostbyname3_r (name, AF_INET6, result, buffer,
- buflen, errnop, h_errnop, NULL, NULL);
+ if (res_use_inet6 ())
+ status = gethostbyname3_context (ctx, name, AF_INET6, result, buffer,
+ buflen, errnop, h_errnop, NULL, NULL);
if (status == NSS_STATUS_NOTFOUND)
- status = _nss_dns_gethostbyname3_r (name, AF_INET, result, buffer,
- buflen, errnop, h_errnop, NULL, NULL);
-
+ status = gethostbyname3_context (ctx, name, AF_INET, result, buffer,
+ buflen, errnop, h_errnop, NULL, NULL);
+ __resolv_context_put (ctx);
return status;
}
@@ -282,8 +313,13 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
char *buffer, size_t buflen, int *errnop,
int *herrnop, int32_t *ttlp)
{
- if (__res_maybe_init (&_res, 0) == -1)
- return NSS_STATUS_UNAVAIL;
+ struct resolv_context *ctx = __resolv_context_get ();
+ if (ctx == NULL)
+ {
+ *errnop = errno;
+ *herrnop = NETDB_INTERNAL;
+ return NSS_STATUS_UNAVAIL;
+ }
/*
* if there aren't any dots, it could be a user-level alias.
@@ -293,7 +329,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
if (strchr (name, '.') == NULL)
{
char *tmp = alloca (NS_MAXDNAME);
- const char *cp = res_hostalias (&_res, name, tmp, NS_MAXDNAME);
+ const char *cp = __res_context_hostalias (ctx, name, tmp, NS_MAXDNAME);
if (cp != NULL)
name = cp;
}
@@ -312,9 +348,9 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
int olderr = errno;
enum nss_status status;
- int n = __libc_res_nsearch (&_res, name, C_IN, T_UNSPEC,
- host_buffer.buf->buf, 2048, &host_buffer.ptr,
- &ans2p, &nans2p, &resplen2, &ans2p_malloced);
+ int n = __res_context_search (ctx, name, C_IN, T_QUERY_A_AND_AAAA,
+ host_buffer.buf->buf, 2048, &host_buffer.ptr,
+ &ans2p, &nans2p, &resplen2, &ans2p_malloced);
if (n >= 0)
{
status = gaih_getanswer (host_buffer.buf, n, (const querybuf *) ans2p,
@@ -357,6 +393,7 @@ _nss_dns_gethostbyname4_r (const char *name, struct gaih_addrtuple **pat,
if (host_buffer.buf != orig_host_buffer)
free (host_buffer.buf);
+ __resolv_context_put (ctx);
return status;
}
@@ -409,8 +446,13 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
host_data = (struct host_data *) buffer;
- if (__res_maybe_init (&_res, 0) == -1)
- return NSS_STATUS_UNAVAIL;
+ struct resolv_context *ctx = __resolv_context_get ();
+ if (ctx == NULL)
+ {
+ *errnop = errno;
+ *h_errnop = NETDB_INTERNAL;
+ return NSS_STATUS_UNAVAIL;
+ }
if (af == AF_INET6 && len == IN6ADDRSZ
&& (memcmp (uaddr, mapped, sizeof mapped) == 0
@@ -435,12 +477,14 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
default:
*errnop = EAFNOSUPPORT;
*h_errnop = NETDB_INTERNAL;
+ __resolv_context_put (ctx);
return NSS_STATUS_UNAVAIL;
}
if (size > len)
{
*errnop = EAFNOSUPPORT;
*h_errnop = NETDB_INTERNAL;
+ __resolv_context_put (ctx);
return NSS_STATUS_UNAVAIL;
}
@@ -453,19 +497,6 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
(uaddr[2] & 0xff), (uaddr[1] & 0xff), (uaddr[0] & 0xff));
break;
case AF_INET6:
- /* Only lookup with the byte string format if the user wants it. */
- if (__glibc_unlikely (_res.options & RES_USEBSTRING))
- {
- qp = stpcpy (qbuf, "\\[x");
- for (n = 0; n < IN6ADDRSZ; ++n)
- qp += sprintf (qp, "%02hhx", uaddr[n]);
- strcpy (qp, "].ip6.arpa");
- n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR,
- host_buffer.buf->buf, 1024, &host_buffer.ptr,
- NULL, NULL, NULL, NULL);
- if (n >= 0)
- goto got_it_already;
- }
qp = qbuf;
for (n = IN6ADDRSZ - 1; n >= 0; n--)
{
@@ -482,55 +513,36 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
break;
}
- n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
- 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
- if (n < 0 && af == AF_INET6 && (_res.options & RES_NOIP6DOTINT) == 0)
- {
- strcpy (qp, "ip6.int");
- n = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
- host_buffer.buf != orig_host_buffer
- ? MAXPACKET : 1024, &host_buffer.ptr,
- NULL, NULL, NULL, NULL);
- }
+ n = __res_context_query (ctx, qbuf, C_IN, T_PTR, host_buffer.buf->buf,
+ 1024, &host_buffer.ptr, NULL, NULL, NULL, NULL);
if (n < 0)
{
*h_errnop = h_errno;
__set_errno (olderr);
if (host_buffer.buf != orig_host_buffer)
free (host_buffer.buf);
+ __resolv_context_put (ctx);
return errno == ECONNREFUSED ? NSS_STATUS_UNAVAIL : NSS_STATUS_NOTFOUND;
}
- got_it_already:
- status = getanswer_r (host_buffer.buf, n, qbuf, T_PTR, result, buffer, buflen,
- errnop, h_errnop, 0 /* XXX */, ttlp, NULL);
+ status = getanswer_r
+ (ctx, host_buffer.buf, n, qbuf, T_PTR, result, buffer, buflen,
+ errnop, h_errnop, 0 /* XXX */, ttlp, NULL);
if (host_buffer.buf != orig_host_buffer)
free (host_buffer.buf);
if (status != NSS_STATUS_SUCCESS)
- return status;
-
-#ifdef SUNSECURITY
- This is not implemented because it is not possible to use the current
- source from bind in a multi-threaded program.
-#endif
+ {
+ __resolv_context_put (ctx);
+ return status;
+ }
result->h_addrtype = af;
result->h_length = len;
memcpy (host_data->host_addr, addr, len);
host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
host_data->h_addr_ptrs[1] = NULL;
-#if 0
- /* XXX I think this is wrong. Why should an IPv4 address be
- converted to IPv6 if the user explicitly asked for IPv4? */
- if (af == AF_INET && (_res.options & RES_USE_INET6))
- {
- map_v4v6_address ((char *) host_data->host_addr,
- (char *) host_data->host_addr);
- result->h_addrtype = AF_INET6;
- result->h_length = IN6ADDRSZ;
- }
-#endif
*h_errnop = NETDB_SUCCESS;
+ __resolv_context_put (ctx);
return NSS_STATUS_SUCCESS;
}
hidden_def (_nss_dns_gethostbyaddr2_r)
@@ -545,26 +557,27 @@ _nss_dns_gethostbyaddr_r (const void *addr, socklen_t len, int af,
errnop, h_errnop, NULL);
}
-#ifdef RESOLVSORT
-static void addrsort (char **ap, int num);
-
static void
-addrsort (char **ap, int num)
+addrsort (struct resolv_context *ctx, char **ap, int num)
{
int i, j;
char **p;
short aval[MAX_NR_ADDRS];
int needsort = 0;
+ size_t nsort = __resolv_context_sort_count (ctx);
p = ap;
if (num > MAX_NR_ADDRS)
num = MAX_NR_ADDRS;
for (i = 0; i < num; i++, p++)
{
- for (j = 0 ; (unsigned)j < _res.nsort; j++)
- if (_res.sort_list[j].addr.s_addr ==
- (((struct in_addr *)(*p))->s_addr & _res.sort_list[j].mask))
- break;
+ for (j = 0 ; (unsigned)j < nsort; j++)
+ {
+ struct resolv_sortlist_entry e
+ = __resolv_context_sort_entry (ctx, j);
+ if (e.addr.s_addr == (((struct in_addr *)(*p))->s_addr & e.mask))
+ break;
+ }
aval[i] = j;
if (needsort == 0 && i > 0 && j < aval[i-1])
needsort = i;
@@ -589,10 +602,10 @@ addrsort (char **ap, int num)
else
break;
}
-#endif
static enum nss_status
-getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
+getanswer_r (struct resolv_context *ctx,
+ const querybuf *answer, int anslen, const char *qname, int qtype,
struct hostent *result, char *buffer, size_t buflen,
int *errnop, int *h_errnop, int map, int32_t *ttlp, char **canonp)
{
@@ -653,7 +666,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
ancount = ntohs (hp->ancount);
qdcount = ntohs (hp->qdcount);
cp = answer->buf + HFIXEDSZ;
- if (__builtin_expect (qdcount, 1) != 1)
+ if (__glibc_unlikely (qdcount != 1))
{
*h_errnop = NO_RECOVERY;
return NSS_STATUS_UNAVAIL;
@@ -667,7 +680,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
packtmp, sizeof packtmp);
if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
{
- if (__builtin_expect (errno, 0) == EMSGSIZE)
+ if (__glibc_unlikely (errno == EMSGSIZE))
goto too_small;
n = -1;
@@ -676,13 +689,19 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
if (n > 0 && bp[0] == '.')
bp[0] = '\0';
- if (__builtin_expect (n < 0 || ((*name_ok) (bp) == 0 && (errno = EBADMSG)),
- 0))
+ if (__glibc_unlikely (n < 0))
{
*errnop = errno;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_UNAVAIL;
}
+ if (__glibc_unlikely (name_ok (bp) == 0))
+ {
+ errno = EBADMSG;
+ *errnop = EBADMSG;
+ *h_errnop = NO_RECOVERY;
+ return NSS_STATUS_UNAVAIL;
+ }
cp += n + QFIXEDSZ;
if (qtype == T_A || qtype == T_AAAA)
@@ -724,7 +743,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
packtmp, sizeof packtmp);
if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
{
- if (__builtin_expect (errno, 0) == EMSGSIZE)
+ if (__glibc_unlikely (errno == EMSGSIZE))
goto too_small;
n = -1;
@@ -751,6 +770,14 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
cp += INT32SZ; /* TTL */
n = __ns_get16 (cp);
cp += INT16SZ; /* len */
+
+ if (end_of_message - cp < n)
+ {
+ /* RDATA extends beyond the end of the packet. */
+ ++had_error;
+ continue;
+ }
+
if (__glibc_unlikely (class != C_IN))
{
/* XXX - debug? syslog? */
@@ -776,7 +803,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
/* Store alias. */
*ap++ = bp;
n = strlen (bp) + 1; /* For the \0. */
- if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
+ if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
{
++had_error;
continue;
@@ -787,7 +814,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
n = strlen (tbuf) + 1; /* For the \0. */
if (__glibc_unlikely (n > linebuflen))
goto too_small;
- if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
+ if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
{
++had_error;
continue;
@@ -815,7 +842,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
n = strlen (tbuf) + 1; /* For the \0. */
if (__glibc_unlikely (n > linebuflen))
goto too_small;
- if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
+ if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
{
++had_error;
continue;
@@ -830,14 +857,6 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
have_to_map = 1;
else if (__glibc_unlikely (type != qtype))
{
- /* Log a low priority message if we get an unexpected record, but
- skip it if we are using DNSSEC since it uses many different types
- in responses that do not match QTYPE. */
- if ((_res.options & RES_USE_DNSSEC) == 0)
- syslog (LOG_NOTICE | LOG_AUTH,
- "gethostby*.getanswer: asked for \"%s %s %s\", "
- "got type \"%s\"",
- qname, p_class (C_IN), p_type (qtype), p_type (type));
cp += n;
continue; /* XXX - had_error++ ? */
}
@@ -847,7 +866,6 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
case T_PTR:
if (__glibc_unlikely (strcasecmp (tname, bp) != 0))
{
- syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, qname, bp);
cp += n;
continue; /* XXX - had_error++ ? */
}
@@ -856,7 +874,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
packtmp, sizeof packtmp);
if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
{
- if (__builtin_expect (errno, 0) == EMSGSIZE)
+ if (__glibc_unlikely (errno == EMSGSIZE))
goto too_small;
n = -1;
@@ -872,29 +890,24 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
/* bind would put multiple PTR records as aliases, but we don't do
that. */
result->h_name = bp;
- if (have_to_map)
- {
- n = strlen (bp) + 1; /* for the \0 */
- if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
- {
- ++had_error;
- break;
- }
- bp += n;
- linebuflen -= n;
- if (map_v4v6_hostent (result, &bp, &linebuflen))
- goto too_small;
- }
*h_errnop = NETDB_SUCCESS;
return NSS_STATUS_SUCCESS;
case T_A:
case T_AAAA:
- if (__builtin_expect (strcasecmp (result->h_name, bp), 0) != 0)
+ if (__glibc_unlikely (strcasecmp (result->h_name, bp) != 0))
{
- syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, result->h_name, bp);
cp += n;
continue; /* XXX - had_error++ ? */
}
+
+ /* Stop parsing at a record whose length is incorrect. */
+ if (n != rrtype_to_rdata_length (type))
+ {
+ ++had_error;
+ break;
+ }
+
+ /* Skip records of the wrong type. */
if (n != result->h_length)
{
cp += n;
@@ -937,15 +950,14 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
{
*ap = NULL;
*hap = NULL;
-#if defined RESOLVSORT
/*
* Note: we sort even if host can take only one address
* in its return structures - should give it the "best"
* address in that case, not some random one
*/
- if (_res.nsort && haveanswer > 1 && qtype == T_A)
- addrsort (host_data->h_addr_ptrs, haveanswer);
-#endif /*RESOLVSORT*/
+ if (haveanswer > 1 && qtype == T_A
+ && __resolv_context_sort_count (ctx) > 0)
+ addrsort (ctx, host_data->h_addr_ptrs, haveanswer);
if (result->h_name == NULL)
{
@@ -1004,7 +1016,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
it later. */
if (n != -1 && __ns_name_ntop (packtmp, buffer, buflen) == -1)
{
- if (__builtin_expect (errno, 0) == EMSGSIZE)
+ if (__glibc_unlikely (errno == EMSGSIZE))
{
too_small:
*errnop = ERANGE;
@@ -1015,13 +1027,19 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
n = -1;
}
- if (__builtin_expect (n < 0 || (res_hnok (buffer) == 0
- && (errno = EBADMSG)), 0))
+ if (__glibc_unlikely (n < 0))
{
*errnop = errno;
*h_errnop = NO_RECOVERY;
return NSS_STATUS_UNAVAIL;
}
+ if (__glibc_unlikely (res_hnok (buffer) == 0))
+ {
+ errno = EBADMSG;
+ *errnop = EBADMSG;
+ *h_errnop = NO_RECOVERY;
+ return NSS_STATUS_UNAVAIL;
+ }
cp += n + QFIXEDSZ;
int haveanswer = 0;
@@ -1043,7 +1061,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
if (n != -1 &&
(h_namelen = __ns_name_ntop (packtmp, buffer, buflen)) == -1)
{
- if (__builtin_expect (errno, 0) == EMSGSIZE)
+ if (__glibc_unlikely (errno == EMSGSIZE))
goto too_small;
n = -1;
@@ -1077,6 +1095,13 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
n = __ns_get16 (cp);
cp += INT16SZ; /* len */
+ if (end_of_message - cp < n)
+ {
+ /* RDATA extends beyond the end of the packet. */
+ ++had_error;
+ continue;
+ }
+
if (class != C_IN)
{
cp += n;
@@ -1124,32 +1149,25 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
}
continue;
}
-#if 1
- // We should not see any types other than those explicitly listed
- // below. Some types sent by server seem missing, though. Just
- // collect the data for now.
- if (__glibc_unlikely (type != T_A && type != T_AAAA))
-#else
- if (__builtin_expect (type == T_SIG, 0)
- || __builtin_expect (type == T_KEY, 0)
- || __builtin_expect (type == T_NXT, 0)
- || __builtin_expect (type == T_PTR, 0)
- || __builtin_expect (type == T_DNAME, 0))
-#endif
- {
- /* We don't support DNSSEC yet. For now, ignore the record
- and send a low priority message to syslog.
- We also don't expect T_PTR or T_DNAME messages. */
- syslog (LOG_DEBUG | LOG_AUTH,
- "getaddrinfo*.gaih_getanswer: got type \"%s\"",
- p_type (type));
+ /* Stop parsing if we encounter a record with incorrect RDATA
+ length. */
+ if (type == T_A || type == T_AAAA)
+ {
+ if (n != rrtype_to_rdata_length (type))
+ {
+ ++had_error;
+ continue;
+ }
+ }
+ else
+ {
+ /* Skip unknown records. */
cp += n;
continue;
}
- if (type != T_A && type != T_AAAA)
- abort ();
+ assert (type == T_A || type == T_AAAA);
if (*pat == NULL)
{
uintptr_t pad = (-(uintptr_t) buffer
@@ -1157,8 +1175,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
buffer += pad;
buflen = buflen > pad ? buflen - pad : 0;
- if (__builtin_expect (buflen < sizeof (struct gaih_addrtuple),
- 0))
+ if (__glibc_unlikely (buflen < sizeof (struct gaih_addrtuple)))
goto too_small;
*pat = (struct gaih_addrtuple *) buffer;
@@ -1183,12 +1200,6 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
}
(*pat)->family = type == T_A ? AF_INET : AF_INET6;
- if (__builtin_expect ((type == T_A && n != INADDRSZ)
- || (type == T_AAAA && n != IN6ADDRSZ), 0))
- {
- ++had_error;
- continue;
- }
memcpy ((*pat)->addr, cp, n);
cp += n;
(*pat)->scopeid = 0;
diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
index 2eb2f67e66..61bddd754f 100644
--- a/resolv/nss_dns/dns-network.c
+++ b/resolv/nss_dns/dns-network.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996.
@@ -62,9 +62,13 @@
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
+#include <stddef.h>
#include "nsswitch.h"
#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <resolv/resolv-internal.h>
+#include <resolv/resolv_context.h>
/* Maximum number of aliases we allow. */
#define MAX_NR_ALIASES 48
@@ -91,13 +95,6 @@ typedef union querybuf
u_char buf[MAXPACKET];
} querybuf;
-/* These functions are defined in res_comp.c. */
-#define NS_MAXCDNAME 255 /* maximum compressed domain name */
-extern int __ns_name_ntop (const u_char *, char *, size_t) __THROW;
-extern int __ns_name_unpack (const u_char *, const u_char *,
- const u_char *, u_char *, size_t) __THROW;
-
-
/* Prototypes for local functions. */
static enum nss_status getanswer_r (const querybuf *answer, int anslen,
struct netent *result, char *buffer,
@@ -118,24 +115,28 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result,
} net_buffer;
querybuf *orig_net_buffer;
int anslen;
- char *qbuf;
enum nss_status status;
- if (__res_maybe_init (&_res, 0) == -1)
- return NSS_STATUS_UNAVAIL;
-
- qbuf = strdupa (name);
+ struct resolv_context *ctx = __resolv_context_get ();
+ if (ctx == NULL)
+ {
+ *errnop = errno;
+ *herrnop = NETDB_INTERNAL;
+ return NSS_STATUS_UNAVAIL;
+ }
net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
- anslen = __libc_res_nsearch (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
- 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
+ anslen = __res_context_search
+ (ctx, name, C_IN, T_PTR, net_buffer.buf->buf,
+ 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
if (anslen < 0)
{
/* Nothing found. */
*errnop = errno;
if (net_buffer.buf != orig_net_buffer)
free (net_buffer.buf);
+ __resolv_context_put (ctx);
return (errno == ECONNREFUSED
|| errno == EPFNOSUPPORT
|| errno == EAFNOSUPPORT)
@@ -146,6 +147,7 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result,
errnop, herrnop, BYNAME);
if (net_buffer.buf != orig_net_buffer)
free (net_buffer.buf);
+ __resolv_context_put (ctx);
return status;
}
@@ -166,17 +168,22 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
unsigned int net_bytes[4];
char qbuf[MAXDNAME];
int cnt, anslen;
- u_int32_t net2;
+ uint32_t net2;
int olderr = errno;
/* No net address lookup for IPv6 yet. */
if (type != AF_INET)
return NSS_STATUS_UNAVAIL;
- if (__res_maybe_init (&_res, 0) == -1)
- return NSS_STATUS_UNAVAIL;
+ struct resolv_context *ctx = __resolv_context_get ();
+ if (ctx == NULL)
+ {
+ *errnop = errno;
+ *herrnop = NETDB_INTERNAL;
+ return NSS_STATUS_UNAVAIL;
+ }
- net2 = (u_int32_t) net;
+ net2 = (uint32_t) net;
for (cnt = 4; net2 != 0; net2 >>= 8)
net_bytes[--cnt] = net2 & 0xff;
@@ -204,8 +211,8 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
- anslen = __libc_res_nquery (&_res, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
- 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
+ anslen = __res_context_query (ctx, qbuf, C_IN, T_PTR, net_buffer.buf->buf,
+ 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
if (anslen < 0)
{
/* Nothing found. */
@@ -213,6 +220,7 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
__set_errno (olderr);
if (net_buffer.buf != orig_net_buffer)
free (net_buffer.buf);
+ __resolv_context_put (ctx);
return (err == ECONNREFUSED
|| err == EPFNOSUPPORT
|| err == EAFNOSUPPORT)
@@ -233,13 +241,11 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
result->n_net = u_net;
}
+ __resolv_context_put (ctx);
return status;
}
-#undef offsetof
-#define offsetof(Type, Member) ((size_t) &((Type *) NULL)->Member)
-
static enum nss_status
getanswer_r (const querybuf *answer, int anslen, struct netent *result,
char *buffer, size_t buflen, int *errnop, int *h_errnop,
@@ -329,11 +335,8 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
while (--answer_count >= 0 && cp < end_of_message)
{
- int n = dn_expand (answer->buf, end_of_message, cp, bp, linebuflen);
- int type, class;
-
- n = __ns_name_unpack (answer->buf, end_of_message, cp,
- packtmp, sizeof packtmp);
+ int n = __ns_name_unpack (answer->buf, end_of_message, cp,
+ packtmp, sizeof packtmp);
if (n != -1 && __ns_name_ntop (packtmp, bp, linebuflen) == -1)
{
if (errno == EMSGSIZE)
@@ -348,10 +351,24 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
if (n < 0 || res_dnok (bp) == 0)
break;
cp += n;
+
+ if (end_of_message - cp < 10)
+ {
+ __set_h_errno (NO_RECOVERY);
+ return NSS_STATUS_UNAVAIL;
+ }
+
+ int type, class;
GETSHORT (type, cp);
GETSHORT (class, cp);
cp += INT32SZ; /* TTL */
- GETSHORT (n, cp);
+ uint16_t rdatalen;
+ GETSHORT (rdatalen, cp);
+ if (end_of_message - cp < rdatalen)
+ {
+ __set_h_errno (NO_RECOVERY);
+ return NSS_STATUS_UNAVAIL;
+ }
if (class == C_IN && type == T_PTR)
{
@@ -373,7 +390,7 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
cp += n;
return NSS_STATUS_UNAVAIL;
}
- cp += n;
+ cp += rdatalen;
if (alias_pointer + 2 < &net_data->aliases[MAX_NR_ALIASES])
{
*alias_pointer++ = bp;
@@ -384,6 +401,9 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
++have_answer;
}
}
+ else
+ /* Skip over unknown record data. */
+ cp += rdatalen;
}
if (have_answer)
diff --git a/resolv/res-close.c b/resolv/res-close.c
new file mode 100644
index 0000000000..1c36dd5f1d
--- /dev/null
+++ b/resolv/res-close.c
@@ -0,0 +1,144 @@
+/* Deallocation functions for the resolver state.
+ Copyright (C) 1995-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/*
+ * Copyright (c) 1985, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include <resolv-internal.h>
+#include <resolv_context.h>
+#include <resolv_conf.h>
+#include <not-cancel.h>
+#include <stdlib.h>
+
+/* Close all open sockets. If FREE_ADDR is true, deallocate any
+ separately allocated name server addresses. */
+void
+__res_iclose (res_state statp, bool free_addr)
+{
+ if (statp->_vcsock >= 0)
+ {
+ __close_nocancel_nostatus (statp->_vcsock);
+ statp->_vcsock = -1;
+ statp->_flags &= ~(RES_F_VC | RES_F_CONN);
+ }
+ for (int ns = 0; ns < statp->nscount; ns++)
+ if (statp->_u._ext.nsaddrs[ns] != NULL)
+ {
+ if (statp->_u._ext.nssocks[ns] != -1)
+ {
+ __close_nocancel_nostatus (statp->_u._ext.nssocks[ns]);
+ statp->_u._ext.nssocks[ns] = -1;
+ }
+ if (free_addr)
+ {
+ free (statp->_u._ext.nsaddrs[ns]);
+ statp->_u._ext.nsaddrs[ns] = NULL;
+ }
+ }
+ if (free_addr)
+ __resolv_conf_detach (statp);
+}
+libc_hidden_def (__res_iclose)
+
+void
+res_nclose (res_state statp)
+{
+ __res_iclose (statp, true);
+}
+libc_hidden_def (__res_nclose)
+
+/* This is called when a thread is exiting to free resources held in _res. */
+void
+__res_thread_freeres (void)
+{
+ __resolv_context_freeres ();
+
+ if (_res.nscount == 0)
+ /* Never called res_ninit. */
+ return;
+
+ __res_iclose (&_res, true); /* Close any VC sockets. */
+
+ /* Make sure we do a full re-initialization the next time. */
+ _res.options = 0;
+}
+/* Also must be called when the main thread exits. */
+text_set_element (__libc_subfreeres, __res_thread_freeres);
diff --git a/resolv/res-state.c b/resolv/res-state.c
index 1eb83523ff..010ae3707d 100644
--- a/resolv/res-state.c
+++ b/resolv/res-state.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1996-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1996-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/resolv/res_comp.c b/resolv/res_comp.c
index 2ff7ddb1cd..367ca3017d 100644
--- a/resolv/res_comp.c
+++ b/resolv/res_comp.c
@@ -1,3 +1,21 @@
+/* Domain name processing functions.
+ Copyright (C) 1995-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
/*
* Copyright (c) 1985, 1993
* The Regents of the University of California. All rights reserved.
@@ -64,11 +82,6 @@
* SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$BINDId: res_comp.c,v 8.15 1999/10/13 16:39:39 vixie Exp $";
-#endif /* LIBC_SCCS and not lint */
-
#include <sys/types.h>
#include <sys/param.h>
#include <netinet/in.h>
@@ -126,114 +139,121 @@ dn_skipname(const u_char *ptr, const u_char *eom) {
}
libresolv_hidden_def (dn_skipname)
-/*
- * Verify that a domain name uses an acceptable character set.
- */
+/* Return true if the string consists of printable ASCII characters
+ only. */
+static bool
+printable_string (const char *dn)
+{
+ while (true)
+ {
+ char ch = *dn;
+ if (ch == '\0')
+ return true;
+ if (ch <= ' ' || ch > '~')
+ return false;
+ ++dn;
+ }
+}
-/*
- * Note the conspicuous absence of ctype macros in these definitions. On
- * non-ASCII hosts, we can't depend on string literals or ctype macros to
- * tell us anything about network-format data. The rest of the BIND system
- * is not careful about this, but for some reason, we're doing it right here.
- */
-#define PERIOD 0x2e
-#define hyphenchar(c) ((c) == 0x2d)
-#define underscorechar(c) ((c) == 0x5f)
-#define bslashchar(c) ((c) == 0x5c)
-#define periodchar(c) ((c) == PERIOD)
-#define asterchar(c) ((c) == 0x2a)
-#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
- || ((c) >= 0x61 && (c) <= 0x7a))
-#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
+/* Return true if DN points to a name consisting only of [0-9a-zA-Z_-]
+ characters. DN must be in DNS wire format, without
+ compression. */
+static bool
+binary_hnok (const unsigned char *dn)
+{
+ while (true)
+ {
+ size_t label_length = *dn;
+ if (label_length == 0)
+ break;
+ ++dn;
+ const unsigned char *label_end = dn + label_length;
+ do
+ {
+ unsigned char ch = *dn;
+ if (!(('0' <= ch && ch <= '9')
+ || ('A' <= ch && ch <= 'Z')
+ || ('a' <= ch && ch <= 'z')
+ || ch == '-' || ch == '_'))
+ return false;
+ ++dn;
+ }
+ while (dn < label_end);
+ }
+ return true;
+}
-#define borderchar(c) (alphachar(c) || digitchar(c))
-#define middlechar(c) (borderchar(c) || hyphenchar(c) || underscorechar(c))
-#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
+/* Return true if the binary domain name has a first labels which
+ starts with '-'. */
+static inline bool
+binary_leading_dash (const unsigned char *dn)
+{
+ return dn[0] > 0 && dn[1] == '-';
+}
+/* Return 1 if res_hnok is a valid host name. Labels must only
+ contain [0-9a-zA-Z_-] characters, and the name must not start with
+ a '-'. The latter is to avoid confusion with program options. */
int
-res_hnok(const char *dn) {
- int pch = PERIOD, ch = *dn++;
-
- while (ch != '\0') {
- int nch = *dn++;
-
- if (periodchar(ch)) {
- (void)NULL;
- } else if (periodchar(pch)) {
- if (!borderchar(ch))
- return (0);
- } else if (periodchar(nch) || nch == '\0') {
- if (!borderchar(ch))
- return (0);
- } else {
- if (!middlechar(ch))
- return (0);
- }
- pch = ch, ch = nch;
- }
- return (1);
+res_hnok (const char *dn)
+{
+ unsigned char buf[NS_MAXCDNAME];
+ if (!printable_string (dn)
+ || ns_name_pton (dn, buf, sizeof (buf)) < 0
+ || binary_leading_dash (buf))
+ return 0;
+ return binary_hnok (buf);
}
libresolv_hidden_def (res_hnok)
-/*
- * hostname-like (A, MX, WKS) owners can have "*" as their first label
- * but must otherwise be as a host name.
- */
+/* Hostname-like (A, MX, WKS) owners can have "*" as their first label
+ but must otherwise be as a host name. */
int
-res_ownok(const char *dn) {
- if (asterchar(dn[0])) {
- if (periodchar(dn[1]))
- return (res_hnok(dn+2));
- if (dn[1] == '\0')
- return (1);
- }
- return (res_hnok(dn));
+res_ownok (const char *dn)
+{
+ unsigned char buf[NS_MAXCDNAME];
+ if (!printable_string (dn)
+ || ns_name_pton (dn, buf, sizeof (buf)) < 0
+ || binary_leading_dash (buf))
+ return 0;
+ if (buf[0] == 1 && buf [1] == '*')
+ /* Skip over the leading "*." part. */
+ return binary_hnok (buf + 2);
+ else
+ return binary_hnok (buf);
}
-/*
- * SOA RNAMEs and RP RNAMEs can have any printable character in their first
- * label, but the rest of the name has to look like a host name.
- */
+/* SOA RNAMEs and RP RNAMEs can have any byte in their first label,
+ but the rest of the name has to look like a host name. */
int
-res_mailok(const char *dn) {
- int ch, escaped = 0;
-
- /* "." is a valid missing representation */
- if (*dn == '\0')
- return (1);
-
- /* otherwise <label>.<hostname> */
- while ((ch = *dn++) != '\0') {
- if (!domainchar(ch))
- return (0);
- if (!escaped && periodchar(ch))
- break;
- if (escaped)
- escaped = 0;
- else if (bslashchar(ch))
- escaped = 1;
- }
- if (periodchar(ch))
- return (res_hnok(dn));
- return (0);
+res_mailok (const char *dn)
+{
+ unsigned char buf[NS_MAXCDNAME];
+ if (!printable_string (dn)
+ || ns_name_pton (dn, buf, sizeof (buf)) < 0)
+ return 0;
+ unsigned char label_length = buf[0];
+ /* "." is a valid missing representation */
+ if (label_length == 0)
+ return 1;
+ /* Skip over the first label. */
+ unsigned char *tail = buf + 1 + label_length;
+ if (*tail == 0)
+ /* More than one label is required (except for "."). */
+ return 0;
+ return binary_hnok (tail);
}
-/*
- * This function is quite liberal, since RFC 1034's character sets are only
- * recommendations.
- */
+/* Return 1 if DN is a syntactically valid domain name. Empty names
+ are accepted. */
int
-res_dnok(const char *dn) {
- int ch;
-
- while ((ch = *dn++) != '\0')
- if (!domainchar(ch))
- return (0);
- return (1);
+res_dnok (const char *dn)
+{
+ unsigned char buf[NS_MAXCDNAME];
+ return printable_string (dn) && ns_name_pton (dn, buf, sizeof (buf)) >= 0;
}
libresolv_hidden_def (res_dnok)
-#ifdef BIND_4_COMPAT
/*
* This module must export the following externally-visible symbols:
* ___putlong
@@ -242,15 +262,12 @@ libresolv_hidden_def (res_dnok)
* __getshort
* Note that one _ comes from C and the others come from us.
*/
-void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); }
+void __putlong(uint32_t src, u_char *dst) { ns_put32(src, dst); }
libresolv_hidden_def (__putlong)
-void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); }
+void __putshort(uint16_t src, u_char *dst) { ns_put16(src, dst); }
libresolv_hidden_def (__putshort)
-#ifndef __ultrix__
-u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); }
-u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); }
-#endif /*__ultrix__*/
-#endif /*BIND_4_COMPAT*/
+uint32_t _getlong(const u_char *src) { return (ns_get32(src)); }
+uint16_t _getshort(const u_char *src) { return (ns_get16(src)); }
#include <shlib-compat.h>
diff --git a/resolv/res_data.c b/resolv/res_data.c
index 81c9ae5bfd..e586d96dc6 100644
--- a/resolv/res_data.c
+++ b/resolv/res_data.c
@@ -1,3 +1,21 @@
+/* Miscellaneous definitions for libresolv.
+ Copyright (C) 1995-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
/*
* Copyright (c) 1995-1999 by Internet Software Consortium.
*
@@ -15,322 +33,22 @@
* SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char rcsid[] = "$BINDId: res_data.c,v 8.17 1999/10/13 17:11:31 vixie Exp $";
-#endif /* LIBC_SCCS and not lint */
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-
-#include <ctype.h>
-#include <netdb.h>
#include <resolv.h>
-#ifdef BIND_UPDATE
-#include <res_update.h>
-#endif
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-const char *_res_opcodes[] = {
- "QUERY",
- "IQUERY",
- "CQUERYM",
- "CQUERYU", /* experimental */
- "NOTIFY", /* experimental */
- "UPDATE",
- "6",
- "7",
- "8",
- "9",
- "10",
- "11",
- "12",
- "13",
- "ZONEINIT",
- "ZONEREF",
-};
-libresolv_hidden_data_def (_res_opcodes)
-
-#ifdef BIND_UPDATE
-const char *_res_sectioncodes[] attribute_hidden = {
- "ZONE",
- "PREREQUISITES",
- "UPDATE",
- "ADDITIONAL",
-};
-#endif
-
-#ifndef __BIND_NOSTATIC
-#ifdef _LIBC
-/* The definition has been moved to res_libc.c. */
-#else
-#undef _res
-struct __res_state _res
-# if defined(__BIND_RES_TEXT)
- = { RES_TIMEOUT, } /* Motorola, et al. */
-# endif
- ;
-#endif
-
-/* Proto. */
-#ifndef _LIBC
-int res_ourserver_p(const res_state, const struct sockaddr_in *);
-void res_pquery(const res_state, const u_char *, int, FILE *);
-#endif
-
-#ifndef _LIBC
-/* Moved to res_libc.c since res_init() should go into libc.so but the
- rest of this file not. */
-int
-res_init(void) {
- extern int __res_vinit(res_state, int);
-
- /*
- * These three fields used to be statically initialized. This made
- * it hard to use this code in a shared library. It is necessary,
- * now that we're doing dynamic initialization here, that we preserve
- * the old semantics: if an application modifies one of these three
- * fields of _res before res_init() is called, res_init() will not
- * alter them. Of course, if an application is setting them to
- * _zero_ before calling res_init(), hoping to override what used
- * to be the static default, we can't detect it and unexpected results
- * will follow. Zero for any of these fields would make no sense,
- * so one can safely assume that the applications were already getting
- * unexpected results.
- *
- * _res.options is tricky since some apps were known to diddle the bits
- * before res_init() was first called. We can't replicate that semantic
- * with dynamic initialization (they may have turned bits off that are
- * set in RES_DEFAULT). Our solution is to declare such applications
- * "broken". They could fool us by setting RES_INIT but none do (yet).
- */
- if (!_res.retrans)
- _res.retrans = RES_TIMEOUT;
- if (!_res.retry)
- _res.retry = 4;
- if (!(_res.options & RES_INIT))
- _res.options = RES_DEFAULT;
-
- /*
- * This one used to initialize implicitly to zero, so unless the app
- * has set it to something in particular, we can randomize it now.
- */
- if (!_res.id)
- _res.id = res_randomid();
-
- return (__res_vinit(&_res, 1));
-}
-#endif
+/* This function belongs to libresolv, which is why it is not included
+ in res-close.c. */
void
-p_query(const u_char *msg) {
- fp_query(msg, stdout);
-}
-
-void
-fp_query(const u_char *msg, FILE *file) {
- fp_nquery(msg, PACKETSZ, file);
-}
-libresolv_hidden_def (fp_query)
-
-void
-fp_nquery(const u_char *msg, int len, FILE *file) {
- if (__res_maybe_init (&_res, 0) == -1)
- return;
-
- res_pquery(&_res, msg, len, file);
-}
-libresolv_hidden_def (fp_nquery)
-
-int
-res_mkquery(int op, /* opcode of query */
- const char *dname, /* domain name */
- int class, int type, /* class and type of query */
- const u_char *data, /* resource record data */
- int datalen, /* length of data */
- const u_char *newrr_in, /* new rr for modify or append */
- u_char *buf, /* buffer to put query */
- int buflen) /* size of buffer */
+__res_close (void)
{
- if (__res_maybe_init (&_res, 1) == -1) {
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
- return (-1);
- }
- return (res_nmkquery(&_res, op, dname, class, type,
- data, datalen,
- newrr_in, buf, buflen));
+ /* Some programs call res_close before res_init. Since _res._vcsock
+ isn't explicitly initialized, these means that we could call
+ close (0), which might lead to some security problems. Therefore
+ we check if res_init was called before by looking at the RES_INIT
+ bit in _res.options. If it hasn't been set we bail out
+ early. */
+ if ((_res.options & RES_INIT) == 0)
+ return;
+ /* We don't free the name server addresses because we never did it
+ and it would be done implicitly on shutdown. */
+ __res_iclose (&_res, false);
}
-
-#ifdef BIND_UPDATE
-int
-res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
- if (__res_maybe_init (&_res, 1) == -1) {
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
- return (-1);
- }
-
- return (res_nmkupdate(&_res, rrecp_in, buf, buflen));
-}
-#endif
-
-int
-res_query(const char *name, /* domain name */
- int class, int type, /* class and type of query */
- u_char *answer, /* buffer to put answer */
- int anslen) /* size of answer buffer */
-{
- if (__res_maybe_init (&_res, 1) == -1) {
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
- return (-1);
- }
- return (res_nquery(&_res, name, class, type, answer, anslen));
-}
-
-void
-res_send_setqhook(res_send_qhook hook) {
- _res.qhook = hook;
-}
-
-void
-res_send_setrhook(res_send_rhook hook) {
- _res.rhook = hook;
-}
-
-int
-res_isourserver(const struct sockaddr_in *inp) {
- return (res_ourserver_p(&_res, (const struct sockaddr_in6 *) inp));
-}
-
-int
-res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
- if (__res_maybe_init (&_res, 1) == -1) {
- /* errno should have been set by res_init() in this case. */
- return (-1);
- }
-
- return (res_nsend(&_res, buf, buflen, ans, anssiz));
-}
-
-#ifndef _LIBC
-int
-res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
- u_char *ans, int anssiz)
-{
- if (__res_maybe_init (&_res, 1) == -1) {
- /* errno should have been set by res_init() in this case. */
- return (-1);
- }
-
- return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz));
-}
-#endif
-
-void
-res_close(void) {
-#ifdef _LIBC
- /*
- * Some stupid programs out there call res_close() before res_init().
- * Since _res._vcsock isn't explicitly initialized, these means that
- * we could do a close(0), which might lead to some security problems.
- * Therefore we check if res_init() was called before by looking at
- * the RES_INIT bit in _res.options. If it hasn't been set we bail out
- * early. */
- if ((_res.options & RES_INIT) == 0)
- return;
-#endif
- /* We don't free the name server addresses because we never
- did it and it would be done implicitly on shutdown. */
- __res_iclose(&_res, false);
-}
-
-#ifdef BIND_UPDATE
-int
-res_update(ns_updrec *rrecp_in) {
- if (__res_maybe_init (&_res, 1) == -1) {
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
- return (-1);
- }
-
- return (res_nupdate(&_res, rrecp_in, NULL));
-}
-#endif
-
-int
-res_search(const char *name, /* domain name */
- int class, int type, /* class and type of query */
- u_char *answer, /* buffer to put answer */
- int anslen) /* size of answer */
-{
- if (__res_maybe_init (&_res, 1) == -1) {
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
- return (-1);
- }
-
- return (res_nsearch(&_res, name, class, type, answer, anslen));
-}
-
-int
-res_querydomain(const char *name,
- const char *domain,
- int class, int type, /* class and type of query */
- u_char *answer, /* buffer to put answer */
- int anslen) /* size of answer */
-{
- if (__res_maybe_init (&_res, 1) == -1) {
- RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
- return (-1);
- }
-
- return (res_nquerydomain(&_res, name, domain,
- class, type,
- answer, anslen));
-}
-
-const char *
-hostalias(const char *name) {
- static char abuf[MAXDNAME];
-
- return (res_hostalias(&_res, name, abuf, sizeof abuf));
-}
-libresolv_hidden_def (hostalias)
-
-#ifdef ultrix
-int
-local_hostname_length(const char *hostname) {
- int len_host, len_domain;
-
- if (!*_res.defdname)
- res_init();
- len_host = strlen(hostname);
- len_domain = strlen(_res.defdname);
- if (len_host > len_domain &&
- !strcasecmp(hostname + len_host - len_domain, _res.defdname) &&
- hostname[len_host - len_domain - 1] == '.')
- return (len_host - len_domain - 1);
- return (0);
-}
-#endif /*ultrix*/
-
-#endif
-
-
-#include <shlib-compat.h>
-
-#if SHLIB_COMPAT(libresolv, GLIBC_2_0, GLIBC_2_2)
-# undef res_mkquery
-# undef res_query
-# undef res_querydomain
-# undef res_search
-weak_alias (__res_mkquery, res_mkquery);
-weak_alias (__res_query, res_query);
-weak_alias (__res_querydomain, res_querydomain);
-weak_alias (__res_search, res_search);
-#endif
diff --git a/resolv/res_debug.c b/resolv/res_debug.c
index 68a407a033..7681ad4639 100644
--- a/resolv/res_debug.c
+++ b/resolv/res_debug.c
@@ -89,11 +89,6 @@
* SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$BINDId: res_debug.c,v 8.34 2000/02/29 05:30:55 vixie Exp $";
-#endif /* LIBC_SCCS and not lint */
-
#include <sys/types.h>
#include <sys/param.h>
#include <sys/socket.h>
@@ -106,11 +101,13 @@ static const char rcsid[] = "$BINDId: res_debug.c,v 8.34 2000/02/29 05:30:55 vix
#include <errno.h>
#include <math.h>
#include <netdb.h>
-#include <resolv.h>
+#include <resolv/resolv-internal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
+#include <shlib-compat.h>
+#include <libc-diag.h>
#ifdef SPRINTF_CHAR
# define SPRINTF(x) strlen(sprintf/**/x)
@@ -120,6 +117,36 @@ static const char rcsid[] = "$BINDId: res_debug.c,v 8.34 2000/02/29 05:30:55 vix
extern const char *_res_sectioncodes[] attribute_hidden;
+/* _res_opcodes was exported by accident as a variable. */
+#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_26)
+static const char *res_opcodes[] =
+#else
+static const char res_opcodes[][9] =
+#endif
+ {
+ "QUERY",
+ "IQUERY",
+ "CQUERYM",
+ "CQUERYU", /* experimental */
+ "NOTIFY", /* experimental */
+ "UPDATE",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12",
+ "13",
+ "ZONEINIT",
+ "ZONEREF",
+ };
+#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_26)
+strong_alias (res_opcodes, _res_opcodes)
+#endif
+
+static const char *p_section(int section, int opcode);
+
/*
* Print the current options.
*/
@@ -135,9 +162,7 @@ fp_resstat(const res_state statp, FILE *file) {
}
static void
-do_section(const res_state statp,
- ns_msg *handle, ns_sect section,
- int pflag, FILE *file)
+do_section (int pfcode, ns_msg *handle, ns_sect section, int pflag, FILE *file)
{
int n, sflag, rrnum;
static int buflen = 2048;
@@ -148,8 +173,8 @@ do_section(const res_state statp,
/*
* Print answer records.
*/
- sflag = (statp->pfcode & pflag);
- if (statp->pfcode && !sflag)
+ sflag = (pfcode & pflag);
+ if (pfcode && !sflag)
return;
buf = malloc(buflen);
@@ -166,11 +191,11 @@ do_section(const res_state statp,
fprintf(file, ";; ns_parserr: %s\n",
strerror(errno));
else if (rrnum > 0 && sflag != 0 &&
- (statp->pfcode & RES_PRF_HEAD1))
+ (pfcode & RES_PRF_HEAD1))
putc('\n', file);
goto cleanup;
}
- if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1))
+ if (rrnum == 0 && sflag != 0 && (pfcode & RES_PRF_HEAD1))
fprintf(file, ";; %s SECTION:\n",
p_section(section, opcode));
if (section == ns_s_qd)
@@ -212,11 +237,19 @@ do_section(const res_state statp,
* This is intended to be primarily a debugging routine.
*/
void
-res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
+fp_nquery (const unsigned char *msg, int len, FILE *file)
+{
ns_msg handle;
int qdcount, ancount, nscount, arcount;
u_int opcode, rcode, id;
+ /* There is no need to initialize _res: If _res is not yet
+ initialized, _res.pfcode is zero. But initialization will
+ leave it at zero, too. _res.pfcode is an unsigned long,
+ but the code here assumes that the flags fit into an int,
+ so use that. */
+ int pfcode = _res.pfcode;
+
if (ns_initparse(msg, len, &handle) < 0) {
fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
return;
@@ -232,13 +265,13 @@ res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
/*
* Print header fields.
*/
- if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode)
+ if ((!pfcode) || (pfcode & RES_PRF_HEADX) || rcode)
fprintf(file,
";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
- _res_opcodes[opcode], p_rcode(rcode), id);
- if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX))
+ res_opcodes[opcode], p_rcode(rcode), id);
+ if ((!pfcode) || (pfcode & RES_PRF_HEADX))
putc(';', file);
- if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) {
+ if ((!pfcode) || (pfcode & RES_PRF_HEAD2)) {
fprintf(file, "; flags:");
if (ns_msg_getflag(handle, ns_f_qr))
fprintf(file, " qr");
@@ -257,7 +290,7 @@ res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
if (ns_msg_getflag(handle, ns_f_cd))
fprintf(file, " cd");
}
- if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) {
+ if ((!pfcode) || (pfcode & RES_PRF_HEAD1)) {
fprintf(file, "; %s: %d",
p_section(ns_s_qd, opcode), qdcount);
fprintf(file, ", %s: %d",
@@ -267,21 +300,35 @@ res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
fprintf(file, ", %s: %d",
p_section(ns_s_ar, opcode), arcount);
}
- if ((!statp->pfcode) || (statp->pfcode &
+ if ((!pfcode) || (pfcode &
(RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
putc('\n',file);
}
/*
* Print the various sections.
*/
- do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file);
- do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file);
- do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file);
- do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file);
+ do_section (pfcode, &handle, ns_s_qd, RES_PRF_QUES, file);
+ do_section (pfcode, &handle, ns_s_an, RES_PRF_ANS, file);
+ do_section (pfcode, &handle, ns_s_ns, RES_PRF_AUTH, file);
+ do_section (pfcode, &handle, ns_s_ar, RES_PRF_ADD, file);
if (qdcount == 0 && ancount == 0 &&
nscount == 0 && arcount == 0)
putc('\n', file);
}
+libresolv_hidden_def (fp_nquery)
+
+void
+fp_query (const unsigned char *msg, FILE *file)
+{
+ fp_nquery (msg, PACKETSZ, file);
+}
+libresolv_hidden_def (fp_query)
+
+void
+p_query (const unsigned char *msg)
+{
+ fp_query (msg, stdout);
+}
const u_char *
p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
@@ -347,13 +394,13 @@ p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
extern const struct res_sym __p_class_syms[];
libresolv_hidden_proto (__p_class_syms)
const struct res_sym __p_class_syms[] = {
- {C_IN, "IN"},
- {C_CHAOS, "CHAOS"},
- {C_HS, "HS"},
- {C_HS, "HESIOD"},
- {C_ANY, "ANY"},
- {C_NONE, "NONE"},
- {C_IN, (char *)0}
+ {C_IN, (char *) "IN"},
+ {C_CHAOS, (char *) "CHAOS"},
+ {C_HS, (char *) "HS"},
+ {C_HS, (char *) "HESIOD"},
+ {C_ANY, (char *) "ANY"},
+ {C_NONE, (char *) "NONE"},
+ {C_IN, NULL, NULL}
};
libresolv_hidden_data_def (__p_class_syms)
@@ -361,93 +408,75 @@ libresolv_hidden_data_def (__p_class_syms)
* Names of message sections.
*/
const struct res_sym __p_default_section_syms[] attribute_hidden = {
- {ns_s_qd, "QUERY"},
- {ns_s_an, "ANSWER"},
- {ns_s_ns, "AUTHORITY"},
- {ns_s_ar, "ADDITIONAL"},
- {0, (char *)0}
+ {ns_s_qd, (char *) "QUERY"},
+ {ns_s_an, (char *) "ANSWER"},
+ {ns_s_ns, (char *) "AUTHORITY"},
+ {ns_s_ar, (char *) "ADDITIONAL"},
+ {0, NULL, NULL}
};
const struct res_sym __p_update_section_syms[] attribute_hidden = {
- {S_ZONE, "ZONE"},
- {S_PREREQ, "PREREQUISITE"},
- {S_UPDATE, "UPDATE"},
- {S_ADDT, "ADDITIONAL"},
- {0, (char *)0}
-};
-
-const struct res_sym __p_key_syms[] attribute_hidden = {
- {NS_ALG_MD5RSA, "RSA", "RSA KEY with MD5 hash"},
- {NS_ALG_DH, "DH", "Diffie Hellman"},
- {NS_ALG_DSA, "DSA", "Digital Signature Algorithm"},
- {NS_ALG_EXPIRE_ONLY, "EXPIREONLY", "No algorithm"},
- {NS_ALG_PRIVATE_OID, "PRIVATE", "Algorithm obtained from OID"},
- {0, NULL, NULL}
-};
-
-const struct res_sym __p_cert_syms[] attribute_hidden = {
- {cert_t_pkix, "PKIX", "PKIX (X.509v3) Certificate"},
- {cert_t_spki, "SPKI", "SPKI certificate"},
- {cert_t_pgp, "PGP", "PGP certificate"},
- {cert_t_url, "URL", "URL Private"},
- {cert_t_oid, "OID", "OID Private"},
- {0, NULL, NULL}
+ {S_ZONE, (char *) "ZONE"},
+ {S_PREREQ, (char *) "PREREQUISITE"},
+ {S_UPDATE, (char *) "UPDATE"},
+ {S_ADDT, (char *) "ADDITIONAL"},
+ {0, NULL, NULL}
};
/*
- * Names of RR types and qtypes. Types and qtypes are the same, except
- * that T_ANY is a qtype but not a type. (You can ask for records of type
- * T_ANY, but you can't have any records of that type in the database.)
+ * Names of RR types and qtypes. The list is incomplete because its
+ * size is part of the ABI.
*/
extern const struct res_sym __p_type_syms[];
libresolv_hidden_proto (__p_type_syms)
const struct res_sym __p_type_syms[] = {
- {ns_t_a, "A", "address"},
- {ns_t_ns, "NS", "name server"},
- {ns_t_md, "MD", "mail destination (deprecated)"},
- {ns_t_mf, "MF", "mail forwarder (deprecated)"},
- {ns_t_cname, "CNAME", "canonical name"},
- {ns_t_soa, "SOA", "start of authority"},
- {ns_t_mb, "MB", "mailbox"},
- {ns_t_mg, "MG", "mail group member"},
- {ns_t_mr, "MR", "mail rename"},
- {ns_t_null, "NULL", "null"},
- {ns_t_wks, "WKS", "well-known service (deprecated)"},
- {ns_t_ptr, "PTR", "domain name pointer"},
- {ns_t_hinfo, "HINFO", "host information"},
- {ns_t_minfo, "MINFO", "mailbox information"},
- {ns_t_mx, "MX", "mail exchanger"},
- {ns_t_txt, "TXT", "text"},
- {ns_t_rp, "RP", "responsible person"},
- {ns_t_afsdb, "AFSDB", "DCE or AFS server"},
- {ns_t_x25, "X25", "X25 address"},
- {ns_t_isdn, "ISDN", "ISDN address"},
- {ns_t_rt, "RT", "router"},
- {ns_t_nsap, "NSAP", "nsap address"},
- {ns_t_nsap_ptr, "NSAP_PTR", "domain name pointer"},
- {ns_t_sig, "SIG", "signature"},
- {ns_t_key, "KEY", "key"},
- {ns_t_px, "PX", "mapping information"},
- {ns_t_gpos, "GPOS", "geographical position (withdrawn)"},
- {ns_t_aaaa, "AAAA", "IPv6 address"},
- {ns_t_loc, "LOC", "location"},
- {ns_t_nxt, "NXT", "next valid name (unimplemented)"},
- {ns_t_eid, "EID", "endpoint identifier (unimplemented)"},
- {ns_t_nimloc, "NIMLOC", "NIMROD locator (unimplemented)"},
- {ns_t_srv, "SRV", "server selection"},
- {ns_t_atma, "ATMA", "ATM address (unimplemented)"},
- {ns_t_dname, "DNAME", "Non-terminal DNAME (for IPv6)"},
- {ns_t_tsig, "TSIG", "transaction signature"},
- {ns_t_ixfr, "IXFR", "incremental zone transfer"},
- {ns_t_axfr, "AXFR", "zone transfer"},
- {ns_t_zxfr, "ZXFR", "compressed zone transfer"},
- {ns_t_mailb, "MAILB", "mailbox-related data (deprecated)"},
- {ns_t_maila, "MAILA", "mail agent (deprecated)"},
- {ns_t_naptr, "NAPTR", "URN Naming Authority"},
- {ns_t_kx, "KX", "Key Exchange"},
- {ns_t_cert, "CERT", "Certificate"},
- {ns_t_any, "ANY", "\"any\""},
- {0, NULL, NULL}
+ {ns_t_a, (char *) "A", (char *) "address"},
+ {ns_t_ns, (char *) "NS", (char *) "name server"},
+ {ns_t_md, (char *) "MD", (char *) "mail destination (deprecated)"},
+ {ns_t_mf, (char *) "MF", (char *) "mail forwarder (deprecated)"},
+ {ns_t_cname, (char *) "CNAME", (char *) "canonical name"},
+ {ns_t_soa, (char *) "SOA", (char *) "start of authority"},
+ {ns_t_mb, (char *) "MB", (char *) "mailbox"},
+ {ns_t_mg, (char *) "MG", (char *) "mail group member"},
+ {ns_t_mr, (char *) "MR", (char *) "mail rename"},
+ {ns_t_null, (char *) "NULL", (char *) "null"},
+ {ns_t_wks, (char *) "WKS", (char *) "well-known service (deprecated)"},
+ {ns_t_ptr, (char *) "PTR", (char *) "domain name pointer"},
+ {ns_t_hinfo, (char *) "HINFO", (char *) "host information"},
+ {ns_t_minfo, (char *) "MINFO", (char *) "mailbox information"},
+ {ns_t_mx, (char *) "MX", (char *) "mail exchanger"},
+ {ns_t_txt, (char *) "TXT", (char *) "text"},
+ {ns_t_rp, (char *) "RP", (char *) "responsible person"},
+ {ns_t_afsdb, (char *) "AFSDB", (char *) "DCE or AFS server"},
+ {ns_t_x25, (char *) "X25", (char *) "X25 address"},
+ {ns_t_isdn, (char *) "ISDN", (char *) "ISDN address"},
+ {ns_t_rt, (char *) "RT", (char *) "router"},
+ {ns_t_nsap, (char *) "NSAP", (char *) "nsap address"},
+ {ns_t_nsap_ptr, (char *) "NSAP_PTR", (char *) "domain name pointer"},
+ {ns_t_sig, (char *) "SIG", (char *) "signature"},
+ {ns_t_key, (char *) "KEY", (char *) "key"},
+ {ns_t_px, (char *) "PX", (char *) "mapping information"},
+ {ns_t_gpos, (char *) "GPOS",
+ (char *) "geographical position (withdrawn)"},
+ {ns_t_aaaa, (char *) "AAAA", (char *) "IPv6 address"},
+ {ns_t_loc, (char *) "LOC", (char *) "location"},
+ {ns_t_nxt, (char *) "NXT", (char *) "next valid name (unimplemented)"},
+ {ns_t_eid, (char *) "EID", (char *) "endpoint identifier (unimplemented)"},
+ {ns_t_nimloc, (char *) "NIMLOC", (char *) "NIMROD locator (unimplemented)"},
+ {ns_t_srv, (char *) "SRV", (char *) "server selection"},
+ {ns_t_atma, (char *) "ATMA", (char *) "ATM address (unimplemented)"},
+ {ns_t_dname, (char *) "DNAME", (char *) "Non-terminal DNAME (for IPv6)"},
+ {ns_t_tsig, (char *) "TSIG", (char *) "transaction signature"},
+ {ns_t_ixfr, (char *) "IXFR", (char *) "incremental zone transfer"},
+ {ns_t_axfr, (char *) "AXFR", (char *) "zone transfer"},
+ {ns_t_mailb, (char *) "MAILB", (char *) "mailbox-related data (deprecated)"},
+ {ns_t_maila, (char *) "MAILA", (char *) "mail agent (deprecated)"},
+ {ns_t_naptr, (char *) "NAPTR", (char *) "URN Naming Authority"},
+ {ns_t_kx, (char *) "KX", (char *) "Key Exchange"},
+ {ns_t_cert, (char *) "CERT", (char *) "Certificate"},
+ {ns_t_any, (char *) "ANY", (char *) "\"any\""},
+ {0, NULL, NULL}, /* Padding to preserve ABI. */
+ {0, NULL, NULL}
};
libresolv_hidden_data_def (__p_type_syms)
@@ -455,22 +484,22 @@ libresolv_hidden_data_def (__p_type_syms)
* Names of DNS rcodes.
*/
const struct res_sym __p_rcode_syms[] attribute_hidden = {
- {ns_r_noerror, "NOERROR", "no error"},
- {ns_r_formerr, "FORMERR", "format error"},
- {ns_r_servfail, "SERVFAIL", "server failed"},
- {ns_r_nxdomain, "NXDOMAIN", "no such domain name"},
- {ns_r_notimpl, "NOTIMP", "not implemented"},
- {ns_r_refused, "REFUSED", "refused"},
- {ns_r_yxdomain, "YXDOMAIN", "domain name exists"},
- {ns_r_yxrrset, "YXRRSET", "rrset exists"},
- {ns_r_nxrrset, "NXRRSET", "rrset doesn't exist"},
- {ns_r_notauth, "NOTAUTH", "not authoritative"},
- {ns_r_notzone, "NOTZONE", "Not in zone"},
- {ns_r_max, "", ""},
- {ns_r_badsig, "BADSIG", "bad signature"},
- {ns_r_badkey, "BADKEY", "bad key"},
- {ns_r_badtime, "BADTIME", "bad time"},
- {0, NULL, NULL}
+ {ns_r_noerror, (char *) "NOERROR", (char *) "no error"},
+ {ns_r_formerr, (char *) "FORMERR", (char *) "format error"},
+ {ns_r_servfail, (char *) "SERVFAIL", (char *) "server failed"},
+ {ns_r_nxdomain, (char *) "NXDOMAIN", (char *) "no such domain name"},
+ {ns_r_notimpl, (char *) "NOTIMP", (char *) "not implemented"},
+ {ns_r_refused, (char *) "REFUSED", (char *) "refused"},
+ {ns_r_yxdomain, (char *) "YXDOMAIN", (char *) "domain name exists"},
+ {ns_r_yxrrset, (char *) "YXRRSET", (char *) "rrset exists"},
+ {ns_r_nxrrset, (char *) "NXRRSET", (char *) "rrset doesn't exist"},
+ {ns_r_notauth, (char *) "NOTAUTH", (char *) "not authoritative"},
+ {ns_r_notzone, (char *) "NOTZONE", (char *) "Not in zone"},
+ {ns_r_max, (char *) "", (char *) ""},
+ {ns_r_badsig, (char *) "BADSIG", (char *) "bad signature"},
+ {ns_r_badkey, (char *) "BADKEY", (char *) "bad key"},
+ {ns_r_badtime, (char *) "BADTIME", (char *) "bad time"},
+ {0, NULL, NULL}
};
int
@@ -535,7 +564,7 @@ libresolv_hidden_def (p_type)
/*
* Return a string for the type.
*/
-const char *
+static const char *
p_section(int section, int opcode) {
const struct res_sym *symbols;
@@ -569,9 +598,7 @@ p_option(u_long option) {
switch (option) {
case RES_INIT: return "init";
case RES_DEBUG: return "debug";
- case RES_AAONLY: return "aaonly(unimpl)";
case RES_USEVC: return "use-vc";
- case RES_PRIMARY: return "primry(unimpl)";
case RES_IGNTC: return "igntc";
case RES_RECURSE: return "recurs";
case RES_DEFNAMES: return "defnam";
@@ -580,18 +607,14 @@ p_option(u_long option) {
case RES_INSECURE1: return "insecure1";
case RES_INSECURE2: return "insecure2";
case RES_NOALIASES: return "noaliases";
- case RES_USE_INET6: return "inet6";
+ case DEPRECATED_RES_USE_INET6: return "inet6";
case RES_ROTATE: return "rotate";
- case RES_NOCHECKNAME: return "no-check-names(unimpl)";
- case RES_KEEPTSIG: return "keeptsig(unimpl)";
- case RES_BLAST: return "blast";
- case RES_USEBSTRING: return "ip6-bytestring";
- case RES_NOIP6DOTINT: return "no-ip6-dotint";
case RES_USE_EDNS0: return "edns0";
case RES_SNGLKUP: return "single-request";
case RES_SNGLKUPREOP: return "single-request-reopen";
case RES_USE_DNSSEC: return "dnssec";
case RES_NOTLDQUERY: return "no-tld-query";
+ case RES_NORELOAD: return "no-reload";
/* XXX nonreentrant */
default: sprintf(nbuf, "?0x%lx?", (u_long)option);
return (nbuf);
@@ -603,7 +626,7 @@ libresolv_hidden_def (p_option)
* Return a mnemonic for a time to live.
*/
const char *
-p_time(u_int32_t value) {
+p_time(uint32_t value) {
static char nbuf[40]; /* XXX nonreentrant */
if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0)
@@ -632,7 +655,7 @@ static const unsigned int poweroften[10]=
/* takes an XeY precision/size value, returns a string representation. */
static const char *
-precsize_ntoa (u_int8_t prec)
+precsize_ntoa (uint8_t prec)
{
static char retbuf[sizeof "90000000.00"]; /* XXX nonreentrant */
unsigned long val;
@@ -648,11 +671,11 @@ precsize_ntoa (u_int8_t prec)
}
/* converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
-static u_int8_t
+static uint8_t
precsize_aton (const char **strptr)
{
unsigned int mval = 0, cmval = 0;
- u_int8_t retval = 0;
+ uint8_t retval = 0;
const char *cp;
int exponent;
int mantissa;
@@ -689,11 +712,11 @@ precsize_aton (const char **strptr)
}
/* converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
-static u_int32_t
+static uint32_t
latlon2ul (const char **latlonstrptr, int *which)
{
const char *cp;
- u_int32_t retval;
+ uint32_t retval;
int deg = 0, min = 0, secs = 0, secsfrac = 0;
cp = *latlonstrptr;
@@ -792,12 +815,12 @@ loc_aton (const char *ascii, u_char *binary)
const char *cp, *maxcp;
u_char *bcp;
- u_int32_t latit = 0, longit = 0, alt = 0;
- u_int32_t lltemp1 = 0, lltemp2 = 0;
+ uint32_t latit = 0, longit = 0, alt = 0;
+ uint32_t lltemp1 = 0, lltemp2 = 0;
int altmeters = 0, altfrac = 0, altsign = 1;
- u_int8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
- u_int8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
- u_int8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
+ uint8_t hp = 0x16; /* default = 1e6 cm = 10000.00m = 10km */
+ uint8_t vp = 0x13; /* default = 1e3 cm = 10.00m */
+ uint8_t siz = 0x12; /* default = 1e2 cm = 1.00m */
int which1 = 0, which2 = 0;
cp = ascii;
@@ -883,7 +906,7 @@ loc_aton (const char *ascii, u_char *binary)
defaults:
bcp = binary;
- *bcp++ = (u_int8_t) 0; /* version byte */
+ *bcp++ = (uint8_t) 0; /* version byte */
*bcp++ = siz;
*bcp++ = hp;
*bcp++ = vp;
@@ -908,11 +931,11 @@ loc_ntoa (const u_char *binary, char *ascii)
char northsouth, eastwest;
int altmeters, altfrac, altsign;
- const u_int32_t referencealt = 100000 * 100;
+ const uint32_t referencealt = 100000 * 100;
int32_t latval, longval, altval;
- u_int32_t templ;
- u_int8_t sizeval, hpval, vpval, versionval;
+ uint32_t templ;
+ uint8_t sizeval, hpval, vpval, versionval;
char *sizestr, *hpstr, *vpstr;
@@ -1029,29 +1052,47 @@ dn_count_labels(const char *name) {
libresolv_hidden_def (__dn_count_labels)
+#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_27)
/*
* Make dates expressed in seconds-since-Jan-1-1970 easy to read.
* SIG records are required to be printed like this, by the Secure DNS RFC.
+ * This is an obsolescent function and does not handle dates outside the
+ * signed 32-bit range.
*/
char *
-p_secstodate (u_long secs) {
+__p_secstodate (u_long secs) {
/* XXX nonreentrant */
static char output[15]; /* YYYYMMDDHHMMSS and null */
time_t clock = secs;
struct tm *time;
-#ifdef HAVE_TIME_R
struct tm timebuf;
-
- time = gmtime_r(&clock, &timebuf);
-#else
- time = gmtime(&clock);
-#endif
+ /* The call to __gmtime_r can never produce a year overflowing
+ the range of int, given the check on SECS, but check for a
+ NULL return anyway to avoid a null pointer dereference in
+ case there are any other unspecified errors. */
+ if (secs > 0x7fffffff
+ || (time = __gmtime_r (&clock, &timebuf)) == NULL) {
+ strcpy (output, "<overflow>");
+ __set_errno (EOVERFLOW);
+ return output;
+ }
time->tm_year += 1900;
time->tm_mon += 1;
+ /* The struct tm fields, given the above range check,
+ must have values that mean this sprintf exactly fills the
+ buffer. But as of GCC 8 of 2017-11-21, GCC cannot tell
+ that, even given range checks on all fields with
+ __builtin_unreachable called for out-of-range values. */
+ DIAG_PUSH_NEEDS_COMMENT;
+# if __GNUC_PREREQ (7, 0)
+ DIAG_IGNORE_NEEDS_COMMENT (8, "-Wformat-overflow=");
+# endif
sprintf(output, "%04d%02d%02d%02d%02d%02d",
time->tm_year, time->tm_mon, time->tm_mday,
time->tm_hour, time->tm_min, time->tm_sec);
+ DIAG_POP_NEEDS_COMMENT;
return (output);
}
-libresolv_hidden_def (__p_secstodate)
+compat_symbol (libresolv, __p_secstodate, __p_secstodate, GLIBC_2_0);
+#endif
diff --git a/resolv/res_debug.h b/resolv/res_debug.h
deleted file mode 100644
index 2d8ad15d60..0000000000
--- a/resolv/res_debug.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright (c) 1999 by Internet Software Consortium.
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
- */
-
-#ifndef _RES_DEBUG_H_
-#define _RES_DEBUG_H_
-
-#ifndef DEBUG
-# define Dprint(cond, args) /*empty*/
-# define DprintQ(cond, args, query, size) /*empty*/
-# define Aerror(statp, file, string, error, address) /*empty*/
-# define Perror(statp, file, string, error) /*empty*/
-#else
-# define Dprint(cond, args) if (cond) {fprintf args;} else {}
-# define DprintQ(cond, args, query, size) if (cond) {\
- fprintf args;\
- res_pquery(statp, query, size, stdout);\
- } else {}
-#endif
-
-#endif /* _RES_DEBUG_H_ */
diff --git a/resolv/res_hconf.c b/resolv/res_hconf.c
index 5cd128916d..50b6d78711 100644
--- a/resolv/res_hconf.c
+++ b/resolv/res_hconf.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by David Mosberger (davidm@azstarnet.com).
@@ -21,9 +21,6 @@
Though mostly compatibly, the following differences exist compared
to the original implementation:
- - new command "spoof" takes an arguments like RESOLV_SPOOF_CHECK
- environment variable (i.e., `off', `nowarn', or `warn').
-
- line comments can appear anywhere (not just at the beginning of
a line)
*/
@@ -55,7 +52,6 @@
/* Environment vars that all user to override default behavior: */
#define ENV_HOSTCONF "RESOLV_HOST_CONF"
-#define ENV_SPOOF "RESOLV_SPOOF_CHECK"
#define ENV_TRIM_OVERR "RESOLV_OVERRIDE_TRIM_DOMAINS"
#define ENV_TRIM_ADD "RESOLV_ADD_TRIM_DOMAINS"
#define ENV_MULTI "RESOLV_MULTI"
@@ -65,7 +61,6 @@ enum parse_cbs
{
CB_none,
CB_arg_trimdomain_list,
- CB_arg_spoof,
CB_arg_bool
};
@@ -78,10 +73,7 @@ static const struct cmd
{
{"order", CB_none, 0},
{"trim", CB_arg_trimdomain_list, 0},
- {"spoof", CB_arg_spoof, 0},
{"multi", CB_arg_bool, HCONF_FLAG_MULTI},
- {"nospoof", CB_arg_bool, HCONF_FLAG_SPOOF},
- {"spoofalert", CB_arg_bool, HCONF_FLAG_SPOOFALERT},
{"reorder", CB_arg_bool, HCONF_FLAG_REORDER}
};
@@ -164,28 +156,6 @@ arg_trimdomain_list (const char *fname, int line_num, const char *args)
static const char *
-arg_spoof (const char *fname, int line_num, const char *args)
-{
- const char *start = args;
- size_t len;
-
- args = skip_string (args);
- len = args - start;
-
- if (len == 3 && __strncasecmp (start, "off", len) == 0)
- _res_hconf.flags &= ~(HCONF_FLAG_SPOOF | HCONF_FLAG_SPOOFALERT);
- else
- {
- _res_hconf.flags |= (HCONF_FLAG_SPOOF | HCONF_FLAG_SPOOFALERT);
- if ((len == 6 && __strncasecmp (start, "nowarn", len) == 0)
- || !(len == 4 && __strncasecmp (start, "warn", len) == 0))
- _res_hconf.flags &= ~HCONF_FLAG_SPOOFALERT;
- }
- return args;
-}
-
-
-static const char *
arg_bool (const char *fname, int line_num, const char *args, unsigned flag)
{
if (__strncasecmp (args, "on", 2) == 0)
@@ -261,8 +231,6 @@ parse_line (const char *fname, int line_num, const char *str)
if (c->cb == CB_arg_trimdomain_list)
str = arg_trimdomain_list (fname, line_num, str);
- else if (c->cb == CB_arg_spoof)
- str = arg_spoof (fname, line_num, str);
else if (c->cb == CB_arg_bool)
str = arg_bool (fname, line_num, str, c->arg);
else
@@ -325,10 +293,6 @@ do_init (void)
fclose (fp);
}
- envval = getenv (ENV_SPOOF);
- if (envval)
- arg_spoof (ENV_SPOOF, 1, envval);
-
envval = getenv (ENV_MULTI);
if (envval)
arg_bool (ENV_MULTI, 1, envval, HCONF_FLAG_MULTI);
@@ -348,7 +312,8 @@ do_init (void)
arg_trimdomain_list (ENV_TRIM_OVERR, 1, envval);
}
- _res_hconf.initialized = 1;
+ /* See comments on the declaration of _res_hconf. */
+ atomic_store_release (&_res_hconf.initialized, 1);
}
@@ -374,8 +339,8 @@ static struct netaddr
{
struct
{
- u_int32_t addr;
- u_int32_t mask;
+ uint32_t addr;
+ uint32_t mask;
} ipv4;
} u;
} *ifaddrs);
@@ -423,7 +388,7 @@ _res_hconf_reorder_addrs (struct hostent *hp)
/* Initialize interface table. */
/* The SIOCGIFNETMASK ioctl will only work on an AF_INET socket. */
- sd = __socket (AF_INET, SOCK_DGRAM, 0);
+ sd = __socket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
if (sd < 0)
return;
@@ -544,8 +509,8 @@ _res_hconf_reorder_addrs (struct hostent *hp)
for (j = 0; j < num_ifs_local; ++j)
{
- u_int32_t if_addr = ifaddrs[j].u.ipv4.addr;
- u_int32_t if_netmask = ifaddrs[j].u.ipv4.mask;
+ uint32_t if_addr = ifaddrs[j].u.ipv4.addr;
+ uint32_t if_netmask = ifaddrs[j].u.ipv4.mask;
if (((haddr->s_addr ^ if_addr) & if_netmask) == 0)
{
diff --git a/resolv/res_hconf.h b/resolv/res_hconf.h
index b97734df9e..49096b1f90 100644
--- a/resolv/res_hconf.h
+++ b/resolv/res_hconf.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1993-2016 Free Software Foundation, Inc.
+/* Copyright (C) 1993-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by David Mosberger (davidm@azstarnet.com).
@@ -25,6 +25,15 @@
struct hconf
{
+ /* We keep the INITIALIZED member only for backwards compatibility. New
+ code should just call _res_hconf_init unconditionally. For this field
+ to be used safely, users must ensure that either (1) a call to
+ _res_hconf_init happens-before any load from INITIALIZED, or (2) an
+ assignment of zero to INITIALIZED happens-before any load from it, and
+ these loads use acquire MO if the intent is to skip calling
+ _res_hconf_init if the load returns a nonzero value. Such acquire MO
+ loads will then synchronize with the release MO store to INITIALIZED
+ in do_init in res_hconf.c; see pthread_once for more detail. */
int initialized;
int unused1;
int unused2[4];
@@ -32,14 +41,12 @@ struct hconf
const char *trimdomain[TRIMDOMAINS_MAX];
unsigned int flags;
# define HCONF_FLAG_INITED (1 << 0) /* initialized? */
-# define HCONF_FLAG_SPOOF (1 << 1) /* refuse spoofed addresses */
-# define HCONF_FLAG_SPOOFALERT (1 << 2) /* syslog warning of spoofed */
# define HCONF_FLAG_REORDER (1 << 3) /* list best address first */
# define HCONF_FLAG_MULTI (1 << 4) /* see comments for gethtbyname() */
};
extern struct hconf _res_hconf;
-extern void _res_hconf_init (void);
+extern void _res_hconf_init (void) attribute_hidden;
extern void _res_hconf_trim_domain (char *domain);
extern void _res_hconf_trim_domains (struct hostent *hp);
extern void _res_hconf_reorder_addrs (struct hostent *hp);
diff --git a/resolv/res_init.c b/resolv/res_init.c
index e0b6a80dc7..f5e52cbbb9 100644
--- a/resolv/res_init.c
+++ b/resolv/res_init.c
@@ -1,3 +1,21 @@
+/* Resolver state initialization and resolv.conf parsing.
+ Copyright (C) 1995-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
/*
* Copyright (c) 1985, 1989, 1993
* The Regents of the University of California. All rights reserved.
@@ -64,14 +82,10 @@
* SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
-static const char rcsid[] = "$BINDId: res_init.c,v 8.16 2000/05/09 07:10:12 vixie Exp $";
-#endif /* LIBC_SCCS and not lint */
-
#include <ctype.h>
#include <netdb.h>
-#include <resolv.h>
+#include <resolv/resolv-internal.h>
+#include <res_hconf.h>
#include <stdio.h>
#include <stdio_ext.h>
#include <stdlib.h>
@@ -86,553 +100,608 @@ static const char rcsid[] = "$BINDId: res_init.c,v 8.16 2000/05/09 07:10:12 vixi
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
+#include <inet/net-internal.h>
+#include <errno.h>
+#include <resolv_conf.h>
-#include <not-cancel.h>
+static uint32_t net_mask (struct in_addr);
-/* Options. Should all be left alone. */
-#define RESOLVSORT
-#define RFC1535
-/* #undef DEBUG */
+int
+res_ninit (res_state statp)
+{
+ return __res_vinit (statp, 0);
+}
+libc_hidden_def (__res_ninit)
-static void res_setoptions (res_state, const char *, const char *)
- internal_function;
+/* Return true if CH separates the netmask in the "sortlist"
+ directive. */
+static inline bool
+is_sort_mask (char ch)
+{
+ return ch == '/' || ch == '&';
+}
-#ifdef RESOLVSORT
-static const char sort_mask_chars[] = "/&";
-#define ISSORTMASK(ch) (strchr(sort_mask_chars, ch) != NULL)
-static u_int32_t net_mask (struct in_addr) __THROW;
-#endif
+/* Array of name server addresses. */
+#define DYNARRAY_STRUCT nameserver_list
+#define DYNARRAY_ELEMENT const struct sockaddr *
+#define DYNARRAY_ELEMENT_FREE(e) free ((struct sockaddr *) *(e))
+#define DYNARRAY_INITIAL_SIZE 3
+#define DYNARRAY_PREFIX nameserver_list_
+#include <malloc/dynarray-skeleton.c>
+
+/* Array of strings for the search array. The backing store is
+ managed separately. */
+#define DYNARRAY_STRUCT search_list
+#define DYNARRAY_ELEMENT const char *
+#define DYNARRAY_INITIAL_SIZE 6
+#define DYNARRAY_PREFIX search_list_
+#include <malloc/dynarray-skeleton.c>
+
+/* Array of name server addresses. */
+#define DYNARRAY_STRUCT sort_list
+#define DYNARRAY_ELEMENT struct resolv_sortlist_entry
+#define DYNARRAY_INITIAL_SIZE 0
+#define DYNARRAY_PREFIX sort_list_
+#include <malloc/dynarray-skeleton.c>
+
+/* resolv.conf parser state and results. */
+struct resolv_conf_parser
+{
+ char *buffer; /* Temporary buffer for reading lines. */
-#if !defined(isascii) /* XXX - could be a function */
-# define isascii(c) (!(c & 0200))
-#endif
+ struct nameserver_list nameserver_list; /* Nameserver addresses. */
-#ifdef _LIBC
-unsigned long long int __res_initstamp attribute_hidden;
-#endif
+ char *search_list_store; /* Backing storage for search list entries. */
+ struct search_list search_list; /* Points into search_list_store. */
-/*
- * Resolver state default settings.
- */
+ struct sort_list sort_list; /* Address preference sorting list. */
-/*
- * Set up default settings. If the configuration file exist, the values
- * there will have precedence. Otherwise, the server address is set to
- * INADDR_ANY and the default domain name comes from the gethostname().
- *
- * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
- * rather than INADDR_ANY ("0.0.0.0") as the default name server address
- * since it was noted that INADDR_ANY actually meant ``the first interface
- * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
- * it had to be "up" in order for you to reach your own name server. It
- * was later decided that since the recommended practice is to always
- * install local static routes through 127.0.0.1 for all your network
- * interfaces, that we could solve this problem without a code change.
- *
- * The configuration file should always be used, since it is the only way
- * to specify a default domain. If you are running a server on your local
- * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
- * in the configuration file.
- *
- * Return 0 if completes successfully, -1 on error
- */
-int
-res_ninit(res_state statp) {
- extern int __res_vinit(res_state, int);
+ /* Configuration template. The non-array elements are filled in
+ directly. The array elements are updated prior to the call to
+ __resolv_conf_attach. */
+ struct resolv_conf template;
+};
- return (__res_vinit(statp, 0));
+/* Return true if *PREINIT contains actual preinitialization. */
+static bool
+has_preinit_values (const struct __res_state *preinit)
+{
+ return (preinit->retrans != 0 && preinit->retrans != RES_TIMEOUT)
+ || (preinit->retry != 0 && preinit->retry != RES_DFLRETRY)
+ || (preinit->options != 0
+ && (preinit->options & ~RES_INIT) != RES_DEFAULT);
}
-#ifdef _LIBC
-libc_hidden_def (__res_ninit)
-#endif
-/* This function has to be reachable by res_data.c but not publically. */
-int
-__res_vinit(res_state statp, int preinit) {
- FILE *fp;
- char *cp, **pp;
- int n;
- char buf[BUFSIZ];
- int nserv = 0; /* number of nameservers read from file */
- int have_serv6 = 0;
- int haveenv = 0;
- int havesearch = 0;
-#ifdef RESOLVSORT
- int nsort = 0;
- char *net;
-#endif
-#ifndef RFC1535
- int dots;
-#endif
-#ifdef _LIBC
- statp->_u._ext.initstamp = __res_initstamp;
-#endif
-
- if (!preinit) {
- statp->retrans = RES_TIMEOUT;
- statp->retry = RES_DFLRETRY;
- statp->options = RES_DEFAULT;
- statp->id = res_randomid();
- }
-
- statp->nscount = 0;
- statp->defdname[0] = '\0';
- statp->ndots = 1;
- statp->pfcode = 0;
- statp->_vcsock = -1;
- statp->_flags = 0;
- statp->qhook = NULL;
- statp->rhook = NULL;
- statp->_u._ext.nscount = 0;
- for (n = 0; n < MAXNS; n++)
- statp->_u._ext.nsaddrs[n] = NULL;
-
- /* Allow user to override the local domain definition */
- if ((cp = getenv("LOCALDOMAIN")) != NULL) {
- (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
- statp->defdname[sizeof(statp->defdname) - 1] = '\0';
- haveenv++;
-
- /*
- * Set search list to be blank-separated strings
- * from rest of env value. Permits users of LOCALDOMAIN
- * to still have a search list, and anyone to set the
- * one that they want to use as an individual (even more
- * important now that the rfc1535 stuff restricts searches)
- */
- cp = statp->defdname;
- pp = statp->dnsrch;
- *pp++ = cp;
- for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
- if (*cp == '\n') /* silly backwards compat */
- break;
- else if (*cp == ' ' || *cp == '\t') {
- *cp = 0;
- n = 1;
- } else if (n) {
- *pp++ = cp;
- n = 0;
- havesearch = 1;
- }
- }
- /* null terminate last domain if there are excess */
- while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
- cp++;
- *cp = '\0';
- *pp++ = 0;
- }
-
-#define MATCH(line, name) \
- (!strncmp(line, name, sizeof(name) - 1) && \
- (line[sizeof(name) - 1] == ' ' || \
- line[sizeof(name) - 1] == '\t'))
-
- if ((fp = fopen(_PATH_RESCONF, "rce")) != NULL) {
- /* No threads use this stream. */
- __fsetlocking (fp, FSETLOCKING_BYCALLER);
- /* read the config file */
- while (__fgets_unlocked(buf, sizeof(buf), fp) != NULL) {
- /* skip comments */
- if (*buf == ';' || *buf == '#')
- continue;
- /* read default domain name */
- if (MATCH(buf, "domain")) {
- if (haveenv) /* skip if have from environ */
- continue;
- cp = buf + sizeof("domain") - 1;
- while (*cp == ' ' || *cp == '\t')
- cp++;
- if ((*cp == '\0') || (*cp == '\n'))
- continue;
- strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
- statp->defdname[sizeof(statp->defdname) - 1] = '\0';
- if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
- *cp = '\0';
- havesearch = 0;
- continue;
- }
- /* set search list */
- if (MATCH(buf, "search")) {
- if (haveenv) /* skip if have from environ */
- continue;
- cp = buf + sizeof("search") - 1;
- while (*cp == ' ' || *cp == '\t')
- cp++;
- if ((*cp == '\0') || (*cp == '\n'))
- continue;
- strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
- statp->defdname[sizeof(statp->defdname) - 1] = '\0';
- if ((cp = strchr(statp->defdname, '\n')) != NULL)
- *cp = '\0';
- /*
- * Set search list to be blank-separated strings
- * on rest of line.
- */
- cp = statp->defdname;
- pp = statp->dnsrch;
- *pp++ = cp;
- for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
- if (*cp == ' ' || *cp == '\t') {
- *cp = 0;
- n = 1;
- } else if (n) {
- *pp++ = cp;
- n = 0;
- }
- }
- /* null terminate last domain if there are excess */
- while (*cp != '\0' && *cp != ' ' && *cp != '\t')
- cp++;
- *cp = '\0';
- *pp++ = 0;
- havesearch = 1;
- continue;
- }
- /* read nameservers to query */
- if (MATCH(buf, "nameserver") && nserv < MAXNS) {
- struct in_addr a;
-
- cp = buf + sizeof("nameserver") - 1;
- while (*cp == ' ' || *cp == '\t')
- cp++;
- if ((*cp != '\0') && (*cp != '\n')
- && __inet_aton(cp, &a)) {
- statp->nsaddr_list[nserv].sin_addr = a;
- statp->nsaddr_list[nserv].sin_family = AF_INET;
- statp->nsaddr_list[nserv].sin_port =
- htons(NAMESERVER_PORT);
- nserv++;
-#ifdef _LIBC
- } else {
- struct in6_addr a6;
- char *el;
-
- if ((el = strpbrk(cp, " \t\n")) != NULL)
- *el = '\0';
- if ((el = strchr(cp, SCOPE_DELIMITER)) != NULL)
- *el = '\0';
- if ((*cp != '\0') &&
- (__inet_pton(AF_INET6, cp, &a6) > 0)) {
- struct sockaddr_in6 *sa6;
-
- sa6 = malloc(sizeof(*sa6));
- if (sa6 != NULL) {
- sa6->sin6_family = AF_INET6;
- sa6->sin6_port = htons(NAMESERVER_PORT);
- sa6->sin6_flowinfo = 0;
- sa6->sin6_addr = a6;
-
- if (__glibc_likely (el == NULL))
- sa6->sin6_scope_id = 0;
- else {
- int try_numericscope = 1;
- if (IN6_IS_ADDR_LINKLOCAL (&a6)
- || IN6_IS_ADDR_MC_LINKLOCAL (&a6)) {
- sa6->sin6_scope_id
- = __if_nametoindex (el + 1);
- if (sa6->sin6_scope_id != 0)
- try_numericscope = 0;
- }
-
- if (try_numericscope) {
- char *end;
- sa6->sin6_scope_id
- = (uint32_t) strtoul (el + 1, &end,
- 10);
- if (*end != '\0')
- sa6->sin6_scope_id = 0;
- }
- }
-
- statp->nsaddr_list[nserv].sin_family = 0;
- statp->_u._ext.nsaddrs[nserv] = sa6;
- statp->_u._ext.nssocks[nserv] = -1;
- have_serv6 = 1;
- nserv++;
- }
- }
-#endif
- }
- continue;
- }
-#ifdef RESOLVSORT
- if (MATCH(buf, "sortlist")) {
- struct in_addr a;
-
- cp = buf + sizeof("sortlist") - 1;
- while (nsort < MAXRESOLVSORT) {
- while (*cp == ' ' || *cp == '\t')
- cp++;
- if (*cp == '\0' || *cp == '\n' || *cp == ';')
- break;
- net = cp;
- while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
- isascii(*cp) && !isspace(*cp))
- cp++;
- n = *cp;
- *cp = 0;
- if (__inet_aton(net, &a)) {
- statp->sort_list[nsort].addr = a;
- if (ISSORTMASK(n)) {
- *cp++ = n;
- net = cp;
- while (*cp && *cp != ';' &&
- isascii(*cp) && !isspace(*cp))
- cp++;
- n = *cp;
- *cp = 0;
- if (__inet_aton(net, &a)) {
- statp->sort_list[nsort].mask = a.s_addr;
- } else {
- statp->sort_list[nsort].mask =
- net_mask(statp->sort_list[nsort].addr);
- }
- } else {
- statp->sort_list[nsort].mask =
- net_mask(statp->sort_list[nsort].addr);
- }
- nsort++;
- }
- *cp = n;
- }
- continue;
- }
-#endif
- if (MATCH(buf, "options")) {
- res_setoptions(statp, buf + sizeof("options") - 1, "conf");
- continue;
- }
- }
- statp->nscount = nserv;
-#ifdef _LIBC
- if (have_serv6) {
- /* We try IPv6 servers again. */
- statp->ipv6_unavail = false;
- }
-#endif
-#ifdef RESOLVSORT
- statp->nsort = nsort;
-#endif
- (void) fclose(fp);
- }
- if (__builtin_expect(statp->nscount == 0, 0)) {
- statp->nsaddr.sin_addr = __inet_makeaddr(IN_LOOPBACKNET, 1);
- statp->nsaddr.sin_family = AF_INET;
- statp->nsaddr.sin_port = htons(NAMESERVER_PORT);
- statp->nscount = 1;
- }
- if (statp->defdname[0] == 0 &&
- __gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
- (cp = strchr(buf, '.')) != NULL)
- strcpy(statp->defdname, cp + 1);
-
- /* find components of local domain that might be searched */
- if (havesearch == 0) {
- pp = statp->dnsrch;
- *pp++ = statp->defdname;
- *pp = NULL;
-
-#ifndef RFC1535
- dots = 0;
- for (cp = statp->defdname; *cp; cp++)
- dots += (*cp == '.');
-
- cp = statp->defdname;
- while (pp < statp->dnsrch + MAXDFLSRCH) {
- if (dots < LOCALDOMAINPARTS)
- break;
- cp = __rawmemchr(cp, '.') + 1; /* we know there is one */
- *pp++ = cp;
- dots--;
- }
- *pp = NULL;
-#ifdef DEBUG
- if (statp->options & RES_DEBUG) {
- printf(";; res_init()... default dnsrch list:\n");
- for (pp = statp->dnsrch; *pp; pp++)
- printf(";;\t%s\n", *pp);
- printf(";;\t..END..\n");
- }
-#endif
-#endif /* !RFC1535 */
- }
-
- if ((cp = getenv("RES_OPTIONS")) != NULL)
- res_setoptions(statp, cp, "env");
- statp->options |= RES_INIT;
- return (0);
+static void
+resolv_conf_parser_init (struct resolv_conf_parser *parser,
+ const struct __res_state *preinit)
+{
+ parser->buffer = NULL;
+ parser->search_list_store = NULL;
+ nameserver_list_init (&parser->nameserver_list);
+ search_list_init (&parser->search_list);
+ sort_list_init (&parser->sort_list);
+
+ if (preinit != NULL)
+ {
+ parser->template.retrans = preinit->retrans;
+ parser->template.retry = preinit->retry;
+ parser->template.options = preinit->options | RES_INIT;
+ }
+ else
+ {
+ parser->template.retrans = RES_TIMEOUT;
+ parser->template.retry = RES_DFLRETRY;
+ parser->template.options = RES_DEFAULT | RES_INIT;
+ }
+ parser->template.ndots = 1;
}
static void
-internal_function
-res_setoptions(res_state statp, const char *options, const char *source) {
- const char *cp = options;
- int i;
-
-#ifdef DEBUG
- if (statp->options & RES_DEBUG)
- printf(";; res_setoptions(\"%s\", \"%s\")...\n",
- options, source);
-#endif
- while (*cp) {
- /* skip leading and inner runs of spaces */
- while (*cp == ' ' || *cp == '\t')
- cp++;
- /* search for and process individual options */
- if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
- i = atoi(cp + sizeof("ndots:") - 1);
- if (i <= RES_MAXNDOTS)
- statp->ndots = i;
- else
- statp->ndots = RES_MAXNDOTS;
-#ifdef DEBUG
- if (statp->options & RES_DEBUG)
- printf(";;\tndots=%d\n", statp->ndots);
-#endif
- } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
- i = atoi(cp + sizeof("timeout:") - 1);
- if (i <= RES_MAXRETRANS)
- statp->retrans = i;
- else
- statp->retrans = RES_MAXRETRANS;
- } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
- i = atoi(cp + sizeof("attempts:") - 1);
- if (i <= RES_MAXRETRY)
- statp->retry = i;
- else
- statp->retry = RES_MAXRETRY;
- } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
-#ifdef DEBUG
- if (!(statp->options & RES_DEBUG)) {
- printf(";; res_setoptions(\"%s\", \"%s\")..\n",
- options, source);
- statp->options |= RES_DEBUG;
- }
- printf(";;\tdebug\n");
-#endif
- } else {
- static const struct
- {
- char str[22];
- uint8_t len;
- uint8_t clear;
- unsigned long int flag;
- } options[] = {
-#define STRnLEN(str) str, sizeof (str) - 1
- { STRnLEN ("inet6"), 0, RES_USE_INET6 },
- { STRnLEN ("ip6-bytestring"), 0, RES_USEBSTRING },
- { STRnLEN ("no-ip6-dotint"), 0, RES_NOIP6DOTINT },
- { STRnLEN ("ip6-dotint"), 1, ~RES_NOIP6DOTINT },
- { STRnLEN ("rotate"), 0, RES_ROTATE },
- { STRnLEN ("no-check-names"), 0, RES_NOCHECKNAME },
- { STRnLEN ("edns0"), 0, RES_USE_EDNS0 },
- { STRnLEN ("single-request-reopen"), 0, RES_SNGLKUPREOP },
- { STRnLEN ("single-request"), 0, RES_SNGLKUP },
- { STRnLEN ("no_tld_query"), 0, RES_NOTLDQUERY },
- { STRnLEN ("no-tld-query"), 0, RES_NOTLDQUERY },
- { STRnLEN ("use-vc"), 0, RES_USEVC }
- };
-#define noptions (sizeof (options) / sizeof (options[0]))
- int i;
- for (i = 0; i < noptions; ++i)
- if (strncmp (cp, options[i].str, options[i].len) == 0)
- {
- if (options[i].clear)
- statp->options &= options[i].flag;
- else
- statp->options |= options[i].flag;
- break;
- }
- if (i == noptions) {
- /* XXX - print a warning here? */
- }
- }
- /* skip to next run of spaces */
- while (*cp && *cp != ' ' && *cp != '\t')
- cp++;
- }
+resolv_conf_parser_free (struct resolv_conf_parser *parser)
+{
+ free (parser->buffer);
+ free (parser->search_list_store);
+ nameserver_list_free (&parser->nameserver_list);
+ search_list_free (&parser->search_list);
+ sort_list_free (&parser->sort_list);
}
-#ifdef RESOLVSORT
-/* XXX - should really support CIDR which means explicit masks always. */
-/* XXX - should really use system's version of this */
-static u_int32_t
-net_mask (struct in_addr in)
+/* Allocate a struct sockaddr_in object on the heap, with the
+ specified address and port. */
+static struct sockaddr *
+allocate_address_v4 (struct in_addr a, uint16_t port)
{
- u_int32_t i = ntohl(in.s_addr);
-
- if (IN_CLASSA(i))
- return (htonl(IN_CLASSA_NET));
- else if (IN_CLASSB(i))
- return (htonl(IN_CLASSB_NET));
- return (htonl(IN_CLASSC_NET));
+ struct sockaddr_in *sa4 = malloc (sizeof (*sa4));
+ if (sa4 == NULL)
+ return NULL;
+ sa4->sin_family = AF_INET;
+ sa4->sin_addr = a;
+ sa4->sin_port = htons (port);
+ return (struct sockaddr *) sa4;
}
-#endif
-u_int
-res_randomid(void) {
- return 0xffff & __getpid();
+/* Try to obtain the domain name from the host name and store it in
+ *RESULT. Return false on memory allocation failure. If the domain
+ name cannot be determined for any other reason, write NULL to
+ *RESULT and return true. */
+static bool
+domain_from_hostname (char **result)
+{
+ char buf[256];
+ /* gethostbyname may not terminate the buffer. */
+ buf[sizeof (buf) - 1] = '\0';
+ if (__gethostname (buf, sizeof (buf) - 1) == 0)
+ {
+ char *dot = strchr (buf, '.');
+ if (dot != NULL)
+ {
+ *result = __strdup (dot + 1);
+ if (*result == NULL)
+ return false;
+ return true;
+ }
+ }
+ *result = NULL;
+ return true;
}
-#ifdef _LIBC
-libc_hidden_def (__res_randomid)
-#endif
+static void res_setoptions (struct resolv_conf_parser *, const char *options);
-/*
- * This routine is for closing the socket if a virtual circuit is used and
- * the program wants to close it. This provides support for endhostent()
- * which expects to close the socket.
- *
- * This routine is not expected to be user visible.
- */
-void
-__res_iclose(res_state statp, bool free_addr) {
- int ns;
-
- if (statp->_vcsock >= 0) {
- close_not_cancel_no_status(statp->_vcsock);
- statp->_vcsock = -1;
- statp->_flags &= ~(RES_F_VC | RES_F_CONN);
- }
- for (ns = 0; ns < statp->_u._ext.nscount; ns++)
- if (statp->_u._ext.nsaddrs[ns]) {
- if (statp->_u._ext.nssocks[ns] != -1) {
- close_not_cancel_no_status(statp->_u._ext.nssocks[ns]);
- statp->_u._ext.nssocks[ns] = -1;
- }
- if (free_addr) {
- free (statp->_u._ext.nsaddrs[ns]);
- statp->_u._ext.nsaddrs[ns] = NULL;
- }
- }
+/* Internal helper function for __res_vinit, to aid with resource
+ deallocation and error handling. Return true on success, false on
+ failure. */
+static bool
+res_vinit_1 (FILE *fp, struct resolv_conf_parser *parser)
+{
+ char *cp;
+ size_t buffer_size = 0;
+ bool haveenv = false;
+
+ /* Allow user to override the local domain definition. */
+ if ((cp = getenv ("LOCALDOMAIN")) != NULL)
+ {
+ /* The code below splits the string in place. */
+ cp = __strdup (cp);
+ if (cp == NULL)
+ return false;
+ free (parser->search_list_store);
+ parser->search_list_store = cp;
+ haveenv = true;
+
+ /* The string will be truncated as needed below. */
+ search_list_add (&parser->search_list, cp);
+
+ /* Set search list to be blank-separated strings from rest of
+ env value. Permits users of LOCALDOMAIN to still have a
+ search list, and anyone to set the one that they want to use
+ as an individual (even more important now that the rfc1535
+ stuff restricts searches). */
+ for (bool in_name = true; *cp != '\0'; cp++)
+ {
+ if (*cp == '\n')
+ {
+ *cp = '\0';
+ break;
+ }
+ else if (*cp == ' ' || *cp == '\t')
+ {
+ *cp = '\0';
+ in_name = false;
+ }
+ else if (!in_name)
+ {
+ search_list_add (&parser->search_list, cp);
+ in_name = true;
+ }
+ }
+ }
+
+#define MATCH(line, name) \
+ (!strncmp ((line), name, sizeof (name) - 1) \
+ && ((line)[sizeof (name) - 1] == ' ' \
+ || (line)[sizeof (name) - 1] == '\t'))
+
+ if (fp != NULL)
+ {
+ /* No threads use this stream. */
+ __fsetlocking (fp, FSETLOCKING_BYCALLER);
+ /* Read the config file. */
+ while (true)
+ {
+ {
+ ssize_t ret = __getline (&parser->buffer, &buffer_size, fp);
+ if (ret <= 0)
+ {
+ if (_IO_ferror_unlocked (fp))
+ return false;
+ else
+ break;
+ }
+ }
+
+ /* Skip comments. */
+ if (*parser->buffer == ';' || *parser->buffer == '#')
+ continue;
+ /* Read default domain name. */
+ if (MATCH (parser->buffer, "domain"))
+ {
+ if (haveenv)
+ /* LOCALDOMAIN overrides the configuration file. */
+ continue;
+ cp = parser->buffer + sizeof ("domain") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+
+ cp = __strdup (cp);
+ if (cp == NULL)
+ return false;
+ free (parser->search_list_store);
+ parser->search_list_store = cp;
+ search_list_clear (&parser->search_list);
+ search_list_add (&parser->search_list, cp);
+ /* Replace trailing whitespace. */
+ if ((cp = strpbrk (cp, " \t\n")) != NULL)
+ *cp = '\0';
+ continue;
+ }
+ /* Set search list. */
+ if (MATCH (parser->buffer, "search"))
+ {
+ if (haveenv)
+ /* LOCALDOMAIN overrides the configuration file. */
+ continue;
+ cp = parser->buffer + sizeof ("search") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+
+ {
+ char *p = strchr (cp, '\n');
+ if (p != NULL)
+ *p = '\0';
+ }
+ cp = __strdup (cp);
+ if (cp == NULL)
+ return false;
+ free (parser->search_list_store);
+ parser->search_list_store = cp;
+
+ /* The string is truncated below. */
+ search_list_clear (&parser->search_list);
+ search_list_add (&parser->search_list, cp);
+
+ /* Set search list to be blank-separated strings on rest
+ of line. */
+ for (bool in_name = true; *cp != '\0'; cp++)
+ {
+ if (*cp == ' ' || *cp == '\t')
+ {
+ *cp = '\0';
+ in_name = false;
+ }
+ else if (!in_name)
+ {
+ search_list_add (&parser->search_list, cp);
+ in_name = true;
+ }
+ }
+ continue;
+ }
+ /* Read nameservers to query. */
+ if (MATCH (parser->buffer, "nameserver"))
+ {
+ struct in_addr a;
+
+ cp = parser->buffer + sizeof ("nameserver") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ struct sockaddr *sa;
+ if ((*cp != '\0') && (*cp != '\n') && __inet_aton (cp, &a))
+ {
+ sa = allocate_address_v4 (a, NAMESERVER_PORT);
+ if (sa == NULL)
+ return false;
+ }
+ else
+ {
+ struct in6_addr a6;
+ char *el;
+
+ if ((el = strpbrk (cp, " \t\n")) != NULL)
+ *el = '\0';
+ if ((el = strchr (cp, SCOPE_DELIMITER)) != NULL)
+ *el = '\0';
+ if ((*cp != '\0') && (__inet_pton (AF_INET6, cp, &a6) > 0))
+ {
+ struct sockaddr_in6 *sa6;
+
+ sa6 = malloc (sizeof (*sa6));
+ if (sa6 == NULL)
+ return false;
+
+ sa6->sin6_family = AF_INET6;
+ sa6->sin6_port = htons (NAMESERVER_PORT);
+ sa6->sin6_flowinfo = 0;
+ sa6->sin6_addr = a6;
+
+ sa6->sin6_scope_id = 0;
+ if (__glibc_likely (el != NULL))
+ /* Ignore errors, for backwards
+ compatibility. */
+ __inet6_scopeid_pton
+ (&a6, el + 1, &sa6->sin6_scope_id);
+ sa = (struct sockaddr *) sa6;
+ }
+ else
+ /* IPv6 address parse failure. */
+ sa = NULL;
+ }
+ if (sa != NULL)
+ {
+ const struct sockaddr **p = nameserver_list_emplace
+ (&parser->nameserver_list);
+ if (p != NULL)
+ *p = sa;
+ else
+ {
+ free (sa);
+ return false;
+ }
+ }
+ continue;
+ }
+ if (MATCH (parser->buffer, "sortlist"))
+ {
+ struct in_addr a;
+
+ cp = parser->buffer + sizeof ("sortlist") - 1;
+ while (true)
+ {
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if (*cp == '\0' || *cp == '\n' || *cp == ';')
+ break;
+ char *net = cp;
+ while (*cp && !is_sort_mask (*cp) && *cp != ';'
+ && isascii (*cp) && !isspace (*cp))
+ cp++;
+ char separator = *cp;
+ *cp = 0;
+ struct resolv_sortlist_entry e;
+ if (__inet_aton (net, &a))
+ {
+ e.addr = a;
+ if (is_sort_mask (separator))
+ {
+ *cp++ = separator;
+ net = cp;
+ while (*cp && *cp != ';'
+ && isascii (*cp) && !isspace (*cp))
+ cp++;
+ separator = *cp;
+ *cp = 0;
+ if (__inet_aton (net, &a))
+ e.mask = a.s_addr;
+ else
+ e.mask = net_mask (e.addr);
+ }
+ else
+ e.mask = net_mask (e.addr);
+ sort_list_add (&parser->sort_list, e);
+ }
+ *cp = separator;
+ }
+ continue;
+ }
+ if (MATCH (parser->buffer, "options"))
+ {
+ res_setoptions (parser, parser->buffer + sizeof ("options") - 1);
+ continue;
+ }
+ }
+ fclose (fp);
+ }
+ if (__glibc_unlikely (nameserver_list_size (&parser->nameserver_list) == 0))
+ {
+ const struct sockaddr **p
+ = nameserver_list_emplace (&parser->nameserver_list);
+ if (p == NULL)
+ return false;
+ *p = allocate_address_v4 (__inet_makeaddr (IN_LOOPBACKNET, 1),
+ NAMESERVER_PORT);
+ if (*p == NULL)
+ return false;
+ }
+
+ if (search_list_size (&parser->search_list) == 0)
+ {
+ char *domain;
+ if (!domain_from_hostname (&domain))
+ return false;
+ if (domain != NULL)
+ {
+ free (parser->search_list_store);
+ parser->search_list_store = domain;
+ search_list_add (&parser->search_list, domain);
+ }
+ }
+
+ if ((cp = getenv ("RES_OPTIONS")) != NULL)
+ res_setoptions (parser, cp);
+
+ if (nameserver_list_has_failed (&parser->nameserver_list)
+ || search_list_has_failed (&parser->search_list)
+ || sort_list_has_failed (&parser->sort_list))
+ {
+ __set_errno (ENOMEM);
+ return false;
+ }
+
+ return true;
}
-libc_hidden_def (__res_iclose)
-void
-res_nclose(res_state statp)
+struct resolv_conf *
+__resolv_conf_load (struct __res_state *preinit)
{
- __res_iclose (statp, true);
+ /* Ensure that /etc/hosts.conf has been loaded (once). */
+ _res_hconf_init ();
+
+ FILE *fp = fopen (_PATH_RESCONF, "rce");
+ if (fp == NULL)
+ switch (errno)
+ {
+ case EACCES:
+ case EISDIR:
+ case ELOOP:
+ case ENOENT:
+ case ENOTDIR:
+ case EPERM:
+ /* Ignore these errors. They are persistent errors caused
+ by file system contents. */
+ break;
+ default:
+ /* Other errors refer to resource allocation problems and
+ need to be handled by the application. */
+ return NULL;
+ }
+
+ struct resolv_conf_parser parser;
+ resolv_conf_parser_init (&parser, preinit);
+
+ struct resolv_conf *conf = NULL;
+ if (res_vinit_1 (fp, &parser))
+ {
+ parser.template.nameserver_list
+ = nameserver_list_begin (&parser.nameserver_list);
+ parser.template.nameserver_list_size
+ = nameserver_list_size (&parser.nameserver_list);
+ parser.template.search_list = search_list_begin (&parser.search_list);
+ parser.template.search_list_size
+ = search_list_size (&parser.search_list);
+ parser.template.sort_list = sort_list_begin (&parser.sort_list);
+ parser.template.sort_list_size = sort_list_size (&parser.sort_list);
+ conf = __resolv_conf_allocate (&parser.template);
+ }
+ resolv_conf_parser_free (&parser);
+
+ return conf;
}
-#ifdef _LIBC
-libc_hidden_def (__res_nclose)
-#endif
-
-#ifdef _LIBC
-# ifdef _LIBC_REENTRANT
-/* This is called when a thread is exiting to free resources held in _res. */
-static void __attribute__ ((section ("__libc_thread_freeres_fn")))
-res_thread_freeres (void)
+
+/* Set up default settings. If the /etc/resolv.conf configuration
+ file exist, the values there will have precedence. Otherwise, the
+ server address is set to INADDR_LOOPBACK and the default domain
+ name comes from gethostname. The RES_OPTIONS and LOCALDOMAIN
+ environment variables can be used to override some settings.
+ Return 0 if completes successfully, -1 on error. */
+int
+__res_vinit (res_state statp, int preinit)
{
- if (_res.nscount == 0)
- /* Never called res_ninit. */
- return;
+ struct resolv_conf *conf;
+ if (preinit && has_preinit_values (statp))
+ /* For the preinit case, we cannot use the cached configuration
+ because some settings could be different. */
+ conf = __resolv_conf_load (statp);
+ else
+ conf = __resolv_conf_get_current ();
+ if (conf == NULL)
+ return -1;
+
+ bool ok = __resolv_conf_attach (statp, conf);
+ __resolv_conf_put (conf);
+ if (ok)
+ {
+ if (preinit)
+ statp->id = res_randomid ();
+ return 0;
+ }
+ else
+ return -1;
+}
- __res_iclose (&_res, true); /* Close any VC sockets. */
+static void
+res_setoptions (struct resolv_conf_parser *parser, const char *options)
+{
+ const char *cp = options;
+
+ while (*cp)
+ {
+ /* Skip leading and inner runs of spaces. */
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ /* Search for and process individual options. */
+ if (!strncmp (cp, "ndots:", sizeof ("ndots:") - 1))
+ {
+ int i = atoi (cp + sizeof ("ndots:") - 1);
+ if (i <= RES_MAXNDOTS)
+ parser->template.ndots = i;
+ else
+ parser->template.ndots = RES_MAXNDOTS;
+ }
+ else if (!strncmp (cp, "timeout:", sizeof ("timeout:") - 1))
+ {
+ int i = atoi (cp + sizeof ("timeout:") - 1);
+ if (i <= RES_MAXRETRANS)
+ parser->template.retrans = i;
+ else
+ parser->template.retrans = RES_MAXRETRANS;
+ }
+ else if (!strncmp (cp, "attempts:", sizeof ("attempts:") - 1))
+ {
+ int i = atoi (cp + sizeof ("attempts:") - 1);
+ if (i <= RES_MAXRETRY)
+ parser->template.retry = i;
+ else
+ parser->template.retry = RES_MAXRETRY;
+ }
+ else
+ {
+ static const struct
+ {
+ char str[22];
+ uint8_t len;
+ uint8_t clear;
+ unsigned long int flag;
+ } options[] = {
+#define STRnLEN(str) str, sizeof (str) - 1
+ { STRnLEN ("inet6"), 0, DEPRECATED_RES_USE_INET6 },
+ { STRnLEN ("rotate"), 0, RES_ROTATE },
+ { STRnLEN ("edns0"), 0, RES_USE_EDNS0 },
+ { STRnLEN ("single-request-reopen"), 0, RES_SNGLKUPREOP },
+ { STRnLEN ("single-request"), 0, RES_SNGLKUP },
+ { STRnLEN ("no_tld_query"), 0, RES_NOTLDQUERY },
+ { STRnLEN ("no-tld-query"), 0, RES_NOTLDQUERY },
+ { STRnLEN ("no-reload"), 0, RES_NORELOAD },
+ { STRnLEN ("use-vc"), 0, RES_USEVC }
+ };
+#define noptions (sizeof (options) / sizeof (options[0]))
+ for (int i = 0; i < noptions; ++i)
+ if (strncmp (cp, options[i].str, options[i].len) == 0)
+ {
+ if (options[i].clear)
+ parser->template.options &= options[i].flag;
+ else
+ parser->template.options |= options[i].flag;
+ break;
+ }
+ }
+ /* Skip to next run of spaces. */
+ while (*cp && *cp != ' ' && *cp != '\t')
+ cp++;
+ }
+}
+
+static uint32_t
+net_mask (struct in_addr in)
+{
+ uint32_t i = ntohl (in.s_addr);
- /* Make sure we do a full re-initialization the next time. */
- _res.options = 0;
+ if (IN_CLASSA (i))
+ return htonl (IN_CLASSA_NET);
+ else if (IN_CLASSB (i))
+ return htonl (IN_CLASSB_NET);
+ return htonl (IN_CLASSC_NET);
}
-text_set_element (__libc_thread_subfreeres, res_thread_freeres);
-text_set_element (__libc_subfreeres, res_thread_freeres);
-# endif
-#endif
diff --git a/resolv/res_libc.c b/resolv/res_libc.c
index a8394e0e7b..6d3e1d2c1a 100644
--- a/resolv/res_libc.c
+++ b/resolv/res_libc.c
@@ -1,3 +1,21 @@
+/* Definitions related to res_init linked into libc instead of libresolv.
+ Copyright (C) 1995-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
/*
* Copyright (c) 1995-1999 by Internet Software Consortium.
*
@@ -22,98 +40,46 @@
#include <arpa/nameser.h>
#include <resolv.h>
#include <libc-lock.h>
-
-
-/* The following bit is copied from res_data.c (where it is #ifdef'ed
- out) since res_init() should go into libc.so but the rest of that
- file should not. */
-
-extern unsigned long long int __res_initstamp attribute_hidden;
-/* We have atomic increment operations on 64-bit platforms. */
-#if __WORDSIZE == 64
-# define atomicinclock(lock) (void) 0
-# define atomicincunlock(lock) (void) 0
-# define atomicinc(var) catomic_increment (&(var))
-#else
-__libc_lock_define_initialized (static, lock);
-# define atomicinclock(lock) __libc_lock_lock (lock)
-# define atomicincunlock(lock) __libc_lock_unlock (lock)
-# define atomicinc(var) ++var
-#endif
+#include <resolv-internal.h>
int
-res_init(void) {
- extern int __res_vinit(res_state, int);
-
- /*
- * These three fields used to be statically initialized. This made
- * it hard to use this code in a shared library. It is necessary,
- * now that we're doing dynamic initialization here, that we preserve
- * the old semantics: if an application modifies one of these three
- * fields of _res before res_init() is called, res_init() will not
- * alter them. Of course, if an application is setting them to
- * _zero_ before calling res_init(), hoping to override what used
- * to be the static default, we can't detect it and unexpected results
- * will follow. Zero for any of these fields would make no sense,
- * so one can safely assume that the applications were already getting
- * unexpected results.
- *
- * _res.options is tricky since some apps were known to diddle the bits
- * before res_init() was first called. We can't replicate that semantic
- * with dynamic initialization (they may have turned bits off that are
- * set in RES_DEFAULT). Our solution is to declare such applications
- * "broken". They could fool us by setting RES_INIT but none do (yet).
- */
- if (!_res.retrans)
- _res.retrans = RES_TIMEOUT;
- if (!_res.retry)
- _res.retry = 4;
- if (!(_res.options & RES_INIT))
- _res.options = RES_DEFAULT;
- else if (_res.nscount > 0)
- __res_iclose (&_res, true); /* Close any VC sockets. */
-
- /*
- * This one used to initialize implicitly to zero, so unless the app
- * has set it to something in particular, we can randomize it now.
- */
- if (!_res.id)
- _res.id = res_randomid();
+res_init (void)
+{
+ /* These three fields used to be statically initialized. This made
+ it hard to use this code in a shared library. It is necessary,
+ now that we're doing dynamic initialization here, that we
+ preserve the old semantics: if an application modifies one of
+ these three fields of _res before res_init is called,
+ res_init will not alter them. Of course, if an application is
+ setting them to _zero_ before calling res_init, hoping to
+ override what used to be the static default, we can't detect it
+ and unexpected results will follow. Zero for any of these fields
+ would make no sense, so one can safely assume that the
+ applications were already getting unexpected results.
- atomicinclock (lock);
- /* Request all threads to re-initialize their resolver states,
- resolv.conf might have changed. */
- atomicinc (__res_initstamp);
- atomicincunlock (lock);
+ _res.options is tricky since some apps were known to diddle the
+ bits before res_init was first called. We can't replicate that
+ semantic with dynamic initialization (they may have turned bits
+ off that are set in RES_DEFAULT). Our solution is to declare
+ such applications "broken". They could fool us by setting
+ RES_INIT but none do (yet). */
+ if (!_res.retrans)
+ _res.retrans = RES_TIMEOUT;
+ if (!_res.retry)
+ _res.retry = RES_DFLRETRY;
+ if (!(_res.options & RES_INIT))
+ _res.options = RES_DEFAULT;
+ else if (_res.nscount > 0)
+ __res_iclose (&_res, true); /* Close any VC sockets. */
- return (__res_vinit(&_res, 1));
-}
+ /* This one used to initialize implicitly to zero, so unless the app
+ has set it to something in particular, we can randomize it *
+ now. */
+ if (!_res.id)
+ _res.id = res_randomid ();
-/* Initialize resp if RES_INIT is not yet set or if res_init in some other
- thread requested re-initializing. */
-int
-__res_maybe_init (res_state resp, int preinit)
-{
- if (resp->options & RES_INIT) {
- if (__res_initstamp != resp->_u._ext.initstamp) {
- if (resp->nscount > 0)
- __res_iclose (resp, true);
- return __res_vinit (resp, 1);
- }
- return 0;
- } else if (preinit) {
- if (!resp->retrans)
- resp->retrans = RES_TIMEOUT;
- if (!resp->retry)
- resp->retry = 4;
- resp->options = RES_DEFAULT;
- if (!resp->id)
- resp->id = res_randomid ();
- return __res_vinit (resp, 1);
- } else
- return __res_ninit (resp);
+ return __res_vinit (&_res, 1);
}
-libc_hidden_def (__res_maybe_init)
/* This needs to be after the use of _res in res_init, above. */
#undef _res
@@ -129,16 +95,15 @@ __thread struct __res_state *__resp = &_res;
extern __thread struct __res_state *__libc_resp
__attribute__ ((alias ("__resp"))) attribute_hidden;
+#include <shlib-compat.h>
+
/* We declare this with compat_symbol so that it's not
visible at link time. Programs must use the accessor functions. */
#ifdef SHARED
-# include <shlib-compat.h>
compat_symbol (libc, _res, _res, GLIBC_2_0);
#endif
-#include <shlib-compat.h>
-
-#if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2)
+#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_2)
# undef res_init
extern int __res_init_weak (void);
weak_extern (__res_init_weak);
diff --git a/resolv/res_mkquery.c b/resolv/res_mkquery.c
index 1635e6a035..213abeefad 100644
--- a/resolv/res_mkquery.c
+++ b/resolv/res_mkquery.c
@@ -1,3 +1,21 @@
+/* Creation of DNS query packets.
+ Copyright (C) 1995-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
/*
* Copyright (c) 1985, 1993
* The Regents of the University of California. All rights reserved.
@@ -64,204 +82,222 @@
* SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$BINDId: res_mkquery.c,v 8.12 1999/10/13 16:39:40 vixie Exp $";
-#endif /* LIBC_SCCS and not lint */
-
#include <sys/types.h>
#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <netdb.h>
-#include <resolv.h>
-#include <stdio.h>
+#include <resolv/resolv-internal.h>
+#include <resolv/resolv_context.h>
#include <string.h>
#include <sys/time.h>
+#include <shlib-compat.h>
-/* Options. Leave them on. */
-/* #define DEBUG */
-
-#ifdef _LIBC
-# include <hp-timing.h>
-# include <stdint.h>
-# if HP_TIMING_AVAIL
-# define RANDOM_BITS(Var) { uint64_t v64; HP_TIMING_NOW (v64); Var = v64; }
-# endif
+#include <hp-timing.h>
+#include <stdint.h>
+#if HP_TIMING_AVAIL
+# define RANDOM_BITS(Var) { uint64_t v64; HP_TIMING_NOW (v64); Var = v64; }
#endif
-/*
- * Form all types of queries.
- * Returns the size of the result or -1.
- */
int
-res_nmkquery(res_state statp,
- int op, /* opcode of query */
- const char *dname, /* domain name */
- int class, int type, /* class and type of query */
- const u_char *data, /* resource record data */
- int datalen, /* length of data */
- const u_char *newrr_in, /* new rr for modify or append */
- u_char *buf, /* buffer to put query */
- int buflen) /* size of buffer */
+__res_context_mkquery (struct resolv_context *ctx, int op, const char *dname,
+ int class, int type, const unsigned char *data,
+ unsigned char *buf, int buflen)
{
- HEADER *hp;
- u_char *cp;
- int n;
- u_char *dnptrs[20], **dpp, **lastdnptr;
-
-#ifdef DEBUG
- if (statp->options & RES_DEBUG)
- printf(";; res_nmkquery(%s, %s, %s, %s)\n",
- _res_opcodes[op], dname, p_class(class), p_type(type));
-#endif
- /*
- * Initialize header fields.
- */
- if ((buf == NULL) || (buflen < HFIXEDSZ))
- return (-1);
- memset(buf, 0, HFIXEDSZ);
- hp = (HEADER *) buf;
- /* We randomize the IDs every time. The old code just
- incremented by one after the initial randomization which
- still predictable if the application does multiple
- requests. */
- int randombits;
- do
- {
+ HEADER *hp;
+ unsigned char *cp;
+ int n;
+ unsigned char *dnptrs[20], **dpp, **lastdnptr;
+
+ if (class < 0 || class > 65535 || type < 0 || type > 65535)
+ return -1;
+
+ /* Initialize header fields. */
+ if ((buf == NULL) || (buflen < HFIXEDSZ))
+ return -1;
+ memset (buf, 0, HFIXEDSZ);
+ hp = (HEADER *) buf;
+ /* We randomize the IDs every time. The old code just incremented
+ by one after the initial randomization which still predictable if
+ the application does multiple requests. */
+ int randombits;
#ifdef RANDOM_BITS
- RANDOM_BITS (randombits);
+ RANDOM_BITS (randombits);
#else
- struct timeval tv;
- __gettimeofday (&tv, NULL);
- randombits = (tv.tv_sec << 8) ^ tv.tv_usec;
+ struct timeval tv;
+ __gettimeofday (&tv, NULL);
+ randombits = (tv.tv_sec << 8) ^ tv.tv_usec;
#endif
- }
- while ((randombits & 0xffff) == 0);
- statp->id = (statp->id + randombits) & 0xffff;
- hp->id = statp->id;
- hp->opcode = op;
- hp->rd = (statp->options & RES_RECURSE) != 0;
- hp->rcode = NOERROR;
- cp = buf + HFIXEDSZ;
- buflen -= HFIXEDSZ;
- dpp = dnptrs;
- *dpp++ = buf;
- *dpp++ = NULL;
- lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
- /*
- * perform opcode specific processing
- */
- switch (op) {
- case NS_NOTIFY_OP:
- if ((buflen -= QFIXEDSZ + (data == NULL ? 0 : RRFIXEDSZ)) < 0)
- return (-1);
- goto compose;
-
- case QUERY:
- if ((buflen -= QFIXEDSZ) < 0)
- return (-1);
- compose:
- n = ns_name_compress(dname, cp, buflen,
- (const u_char **) dnptrs,
- (const u_char **) lastdnptr);
- if (n < 0)
- return (-1);
- cp += n;
- buflen -= n;
- NS_PUT16 (type, cp);
- NS_PUT16 (class, cp);
- hp->qdcount = htons(1);
- if (op == QUERY || data == NULL)
- break;
- /*
- * Make an additional record for completion domain.
- */
- n = ns_name_compress((char *)data, cp, buflen,
- (const u_char **) dnptrs,
- (const u_char **) lastdnptr);
- if (__glibc_unlikely (n < 0))
- return (-1);
- cp += n;
- buflen -= n;
- NS_PUT16 (T_NULL, cp);
- NS_PUT16 (class, cp);
- NS_PUT32 (0, cp);
- NS_PUT16 (0, cp);
- hp->arcount = htons(1);
- break;
-
- case IQUERY:
- /*
- * Initialize answer section
- */
- if (__glibc_unlikely (buflen < 1 + RRFIXEDSZ + datalen))
- return (-1);
- *cp++ = '\0'; /* no domain name */
- NS_PUT16 (type, cp);
- NS_PUT16 (class, cp);
- NS_PUT32 (0, cp);
- NS_PUT16 (datalen, cp);
- if (datalen) {
- memcpy(cp, data, datalen);
- cp += datalen;
- }
- hp->ancount = htons(1);
- break;
-
- default:
- return (-1);
- }
- return (cp - buf);
+
+ hp->id = randombits;
+ hp->opcode = op;
+ hp->rd = (ctx->resp->options & RES_RECURSE) != 0;
+ hp->rcode = NOERROR;
+ cp = buf + HFIXEDSZ;
+ buflen -= HFIXEDSZ;
+ dpp = dnptrs;
+ *dpp++ = buf;
+ *dpp++ = NULL;
+ lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+
+ /* Perform opcode specific processing. */
+ switch (op)
+ {
+ case NS_NOTIFY_OP:
+ if ((buflen -= QFIXEDSZ + (data == NULL ? 0 : RRFIXEDSZ)) < 0)
+ return -1;
+ goto compose;
+
+ case QUERY:
+ if ((buflen -= QFIXEDSZ) < 0)
+ return -1;
+ compose:
+ n = ns_name_compress (dname, cp, buflen,
+ (const unsigned char **) dnptrs,
+ (const unsigned char **) lastdnptr);
+ if (n < 0)
+ return -1;
+ cp += n;
+ buflen -= n;
+ NS_PUT16 (type, cp);
+ NS_PUT16 (class, cp);
+ hp->qdcount = htons (1);
+ if (op == QUERY || data == NULL)
+ break;
+
+ /* Make an additional record for completion domain. */
+ n = ns_name_compress ((char *)data, cp, buflen,
+ (const unsigned char **) dnptrs,
+ (const unsigned char **) lastdnptr);
+ if (__glibc_unlikely (n < 0))
+ return -1;
+ cp += n;
+ buflen -= n;
+ NS_PUT16 (T_NULL, cp);
+ NS_PUT16 (class, cp);
+ NS_PUT32 (0, cp);
+ NS_PUT16 (0, cp);
+ hp->arcount = htons (1);
+ break;
+
+ default:
+ return -1;
+ }
+ return cp - buf;
+}
+
+/* Common part of res_nmkquery and res_mkquery. */
+static int
+context_mkquery_common (struct resolv_context *ctx,
+ int op, const char *dname, int class, int type,
+ const unsigned char *data,
+ unsigned char *buf, int buflen)
+{
+ if (ctx == NULL)
+ return -1;
+ int result = __res_context_mkquery
+ (ctx, op, dname, class, type, data, buf, buflen);
+ if (result >= 2)
+ memcpy (&ctx->resp->id, buf, 2);
+ __resolv_context_put (ctx);
+ return result;
}
-libresolv_hidden_def (res_nmkquery)
+/* Form all types of queries. Returns the size of the result or -1 on
+ error.
-/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
-#ifndef T_OPT
-#define T_OPT 41
-#endif
+ STATP points to an initialized resolver state. OP is the opcode of
+ the query. DNAME is the domain. CLASS and TYPE are the DNS query
+ class and type. DATA can be NULL; otherwise, it is a pointer to a
+ domain name which is included in the generated packet (if op ==
+ NS_NOTIFY_OP). BUF must point to the out buffer of BUFLEN bytes.
+ DATALEN and NEWRR_IN are currently ignored. */
int
-__res_nopt(res_state statp,
- int n0, /* current offset in buffer */
- u_char *buf, /* buffer to put query */
- int buflen, /* size of buffer */
- int anslen) /* UDP answer buffer size */
+res_nmkquery (res_state statp, int op, const char *dname,
+ int class, int type,
+ const unsigned char *data, int datalen,
+ const unsigned char *newrr_in,
+ unsigned char *buf, int buflen)
{
- u_int16_t flags = 0;
+ return context_mkquery_common
+ (__resolv_context_get_override (statp),
+ op, dname, class, type, data, buf, buflen);
+}
-#ifdef DEBUG
- if ((statp->options & RES_DEBUG) != 0U)
- printf(";; res_nopt()\n");
-#endif
+int
+res_mkquery (int op, const char *dname, int class, int type,
+ const unsigned char *data, int datalen,
+ const unsigned char *newrr_in,
+ unsigned char *buf, int buflen)
+{
+ return context_mkquery_common
+ (__resolv_context_get_preinit (),
+ op, dname, class, type, data, buf, buflen);
+}
- HEADER *hp = (HEADER *) buf;
- u_char *cp = buf + n0;
- u_char *ep = buf + buflen;
+/* Create an OPT resource record. Return the length of the final
+ packet, or -1 on error.
- if ((ep - cp) < 1 + RRFIXEDSZ)
- return -1;
+ STATP must be an initialized resolver state. N0 is the current
+ number of bytes of the packet (already written to BUF by the
+ aller). BUF is the packet being constructed. The array it
+ pointers to must be BUFLEN bytes long. ANSLEN is the advertised
+ EDNS buffer size (to be included in the OPT resource record). */
+int
+__res_nopt (struct resolv_context *ctx,
+ int n0, unsigned char *buf, int buflen, int anslen)
+{
+ uint16_t flags = 0;
+ HEADER *hp = (HEADER *) buf;
+ unsigned char *cp = buf + n0;
+ unsigned char *ep = buf + buflen;
- *cp++ = 0; /* "." */
+ if ((ep - cp) < 1 + RRFIXEDSZ)
+ return -1;
- NS_PUT16(T_OPT, cp); /* TYPE */
- NS_PUT16(MIN(anslen, 0xffff), cp); /* CLASS = UDP payload size */
- *cp++ = NOERROR; /* extended RCODE */
- *cp++ = 0; /* EDNS version */
+ /* Add the root label. */
+ *cp++ = 0;
- if (statp->options & RES_USE_DNSSEC) {
-#ifdef DEBUG
- if (statp->options & RES_DEBUG)
- printf(";; res_opt()... ENDS0 DNSSEC\n");
-#endif
- flags |= NS_OPT_DNSSEC_OK;
- }
+ NS_PUT16 (T_OPT, cp); /* Record type. */
+
+ /* Lowering the advertised buffer size based on the actual
+ answer buffer size is desirable because the server will
+ minimize the reply to fit into the UDP packet (and A
+ non-minimal response might not fit the buffer).
+
+ The RESOLV_EDNS_BUFFER_SIZE limit could still result in TCP
+ fallback and a non-minimal response which has to be
+ hard-truncated in the stub resolver, but this is price to
+ pay for avoiding fragmentation. (This issue does not
+ affect the nss_dns functions because they use the stub
+ resolver in such a way that it allocates a properly sized
+ response buffer.) */
+ {
+ uint16_t buffer_size;
+ if (anslen < 512)
+ buffer_size = 512;
+ else if (anslen > RESOLV_EDNS_BUFFER_SIZE)
+ buffer_size = RESOLV_EDNS_BUFFER_SIZE;
+ else
+ buffer_size = anslen;
+ NS_PUT16 (buffer_size, cp);
+ }
- NS_PUT16(flags, cp);
- NS_PUT16(0, cp); /* RDLEN */
- hp->arcount = htons(ntohs(hp->arcount) + 1);
+ *cp++ = NOERROR; /* Extended RCODE. */
+ *cp++ = 0; /* EDNS version. */
- return cp - buf;
+ if (ctx->resp->options & RES_USE_DNSSEC)
+ flags |= NS_OPT_DNSSEC_OK;
+
+ NS_PUT16 (flags, cp);
+ NS_PUT16 (0, cp); /* RDATA length (no options are preent). */
+ hp->arcount = htons (ntohs (hp->arcount) + 1);
+
+ return cp - buf;
}
-libresolv_hidden_def (__res_nopt)
+
+#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_2)
+# undef res_mkquery
+weak_alias (__res_mkquery, res_mkquery);
+#endif
diff --git a/resolv/res_query.c b/resolv/res_query.c
index 95470a93e9..ebbe5a6a4e 100644
--- a/resolv/res_query.c
+++ b/resolv/res_query.c
@@ -64,11 +64,6 @@
* SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$BINDId: res_query.c,v 8.20 2000/02/29 05:39:12 vixie Exp $";
-#endif /* LIBC_SCCS and not lint */
-
#include <assert.h>
#include <sys/types.h>
#include <sys/param.h>
@@ -79,12 +74,12 @@ static const char rcsid[] = "$BINDId: res_query.c,v 8.20 2000/02/29 05:39:12 vix
#include <errno.h>
#include <netdb.h>
#include <resolv.h>
+#include <resolv/resolv-internal.h>
+#include <resolv/resolv_context.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-
-/* Options. Leave them on. */
-/* #undef DEBUG */
+#include <shlib-compat.h>
#if PACKETSZ > 65536
#define MAXPACKET PACKETSZ
@@ -95,39 +90,33 @@ static const char rcsid[] = "$BINDId: res_query.c,v 8.20 2000/02/29 05:39:12 vix
#define QUERYSIZE (HFIXEDSZ + QFIXEDSZ + MAXCDNAME + 1)
static int
-__libc_res_nquerydomain(res_state statp, const char *name, const char *domain,
- int class, int type, u_char *answer, int anslen,
- u_char **answerp, u_char **answerp2, int *nanswerp2,
- int *resplen2, int *answerp2_malloced);
-
-/*
- * Formulate a normal query, send, and await answer.
- * Returned answer is placed in supplied buffer "answer".
- * Perform preliminary check of answer, returning success only
- * if no error is indicated and the answer count is nonzero.
- * Return the size of the response on success, -1 on error.
- * Error number is left in H_ERRNO.
- *
- * Caller must parse answer and determine whether it answers the question.
- */
+__res_context_querydomain (struct resolv_context *,
+ const char *name, const char *domain,
+ int class, int type, unsigned char *answer, int anslen,
+ unsigned char **answerp, unsigned char **answerp2, int *nanswerp2,
+ int *resplen2, int *answerp2_malloced);
+
+/* Formulate a normal query, send, and await answer. Returned answer
+ is placed in supplied buffer ANSWER. Perform preliminary check of
+ answer, returning success only if no error is indicated and the
+ answer count is nonzero. Return the size of the response on
+ success, -1 on error. Error number is left in h_errno.
+
+ Caller must parse answer and determine whether it answers the
+ question. */
int
-__libc_res_nquery(res_state statp,
- const char *name, /* domain name */
- int class, int type, /* class and type of query */
- u_char *answer, /* buffer to put answer */
- int anslen, /* size of answer buffer */
- u_char **answerp, /* if buffer needs to be enlarged */
- u_char **answerp2,
- int *nanswerp2,
- int *resplen2,
- int *answerp2_malloced)
+__res_context_query (struct resolv_context *ctx, const char *name,
+ int class, int type,
+ unsigned char *answer, int anslen,
+ unsigned char **answerp, unsigned char **answerp2,
+ int *nanswerp2, int *resplen2, int *answerp2_malloced)
{
+ struct __res_state *statp = ctx->resp;
HEADER *hp = (HEADER *) answer;
HEADER *hp2;
int n, use_malloc = 0;
- u_int oflags = statp->_flags;
- size_t bufsize = (type == T_UNSPEC ? 2 : 1) * QUERYSIZE;
+ size_t bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * QUERYSIZE;
u_char *buf = alloca (bufsize);
u_char *query1 = buf;
int nquery1 = -1;
@@ -137,21 +126,18 @@ __libc_res_nquery(res_state statp,
again:
hp->rcode = NOERROR; /* default */
-#ifdef DEBUG
- if (statp->options & RES_DEBUG)
- printf(";; res_query(%s, %d, %d)\n", name, class, type);
-#endif
-
- if (type == T_UNSPEC)
+ if (type == T_QUERY_A_AND_AAAA)
{
- n = res_nmkquery(statp, QUERY, name, class, T_A, NULL, 0, NULL,
- query1, bufsize);
+ n = __res_context_mkquery (ctx, QUERY, name, class, T_A, NULL,
+ query1, bufsize);
if (n > 0)
{
- if ((oflags & RES_F_EDNS0ERR) == 0
- && (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
+ if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
{
- n = __res_nopt(statp, n, query1, bufsize, anslen / 2);
+ /* Use RESOLV_EDNS_BUFFER_SIZE because the receive
+ buffer can be reallocated. */
+ n = __res_nopt (ctx, n, query1, bufsize,
+ RESOLV_EDNS_BUFFER_SIZE);
if (n < 0)
goto unspec_nomem;
}
@@ -167,13 +153,14 @@ __libc_res_nquery(res_state statp,
}
int nused = n + npad;
query2 = buf + nused;
- n = res_nmkquery(statp, QUERY, name, class, T_AAAA, NULL, 0,
- NULL, query2, bufsize - nused);
+ n = __res_context_mkquery (ctx, QUERY, name, class, T_AAAA,
+ NULL, query2, bufsize - nused);
if (n > 0
- && (oflags & RES_F_EDNS0ERR) == 0
&& (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
- n = __res_nopt(statp, n, query2, bufsize - nused - n,
- anslen / 2);
+ /* Use RESOLV_EDNS_BUFFER_SIZE because the receive
+ buffer can be reallocated. */
+ n = __res_nopt (ctx, n, query2, bufsize,
+ RESOLV_EDNS_BUFFER_SIZE);
nquery2 = n;
}
@@ -181,21 +168,29 @@ __libc_res_nquery(res_state statp,
}
else
{
- n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
- query1, bufsize);
+ n = __res_context_mkquery (ctx, QUERY, name, class, type, NULL,
+ query1, bufsize);
if (n > 0
- && (oflags & RES_F_EDNS0ERR) == 0
&& (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0)
- n = __res_nopt(statp, n, query1, bufsize, anslen);
+ {
+ /* Use RESOLV_EDNS_BUFFER_SIZE if the receive buffer
+ can be reallocated. */
+ size_t advertise;
+ if (answerp == NULL)
+ advertise = anslen;
+ else
+ advertise = RESOLV_EDNS_BUFFER_SIZE;
+ n = __res_nopt (ctx, n, query1, bufsize, advertise);
+ }
nquery1 = n;
}
- if (__builtin_expect (n <= 0, 0) && !use_malloc) {
+ if (__glibc_unlikely (n <= 0) && !use_malloc) {
/* Retry just in case res_nmkquery failed because of too
short buffer. Shouldn't happen. */
- bufsize = (type == T_UNSPEC ? 2 : 1) * MAXPACKET;
+ bufsize = (type == T_QUERY_A_AND_AAAA ? 2 : 1) * MAXPACKET;
buf = malloc (bufsize);
if (buf != NULL) {
query1 = buf;
@@ -204,42 +199,24 @@ __libc_res_nquery(res_state statp,
}
}
if (__glibc_unlikely (n <= 0)) {
- /* If the query choked with EDNS0, retry without EDNS0. */
- if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0
- && ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) {
- statp->_flags |= RES_F_EDNS0ERR;
-#ifdef DEBUG
- if (statp->options & RES_DEBUG)
- printf(";; res_nquery: retry without EDNS0\n");
-#endif
- goto again;
- }
-#ifdef DEBUG
- if (statp->options & RES_DEBUG)
- printf(";; res_query: mkquery failed\n");
-#endif
RES_SET_H_ERRNO(statp, NO_RECOVERY);
if (use_malloc)
free (buf);
return (n);
}
assert (answerp == NULL || (void *) *answerp == (void *) answer);
- n = __libc_res_nsend(statp, query1, nquery1, query2, nquery2, answer,
- anslen, answerp, answerp2, nanswerp2, resplen2,
- answerp2_malloced);
+ n = __res_context_send (ctx, query1, nquery1, query2, nquery2, answer,
+ anslen, answerp, answerp2, nanswerp2, resplen2,
+ answerp2_malloced);
if (use_malloc)
free (buf);
if (n < 0) {
-#ifdef DEBUG
- if (statp->options & RES_DEBUG)
- printf(";; res_query: send error\n");
-#endif
RES_SET_H_ERRNO(statp, TRY_AGAIN);
return (n);
}
if (answerp != NULL)
- /* __libc_res_nsend might have reallocated the buffer. */
+ /* __res_context_send might have reallocated the buffer. */
hp = (HEADER *) *answerp;
/* We simplify the following tests by assigning HP to HP2 or
@@ -263,15 +240,6 @@ __libc_res_nquery(res_state statp,
if ((hp->rcode != NOERROR || ntohs(hp->ancount) == 0)
&& (hp2->rcode != NOERROR || ntohs(hp2->ancount) == 0)) {
-#ifdef DEBUG
- if (statp->options & RES_DEBUG) {
- printf(";; rcode = %d, ancount=%d\n", hp->rcode,
- ntohs(hp->ancount));
- if (hp != hp2)
- printf(";; rcode2 = %d, ancount2=%d\n", hp2->rcode,
- ntohs(hp2->ancount));
- }
-#endif
switch (hp->rcode == NOERROR ? hp2->rcode : hp->rcode) {
case NXDOMAIN:
if ((hp->rcode == NOERROR && ntohs (hp->ancount) != 0)
@@ -308,7 +276,24 @@ __libc_res_nquery(res_state statp,
success:
return (n);
}
-libresolv_hidden_def (__libc_res_nquery)
+libresolv_hidden_def (__res_context_query)
+
+/* Common part of res_nquery and res_query. */
+static int
+context_query_common (struct resolv_context *ctx,
+ const char *name, int class, int type,
+ unsigned char *answer, int anslen)
+{
+ if (ctx == NULL)
+ {
+ RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
+ return -1;
+ }
+ int result = __res_context_query (ctx, name, class, type, answer, anslen,
+ NULL, NULL, NULL, NULL, NULL);
+ __resolv_context_put (ctx);
+ return result;
+}
int
res_nquery(res_state statp,
@@ -317,30 +302,31 @@ res_nquery(res_state statp,
u_char *answer, /* buffer to put answer */
int anslen) /* size of answer buffer */
{
- return __libc_res_nquery(statp, name, class, type, answer, anslen,
- NULL, NULL, NULL, NULL, NULL);
+ return context_query_common
+ (__resolv_context_get_override (statp), name, class, type, answer, anslen);
}
-libresolv_hidden_def (res_nquery)
-/*
- * Formulate a normal query, send, and retrieve answer in supplied buffer.
- * Return the size of the response on success, -1 on error.
- * If enabled, implement search rules until answer or unrecoverable failure
- * is detected. Error code, if any, is left in H_ERRNO.
- */
int
-__libc_res_nsearch(res_state statp,
- const char *name, /* domain name */
- int class, int type, /* class and type of query */
- u_char *answer, /* buffer to put answer */
- int anslen, /* size of answer */
- u_char **answerp,
- u_char **answerp2,
- int *nanswerp2,
- int *resplen2,
- int *answerp2_malloced)
+res_query (const char *name, int class, int type,
+ unsigned char *answer, int anslen)
{
- const char *cp, * const *domain;
+ return context_query_common
+ (__resolv_context_get (), name, class, type, answer, anslen);
+}
+
+/* Formulate a normal query, send, and retrieve answer in supplied
+ buffer. Return the size of the response on success, -1 on error.
+ If enabled, implement search rules until answer or unrecoverable
+ failure is detected. Error code, if any, is left in h_errno. */
+int
+__res_context_search (struct resolv_context *ctx,
+ const char *name, int class, int type,
+ unsigned char *answer, int anslen,
+ unsigned char **answerp, unsigned char **answerp2,
+ int *nanswerp2, int *resplen2, int *answerp2_malloced)
+{
+ struct __res_state *statp = ctx->resp;
+ const char *cp;
HEADER *hp = (HEADER *) answer;
char tmp[NS_MAXDNAME];
u_int dots;
@@ -360,16 +346,11 @@ __libc_res_nsearch(res_state statp,
trailing_dot++;
/* If there aren't any dots, it could be a user-level alias. */
- if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
- return (__libc_res_nquery(statp, cp, class, type, answer,
- anslen, answerp, answerp2,
- nanswerp2, resplen2, answerp2_malloced));
-
-#ifdef DEBUG
- if (statp->options & RES_DEBUG)
- printf("dots=%d, statp->ndots=%d, trailing_dot=%d, name=%s\n",
- (int)dots,(int)statp->ndots,(int)trailing_dot,name);
-#endif
+ if (!dots && (cp = __res_context_hostalias
+ (ctx, name, tmp, sizeof tmp))!= NULL)
+ return __res_context_query (ctx, cp, class, type, answer,
+ anslen, answerp, answerp2,
+ nanswerp2, resplen2, answerp2_malloced);
/*
* If there are enough dots in the name, let's just give it a
@@ -378,10 +359,10 @@ __libc_res_nsearch(res_state statp,
*/
saved_herrno = -1;
if (dots >= statp->ndots || trailing_dot) {
- ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
- answer, anslen, answerp,
- answerp2, nanswerp2, resplen2,
- answerp2_malloced);
+ ret = __res_context_querydomain (ctx, name, NULL, class, type,
+ answer, anslen, answerp,
+ answerp2, nanswerp2, resplen2,
+ answerp2_malloced);
if (ret > 0 || trailing_dot
/* If the second response is valid then we use that. */
|| (ret == 0 && resplen2 != NULL && *resplen2 > 0))
@@ -411,13 +392,14 @@ __libc_res_nsearch(res_state statp,
(dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0)) {
int done = 0;
- for (domain = (const char * const *)statp->dnsrch;
- *domain && !done;
- domain++) {
- const char *dname = domain[0];
+ for (size_t domain_index = 0; !done; ++domain_index) {
+ const char *dname = __resolv_context_search_list
+ (ctx, domain_index);
+ if (dname == NULL)
+ break;
searched = 1;
- /* __libc_res_nquerydoman concatenates name
+ /* __res_context_querydoman concatenates name
with dname with a "." in between. If we
pass it in dname the "." we got from the
configured default search path, we'll end
@@ -431,11 +413,10 @@ __libc_res_nsearch(res_state statp,
if (dname[0] == '\0')
root_on_list++;
- ret = __libc_res_nquerydomain(statp, name, dname,
- class, type,
- answer, anslen, answerp,
- answerp2, nanswerp2,
- resplen2, answerp2_malloced);
+ ret = __res_context_querydomain
+ (ctx, name, dname, class, type,
+ answer, anslen, answerp, answerp2, nanswerp2,
+ resplen2, answerp2_malloced);
if (ret > 0 || (ret == 0 && resplen2 != NULL
&& *resplen2 > 0))
return (ret);
@@ -503,10 +484,10 @@ __libc_res_nsearch(res_state statp,
*/
if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0)
&& !(tried_as_is || root_on_list)) {
- ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
- answer, anslen, answerp,
- answerp2, nanswerp2, resplen2,
- answerp2_malloced);
+ ret = __res_context_querydomain
+ (ctx, name, NULL, class, type,
+ answer, anslen, answerp, answerp2, nanswerp2,
+ resplen2, answerp2_malloced);
if (ret > 0 || (ret == 0 && resplen2 != NULL
&& *resplen2 > 0))
return (ret);
@@ -534,7 +515,24 @@ __libc_res_nsearch(res_state statp,
RES_SET_H_ERRNO(statp, TRY_AGAIN);
return (-1);
}
-libresolv_hidden_def (__libc_res_nsearch)
+libresolv_hidden_def (__res_context_search)
+
+/* Common part of res_nsearch and res_search. */
+static int
+context_search_common (struct resolv_context *ctx,
+ const char *name, int class, int type,
+ unsigned char *answer, int anslen)
+{
+ if (ctx == NULL)
+ {
+ RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
+ return -1;
+ }
+ int result = __res_context_search (ctx, name, class, type, answer, anslen,
+ NULL, NULL, NULL, NULL, NULL);
+ __resolv_context_put (ctx);
+ return result;
+}
int
res_nsearch(res_state statp,
@@ -543,36 +541,34 @@ res_nsearch(res_state statp,
u_char *answer, /* buffer to put answer */
int anslen) /* size of answer */
{
- return __libc_res_nsearch(statp, name, class, type, answer,
- anslen, NULL, NULL, NULL, NULL, NULL);
+ return context_search_common
+ (__resolv_context_get_override (statp), name, class, type, answer, anslen);
}
-libresolv_hidden_def (res_nsearch)
-/*
- * Perform a call on res_query on the concatenation of name and domain.
- */
+int
+res_search (const char *name, int class, int type,
+ unsigned char *answer, int anslen)
+{
+ return context_search_common
+ (__resolv_context_get (), name, class, type, answer, anslen);
+}
+
+/* Perform a call on res_query on the concatenation of name and
+ domain. */
static int
-__libc_res_nquerydomain(res_state statp,
- const char *name,
- const char *domain,
- int class, int type, /* class and type of query */
- u_char *answer, /* buffer to put answer */
- int anslen, /* size of answer */
- u_char **answerp,
- u_char **answerp2,
- int *nanswerp2,
- int *resplen2,
- int *answerp2_malloced)
+__res_context_querydomain (struct resolv_context *ctx,
+ const char *name, const char *domain,
+ int class, int type,
+ unsigned char *answer, int anslen,
+ unsigned char **answerp, unsigned char **answerp2,
+ int *nanswerp2, int *resplen2,
+ int *answerp2_malloced)
{
+ struct __res_state *statp = ctx->resp;
char nbuf[MAXDNAME];
const char *longname = nbuf;
size_t n, d;
-#ifdef DEBUG
- if (statp->options & RES_DEBUG)
- printf(";; res_nquerydomain(%s, %s, %d, %d)\n",
- name, domain?domain:"<Nil>", class, type);
-#endif
if (domain == NULL) {
n = strlen(name);
@@ -594,9 +590,28 @@ __libc_res_nquerydomain(res_state statp,
}
sprintf(nbuf, "%s.%s", name, domain);
}
- return (__libc_res_nquery(statp, longname, class, type, answer,
- anslen, answerp, answerp2, nanswerp2,
- resplen2, answerp2_malloced));
+ return __res_context_query (ctx, longname, class, type, answer,
+ anslen, answerp, answerp2, nanswerp2,
+ resplen2, answerp2_malloced);
+}
+
+/* Common part of res_nquerydomain and res_querydomain. */
+static int
+context_querydomain_common (struct resolv_context *ctx,
+ const char *name, const char *domain,
+ int class, int type,
+ unsigned char *answer, int anslen)
+{
+ if (ctx == NULL)
+ {
+ RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
+ return -1;
+ }
+ int result = __res_context_querydomain (ctx, name, domain, class, type,
+ answer, anslen,
+ NULL, NULL, NULL, NULL, NULL);
+ __resolv_context_put (ctx);
+ return result;
}
int
@@ -607,19 +622,28 @@ res_nquerydomain(res_state statp,
u_char *answer, /* buffer to put answer */
int anslen) /* size of answer */
{
- return __libc_res_nquerydomain(statp, name, domain, class, type,
- answer, anslen, NULL, NULL, NULL, NULL,
- NULL);
+ return context_querydomain_common
+ (__resolv_context_get_override (statp),
+ name, domain, class, type, answer, anslen);
+}
+
+int
+res_querydomain (const char *name, const char *domain, int class, int type,
+ unsigned char *answer, int anslen)
+{
+ return context_querydomain_common
+ (__resolv_context_get (), name, domain, class, type, answer, anslen);
}
-libresolv_hidden_def (res_nquerydomain)
const char *
-res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
+__res_context_hostalias (struct resolv_context *ctx,
+ const char *name, char *dst, size_t siz)
+{
char *file, *cp1, *cp2;
char buf[BUFSIZ];
FILE *fp;
- if (statp->options & RES_NOALIASES)
+ if (ctx->resp->options & RES_NOALIASES)
return (NULL);
file = getenv("HOSTALIASES");
if (file == NULL || (fp = fopen(file, "rce")) == NULL)
@@ -649,4 +673,43 @@ res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
fclose(fp);
return (NULL);
}
-libresolv_hidden_def (res_hostalias)
+libresolv_hidden_def (__res_context_hostalias)
+
+/* Common part of res_hostalias and hostalias. */
+static const char *
+context_hostalias_common (struct resolv_context *ctx,
+ const char *name, char *dst, size_t siz)
+{
+ if (ctx == NULL)
+ {
+ RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
+ return NULL;
+ }
+ const char *result = __res_context_hostalias (ctx, name, dst, siz);
+ __resolv_context_put (ctx);
+ return result;
+}
+
+const char *
+res_hostalias (res_state statp, const char *name, char *dst, size_t siz)
+{
+ return context_hostalias_common
+ (__resolv_context_get_override (statp), name, dst, siz);
+}
+
+const char *
+hostalias (const char *name)
+{
+ static char abuf[MAXDNAME];
+ return context_hostalias_common
+ (__resolv_context_get (), name, abuf, sizeof (abuf));
+}
+
+#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_2)
+# undef res_query
+# undef res_querydomain
+# undef res_search
+weak_alias (__res_query, res_query);
+weak_alias (__res_querydomain, res_querydomain);
+weak_alias (__res_search, res_search);
+#endif
diff --git a/resolv/res_randomid.c b/resolv/res_randomid.c
new file mode 100644
index 0000000000..b96865c515
--- /dev/null
+++ b/resolv/res_randomid.c
@@ -0,0 +1,92 @@
+/* Legacy libresolv random number generator.
+ Copyright (C) 1995-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/*
+ * Copyright (c) 1985, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+#include <resolv.h>
+#include <unistd.h>
+
+unsigned int
+res_randomid (void) {
+ return 0xffff & __getpid ();
+}
+libc_hidden_def (__res_randomid)
diff --git a/resolv/res_send.c b/resolv/res_send.c
index 25c19f12c3..947ebf5212 100644
--- a/resolv/res_send.c
+++ b/resolv/res_send.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2016 Free Software Foundation, Inc.
+/* Copyright (C) 2016-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -81,11 +81,6 @@
* SOFTWARE.
*/
-#if defined(LIBC_SCCS) && !defined(lint)
-static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
-static const char rcsid[] = "$BINDId: res_send.c,v 8.38 2000/03/30 20:16:51 vixie Exp $";
-#endif /* LIBC_SCCS and not lint */
-
/*
* Send query to name server and wait for reply.
*/
@@ -106,14 +101,15 @@ static const char rcsid[] = "$BINDId: res_send.c,v 8.38 2000/03/30 20:16:51 vixi
#include <errno.h>
#include <fcntl.h>
#include <netdb.h>
-#include <resolv.h>
+#include <resolv/resolv-internal.h>
+#include <resolv/resolv_context.h>
#include <signal.h>
-#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <kernel-features.h>
-#include <libc-internal.h>
+#include <libc-diag.h>
+#include <hp-timing.h>
#if PACKETSZ > 65536
#define MAXPACKET PACKETSZ
@@ -185,15 +181,11 @@ evNowTime(struct timespec *res) {
}
-/* Options. Leave them on. */
-/* #undef DEBUG */
-#include "res_debug.h"
-
#define EXT(res) ((res)->_u._ext)
/* Forward. */
-static struct sockaddr *get_nsaddr (res_state, int);
+static struct sockaddr *get_nsaddr (res_state, unsigned int);
static int send_vc(res_state, const u_char *, int,
const u_char *, int,
u_char **, int *, int *, int, u_char **,
@@ -203,11 +195,6 @@ static int send_dg(res_state, const u_char *, int,
u_char **, int *, int *, int,
int *, int *, u_char **,
u_char **, int *, int *, int *);
-#ifdef DEBUG
-static void Aerror(const res_state, FILE *, const char *, int,
- const struct sockaddr *);
-static void Perror(const res_state, FILE *, const char *, int);
-#endif
static int sock_eq(struct sockaddr_in6 *, struct sockaddr_in6 *);
/* Public. */
@@ -257,6 +244,12 @@ res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp)
return (0);
}
+int
+res_isourserver (const struct sockaddr_in *inp)
+{
+ return res_ourserver_p (&_res, (const struct sockaddr_in6 *) inp);
+}
+
/* int
* res_nameinquery(name, type, class, buf, eom)
* look for (name,type,class) in the query section of packet (buf,eom)
@@ -296,6 +289,62 @@ res_nameinquery(const char *name, int type, int class,
}
libresolv_hidden_def (res_nameinquery)
+/* Returns a shift value for the name server index. Used to implement
+ RES_ROTATE. */
+static unsigned int
+nameserver_offset (struct __res_state *statp)
+{
+ /* If we only have one name server or rotation is disabled, return
+ offset 0 (no rotation). */
+ unsigned int nscount = statp->nscount;
+ if (nscount <= 1 || !(statp->options & RES_ROTATE))
+ return 0;
+
+ /* Global offset. The lowest bit indicates whether the offset has
+ been initialized with a random value. Use relaxed MO to access
+ global_offset because all we need is a sequence of roughly
+ sequential value. */
+ static unsigned int global_offset;
+ unsigned int offset = atomic_fetch_add_relaxed (&global_offset, 2);
+ if ((offset & 1) == 0)
+ {
+ /* Initialization is required. */
+#if HP_TIMING_AVAIL
+ uint64_t ticks;
+ HP_TIMING_NOW (ticks);
+ offset = ticks;
+#else
+ struct timeval tv;
+ __gettimeofday (&tv, NULL);
+ offset = ((tv.tv_sec << 8) ^ tv.tv_usec);
+#endif
+ /* The lowest bit is the most random. Preserve it. */
+ offset <<= 1;
+
+ /* Store the new starting value. atomic_fetch_add_relaxed
+ returns the old value, so emulate that by storing the new
+ (incremented) value. Concurrent initialization with
+ different random values is harmless. */
+ atomic_store_relaxed (&global_offset, (offset | 1) + 2);
+ }
+
+ /* Remove the initialization bit. */
+ offset >>= 1;
+
+ /* Avoid the division in the most common cases. */
+ switch (nscount)
+ {
+ case 2:
+ return offset & 1;
+ case 3:
+ return offset % 3;
+ case 4:
+ return offset & 3;
+ default:
+ return offset % nscount;
+ }
+}
+
/* int
* res_queriesmatch(buf1, eom1, buf2, eom2)
* is there a 1:1 mapping of (name,type,class)
@@ -352,12 +401,15 @@ res_queriesmatch(const u_char *buf1, const u_char *eom1,
libresolv_hidden_def (res_queriesmatch)
int
-__libc_res_nsend(res_state statp, const u_char *buf, int buflen,
- const u_char *buf2, int buflen2,
- u_char *ans, int anssiz, u_char **ansp, u_char **ansp2,
- int *nansp2, int *resplen2, int *ansp2_malloced)
+__res_context_send (struct resolv_context *ctx,
+ const unsigned char *buf, int buflen,
+ const unsigned char *buf2, int buflen2,
+ unsigned char *ans, int anssiz,
+ unsigned char **ansp, unsigned char **ansp2,
+ int *nansp2, int *resplen2, int *ansp2_malloced)
{
- int gotsomewhere, terrno, try, v_circuit, resplen, ns, n;
+ struct __res_state *statp = ctx->resp;
+ int gotsomewhere, terrno, try, v_circuit, resplen, n;
if (statp->nscount == 0) {
__set_errno (ESRCH);
@@ -369,24 +421,6 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
return (-1);
}
-#ifdef USE_HOOKS
- if (__glibc_unlikely (statp->qhook || statp->rhook)) {
- if (anssiz < MAXPACKET && ansp) {
- /* Always allocate MAXPACKET, callers expect
- this specific size. */
- u_char *buf = malloc (MAXPACKET);
- if (buf == NULL)
- return (-1);
- memcpy (buf, ans, HFIXEDSZ);
- *ansp = buf;
- ans = buf;
- anssiz = MAXPACKET;
- }
- }
-#endif
-
- DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
- (stdout, ";; res_send()\n"), buf, buflen);
v_circuit = ((statp->options & RES_USEVC)
|| buflen > PACKETSZ
|| buflen2 > PACKETSZ);
@@ -403,7 +437,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
if (EXT(statp).nscount != statp->nscount)
needclose++;
else
- for (ns = 0; ns < statp->nscount; ns++) {
+ for (unsigned int ns = 0; ns < statp->nscount; ns++) {
if (statp->nsaddr_list[ns].sin_family != 0
&& !sock_eq((struct sockaddr_in6 *)
&statp->nsaddr_list[ns],
@@ -423,7 +457,7 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
* Maybe initialize our private copy of the ns_addr_list.
*/
if (EXT(statp).nscount == 0) {
- for (ns = 0; ns < statp->nscount; ns++) {
+ for (unsigned int ns = 0; ns < statp->nscount; ns++) {
EXT(statp).nssocks[ns] = -1;
if (statp->nsaddr_list[ns].sin_family == 0)
continue;
@@ -437,91 +471,29 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
'\0',
sizeof (struct sockaddr_in6)
- sizeof (struct sockaddr_in));
+ else
+ return -1;
}
EXT(statp).nscount = statp->nscount;
}
- /*
- * Some resolvers want to even out the load on their nameservers.
- * Note that RES_BLAST overrides RES_ROTATE.
- */
- if (__builtin_expect ((statp->options & RES_ROTATE) != 0, 0) &&
- (statp->options & RES_BLAST) == 0) {
- struct sockaddr_in ina;
- struct sockaddr_in6 *inp;
- int lastns = statp->nscount - 1;
- int fd;
-
- inp = EXT(statp).nsaddrs[0];
- ina = statp->nsaddr_list[0];
- fd = EXT(statp).nssocks[0];
- for (ns = 0; ns < lastns; ns++) {
- EXT(statp).nsaddrs[ns] = EXT(statp).nsaddrs[ns + 1];
- statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
- EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
- }
- EXT(statp).nsaddrs[lastns] = inp;
- statp->nsaddr_list[lastns] = ina;
- EXT(statp).nssocks[lastns] = fd;
- }
+ /* Name server index offset. Used to implement
+ RES_ROTATE. */
+ unsigned int ns_offset = nameserver_offset (statp);
/*
* Send request, RETRY times, or until successful.
*/
for (try = 0; try < statp->retry; try++) {
- for (ns = 0; ns < statp->nscount; ns++)
+ for (unsigned ns_shift = 0; ns_shift < statp->nscount; ns_shift++)
{
-#ifdef DEBUG
- char tmpbuf[40];
-#endif
-#if defined USE_HOOKS || defined DEBUG
- struct sockaddr *nsap = get_nsaddr (statp, ns);
-#endif
+ /* The actual name server index. This implements
+ RES_ROTATE. */
+ unsigned int ns = ns_shift + ns_offset;
+ if (ns >= statp->nscount)
+ ns -= statp->nscount;
same_ns:
-#ifdef USE_HOOKS
- if (__glibc_unlikely (statp->qhook != NULL)) {
- int done = 0, loops = 0;
-
- do {
- res_sendhookact act;
-
- struct sockaddr_in *nsap4;
- nsap4 = (struct sockaddr_in *) nsap;
- act = (*statp->qhook)(&nsap4, &buf, &buflen,
- ans, anssiz, &resplen);
- nsap = (struct sockaddr_in6 *) nsap4;
- switch (act) {
- case res_goahead:
- done = 1;
- break;
- case res_nextns:
- __res_iclose(statp, false);
- goto next_ns;
- case res_done:
- return (resplen);
- case res_modified:
- /* give the hook another try */
- if (++loops < 42) /*doug adams*/
- break;
- /*FALLTHROUGH*/
- case res_error:
- /*FALLTHROUGH*/
- default:
- return (-1);
- }
- } while (!done);
- }
-#endif
-
- Dprint(statp->options & RES_DEBUG,
- (stdout, ";; Querying server (# %d) address = %s\n",
- ns + 1, inet_ntop(nsap->sa_family,
- (nsap->sa_family == AF_INET6
- ? (void *) &((struct sockaddr_in6 *) nsap)->sin6_addr
- : (void *) &((struct sockaddr_in *) nsap)->sin_addr),
- tmpbuf, sizeof (tmpbuf))));
-
if (__glibc_unlikely (v_circuit)) {
/* Use VC; at most one attempt per server. */
try = statp->retry;
@@ -551,22 +523,6 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
resplen = n;
- Dprint((statp->options & RES_DEBUG) ||
- ((statp->pfcode & RES_PRF_REPLY) &&
- (statp->pfcode & RES_PRF_HEAD1)),
- (stdout, ";; got answer:\n"));
-
- DprintQ((statp->options & RES_DEBUG) ||
- (statp->pfcode & RES_PRF_REPLY),
- (stdout, "%s", ""),
- ans, (resplen > anssiz) ? anssiz : resplen);
- if (buf2 != NULL) {
- DprintQ((statp->options & RES_DEBUG) ||
- (statp->pfcode & RES_PRF_REPLY),
- (stdout, "%s", ""),
- *ansp2, (*resplen2 > *nansp2) ? *nansp2 : *resplen2);
- }
-
/*
* If we have temporarily opened a virtual circuit,
* or if we haven't been asked to keep a socket open,
@@ -576,38 +532,6 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
(statp->options & RES_STAYOPEN) == 0) {
__res_iclose(statp, false);
}
-#ifdef USE_HOOKS
- if (__glibc_unlikely (statp->rhook)) {
- int done = 0, loops = 0;
-
- do {
- res_sendhookact act;
-
- act = (*statp->rhook)((struct sockaddr_in *)
- nsap, buf, buflen,
- ans, anssiz, &resplen);
- switch (act) {
- case res_goahead:
- case res_done:
- done = 1;
- break;
- case res_nextns:
- __res_iclose(statp, false);
- goto next_ns;
- case res_modified:
- /* give the hook another try */
- if (++loops < 42) /*doug adams*/
- break;
- /*FALLTHROUGH*/
- case res_error:
- /*FALLTHROUGH*/
- default:
- return (-1);
- }
- } while (!done);
-
- }
-#endif
return (resplen);
next_ns: ;
} /*foreach ns*/
@@ -623,20 +547,44 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
return (-1);
}
+/* Common part of res_nsend and res_send. */
+static int
+context_send_common (struct resolv_context *ctx,
+ const unsigned char *buf, int buflen,
+ unsigned char *ans, int anssiz)
+{
+ if (ctx == NULL)
+ {
+ RES_SET_H_ERRNO (&_res, NETDB_INTERNAL);
+ return -1;
+ }
+ int result = __res_context_send (ctx, buf, buflen, NULL, 0, ans, anssiz,
+ NULL, NULL, NULL, NULL, NULL);
+ __resolv_context_put (ctx);
+ return result;
+}
+
int
-res_nsend(res_state statp,
- const u_char *buf, int buflen, u_char *ans, int anssiz)
+res_nsend (res_state statp, const unsigned char *buf, int buflen,
+ unsigned char *ans, int anssiz)
{
- return __libc_res_nsend(statp, buf, buflen, NULL, 0, ans, anssiz,
- NULL, NULL, NULL, NULL, NULL);
+ return context_send_common
+ (__resolv_context_get_override (statp), buf, buflen, ans, anssiz);
+}
+
+int
+res_send (const unsigned char *buf, int buflen, unsigned char *ans, int anssiz)
+{
+ return context_send_common
+ (__resolv_context_get (), buf, buflen, ans, anssiz);
}
-libresolv_hidden_def (res_nsend)
/* Private */
static struct sockaddr *
-get_nsaddr (res_state statp, int n)
+get_nsaddr (res_state statp, unsigned int n)
{
+ assert (n < statp->nscount);
if (statp->nsaddr_list[n].sin_family == 0 && EXT(statp).nsaddrs[n] != NULL)
/* EXT(statp).nsaddrs[n] holds an address that is larger than
@@ -649,6 +597,18 @@ get_nsaddr (res_state statp, int n)
return (struct sockaddr *) (void *) &statp->nsaddr_list[n];
}
+/* Close the resolver structure, assign zero to *RESPLEN2 if RESPLEN2
+ is not NULL, and return zero. */
+static int
+__attribute__ ((warn_unused_result))
+close_and_return_error (res_state statp, int *resplen2)
+{
+ __res_iclose(statp, false);
+ if (resplen2 != NULL)
+ *resplen2 = 0;
+ return 0;
+}
+
/* The send_vc function is responsible for sending a DNS query over TCP
to the nameserver numbered NS from the res_state STATP i.e.
EXT(statp).nssocks[ns]. The function supports sending both IPv4 and
@@ -657,7 +617,7 @@ get_nsaddr (res_state statp, int n)
Please note that for TCP there is no way to disable sending both
queries, unlike UDP, which honours RES_SNGLKUP and RES_SNGLKUPREOP
and sends the queries serially and waits for the result after each
- sent query. This implemetnation should be corrected to honour these
+ sent query. This implementation should be corrected to honour these
options.
Please also note that for TCP we send both queries over the same
@@ -750,8 +710,6 @@ send_vc(res_state statp,
u_short len2;
u_char *cp;
- if (resplen2 != NULL)
- *resplen2 = 0;
connreset = 0;
same_ns:
truncating = 0;
@@ -773,10 +731,12 @@ send_vc(res_state statp,
if (statp->_vcsock >= 0)
__res_iclose(statp, false);
- statp->_vcsock = socket(nsap->sa_family, SOCK_STREAM, 0);
+ statp->_vcsock = socket
+ (nsap->sa_family, SOCK_STREAM | SOCK_CLOEXEC, 0);
if (statp->_vcsock < 0) {
*terrno = errno;
- Perror(statp, stderr, "socket(vc)", errno);
+ if (resplen2 != NULL)
+ *resplen2 = 0;
return (-1);
}
__set_errno (0);
@@ -785,9 +745,7 @@ send_vc(res_state statp,
? sizeof (struct sockaddr_in)
: sizeof (struct sockaddr_in6)) < 0) {
*terrno = errno;
- Aerror(statp, stderr, "connect/vc", errno, nsap);
- __res_iclose(statp, false);
- return (0);
+ return close_and_return_error (statp, resplen2);
}
statp->_flags |= RES_F_VC;
}
@@ -809,9 +767,7 @@ send_vc(res_state statp,
}
if (TEMP_FAILURE_RETRY (writev(statp->_vcsock, iov, niov)) != explen) {
*terrno = errno;
- Perror(statp, stderr, "write failed", errno);
- __res_iclose(statp, false);
- return (0);
+ return close_and_return_error (statp, resplen2);
}
/*
* Receive length & response
@@ -832,8 +788,6 @@ send_vc(res_state statp,
}
if (n <= 0) {
*terrno = errno;
- Perror(statp, stderr, "read failed", errno);
- __res_iclose(statp, false);
/*
* A long running process might get its TCP
* connection reset if the remote server was
@@ -843,11 +797,13 @@ send_vc(res_state statp,
* instead of failing. We only allow one reset
* per query to prevent looping.
*/
- if (*terrno == ECONNRESET && !connreset) {
- connreset = 1;
- goto same_ns;
- }
- return (0);
+ if (*terrno == ECONNRESET && !connreset)
+ {
+ __res_iclose (statp, false);
+ connreset = 1;
+ goto same_ns;
+ }
+ return close_and_return_error (statp, resplen2);
}
int rlen = ntohs (rlen16);
@@ -879,11 +835,11 @@ send_vc(res_state statp,
/* Always allocate MAXPACKET, callers expect
this specific size. */
u_char *newp = malloc (MAXPACKET);
- if (newp == NULL) {
- *terrno = ENOMEM;
- __res_iclose(statp, false);
- return (0);
- }
+ if (newp == NULL)
+ {
+ *terrno = ENOMEM;
+ return close_and_return_error (statp, resplen2);
+ }
*thisanssizp = MAXPACKET;
*thisansp = newp;
if (thisansp == ansp2)
@@ -894,9 +850,6 @@ send_vc(res_state statp,
read RLEN bytes instead. */
len = rlen;
} else {
- Dprint(statp->options & RES_DEBUG,
- (stdout, ";; response truncated\n")
- );
truncating = 1;
len = *thisanssizp;
}
@@ -907,11 +860,8 @@ send_vc(res_state statp,
/*
* Undersized message.
*/
- Dprint(statp->options & RES_DEBUG,
- (stdout, ";; undersized: %d\n", len));
*terrno = EMSGSIZE;
- __res_iclose(statp, false);
- return (0);
+ return close_and_return_error (statp, resplen2);
}
cp = *thisansp;
@@ -921,9 +871,7 @@ send_vc(res_state statp,
}
if (__glibc_unlikely (n <= 0)) {
*terrno = errno;
- Perror(statp, stderr, "read(vc)", errno);
- __res_iclose(statp, false);
- return (0);
+ return close_and_return_error (statp, resplen2);
}
if (__glibc_unlikely (truncating)) {
/*
@@ -950,14 +898,8 @@ send_vc(res_state statp,
* wait for the correct one.
*/
if ((recvresp1 || hp->id != anhp->id)
- && (recvresp2 || hp2->id != anhp->id)) {
- DprintQ((statp->options & RES_DEBUG) ||
- (statp->pfcode & RES_PRF_REPLY),
- (stdout, ";; old answer (unexpected):\n"),
- *thisansp,
- (rlen > *thisanssizp) ? *thisanssizp: rlen);
+ && (recvresp2 || hp2->id != anhp->id))
goto read_len;
- }
/* Mark which reply we received. */
if (recvresp1 == 0 && hp->id == anhp->id)
@@ -984,19 +926,20 @@ reopen (res_state statp, int *terrno, int ns)
/* only try IPv6 if IPv6 NS and if not failed before */
if (nsap->sa_family == AF_INET6 && !statp->ipv6_unavail) {
- EXT(statp).nssocks[ns]
- = socket(PF_INET6, SOCK_DGRAM|SOCK_NONBLOCK, 0);
+ EXT(statp).nssocks[ns] = socket
+ (PF_INET6,
+ SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
if (EXT(statp).nssocks[ns] < 0)
statp->ipv6_unavail = errno == EAFNOSUPPORT;
slen = sizeof (struct sockaddr_in6);
} else if (nsap->sa_family == AF_INET) {
- EXT(statp).nssocks[ns]
- = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK, 0);
+ EXT(statp).nssocks[ns] = socket
+ (PF_INET,
+ SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
slen = sizeof (struct sockaddr_in);
}
if (EXT(statp).nssocks[ns] < 0) {
*terrno = errno;
- Perror(statp, stderr, "socket(dg)", errno);
return (-1);
}
@@ -1011,8 +954,16 @@ reopen (res_state statp, int *terrno, int ns)
* error message is received. We can thus detect
* the absence of a nameserver without timing out.
*/
+ /* With GCC 5.3 when compiling with -Os the compiler
+ emits a warning that slen may be used uninitialized,
+ but that is never true. Both slen and
+ EXT(statp).nssocks[ns] are initialized together or
+ the function return -1 before control flow reaches
+ the call to connect with slen. */
+ DIAG_PUSH_NEEDS_COMMENT;
+ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
if (connect(EXT(statp).nssocks[ns], nsap, slen) < 0) {
- Aerror(statp, stderr, "connect(dg)", errno, nsap);
+ DIAG_POP_NEEDS_COMMENT;
__res_iclose(statp, false);
return (0);
}
@@ -1114,7 +1065,11 @@ send_dg(res_state statp,
retry_reopen:
retval = reopen (statp, terrno, ns);
if (retval <= 0)
- return retval;
+ {
+ if (resplen2 != NULL)
+ *resplen2 = 0;
+ return retval;
+ }
retry:
evNowTime(&now);
evConsTime(&timeout, seconds, 0);
@@ -1127,18 +1082,13 @@ send_dg(res_state statp,
int recvresp2 = buf2 == NULL;
pfd[0].fd = EXT(statp).nssocks[ns];
pfd[0].events = POLLOUT;
- if (resplen2 != NULL)
- *resplen2 = 0;
wait:
if (need_recompute) {
recompute_resend:
evNowTime(&now);
if (evCmpTime(finish, now) <= 0) {
poll_err_out:
- Perror(statp, stderr, "poll", errno);
- err_out:
- __res_iclose(statp, false);
- return (0);
+ return close_and_return_error (statp, resplen2);
}
evSubTime(&timeout, &finish, &now);
need_recompute = 0;
@@ -1154,7 +1104,6 @@ send_dg(res_state statp,
need_recompute = 1;
}
if (n == 0) {
- Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
if (resplen > 1 && (recvresp1 || (buf2 != NULL && recvresp2)))
{
/* There are quite a few broken name servers out
@@ -1185,7 +1134,9 @@ send_dg(res_state statp,
}
*gotsomewhere = 1;
- return (0);
+ if (resplen2 != NULL)
+ *resplen2 = 0;
+ return 0;
}
if (n < 0) {
if (errno == EINTR)
@@ -1203,25 +1154,27 @@ send_dg(res_state statp,
if (have_sendmmsg >= 0 && nwritten == 0 && buf2 != NULL
&& !single_request)
{
- struct iovec iov[2];
- struct mmsghdr reqs[2];
- reqs[0].msg_hdr.msg_name = NULL;
- reqs[0].msg_hdr.msg_namelen = 0;
- reqs[0].msg_hdr.msg_iov = &iov[0];
- reqs[0].msg_hdr.msg_iovlen = 1;
- iov[0].iov_base = (void *) buf;
- iov[0].iov_len = buflen;
- reqs[0].msg_hdr.msg_control = NULL;
- reqs[0].msg_hdr.msg_controllen = 0;
-
- reqs[1].msg_hdr.msg_name = NULL;
- reqs[1].msg_hdr.msg_namelen = 0;
- reqs[1].msg_hdr.msg_iov = &iov[1];
- reqs[1].msg_hdr.msg_iovlen = 1;
- iov[1].iov_base = (void *) buf2;
- iov[1].iov_len = buflen2;
- reqs[1].msg_hdr.msg_control = NULL;
- reqs[1].msg_hdr.msg_controllen = 0;
+ struct iovec iov =
+ { .iov_base = (void *) buf, .iov_len = buflen };
+ struct iovec iov2 =
+ { .iov_base = (void *) buf2, .iov_len = buflen2 };
+ struct mmsghdr reqs[2] =
+ {
+ {
+ .msg_hdr =
+ {
+ .msg_iov = &iov,
+ .msg_iovlen = 1,
+ },
+ },
+ {
+ .msg_hdr =
+ {
+ .msg_iov = &iov2,
+ .msg_iovlen = 1,
+ }
+ },
+ };
int ndg = __sendmmsg (pfd[0].fd, reqs, 2, MSG_NOSIGNAL);
if (__glibc_likely (ndg == 2))
@@ -1252,8 +1205,7 @@ send_dg(res_state statp,
#endif
fail_sendmmsg:
- Perror(statp, stderr, "sendmmsg", errno);
- goto err_out;
+ return close_and_return_error (statp, resplen2);
}
}
else
@@ -1270,8 +1222,7 @@ send_dg(res_state statp,
if (sr != (nwritten != 0 ? buflen2 : buflen)) {
if (errno == EINTR || errno == EAGAIN)
goto recompute_resend;
- Perror(statp, stderr, "send", errno);
- goto err_out;
+ return close_and_return_error (statp, resplen2);
}
just_one:
if (nwritten != 0 || buf2 == NULL || single_request)
@@ -1331,12 +1282,6 @@ send_dg(res_state statp,
MSG_TRUNC which is only available on Linux. We
can abstract out the Linux-specific feature in the
future to detect truncation. */
- if (__glibc_unlikely (*thisanssizp < *thisresplenp)) {
- Dprint(statp->options & RES_DEBUG,
- (stdout, ";; response may be truncated (UDP)\n")
- );
- }
-
HEADER *anhp = (HEADER *) *thisansp;
socklen_t fromlen = sizeof(struct sockaddr_in6);
assert (sizeof(from) <= fromlen);
@@ -1348,19 +1293,15 @@ send_dg(res_state statp,
need_recompute = 1;
goto wait;
}
- Perror(statp, stderr, "recvfrom", errno);
- goto err_out;
+ return close_and_return_error (statp, resplen2);
}
*gotsomewhere = 1;
if (__glibc_unlikely (*thisresplenp < HFIXEDSZ)) {
/*
* Undersized message.
*/
- Dprint(statp->options & RES_DEBUG,
- (stdout, ";; undersized: %d\n",
- *thisresplenp));
*terrno = EMSGSIZE;
- goto err_out;
+ return close_and_return_error (statp, resplen2);
}
if ((recvresp1 || hp->id != anhp->id)
&& (recvresp2 || hp2->id != anhp->id)) {
@@ -1369,12 +1310,6 @@ send_dg(res_state statp,
* XXX - potential security hazard could
* be detected here.
*/
- DprintQ((statp->options & RES_DEBUG) ||
- (statp->pfcode & RES_PRF_REPLY),
- (stdout, ";; old answer:\n"),
- *thisansp,
- (*thisresplenp > *thisanssizp)
- ? *thisanssizp : *thisresplenp);
goto wait;
}
if (!(statp->options & RES_INSECURE1) &&
@@ -1384,34 +1319,8 @@ send_dg(res_state statp,
* XXX - potential security hazard could
* be detected here.
*/
- DprintQ((statp->options & RES_DEBUG) ||
- (statp->pfcode & RES_PRF_REPLY),
- (stdout, ";; not our server:\n"),
- *thisansp,
- (*thisresplenp > *thisanssizp)
- ? *thisanssizp : *thisresplenp);
goto wait;
}
-#ifdef RES_USE_EDNS0
- if (anhp->rcode == FORMERR
- && (statp->options & RES_USE_EDNS0) != 0U) {
- /*
- * Do not retry if the server does not understand
- * EDNS0. The case has to be captured here, as
- * FORMERR packet do not carry query section, hence
- * res_queriesmatch() returns 0.
- */
- DprintQ(statp->options & RES_DEBUG,
- (stdout,
- "server rejected query with EDNS0:\n"),
- *thisansp,
- (*thisresplenp > *thisanssizp)
- ? *thisanssizp : *thisresplenp);
- /* record the error */
- statp->_flags |= RES_F_EDNS0ERR;
- goto err_out;
- }
-#endif
if (!(statp->options & RES_INSECURE2)
&& (recvresp1 || !res_queriesmatch(buf, buf + buflen,
*thisansp,
@@ -1426,23 +1335,11 @@ send_dg(res_state statp,
* XXX - potential security hazard could
* be detected here.
*/
- DprintQ((statp->options & RES_DEBUG) ||
- (statp->pfcode & RES_PRF_REPLY),
- (stdout, ";; wrong query name:\n"),
- *thisansp,
- (*thisresplenp > *thisanssizp)
- ? *thisanssizp : *thisresplenp);
goto wait;
}
if (anhp->rcode == SERVFAIL ||
anhp->rcode == NOTIMP ||
anhp->rcode == REFUSED) {
- DprintQ(statp->options & RES_DEBUG,
- (stdout, "server rejected query:\n"),
- *thisansp,
- (*thisresplenp > *thisanssizp)
- ? *thisanssizp : *thisresplenp);
-
next_ns:
if (recvresp1 || (buf2 != NULL && recvresp2)) {
*resplen2 = 0;
@@ -1461,18 +1358,13 @@ send_dg(res_state statp,
goto wait;
}
- __res_iclose(statp, false);
/* don't retry if called from dig */
if (!statp->pfcode)
- return (0);
+ return close_and_return_error (statp, resplen2);
+ __res_iclose(statp, false);
}
if (anhp->rcode == NOERROR && anhp->ancount == 0
&& anhp->aa == 0 && anhp->ra == 0 && anhp->arcount == 0) {
- DprintQ(statp->options & RES_DEBUG,
- (stdout, "referred query:\n"),
- *thisansp,
- (*thisresplenp > *thisanssizp)
- ? *thisanssizp : *thisresplenp);
goto next_ns;
}
if (!(statp->options & RES_IGNTC) && anhp->tc) {
@@ -1480,12 +1372,12 @@ send_dg(res_state statp,
* To get the rest of answer,
* use TCP with same server.
*/
- Dprint(statp->options & RES_DEBUG,
- (stdout, ";; truncated answer\n"));
*v_circuit = 1;
__res_iclose(statp, false);
// XXX if we have received one reply we could
// XXX use it and not repeat it over TCP...
+ if (resplen2 != NULL)
+ *resplen2 = 0;
return (1);
}
/* Mark which reply we received. */
@@ -1501,67 +1393,28 @@ send_dg(res_state statp,
__res_iclose (statp, false);
retval = reopen (statp, terrno, ns);
if (retval <= 0)
- return retval;
+ {
+ if (resplen2 != NULL)
+ *resplen2 = 0;
+ return retval;
+ }
pfd[0].fd = EXT(statp).nssocks[ns];
}
}
goto wait;
}
- /*
- * All is well, or the error is fatal. Signal that the
- * next nameserver ought not be tried.
- */
+ /* All is well. We have received both responses (if
+ two responses were requested). */
return (resplen);
- } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL)) {
- /* Something went wrong. We can stop trying. */
- goto err_out;
- }
+ } else if (pfd[0].revents & (POLLERR | POLLHUP | POLLNVAL))
+ /* Something went wrong. We can stop trying. */
+ return close_and_return_error (statp, resplen2);
else {
/* poll should not have returned > 0 in this case. */
abort ();
}
}
-#ifdef DEBUG
-static void
-Aerror(const res_state statp, FILE *file, const char *string, int error,
- const struct sockaddr *address)
-{
- int save = errno;
-
- if ((statp->options & RES_DEBUG) != 0) {
- char tmp[sizeof "xxxx.xxxx.xxxx.255.255.255.255"];
-
- fprintf(file, "res_send: %s ([%s].%u): %s\n",
- string,
- (address->sa_family == AF_INET
- ? inet_ntop(address->sa_family,
- &((const struct sockaddr_in *) address)->sin_addr,
- tmp, sizeof tmp)
- : inet_ntop(address->sa_family,
- &((const struct sockaddr_in6 *) address)->sin6_addr,
- tmp, sizeof tmp)),
- (address->sa_family == AF_INET
- ? ntohs(((struct sockaddr_in *) address)->sin_port)
- : address->sa_family == AF_INET6
- ? ntohs(((struct sockaddr_in6 *) address)->sin6_port)
- : 0),
- strerror(error));
- }
- __set_errno (save);
-}
-
-static void
-Perror(const res_state statp, FILE *file, const char *string, int error) {
- int save = errno;
-
- if ((statp->options & RES_DEBUG) != 0)
- fprintf(file, "res_send: %s: %s\n",
- string, strerror(error));
- __set_errno (save);
-}
-#endif
-
static int
sock_eq(struct sockaddr_in6 *a1, struct sockaddr_in6 *a2) {
if (a1->sin6_family == a2->sin6_family) {
diff --git a/resolv/res_use_inet6.h b/resolv/res_use_inet6.h
new file mode 100644
index 0000000000..dd5a31c54c
--- /dev/null
+++ b/resolv/res_use_inet6.h
@@ -0,0 +1,49 @@
+/* Support functions for handling RES_USE_INET6 in getaddrinfo/nscd.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _RES_USE_INET6_H
+#define _RES_USE_INET6_H
+
+#include <resolv/resolv_context.h>
+#include <resolv/resolv-internal.h>
+
+/* Ensure that RES_USE_INET6 is disabled in *CTX. Return true if
+ __resolv_context_enable_inet6 below should enable RES_USE_INET6
+ again. */
+static inline bool
+__resolv_context_disable_inet6 (struct resolv_context *ctx)
+{
+ if (ctx != NULL && ctx->resp->options & DEPRECATED_RES_USE_INET6)
+ {
+ ctx->resp->options &= ~DEPRECATED_RES_USE_INET6;
+ return true;
+ }
+ else
+ return false;
+}
+
+/* If ENABLE, re-enable RES_USE_INET6 in *CTX. To be paired with
+ __resolv_context_disable_inet6. */
+static inline void
+__resolv_context_enable_inet6 (struct resolv_context *ctx, bool enable)
+{
+ if (ctx != NULL && enable)
+ ctx->resp->options |= DEPRECATED_RES_USE_INET6;
+}
+
+#endif
diff --git a/resolv/resolv-internal.h b/resolv/resolv-internal.h
new file mode 100644
index 0000000000..b8e447c726
--- /dev/null
+++ b/resolv/resolv-internal.h
@@ -0,0 +1,103 @@
+/* libresolv interfaces for internal use across glibc.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef _RESOLV_INTERNAL_H
+#define _RESOLV_INTERNAL_H 1
+
+#include <resolv.h>
+#include <stdbool.h>
+
+/* Resolver flags. Used for _flags in struct __res_state. */
+#define RES_F_VC 0x00000001 /* Socket is TCP. */
+#define RES_F_CONN 0x00000002 /* Socket is connected. */
+#define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors. */
+
+
+/* Internal version of RES_USE_INET6 which does not trigger a
+ deprecation warning. */
+#define DEPRECATED_RES_USE_INET6 0x00002000
+
+static inline bool
+res_use_inet6 (void)
+{
+ return _res.options & DEPRECATED_RES_USE_INET6;
+}
+
+enum
+ {
+ /* The advertized EDNS buffer size. The value 1200 is derived
+ from the IPv6 minimum MTU (1280 bytes) minus some arbitrary
+ space for tunneling overhead. If the DNS server does not react
+ to ICMP Fragmentation Needed But DF Set messages, this should
+ avoid all UDP fragments on current networks. Avoiding UDP
+ fragments is desirable because it prevents fragmentation-based
+ spoofing attacks because the randomness in a DNS packet is
+ concentrated in the first fragment (with the headers) and does
+ not protect subsequent fragments. */
+ RESOLV_EDNS_BUFFER_SIZE = 1200,
+ };
+
+struct resolv_context;
+
+/* Internal function for implementing res_nmkquery and res_mkquery.
+ Also used by __res_context_query. */
+int __res_context_mkquery (struct resolv_context *, int op, const char *dname,
+ int class, int type, const unsigned char *data,
+ unsigned char *buf, int buflen) attribute_hidden;
+
+/* Main resolver query function for use within glibc. */
+int __res_context_search (struct resolv_context *, const char *, int, int,
+ unsigned char *, int, unsigned char **,
+ unsigned char **, int *, int *, int *);
+libresolv_hidden_proto (__res_context_search)
+
+/* Main resolver query function for use within glibc. */
+int __res_context_query (struct resolv_context *, const char *, int, int,
+ unsigned char *, int, unsigned char **,
+ unsigned char **, int *, int *, int *);
+libresolv_hidden_proto (__res_context_query)
+
+/* Internal function used to implement the query and search
+ functions. */
+int __res_context_send (struct resolv_context *, const unsigned char *, int,
+ const unsigned char *, int, unsigned char *,
+ int, unsigned char **, unsigned char **,
+ int *, int *, int *) attribute_hidden;
+
+/* Internal function similar to res_hostalias. */
+const char *__res_context_hostalias (struct resolv_context *,
+ const char *, char *, size_t);
+libresolv_hidden_proto (__res_context_hostalias);
+
+/* Add an OPT record to a DNS query. */
+int __res_nopt (struct resolv_context *, int n0,
+ unsigned char *buf, int buflen, int anslen) attribute_hidden;
+
+/* Convert from presentation format (which usually means ASCII
+ printable) to network format (which is usually some kind of binary
+ format). The input is in the range [SRC, SRC + SRCLEN). The
+ output is written to DST (which has to be 4 or 16 bytes long,
+ depending on AF). Return 0 for invalid input, 1 for success, -1
+ for an invalid address family. */
+int __inet_pton_length (int af, const char *src, size_t srclen, void *);
+libc_hidden_proto (__inet_pton_length)
+
+/* Called as part of the thread shutdown sequence. */
+void __res_thread_freeres (void) attribute_hidden;
+
+#endif /* _RESOLV_INTERNAL_H */
diff --git a/resolv/resolv.h b/resolv/resolv.h
index 53c3bba182..80a523e5e4 100644
--- a/resolv/resolv.h
+++ b/resolv/resolv.h
@@ -50,109 +50,30 @@
*/
#ifndef _RESOLV_H_
+#define _RESOLV_H_
-/* These headers are needed for types used in the `struct res_state'
- declaration. */
+#include <sys/cdefs.h>
+#include <sys/param.h>
#include <sys/types.h>
+#include <stdio.h>
#include <netinet/in.h>
-
-#ifndef __need_res_state
-# define _RESOLV_H_
-
-# include <sys/param.h>
-# include <sys/cdefs.h>
-# include <stdio.h>
-# include <arpa/nameser.h>
-#endif
-
-#ifndef __res_state_defined
-# define __res_state_defined
-
-typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error }
- res_sendhookact;
-
-typedef res_sendhookact (*res_send_qhook) (struct sockaddr_in * const *__ns,
- const u_char **__query,
- int *__querylen,
- u_char *__ans,
- int __anssiz,
- int *__resplen);
-
-typedef res_sendhookact (*res_send_rhook) (const struct sockaddr_in *__ns,
- const u_char *__query,
- int __querylen,
- u_char *__ans,
- int __anssiz,
- int *__resplen);
+#include <arpa/nameser.h>
+#include <bits/types/res_state.h>
/*
* Global defines and variables for resolver stub.
*/
-# define MAXNS 3 /* max # name servers we'll track */
-# define MAXDFLSRCH 3 /* # default domain levels to try */
-# define MAXDNSRCH 6 /* max # domains in search path */
-# define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */
+#define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */
-# define RES_TIMEOUT 5 /* min. seconds between retries */
-# define MAXRESOLVSORT 10 /* number of net to sort on */
-# define RES_MAXNDOTS 15 /* should reflect bit field size */
-# define RES_MAXRETRANS 30 /* only for resolv.conf/RES_OPTIONS */
-# define RES_MAXRETRY 5 /* only for resolv.conf/RES_OPTIONS */
-# define RES_DFLRETRY 2 /* Default #/tries. */
-# define RES_MAXTIME 65535 /* Infinity, in milliseconds. */
+#define RES_TIMEOUT 5 /* min. seconds between retries */
+#define RES_MAXNDOTS 15 /* should reflect bit field size */
+#define RES_MAXRETRANS 30 /* only for resolv.conf/RES_OPTIONS */
+#define RES_MAXRETRY 5 /* only for resolv.conf/RES_OPTIONS */
+#define RES_DFLRETRY 2 /* Default #/tries. */
+#define RES_MAXTIME 65535 /* Infinity, in milliseconds. */
-struct __res_state {
- int retrans; /* retransmition time interval */
- int retry; /* number of times to retransmit */
- u_long options; /* option flags - see below. */
- int nscount; /* number of name servers */
- struct sockaddr_in
- nsaddr_list[MAXNS]; /* address of name server */
-# define nsaddr nsaddr_list[0] /* for backward compatibility */
- u_short id; /* current message id */
- /* 2 byte hole here. */
- char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */
- char defdname[256]; /* default domain (deprecated) */
- u_long pfcode; /* RES_PRF_ flags - see below. */
- unsigned ndots:4; /* threshold for initial abs. query */
- unsigned nsort:4; /* number of elements in sort_list[] */
- unsigned ipv6_unavail:1; /* connecting to IPv6 server failed */
- unsigned unused:23;
- struct {
- struct in_addr addr;
- u_int32_t mask;
- } sort_list[MAXRESOLVSORT];
- /* 4 byte hole here on 64-bit architectures. */
- res_send_qhook qhook; /* query hook */
- res_send_rhook rhook; /* response hook */
- int res_h_errno; /* last one set for this context */
- int _vcsock; /* PRIVATE: for res_send VC i/o */
- u_int _flags; /* PRIVATE: see below */
- /* 4 byte hole here on 64-bit architectures. */
- union {
- char pad[52]; /* On an i386 this means 512b total. */
- struct {
- u_int16_t nscount;
- u_int16_t nsmap[MAXNS];
- int nssocks[MAXNS];
- u_int16_t nscount6;
- u_int16_t nsinit;
- struct sockaddr_in6 *nsaddrs[MAXNS];
-#ifdef _LIBC
- unsigned long long int initstamp
- __attribute__((packed));
-#else
- unsigned int _initstamp[2];
-#endif
- } _ext;
- } _u;
-};
-
-typedef struct __res_state *res_state;
-# undef __need_res_state
-#endif
+#define nsaddr nsaddr_list[0] /* for backward compatibility */
-#ifdef _RESOLV_H_
/*
* Revision information. This is the release date in YYYYMMDD format.
* It can change every day so the right thing to do with it is use it
@@ -180,23 +101,15 @@ struct res_sym {
};
/*
- * Resolver flags (used to be discrete per-module statics ints).
- */
-#define RES_F_VC 0x00000001 /* socket is TCP */
-#define RES_F_CONN 0x00000002 /* socket is connected */
-#define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors */
-
-/* res_findzonecut() options */
-#define RES_EXHAUSTIVE 0x00000001 /* always do all queries */
-
-/*
* Resolver options (keep these in synch with res_debug.c, please)
*/
#define RES_INIT 0x00000001 /* address initialized */
#define RES_DEBUG 0x00000002 /* print debug messages */
-#define RES_AAONLY 0x00000004 /* authoritative answers only (!IMPL)*/
+#define RES_AAONLY \
+ __glibc_macro_warning ("RES_AAONLY is deprecated") 0x00000004
#define RES_USEVC 0x00000008 /* use virtual circuit */
-#define RES_PRIMARY 0x00000010 /* query primary server only (!IMPL) */
+#define RES_PRIMARY \
+ __glibc_macro_warning ("RES_PRIMARY is deprecated") 0x00000010
#define RES_IGNTC 0x00000020 /* ignore trucation errors */
#define RES_RECURSE 0x00000040 /* recursion desired */
#define RES_DEFNAMES 0x00000080 /* use default domain name */
@@ -205,15 +118,15 @@ struct res_sym {
#define RES_INSECURE1 0x00000400 /* type 1 security disabled */
#define RES_INSECURE2 0x00000800 /* type 2 security disabled */
#define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */
-#define RES_USE_INET6 0x00002000 /* use/map IPv6 in gethostbyname() */
+#define RES_USE_INET6 \
+ __glibc_macro_warning ("RES_USE_INET6 is deprecated") 0x00002000
#define RES_ROTATE 0x00004000 /* rotate ns list after each query */
-#define RES_NOCHECKNAME 0x00008000 /* do not check names for sanity (!IMPL) */
-#define RES_KEEPTSIG 0x00010000 /* do not strip TSIG records */
-#define RES_BLAST 0x00020000 /* blast all recursive servers */
-#define RES_USEBSTRING 0x00040000 /* IPv6 reverse lookup with byte
- strings */
-#define RES_NOIP6DOTINT 0x00080000 /* Do not use .ip6.int in IPv6
- reverse lookup */
+#define RES_NOCHECKNAME \
+ __glibc_macro_warning ("RES_NOCHECKNAME is deprecated") 0x00008000
+#define RES_KEEPTSIG \
+ __glibc_macro_warning ("RES_KEEPTSIG is deprecated") 0x00010000
+#define RES_BLAST \
+ __glibc_macro_warning ("RES_BLAST is deprecated") 0x00020000
#define RES_USE_EDNS0 0x00100000 /* Use EDNS0. */
#define RES_SNGLKUP 0x00200000 /* one outstanding request at a time */
#define RES_SNGLKUPREOP 0x00400000 /* -"-, but open new socket for each
@@ -221,8 +134,9 @@ struct res_sym {
#define RES_USE_DNSSEC 0x00800000 /* use DNSSEC using OK bit in OPT */
#define RES_NOTLDQUERY 0x01000000 /* Do not look up unqualified name
as a TLD. */
+#define RES_NORELOAD 0x02000000 /* No automatic configuration reload. */
-#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH|RES_NOIP6DOTINT)
+#define RES_DEFAULT (RES_RECURSE|RES_DEFNAMES|RES_DNSRCH)
/*
* Resolver "pfcode" values. Used by dig.
@@ -250,7 +164,6 @@ extern struct __res_state *__res_state(void) __attribute__ ((__const__));
__END_DECLS
#define _res (*__res_state())
-#ifndef __BIND_NOSTATIC
#define fp_nquery __fp_nquery
#define fp_query __fp_query
#define hostalias __hostalias
@@ -265,22 +178,25 @@ __END_DECLS
#define res_send __res_send
__BEGIN_DECLS
-void fp_nquery (const u_char *, int, FILE *) __THROW;
-void fp_query (const u_char *, FILE *) __THROW;
+void fp_nquery (const unsigned char *, int, FILE *) __THROW;
+void fp_query (const unsigned char *, FILE *) __THROW;
const char * hostalias (const char *) __THROW;
-void p_query (const u_char *) __THROW;
+void p_query (const unsigned char *) __THROW;
void res_close (void) __THROW;
int res_init (void) __THROW;
int res_isourserver (const struct sockaddr_in *) __THROW;
-int res_mkquery (int, const char *, int, int, const u_char *,
- int, const u_char *, u_char *, int) __THROW;
-int res_query (const char *, int, int, u_char *, int) __THROW;
+int res_mkquery (int, const char *, int, int,
+ const unsigned char *, int, const unsigned char *,
+ unsigned char *, int) __THROW;
+int res_query (const char *, int, int, unsigned char *, int)
+ __THROW;
int res_querydomain (const char *, const char *, int, int,
- u_char *, int) __THROW;
-int res_search (const char *, int, int, u_char *, int) __THROW;
-int res_send (const u_char *, int, u_char *, int) __THROW;
+ unsigned char *, int) __THROW;
+int res_search (const char *, int, int, unsigned char *, int)
+ __THROW;
+int res_send (const unsigned char *, int, unsigned char *, int)
+ __THROW;
__END_DECLS
-#endif
#define b64_ntop __b64_ntop
#define b64_pton __b64_pton
@@ -297,8 +213,6 @@ __END_DECLS
#define p_fqname __p_fqname
#define p_fqnname __p_fqnname
#define p_option __p_option
-#define p_secstodate __p_secstodate
-#define p_section __p_section
#define p_time __p_time
#define p_type __p_type
#define p_rcode __p_rcode
@@ -312,12 +226,10 @@ __END_DECLS
#define res_nclose __res_nclose
#define res_ninit __res_ninit
#define res_nmkquery __res_nmkquery
-#define res_npquery __res_npquery
#define res_nquery __res_nquery
#define res_nquerydomain __res_nquerydomain
#define res_nsearch __res_nsearch
#define res_nsend __res_nsend
-#define res_nisourserver __res_nisourserver
#define res_ownok __res_ownok
#define res_queriesmatch __res_queriesmatch
#define res_randomid __res_randomid
@@ -332,58 +244,61 @@ int res_dnok (const char *) __THROW;
int sym_ston (const struct res_sym *, const char *, int *) __THROW;
const char * sym_ntos (const struct res_sym *, int, int *) __THROW;
const char * sym_ntop (const struct res_sym *, int, int *) __THROW;
-int b64_ntop (u_char const *, size_t, char *, size_t) __THROW;
-int b64_pton (char const *, u_char *, size_t) __THROW;
-int loc_aton (const char *__ascii, u_char *__binary) __THROW;
-const char * loc_ntoa (const u_char *__binary, char *__ascii) __THROW;
-int dn_skipname (const u_char *, const u_char *) __THROW;
-void putlong (u_int32_t, u_char *) __THROW;
-void putshort (u_int16_t, u_char *) __THROW;
+int b64_ntop (const unsigned char *, size_t, char *, size_t)
+ __THROW;
+int b64_pton (char const *, unsigned char *, size_t) __THROW;
+int loc_aton (const char *__ascii, unsigned char *__binary) __THROW;
+const char * loc_ntoa (const unsigned char *__binary, char *__ascii) __THROW;
+int dn_skipname (const unsigned char *, const unsigned char *)
+ __THROW;
+void putlong (uint32_t, unsigned char *) __THROW;
+void putshort (uint16_t, unsigned char *) __THROW;
const char * p_class (int) __THROW;
-const char * p_time (u_int32_t) __THROW;
+const char * p_time (uint32_t) __THROW;
const char * p_type (int) __THROW;
const char * p_rcode (int) __THROW;
-const u_char * p_cdnname (const u_char *, const u_char *, int, FILE *)
- __THROW;
-const u_char * p_cdname (const u_char *, const u_char *, FILE *) __THROW;
-const u_char * p_fqnname (const u_char *__cp, const u_char *__msg,
- int, char *, int) __THROW;
-const u_char * p_fqname (const u_char *, const u_char *, FILE *) __THROW;
-const char * p_option (u_long __option) __THROW;
-char * p_secstodate (u_long) __THROW;
+const unsigned char * p_cdnname (const unsigned char *,
+ const unsigned char *, int, FILE *) __THROW;
+const unsigned char * p_cdname (const unsigned char *, const unsigned char *,
+ FILE *) __THROW;
+const unsigned char * p_fqnname (const unsigned char *__cp,
+ const unsigned char *__msg,
+ int, char *, int) __THROW;
+const unsigned char * p_fqname (const unsigned char *,
+ const unsigned char *, FILE *) __THROW;
+const char * p_option (unsigned long __option) __THROW;
int dn_count_labels (const char *) __THROW;
-int dn_comp (const char *, u_char *, int, u_char **, u_char **)
- __THROW;
-int dn_expand (const u_char *, const u_char *, const u_char *,
- char *, int) __THROW;
-u_int res_randomid (void) __THROW;
+int dn_comp (const char *, unsigned char *, int, unsigned char **,
+ unsigned char **) __THROW;
+int dn_expand (const unsigned char *, const unsigned char *,
+ const unsigned char *, char *, int) __THROW;
+unsigned int res_randomid (void) __THROW;
int res_nameinquery (const char *, int, int,
- const u_char *, const u_char *) __THROW;
-int res_queriesmatch (const u_char *, const u_char *,
- const u_char *, const u_char *) __THROW;
-const char * p_section (int __section, int __opcode) __THROW;
+ const unsigned char *,
+ const unsigned char *) __THROW;
+int res_queriesmatch (const unsigned char *,
+ const unsigned char *,
+ const unsigned char *,
+ const unsigned char *) __THROW;
/* Things involving a resolver context. */
int res_ninit (res_state) __THROW;
-int res_nisourserver (const res_state,
- const struct sockaddr_in *) __THROW;
void fp_resstat (const res_state, FILE *) __THROW;
-void res_npquery (const res_state, const u_char *, int, FILE *)
- __THROW;
const char * res_hostalias (const res_state, const char *, char *, size_t)
__THROW;
-int res_nquery (res_state, const char *, int, int, u_char *, int)
- __THROW;
-int res_nsearch (res_state, const char *, int, int, u_char *, int)
- __THROW;
+int res_nquery (res_state, const char *, int, int,
+ unsigned char *, int) __THROW;
+int res_nsearch (res_state, const char *, int, int,
+ unsigned char *, int) __THROW;
int res_nquerydomain (res_state, const char *, const char *, int,
- int, u_char *, int) __THROW;
+ int, unsigned char *, int) __THROW;
int res_nmkquery (res_state, int, const char *, int, int,
- const u_char *, int, const u_char *, u_char *,
- int) __THROW;
-int res_nsend (res_state, const u_char *, int, u_char *, int)
+ const unsigned char *, int,
+ const unsigned char *, unsigned char *, int)
__THROW;
+int res_nsend (res_state, const unsigned char *, int,
+ unsigned char *, int) __THROW;
void res_nclose (res_state) __THROW;
+
__END_DECLS
-#endif
#endif /* !_RESOLV_H_ */
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
new file mode 100644
index 0000000000..2f0ffbc524
--- /dev/null
+++ b/resolv/resolv_conf.c
@@ -0,0 +1,700 @@
+/* Extended resolver state separate from struct __res_state.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <resolv_conf.h>
+
+#include <alloc_buffer.h>
+#include <assert.h>
+#include <libc-lock.h>
+#include <resolv-internal.h>
+#include <sys/stat.h>
+#include <libc-symbols.h>
+
+/* _res._u._ext.__glibc_extension_index is used as an index into a
+ struct resolv_conf_array object. The intent of this construction
+ is to make reasonably sure that even if struct __res_state objects
+ are copied around and patched by applications, we can still detect
+ accesses to stale extended resolver state. The array elements are
+ either struct resolv_conf * pointers (if the LSB is cleared) or
+ free list entries (if the LSB is set). The free list is used to
+ speed up finding available entries in the array. */
+#define DYNARRAY_STRUCT resolv_conf_array
+#define DYNARRAY_ELEMENT uintptr_t
+#define DYNARRAY_PREFIX resolv_conf_array_
+#define DYNARRAY_INITIAL_SIZE 0
+#include <malloc/dynarray-skeleton.c>
+
+/* A magic constant for XORing the extension index
+ (_res._u._ext.__glibc_extension_index). This makes it less likely
+ that a valid index is created by accident. In particular, a zero
+ value leads to an invalid index. */
+#define INDEX_MAGIC 0x26a8fa5e48af8061ULL
+
+/* Global resolv.conf-related state. */
+struct resolv_conf_global
+{
+ /* struct __res_state objects contain the extension index
+ (_res._u._ext.__glibc_extension_index ^ INDEX_MAGIC), which
+ refers to an element of this array. When a struct resolv_conf
+ object (extended resolver state) is associated with a struct
+ __res_state object (legacy resolver state), its reference count
+ is increased and added to this array. Conversely, if the
+ extended state is detached from the basic state (during
+ reinitialization or deallocation), the index is decremented, and
+ the array element is overwritten with NULL. */
+ struct resolv_conf_array array;
+
+ /* Start of the free list in the array. Zero if the free list is
+ empty. Otherwise, free_list_start >> 1 is the first element of
+ the free list (and the free list entries all have their LSB set
+ and are shifted one to the left). */
+ uintptr_t free_list_start;
+
+ /* Cached current configuration object for /etc/resolv.conf. */
+ struct resolv_conf *conf_current;
+
+ /* These properties of /etc/resolv.conf are used to check if the
+ configuration needs reloading. */
+ struct timespec conf_mtime;
+ struct timespec conf_ctime;
+ off64_t conf_size;
+ ino64_t conf_ino;
+};
+
+/* Lazily allocated storage for struct resolv_conf_global. */
+static struct resolv_conf_global *global;
+
+/* The lock synchronizes access to global and *global. It also
+ protects the __refcount member of struct resolv_conf. */
+__libc_lock_define_initialized (static, lock);
+
+/* Ensure that GLOBAL is allocated and lock it. Return NULL if
+ memory allocation failes. */
+static struct resolv_conf_global *
+get_locked_global (void)
+{
+ __libc_lock_lock (lock);
+ /* Use relaxed MO through because of load outside the lock in
+ __resolv_conf_detach. */
+ struct resolv_conf_global *global_copy = atomic_load_relaxed (&global);
+ if (global_copy == NULL)
+ {
+ global_copy = calloc (1, sizeof (*global));
+ if (global_copy == NULL)
+ return NULL;
+ atomic_store_relaxed (&global, global_copy);
+ resolv_conf_array_init (&global_copy->array);
+ }
+ return global_copy;
+}
+
+/* Relinquish the lock acquired by get_locked_global. */
+static void
+put_locked_global (struct resolv_conf_global *global_copy)
+{
+ __libc_lock_unlock (lock);
+}
+
+/* Decrement the reference counter. The caller must acquire the lock
+ around the function call. */
+static void
+conf_decrement (struct resolv_conf *conf)
+{
+ assert (conf->__refcount > 0);
+ if (--conf->__refcount == 0)
+ free (conf);
+}
+
+struct resolv_conf *
+__resolv_conf_get_current (void)
+{
+ struct stat64 st;
+ if (stat64 (_PATH_RESCONF, &st) != 0)
+ {
+ switch (errno)
+ {
+ case EACCES:
+ case EISDIR:
+ case ELOOP:
+ case ENOENT:
+ case ENOTDIR:
+ case EPERM:
+ /* Ignore errors due to file system contents. */
+ memset (&st, 0, sizeof (st));
+ break;
+ default:
+ /* Other errors are fatal. */
+ return NULL;
+ }
+ }
+
+ struct resolv_conf_global *global_copy = get_locked_global ();
+ if (global_copy == NULL)
+ return NULL;
+ struct resolv_conf *conf;
+ if (global_copy->conf_current != NULL
+ && (global_copy->conf_mtime.tv_sec == st.st_mtim.tv_sec
+ && global_copy->conf_mtime.tv_nsec == st.st_mtim.tv_nsec
+ && global_copy->conf_ctime.tv_sec == st.st_ctim.tv_sec
+ && global_copy->conf_ctime.tv_nsec == st.st_ctim.tv_nsec
+ && global_copy->conf_ino == st.st_ino
+ && global_copy->conf_size == st.st_size))
+ /* We can reuse the cached configuration object. */
+ conf = global_copy->conf_current;
+ else
+ {
+ /* Parse configuration while holding the lock. This avoids
+ duplicate work. */
+ conf = __resolv_conf_load (NULL);
+ if (conf != NULL)
+ {
+ if (global_copy->conf_current != NULL)
+ conf_decrement (global_copy->conf_current);
+ global_copy->conf_current = conf; /* Takes ownership. */
+
+ /* Update file modification stamps. The configuration we
+ read could be a newer version of the file, but this does
+ not matter because this will lead to an extraneous reload
+ later. */
+ global_copy->conf_mtime = st.st_mtim;
+ global_copy->conf_ctime = st.st_ctim;
+ global_copy->conf_ino = st.st_ino;
+ global_copy->conf_size = st.st_size;
+ }
+ }
+
+ if (conf != NULL)
+ {
+ /* Return an additional reference. */
+ assert (conf->__refcount > 0);
+ ++conf->__refcount;
+ assert (conf->__refcount > 0);
+ }
+ put_locked_global (global_copy);
+ return conf;
+}
+
+/* Internal implementation of __resolv_conf_get, without validation
+ against *RESP. */
+static struct resolv_conf *
+resolv_conf_get_1 (const struct __res_state *resp)
+{
+ /* Not initialized, and therefore no assoicated context. */
+ if (!(resp->options & RES_INIT))
+ return NULL;
+
+ struct resolv_conf_global *global_copy = get_locked_global ();
+ if (global_copy == NULL)
+ /* A memory allocation failure here means that no associated
+ contexts exists, so returning NULL is correct. */
+ return NULL;
+ size_t index = resp->_u._ext.__glibc_extension_index ^ INDEX_MAGIC;
+ struct resolv_conf *conf = NULL;
+ if (index < resolv_conf_array_size (&global_copy->array))
+ {
+ uintptr_t *slot = resolv_conf_array_at (&global_copy->array, index);
+ if (!(*slot & 1))
+ {
+ conf = (struct resolv_conf *) *slot;
+ assert (conf->__refcount > 0);
+ ++conf->__refcount;
+ }
+ }
+ put_locked_global (global_copy);
+ return conf;
+}
+
+/* Return true if both IPv4 addresses are equal. */
+static bool
+same_address_v4 (const struct sockaddr_in *left,
+ const struct sockaddr_in *right)
+{
+ return left->sin_addr.s_addr == right->sin_addr.s_addr
+ && left->sin_port == right->sin_port;
+}
+
+/* Return true if both IPv6 addresses are equal. This ignores the
+ flow label. */
+static bool
+same_address_v6 (const struct sockaddr_in6 *left,
+ const struct sockaddr_in6 *right)
+{
+ return memcmp (&left->sin6_addr, &right->sin6_addr,
+ sizeof (left->sin6_addr)) == 0
+ && left->sin6_port == right->sin6_port
+ && left->sin6_scope_id == right->sin6_scope_id;
+}
+
+static bool
+same_address (const struct sockaddr *left, const struct sockaddr *right)
+{
+ if (left->sa_family != right->sa_family)
+ return false;
+ switch (left->sa_family)
+ {
+ case AF_INET:
+ return same_address_v4 ((const struct sockaddr_in *) left,
+ (const struct sockaddr_in *) right);
+ case AF_INET6:
+ return same_address_v6 ((const struct sockaddr_in6 *) left,
+ (const struct sockaddr_in6 *) right);
+ }
+ return false;
+}
+
+/* Check that *RESP and CONF match. Used by __resolv_conf_get. */
+static bool
+resolv_conf_matches (const struct __res_state *resp,
+ const struct resolv_conf *conf)
+{
+ /* NB: Do not compare the options, retrans, retry, ndots. These can
+ be changed by applicaiton. */
+
+ /* Check that the name servers in *RESP have not been modified by
+ the application. */
+ {
+ size_t nserv = conf->nameserver_list_size;
+ if (nserv > MAXNS)
+ nserv = MAXNS;
+ /* _ext.nscount is 0 until initialized by res_send.c. */
+ if (resp->nscount != nserv
+ || (resp->_u._ext.nscount != 0 && resp->_u._ext.nscount != nserv))
+ return false;
+ for (size_t i = 0; i < nserv; ++i)
+ {
+ if (resp->nsaddr_list[i].sin_family == 0)
+ {
+ if (resp->_u._ext.nsaddrs[i]->sin6_family != AF_INET6)
+ return false;
+ if (!same_address ((struct sockaddr *) resp->_u._ext.nsaddrs[i],
+ conf->nameserver_list[i]))
+ return false;
+ }
+ else if (resp->nsaddr_list[i].sin_family != AF_INET)
+ return false;
+ else if (!same_address ((struct sockaddr *) &resp->nsaddr_list[i],
+ conf->nameserver_list[i]))
+ return false;
+ }
+ }
+
+ /* Check that the search list in *RESP has not been modified by the
+ application. */
+ {
+ if (resp->dnsrch[0] == NULL)
+ {
+ /* Empty search list. No default domain name. */
+ return conf->search_list_size == 0 && resp->defdname[0] == '\0';
+ }
+
+ if (resp->dnsrch[0] != resp->defdname)
+ /* If the search list is not empty, it must start with the
+ default domain name. */
+ return false;
+
+ size_t nsearch;
+ for (nsearch = 0; nsearch < MAXDNSRCH; ++nsearch)
+ if (resp->dnsrch[nsearch] == NULL)
+ break;
+ if (nsearch > MAXDNSRCH)
+ /* Search list is not null-terminated. */
+ return false;
+
+ size_t search_list_size = 0;
+ for (size_t i = 0; i < conf->search_list_size; ++i)
+ {
+ if (resp->dnsrch[i] != NULL)
+ {
+ search_list_size += strlen (resp->dnsrch[i]) + 1;
+ if (strcmp (resp->dnsrch[i], conf->search_list[i]) != 0)
+ return false;
+ }
+ else
+ {
+ /* resp->dnsrch is truncated if the number of elements
+ exceeds MAXDNSRCH, or if the combined storage space for
+ the search list exceeds what can be stored in
+ resp->defdname. */
+ if (i == MAXDNSRCH || search_list_size > sizeof (resp->dnsrch))
+ break;
+ /* Otherwise, a mismatch indicates a match failure. */
+ return false;
+ }
+ }
+ }
+
+ /* Check that the sort list has not been modified. */
+ {
+ size_t nsort = conf->sort_list_size;
+ if (nsort > MAXRESOLVSORT)
+ nsort = MAXRESOLVSORT;
+ if (resp->nsort != nsort)
+ return false;
+ for (size_t i = 0; i < nsort; ++i)
+ if (resp->sort_list[i].addr.s_addr != conf->sort_list[i].addr.s_addr
+ || resp->sort_list[i].mask != conf->sort_list[i].mask)
+ return false;
+ }
+
+ return true;
+}
+
+struct resolv_conf *
+__resolv_conf_get (struct __res_state *resp)
+{
+ struct resolv_conf *conf = resolv_conf_get_1 (resp);
+ if (conf == NULL)
+ return NULL;
+ if (resolv_conf_matches (resp, conf))
+ return conf;
+ __resolv_conf_put (conf);
+ return NULL;
+}
+
+void
+__resolv_conf_put (struct resolv_conf *conf)
+{
+ if (conf == NULL)
+ return;
+
+ __libc_lock_lock (lock);
+ conf_decrement (conf);
+ __libc_lock_unlock (lock);
+}
+
+struct resolv_conf *
+__resolv_conf_allocate (const struct resolv_conf *init)
+{
+ /* Allocate in decreasing order of alignment. */
+ _Static_assert (__alignof__ (const char *const *)
+ <= __alignof__ (struct resolv_conf), "alignment");
+ _Static_assert (__alignof__ (struct sockaddr_in6)
+ <= __alignof__ (const char *const *), "alignment");
+ _Static_assert (__alignof__ (struct sockaddr_in)
+ == __alignof__ (struct sockaddr_in6), "alignment");
+ _Static_assert (__alignof__ (struct resolv_sortlist_entry)
+ <= __alignof__ (struct sockaddr_in), "alignment");
+
+ /* Space needed by the nameserver addresses. */
+ size_t address_space = 0;
+ for (size_t i = 0; i < init->nameserver_list_size; ++i)
+ if (init->nameserver_list[i]->sa_family == AF_INET)
+ address_space += sizeof (struct sockaddr_in);
+ else
+ {
+ assert (init->nameserver_list[i]->sa_family == AF_INET6);
+ address_space += sizeof (struct sockaddr_in6);
+ }
+
+ /* Space needed by the search list strings. */
+ size_t string_space = 0;
+ for (size_t i = 0; i < init->search_list_size; ++i)
+ string_space += strlen (init->search_list[i]) + 1;
+
+ /* Allocate the buffer. */
+ void *ptr;
+ struct alloc_buffer buffer = alloc_buffer_allocate
+ (sizeof (struct resolv_conf)
+ + init->nameserver_list_size * sizeof (init->nameserver_list[0])
+ + address_space
+ + init->search_list_size * sizeof (init->search_list[0])
+ + init->sort_list_size * sizeof (init->sort_list[0])
+ + string_space,
+ &ptr);
+ struct resolv_conf *conf
+ = alloc_buffer_alloc (&buffer, struct resolv_conf);
+ if (conf == NULL)
+ /* Memory allocation failure. */
+ return NULL;
+ assert (conf == ptr);
+
+ /* Initialize the contents. */
+ conf->__refcount = 1;
+ conf->retrans = init->retrans;
+ conf->retry = init->retry;
+ conf->options = init->options;
+ conf->ndots = init->ndots;
+
+ /* Allocate the arrays with pointers. These must come first because
+ they have the highets alignment. */
+ conf->nameserver_list_size = init->nameserver_list_size;
+ const struct sockaddr **nameserver_array = alloc_buffer_alloc_array
+ (&buffer, const struct sockaddr *, init->nameserver_list_size);
+ conf->nameserver_list = nameserver_array;
+
+ conf->search_list_size = init->search_list_size;
+ const char **search_array = alloc_buffer_alloc_array
+ (&buffer, const char *, init->search_list_size);
+ conf->search_list = search_array;
+
+ /* Fill the name server list array. */
+ for (size_t i = 0; i < init->nameserver_list_size; ++i)
+ if (init->nameserver_list[i]->sa_family == AF_INET)
+ {
+ struct sockaddr_in *sa = alloc_buffer_alloc
+ (&buffer, struct sockaddr_in);
+ *sa = *(struct sockaddr_in *) init->nameserver_list[i];
+ nameserver_array[i] = (struct sockaddr *) sa;
+ }
+ else
+ {
+ struct sockaddr_in6 *sa = alloc_buffer_alloc
+ (&buffer, struct sockaddr_in6);
+ *sa = *(struct sockaddr_in6 *) init->nameserver_list[i];
+ nameserver_array[i] = (struct sockaddr *) sa;
+ }
+
+ /* Allocate and fill the sort list array. */
+ {
+ conf->sort_list_size = init->sort_list_size;
+ struct resolv_sortlist_entry *array = alloc_buffer_alloc_array
+ (&buffer, struct resolv_sortlist_entry, init->sort_list_size);
+ conf->sort_list = array;
+ for (size_t i = 0; i < init->sort_list_size; ++i)
+ array[i] = init->sort_list[i];
+ }
+
+ /* Fill the search list array. This must come last because the
+ strings are the least aligned part of the allocation. */
+ {
+ for (size_t i = 0; i < init->search_list_size; ++i)
+ search_array[i] = alloc_buffer_copy_string
+ (&buffer, init->search_list[i]);
+ }
+
+ assert (!alloc_buffer_has_failed (&buffer));
+ return conf;
+}
+
+/* Update *RESP from the extended state. */
+static __attribute__ ((nonnull (1, 2), warn_unused_result)) bool
+update_from_conf (struct __res_state *resp, const struct resolv_conf *conf)
+{
+ resp->defdname[0] = '\0';
+ resp->pfcode = 0;
+ resp->_vcsock = -1;
+ resp->_flags = 0;
+ resp->ipv6_unavail = false;
+ resp->__glibc_unused_qhook = NULL;
+ resp->__glibc_unused_rhook = NULL;
+
+ resp->retrans = conf->retrans;
+ resp->retry = conf->retry;
+ resp->options = conf->options;
+ resp->ndots = conf->ndots;
+
+ /* Copy the name server addresses. */
+ {
+ resp->nscount = 0;
+ resp->_u._ext.nscount = 0;
+ size_t nserv = conf->nameserver_list_size;
+ if (nserv > MAXNS)
+ nserv = MAXNS;
+ for (size_t i = 0; i < nserv; i++)
+ {
+ if (conf->nameserver_list[i]->sa_family == AF_INET)
+ {
+ resp->nsaddr_list[i]
+ = *(struct sockaddr_in *)conf->nameserver_list[i];
+ resp->_u._ext.nsaddrs[i] = NULL;
+ }
+ else
+ {
+ assert (conf->nameserver_list[i]->sa_family == AF_INET6);
+ resp->nsaddr_list[i].sin_family = 0;
+ /* Make a defensive copy of the name server address, in
+ case the application overwrites it. */
+ struct sockaddr_in6 *sa = malloc (sizeof (*sa));
+ if (sa == NULL)
+ {
+ for (size_t j = 0; j < i; ++j)
+ free (resp->_u._ext.nsaddrs[j]);
+ return false;
+ }
+ *sa = *(struct sockaddr_in6 *)conf->nameserver_list[i];
+ resp->_u._ext.nsaddrs[i] = sa;
+ }
+ resp->_u._ext.nssocks[i] = -1;
+ }
+ resp->nscount = nserv;
+ /* Leave resp->_u._ext.nscount at 0. res_send.c handles this. */
+ }
+
+ /* Fill in the prefix of the search list. It is truncated either at
+ MAXDNSRCH, or if reps->defdname has insufficient space. */
+ {
+ struct alloc_buffer buffer
+ = alloc_buffer_create (resp->defdname, sizeof (resp->defdname));
+ size_t size = conf->search_list_size;
+ size_t i;
+ for (i = 0; i < size && i < MAXDNSRCH; ++i)
+ {
+ resp->dnsrch[i] = alloc_buffer_copy_string
+ (&buffer, conf->search_list[i]);
+ if (resp->dnsrch[i] == NULL)
+ /* No more space in resp->defdname. Truncate. */
+ break;
+ }
+ resp->dnsrch[i] = NULL;
+ }
+
+ /* Copy the sort list. */
+ {
+ size_t nsort = conf->sort_list_size;
+ if (nsort > MAXRESOLVSORT)
+ nsort = MAXRESOLVSORT;
+ for (size_t i = 0; i < nsort; ++i)
+ {
+ resp->sort_list[i].addr = conf->sort_list[i].addr;
+ resp->sort_list[i].mask = conf->sort_list[i].mask;
+ }
+ resp->nsort = nsort;
+ }
+
+ /* The overlapping parts of both configurations should agree after
+ initialization. */
+ assert (resolv_conf_matches (resp, conf));
+ return true;
+}
+
+/* Decrement the configuration object at INDEX and free it if the
+ reference counter reaches 0. *GLOBAL_COPY must be locked and
+ remains so. */
+static void
+decrement_at_index (struct resolv_conf_global *global_copy, size_t index)
+{
+ if (index < resolv_conf_array_size (&global_copy->array))
+ {
+ /* Index found. */
+ uintptr_t *slot = resolv_conf_array_at (&global_copy->array, index);
+ /* Check that the slot is not already part of the free list. */
+ if (!(*slot & 1))
+ {
+ struct resolv_conf *conf = (struct resolv_conf *) *slot;
+ conf_decrement (conf);
+ /* Put the slot onto the free list. */
+ *slot = global_copy->free_list_start;
+ global_copy->free_list_start = (index << 1) | 1;
+ }
+ }
+}
+
+bool
+__resolv_conf_attach (struct __res_state *resp, struct resolv_conf *conf)
+{
+ assert (conf->__refcount > 0);
+
+ struct resolv_conf_global *global_copy = get_locked_global ();
+ if (global_copy == NULL)
+ return false;
+
+ /* Try to find an unused index in the array. */
+ size_t index;
+ {
+ if (global_copy->free_list_start & 1)
+ {
+ /* Unlink from the free list. */
+ index = global_copy->free_list_start >> 1;
+ uintptr_t *slot = resolv_conf_array_at (&global_copy->array, index);
+ global_copy->free_list_start = *slot;
+ assert (global_copy->free_list_start == 0
+ || global_copy->free_list_start & 1);
+ /* Install the configuration pointer. */
+ *slot = (uintptr_t) conf;
+ }
+ else
+ {
+ size_t size = resolv_conf_array_size (&global_copy->array);
+ /* No usable index found. Increase the array size. */
+ resolv_conf_array_add (&global_copy->array, (uintptr_t) conf);
+ if (resolv_conf_array_has_failed (&global_copy->array))
+ {
+ put_locked_global (global_copy);
+ __set_errno (ENOMEM);
+ return false;
+ }
+ /* The new array element was added at the end. */
+ index = size;
+ }
+ }
+
+ /* We have added a new reference to the object. */
+ ++conf->__refcount;
+ assert (conf->__refcount > 0);
+ put_locked_global (global_copy);
+
+ if (!update_from_conf (resp, conf))
+ {
+ /* Drop the reference we acquired. Reacquire the lock. The
+ object has already been allocated, so it cannot be NULL this
+ time. */
+ global_copy = get_locked_global ();
+ decrement_at_index (global_copy, index);
+ put_locked_global (global_copy);
+ return false;
+ }
+ resp->_u._ext.__glibc_extension_index = index ^ INDEX_MAGIC;
+
+ return true;
+}
+
+void
+__resolv_conf_detach (struct __res_state *resp)
+{
+ if (atomic_load_relaxed (&global) == NULL)
+ /* Detach operation after a shutdown, or without any prior
+ attachment. We cannot free the data (and there might not be
+ anything to free anyway). */
+ return;
+
+ struct resolv_conf_global *global_copy = get_locked_global ();
+ size_t index = resp->_u._ext.__glibc_extension_index ^ INDEX_MAGIC;
+ decrement_at_index (global_copy, index);
+
+ /* Clear the index field, so that accidental reuse is less
+ likely. */
+ resp->_u._ext.__glibc_extension_index = 0;
+
+ put_locked_global (global_copy);
+}
+
+/* Deallocate the global data. */
+libc_freeres_fn (freeres)
+{
+ /* No locking because this function is supposed to be called when
+ the process has turned single-threaded. */
+ if (global == NULL)
+ return;
+
+ if (global->conf_current != NULL)
+ {
+ conf_decrement (global->conf_current);
+ global->conf_current = NULL;
+ }
+
+ /* Note that this frees only the array itself. The pointed-to
+ configuration objects should have been deallocated by res_nclose
+ and per-thread cleanup functions. */
+ resolv_conf_array_free (&global->array);
+
+ free (global);
+
+ /* Stop potential future __resolv_conf_detach calls from accessing
+ deallocated memory. */
+ global = NULL;
+}
diff --git a/resolv/resolv_conf.h b/resolv/resolv_conf.h
new file mode 100644
index 0000000000..e903a206da
--- /dev/null
+++ b/resolv/resolv_conf.h
@@ -0,0 +1,103 @@
+/* Extended resolver state separate from struct __res_state.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#ifndef RESOLV_STATE_H
+#define RESOLV_STATE_H
+
+#include <netinet/in.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+/* This type corresponds to members of the _res.sort_list array. */
+struct resolv_sortlist_entry
+{
+ struct in_addr addr;
+ uint32_t mask;
+};
+
+/* Extended resolver state associated with res_state objects. Client
+ code can reach this state through a struct resolv_context
+ object. */
+struct resolv_conf
+{
+ /* Reference counter. The object is deallocated once it reaches
+ zero. For internal use within resolv_conf only. */
+ size_t __refcount;
+
+ /* List of IPv4 and IPv6 name server addresses. */
+ const struct sockaddr **nameserver_list;
+ size_t nameserver_list_size;
+
+ /* The domain names forming the search list. */
+ const char *const *search_list;
+ size_t search_list_size;
+
+ /* IPv4 address preference rules. */
+ const struct resolv_sortlist_entry *sort_list;
+ size_t sort_list_size;
+
+ /* _res.options has type unsigned long, but we can only use 32 bits
+ for portability across all architectures. */
+ unsigned int options;
+ unsigned int retrans; /* Timeout. */
+ unsigned int retry; /* Number of times to retry. */
+ unsigned int ndots; /* Dots needed for initial non-search query. */
+};
+
+/* The functions below are for use by the res_init resolv.conf parser
+ and the struct resolv_context facility. */
+
+struct __res_state;
+
+/* Read /etc/resolv.conf and return a configuration object, or NULL if
+ /etc/resolv.conf cannot be read due to memory allocation errors.
+ If PREINIT is not NULL, some configuration values are taken from the
+ struct __res_state object. */
+struct resolv_conf *__resolv_conf_load (struct __res_state *preinit)
+ attribute_hidden __attribute__ ((warn_unused_result));
+
+/* Return a configuration object for the current /etc/resolv.conf
+ settings, or NULL on failure. The object is cached. */
+struct resolv_conf *__resolv_conf_get_current (void)
+ attribute_hidden __attribute__ ((warn_unused_result));
+
+/* Return the extended resolver state for *RESP, or NULL if it cannot
+ be determined. A call to this function must be paired with a call
+ to __resolv_conf_put. */
+struct resolv_conf *__resolv_conf_get (struct __res_state *) attribute_hidden;
+
+/* Converse of __resolv_conf_get. */
+void __resolv_conf_put (struct resolv_conf *) attribute_hidden;
+
+/* Allocate a new struct resolv_conf object and copy the
+ pre-configured values from *INIT. Return NULL on allocation
+ failure. The object must be deallocated using
+ __resolv_conf_put. */
+struct resolv_conf *__resolv_conf_allocate (const struct resolv_conf *init)
+ attribute_hidden __attribute__ ((nonnull (1), warn_unused_result));
+
+/* Associate an existing extended resolver state with *RESP. Return
+ false on allocation failure. In addition, update *RESP with the
+ overlapping non-extended resolver state. */
+bool __resolv_conf_attach (struct __res_state *, struct resolv_conf *)
+ attribute_hidden;
+
+/* Detach the extended resolver state from *RESP. */
+void __resolv_conf_detach (struct __res_state *resp) attribute_hidden;
+
+#endif /* RESOLV_STATE_H */
diff --git a/resolv/resolv_context.c b/resolv/resolv_context.c
new file mode 100644
index 0000000000..4bd79111f0
--- /dev/null
+++ b/resolv/resolv_context.c
@@ -0,0 +1,252 @@
+/* Temporary, thread-local resolver state.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <resolv_context.h>
+#include <resolv_conf.h>
+#include <resolv-internal.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* Currently active struct resolv_context object. This pointer forms
+ the start of a single-linked list, using the __next member of
+ struct resolv_context. This list serves two purposes:
+
+ (a) A subsequent call to __resolv_context_get will only increment
+ the reference counter and will not allocate a new object. The
+ _res state freshness check is skipped in this case, too.
+
+ (b) The per-thread cleanup function defined by the resolver calls
+ __resolv_context_freeres, which will deallocate all the context
+ objects. This avoids the need for cancellation handlers and
+ the complexity they bring, but it requires heap allocation of
+ the context object because the per-thread cleanup functions run
+ only after the stack has been fully unwound (and all on-stack
+ objects have been deallocated at this point).
+
+ The TLS variable current is updated even in
+ __resolv_context_get_override, to support case (b) above. This does
+ not override the per-thread resolver state (as obtained by the
+ non-res_state function such as __resolv_context_get) in an
+ observable way because the wrapped context is only used to
+ implement the res_n* functions in the resolver, and those do not
+ call back into user code which could indirectly use the per-thread
+ resolver state. */
+static __thread struct resolv_context *current attribute_tls_model_ie;
+
+/* The resolv_conf handling will gives us a ctx->conf pointer even if
+ these fields do not match because a mis-match does not cause a loss
+ of state (_res objects can store the full information). This
+ function checks to ensure that there is a full patch, to prevent
+ overwriting a patched configuration. */
+static bool
+replicated_configuration_matches (const struct resolv_context *ctx)
+{
+ return ctx->resp->options == ctx->conf->options
+ && ctx->resp->retrans == ctx->conf->retrans
+ && ctx->resp->retry == ctx->conf->retry
+ && ctx->resp->ndots == ctx->conf->ndots;
+}
+
+/* Initialize *RESP if RES_INIT is not yet set in RESP->options, or if
+ res_init in some other thread requested re-initializing. */
+static __attribute__ ((warn_unused_result)) bool
+maybe_init (struct resolv_context *ctx, bool preinit)
+{
+ struct __res_state *resp = ctx->resp;
+ if (resp->options & RES_INIT)
+ {
+ if (resp->options & RES_NORELOAD)
+ /* Configuration reloading was explicitly disabled. */
+ return true;
+
+ /* If there is no associated resolv_conf object despite the
+ initialization, something modified *ctx->resp. Do not
+ override those changes. */
+ if (ctx->conf != NULL && replicated_configuration_matches (ctx))
+ {
+ struct resolv_conf *current = __resolv_conf_get_current ();
+ if (current == NULL)
+ return false;
+
+ /* Check if the configuration changed. */
+ if (current != ctx->conf)
+ {
+ /* This call will detach the extended resolver state. */
+ if (resp->nscount > 0)
+ __res_iclose (resp, true);
+ /* Reattach the current configuration. */
+ if (__resolv_conf_attach (ctx->resp, current))
+ {
+ __resolv_conf_put (ctx->conf);
+ /* ctx takes ownership, so we do not release current. */
+ ctx->conf = current;
+ }
+ }
+ else
+ /* No change. Drop the reference count for current. */
+ __resolv_conf_put (current);
+ }
+ return true;
+ }
+
+ assert (ctx->conf == NULL);
+ if (preinit)
+ {
+ if (!resp->retrans)
+ resp->retrans = RES_TIMEOUT;
+ if (!resp->retry)
+ resp->retry = RES_DFLRETRY;
+ resp->options = RES_DEFAULT;
+ if (!resp->id)
+ resp->id = res_randomid ();
+ }
+
+ if (__res_vinit (resp, preinit) < 0)
+ return false;
+ ctx->conf = __resolv_conf_get (ctx->resp);
+ return true;
+}
+
+/* Allocate a new context object and initialize it. The object is put
+ on the current list. */
+static struct resolv_context *
+context_alloc (struct __res_state *resp)
+{
+ struct resolv_context *ctx = malloc (sizeof (*ctx));
+ if (ctx == NULL)
+ return NULL;
+ ctx->resp = resp;
+ ctx->conf = __resolv_conf_get (resp);
+ ctx->__refcount = 1;
+ ctx->__from_res = true;
+ ctx->__next = current;
+ current = ctx;
+ return ctx;
+}
+
+/* Deallocate the context object and all the state within. */
+static void
+context_free (struct resolv_context *ctx)
+{
+ int error_code = errno;
+ current = ctx->__next;
+ __resolv_conf_put (ctx->conf);
+ free (ctx);
+ __set_errno (error_code);
+}
+
+/* Reuse the current context object. */
+static struct resolv_context *
+context_reuse (void)
+{
+ /* A context object created by __resolv_context_get_override cannot
+ be reused. */
+ assert (current->__from_res);
+
+ ++current->__refcount;
+
+ /* Check for reference counter wraparound. This can only happen if
+ the get/put functions are not properly paired. */
+ assert (current->__refcount > 0);
+
+ return current;
+}
+
+/* Backing function for the __resolv_context_get family of
+ functions. */
+static struct resolv_context *
+context_get (bool preinit)
+{
+ if (current != NULL)
+ return context_reuse ();
+
+ struct resolv_context *ctx = context_alloc (&_res);
+ if (ctx == NULL)
+ return NULL;
+ if (!maybe_init (ctx, preinit))
+ {
+ context_free (ctx);
+ return NULL;
+ }
+ return ctx;
+}
+
+struct resolv_context *
+__resolv_context_get (void)
+{
+ return context_get (false);
+}
+libc_hidden_def (__resolv_context_get)
+
+struct resolv_context *
+__resolv_context_get_preinit (void)
+{
+ return context_get (true);
+}
+libc_hidden_def (__resolv_context_get_preinit)
+
+struct resolv_context *
+__resolv_context_get_override (struct __res_state *resp)
+{
+ /* NB: As explained asbove, context_alloc will put the context on
+ the current list. */
+ struct resolv_context *ctx = context_alloc (resp);
+ if (ctx == NULL)
+ return NULL;
+
+ ctx->__from_res = false;
+ return ctx;
+}
+libc_hidden_def (__resolv_context_get_override)
+
+void
+__resolv_context_put (struct resolv_context *ctx)
+{
+ if (ctx == NULL)
+ return;
+
+ /* NB: Callers assume that this function preserves errno and
+ h_errno. */
+
+ assert (current == ctx);
+ assert (ctx->__refcount > 0);
+
+ if (ctx->__from_res && --ctx->__refcount > 0)
+ /* Do not pop this context yet. */
+ return;
+
+ context_free (ctx);
+}
+libc_hidden_def (__resolv_context_put)
+
+void
+__resolv_context_freeres (void)
+{
+ /* Deallocate the entire chain of context objects. */
+ struct resolv_context *ctx = current;
+ current = NULL;
+ while (ctx != NULL)
+ {
+ struct resolv_context *next = ctx->__next;
+ context_free (ctx);
+ ctx = next;
+ }
+}
diff --git a/resolv/resolv_context.h b/resolv/resolv_context.h
new file mode 100644
index 0000000000..c1dff76cb9
--- /dev/null
+++ b/resolv/resolv_context.h
@@ -0,0 +1,182 @@
+/* Temporary, thread-local resolver state.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* struct resolv_context objects are allocated on the heap,
+ initialized by __resolv_context_get (and its variants), and
+ destroyed by __resolv_context_put.
+
+ A nested call to __resolv_context_get (after another call to
+ __resolv_context_get without a matching __resolv_context_put call,
+ on the same thread) returns the original pointer, instead of
+ allocating a new context. This prevents unexpected reloading of
+ the resolver configuration. Care is taken to keep the context in
+ sync with the thread-local _res object. (This does not happen with
+ __resolv_context_get_override, and __resolv_context_get_no_inet6 may
+ also interpose another context object if RES_USE_INET6 needs to be
+ disabled.)
+
+ In contrast to struct __res_state, struct resolv_context is not
+ affected by ABI compatibility concerns.
+
+ For the benefit of the res_n* functions, a struct __res_state
+ pointer is included in the context object, and a separate
+ initialization function is provided. */
+
+#ifndef _RESOLV_CONTEXT_H
+#define _RESOLV_CONTEXT_H
+
+#include <bits/types/res_state.h>
+#include <resolv/resolv_conf.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+/* Temporary resolver state. */
+struct resolv_context
+{
+ struct __res_state *resp; /* Backing resolver state. */
+
+ /* Extended resolver state. This is set to NULL if the
+ __resolv_context_get functions are unable to locate an associated
+ extended state. In this case, the configuration data in *resp
+ has to be used; otherwise, the data from *conf should be
+ preferred (because it is a superset). */
+ struct resolv_conf *conf;
+
+ /* The following fields are for internal use within the
+ resolv_context module. */
+ size_t __refcount; /* Count of reusages by the get functions. */
+ bool __from_res; /* True if created from _res. */
+
+ /* If RES_USE_INET6 was disabled at this level, this field points to
+ the previous context. */
+ struct resolv_context *__next;
+};
+
+/* Return the current temporary resolver context, or NULL if there was
+ an error (indicated by errno). A call to this function must be
+ paired with a call to __resolv_context_put. */
+struct resolv_context *__resolv_context_get (void)
+ __attribute__ ((warn_unused_result));
+libc_hidden_proto (__resolv_context_get)
+
+/* Deallocate the temporary resolver context. Converse of
+ __resolv_context_get. Restore the RES_USE_INET6 flag if necessary.
+ Do nothing if CTX is NULL. */
+void __resolv_context_put (struct resolv_context *ctx);
+libc_hidden_proto (__resolv_context_put)
+
+/* Like __resolv_context_get, but the _res structure can be partially
+ initialzed and those changes will not be overwritten. */
+struct resolv_context *__resolv_context_get_preinit (void)
+ __attribute__ ((warn_unused_result));
+libc_hidden_proto (__resolv_context_get_preinit)
+
+/* Wrap a struct __res_state object in a struct resolv_context object.
+ A call to this function must be paired with a call to
+ __resolv_context_put. */
+struct resolv_context *__resolv_context_get_override (struct __res_state *)
+ __attribute__ ((nonnull (1), warn_unused_result));
+libc_hidden_proto (__resolv_context_get_override)
+
+/* Return the search path entry at INDEX, or NULL if there are fewer
+ than INDEX entries. */
+static __attribute__ ((nonnull (1), unused)) const char *
+__resolv_context_search_list (const struct resolv_context *ctx, size_t index)
+{
+ if (ctx->conf != NULL)
+ {
+ if (index < ctx->conf->search_list_size)
+ return ctx->conf->search_list[index];
+ else
+ return NULL;
+ }
+ /* Fallback. ctx->resp->dnsrch is a NULL-terminated array. */
+ for (size_t i = 0; ctx->resp->dnsrch[i] != NULL && i < MAXDNSRCH; ++i)
+ if (i == index)
+ return ctx->resp->dnsrch[i];
+ return NULL;
+}
+
+/* Return the number of name servers. */
+static __attribute__ ((nonnull (1), unused)) size_t
+__resolv_context_nameserver_count (const struct resolv_context *ctx)
+{
+ if (ctx->conf != NULL)
+ return ctx->conf->nameserver_list_size;
+ else
+ return ctx->resp->nscount;
+}
+
+/* Return a pointer to the socket address of the name server INDEX, or
+ NULL if the index is out of bounds. */
+static __attribute__ ((nonnull (1), unused)) const struct sockaddr *
+__resolv_context_nameserver (const struct resolv_context *ctx, size_t index)
+{
+ if (ctx->conf != NULL)
+ {
+ if (index < ctx->conf->nameserver_list_size)
+ return ctx->conf->nameserver_list[index];
+ }
+ else
+ if (index < ctx->resp->nscount)
+ {
+ if (ctx->resp->nsaddr_list[index].sin_family != 0)
+ return (const struct sockaddr *) &ctx->resp->nsaddr_list[index];
+ else
+ return (const struct sockaddr *) &ctx->resp->_u._ext.nsaddrs[index];
+ }
+ return NULL;
+}
+
+/* Return the number of sort list entries. */
+static __attribute__ ((nonnull (1), unused)) size_t
+__resolv_context_sort_count (const struct resolv_context *ctx)
+{
+ if (ctx->conf != NULL)
+ return ctx->conf->sort_list_size;
+ else
+ return ctx->resp->nsort;
+}
+
+/* Return the sort list entry at INDEX. */
+static __attribute__ ((nonnull (1), unused)) struct resolv_sortlist_entry
+__resolv_context_sort_entry (const struct resolv_context *ctx, size_t index)
+{
+ if (ctx->conf != NULL)
+ {
+ if (index < ctx->conf->sort_list_size)
+ return ctx->conf->sort_list[index];
+ /* Fall through. */
+ }
+ else if (index < ctx->resp->nsort)
+ return (struct resolv_sortlist_entry)
+ {
+ .addr = ctx->resp->sort_list[index].addr,
+ .mask = ctx->resp->sort_list[index].mask,
+ };
+
+ return (struct resolv_sortlist_entry) { .mask = 0, };
+}
+
+/* Called during thread shutdown to free the associated resolver
+ context (mostly in response to cancellation, otherwise the
+ __resolv_context_get/__resolv_context_put pairing will already have
+ deallocated the context object). */
+void __resolv_context_freeres (void) attribute_hidden;
+
+#endif /* _RESOLV_CONTEXT_H */
diff --git a/resolv/tst-bug18665-tcp.c b/resolv/tst-bug18665-tcp.c
new file mode 100644
index 0000000000..52849fabb9
--- /dev/null
+++ b/resolv/tst-bug18665-tcp.c
@@ -0,0 +1,230 @@
+/* Test __libc_res_nsend buffer mismanagement, basic TCP coverage.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/check_nss.h>
+#include <support/resolv_test.h>
+#include <support/xthread.h>
+#include <support/xmemstream.h>
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+static int initial_address_count = 1;
+static int subsequent_address_count = 2000;
+static int response_number = 0;
+
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ TEST_VERIFY_EXIT (qname != NULL);
+
+ /* If not using TCP, just force its use. */
+ if (!ctx->tcp)
+ {
+ struct resolv_response_flags flags = {.tc = true};
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+ return;
+ }
+
+ struct resolv_response_flags flags = {};
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+
+ resolv_response_section (b, ns_s_an);
+
+ /* The number of addresses (in the additional section) for the name
+ server record (in the authoritative section). */
+ int address_count;
+ xpthread_mutex_lock (&lock);
+ ++response_number;
+ if (response_number == 1)
+ address_count = initial_address_count;
+ else if (response_number == 2)
+ {
+ address_count = 0;
+ resolv_response_drop (b);
+ resolv_response_close (b);
+ }
+ else
+ address_count = subsequent_address_count;
+ xpthread_mutex_unlock (&lock);
+
+ /* Only add the address record to the answer section if we requested
+ any name server addresses. */
+ if (address_count > 0)
+ {
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
+ switch (qtype)
+ {
+ case T_A:
+ {
+ char ipv4[4] = {10, response_number >> 8, response_number, 0};
+ ipv4[3] = 2 * ctx->tcp + 4 * ctx->server_index;
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
+ }
+ break;
+ case T_AAAA:
+ {
+ char ipv6[16]
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0,
+ response_number >> 8, response_number, 0, 0};
+ ipv6[15] = 2 * ctx->tcp + 4 * ctx->server_index;
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
+ }
+ break;
+ default:
+ support_record_failure ();
+ printf ("error: unexpected QTYPE: %s/%u/%u\n",
+ qname, qclass, qtype);
+ }
+ resolv_response_close_record (b);
+
+ /* Add the name server record. */
+ resolv_response_section (b, ns_s_ns);
+ resolv_response_open_record (b, "example", C_IN, T_NS, 0);
+ resolv_response_add_name (b, "ns.example");
+ resolv_response_close_record (b);
+
+ /* Increase the response size with name server addresses. These
+ addresses are not copied out of nss_dns, and thus do not
+ trigger getaddrinfo retries with a larger buffer, making
+ testing more predictable. */
+ resolv_response_section (b, ns_s_ar);
+ for (int i = 1; i <= address_count; ++i)
+ {
+ resolv_response_open_record (b, "ns.example", qclass, qtype, 0);
+ switch (qtype)
+ {
+ case T_A:
+ {
+ char ipv4[4] = {response_number, i >> 8, i, 0};
+ ipv4[3] = 2 * ctx->tcp + 4 * ctx->server_index;
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
+ }
+ break;
+ case T_AAAA:
+ {
+ char ipv6[16]
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0,
+ response_number >> 8, response_number,
+ i >> 8, i, 0, 0};
+ ipv6[15] = 2 * ctx->tcp + 4 * ctx->server_index;
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
+ }
+ break;
+ default:
+ support_record_failure ();
+ printf ("error: unexpected QTYPE: %s/%u/%u\n",
+ qname, qclass, qtype);
+ }
+ resolv_response_close_record (b);
+ }
+ }
+}
+
+static char *
+expected_result (unsigned port, unsigned response_number)
+{
+ struct xmemstream mem;
+ xopen_memstream (&mem);
+ /* We fail the second TCP query to the first server by closing the
+ connection immediately, without returning any data. This should
+ cause failover to the second server. */
+ int server_index = 1;
+ fprintf (mem.out, "address: STREAM/TCP 10.%u.%u.%u %u\n",
+ (response_number >> 8) & 0xff, response_number & 0xff,
+ 2 + 4 * server_index, port);
+ fprintf (mem.out, "address: STREAM/TCP 2001:db8::%x:%x %u\n",
+ (response_number + 1) & 0xffff,
+ 2 + 4 * server_index, port);
+ xfclose_memstream (&mem);
+ return mem.buffer;
+}
+
+static void
+test_different_sizes (void)
+{
+ struct addrinfo hints =
+ {
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_STREAM,
+ .ai_protocol = IPPROTO_TCP,
+ };
+ struct addrinfo *ai;
+ char *expected;
+ int ret;
+
+ /* This magic number produces a response size close to 2048
+ bytes. */
+ initial_address_count = 124;
+ response_number = 0;
+
+ ret = getaddrinfo ("www.example", "80", &hints, &ai);
+ expected = expected_result (80, 3);
+ check_addrinfo ("www.example:80", ai, ret, expected);
+ if (ret == 0)
+ freeaddrinfo (ai);
+ free (expected);
+
+ response_number = 0;
+ ret = getaddrinfo ("www123.example", "80", &hints, &ai);
+ if (ret == 0)
+ freeaddrinfo (ai);
+
+ response_number = 0;
+ ret = getaddrinfo ("www1234.example", "80", &hints, &ai);
+ if (ret == 0)
+ freeaddrinfo (ai);
+
+ response_number = 0;
+ ret = getaddrinfo ("www12345.example", "80", &hints, &ai);
+ if (ret == 0)
+ freeaddrinfo (ai);
+}
+
+static int
+do_test (void)
+{
+ struct resolv_test *obj = resolv_test_start
+ ((struct resolv_redirect_config)
+ {
+ .response_callback = response
+ });
+
+ test_different_sizes ();
+
+ _res.options |= RES_SNGLKUP;
+ test_different_sizes ();
+
+ _res.options |= RES_SNGLKUPREOP;
+ test_different_sizes ();
+
+ resolv_test_end (obj);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-bug18665.c b/resolv/tst-bug18665.c
new file mode 100644
index 0000000000..dc911f0468
--- /dev/null
+++ b/resolv/tst-bug18665.c
@@ -0,0 +1,138 @@
+/* Test for __libc_res_nsend buffer mismanagent (bug 18665), UDP case.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/resolv_test.h>
+#include <support/xthread.h>
+
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
+
+static int initial_address_count;
+static int response_count;
+
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ TEST_VERIFY_EXIT (qname != NULL);
+ struct resolv_response_flags flags = {};
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+
+ resolv_response_section (b, ns_s_an);
+
+ /* Add many A/AAAA records to the second response. */
+ int address_count;
+ xpthread_mutex_lock (&lock);
+ if (response_count == 0)
+ address_count = initial_address_count;
+ else
+ address_count = 2000;
+ ++response_count;
+ xpthread_mutex_unlock (&lock);
+
+ for (int i = 0; i < address_count; ++i)
+ {
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
+ switch (qtype)
+ {
+ case T_A:
+ {
+ char ipv4[4] = {10, i >> 8, i, 0};
+ ipv4[3] = 2 * ctx->tcp + 4 * ctx->server_index;
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
+ }
+ break;
+ case T_AAAA:
+ {
+ char ipv6[16]
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ i >> 8, i, 0};
+ ipv6[15] = 2 * ctx->tcp + 4 * ctx->server_index;
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
+ }
+ break;
+ default:
+ support_record_failure ();
+ printf ("error: unexpected QTYPE: %s/%u/%u\n",
+ qname, qclass, qtype);
+ }
+ resolv_response_close_record (b);
+ }
+}
+
+static void
+test_different_sizes (void)
+{
+ struct addrinfo hints = { .ai_family = AF_UNSPEC, };
+ struct addrinfo *ai;
+ int ret;
+
+ /* This magic number produces a response size close to 2048
+ bytes. */
+ initial_address_count = 126;
+ response_count = 0;
+
+ ret = getaddrinfo ("www.example", "80", &hints, &ai);
+ if (ret == 0)
+ freeaddrinfo (ai);
+
+ response_count = 0;
+ ret = getaddrinfo ("www123.example", "80", &hints, &ai);
+ if (ret == 0)
+ freeaddrinfo (ai);
+
+ response_count = 0;
+ ret = getaddrinfo ("www1234.example", "80", &hints, &ai);
+ if (ret == 0)
+ freeaddrinfo (ai);
+
+ response_count = 0;
+ ret = getaddrinfo ("www12345.example", "80", &hints, &ai);
+ if (ret == 0)
+ freeaddrinfo (ai);
+}
+
+static int
+do_test (void)
+{
+ struct resolv_test *obj = resolv_test_start
+ ((struct resolv_redirect_config)
+ {
+ .response_callback = response
+ });
+
+ test_different_sizes ();
+
+ _res.options |= RES_SNGLKUP;
+ test_different_sizes ();
+
+ _res.options |= RES_SNGLKUPREOP;
+ test_different_sizes ();
+
+ resolv_test_end (obj);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-inet_pton.c b/resolv/tst-inet_pton.c
new file mode 100644
index 0000000000..af12f38fa9
--- /dev/null
+++ b/resolv/tst-inet_pton.c
@@ -0,0 +1,492 @@
+/* Test inet_pton functions.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <arpa/inet.h>
+#include <resolv/resolv-internal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/next_to_fault.h>
+#include <support/xunistd.h>
+#include <unistd.h>
+
+struct test_case
+{
+ /* The input data. */
+ const char *input;
+
+ /* True if AF_INET parses successfully. */
+ bool ipv4_ok;
+
+ /* True if AF_INET6 parses successfully. */
+ bool ipv6_ok;
+
+ /* Expected result for AF_INET. */
+ unsigned char ipv4_expected[4];
+
+ /* Expected result for AF_INET6. */
+ unsigned char ipv6_expected[16];
+};
+
+static void
+check_result (const char *what, const struct test_case *t, int family,
+ void *result_buffer, int inet_ret)
+{
+ TEST_VERIFY_EXIT (inet_ret >= -1);
+ TEST_VERIFY_EXIT (inet_ret <= 1);
+
+ int ok;
+ const unsigned char *expected;
+ size_t result_size;
+ switch (family)
+ {
+ case AF_INET:
+ ok = t->ipv4_ok;
+ expected = t->ipv4_expected;
+ result_size = 4;
+ break;
+ case AF_INET6:
+ ok = t->ipv6_ok;
+ expected = t->ipv6_expected;
+ result_size = 16;
+ break;
+ default:
+ FAIL_EXIT1 ("invalid address family %d", family);
+ }
+
+ if (inet_ret != ok)
+ {
+ support_record_failure ();
+ printf ("error: %s return value mismatch for [[%s]], family %d\n"
+ " expected: %d\n"
+ " actual: %d\n",
+ what, t->input, family, ok, inet_ret);
+ return;
+ }
+ if (memcmp (result_buffer, expected, result_size) != 0)
+ {
+ support_record_failure ();
+ printf ("error: %s result mismatch for [[%s]], family %d\n",
+ what, t->input, family);
+ }
+}
+
+static void
+run_one_test (const struct test_case *t)
+{
+ size_t test_len = strlen (t->input);
+
+ struct support_next_to_fault ntf_out4 = support_next_to_fault_allocate (4);
+ struct support_next_to_fault ntf_out6 = support_next_to_fault_allocate (16);
+
+ /* inet_pton requires NUL termination. */
+ {
+ struct support_next_to_fault ntf_in
+ = support_next_to_fault_allocate (test_len + 1);
+ memcpy (ntf_in.buffer, t->input, test_len + 1);
+ memset (ntf_out4.buffer, 0, 4);
+ check_result ("inet_pton", t, AF_INET, ntf_out4.buffer,
+ inet_pton (AF_INET, ntf_in.buffer, ntf_out4.buffer));
+ memset (ntf_out6.buffer, 0, 16);
+ check_result ("inet_pton", t, AF_INET6, ntf_out6.buffer,
+ inet_pton (AF_INET6, ntf_in.buffer, ntf_out6.buffer));
+ support_next_to_fault_free (&ntf_in);
+ }
+
+ /* __inet_pton_length does not require NUL termination. */
+ {
+ struct support_next_to_fault ntf_in
+ = support_next_to_fault_allocate (test_len);
+ memcpy (ntf_in.buffer, t->input, test_len);
+ memset (ntf_out4.buffer, 0, 4);
+ check_result ("__inet_pton_length", t, AF_INET, ntf_out4.buffer,
+ __inet_pton_length (AF_INET, ntf_in.buffer, ntf_in.length,
+ ntf_out4.buffer));
+ memset (ntf_out6.buffer, 0, 16);
+ check_result ("__inet_pton_length", t, AF_INET6, ntf_out6.buffer,
+ __inet_pton_length (AF_INET6, ntf_in.buffer, ntf_in.length,
+ ntf_out6.buffer));
+ support_next_to_fault_free (&ntf_in);
+ }
+
+ support_next_to_fault_free (&ntf_out4);
+ support_next_to_fault_free (&ntf_out6);
+}
+
+/* The test cases were manually crafted and the set enhanced with
+ American Fuzzy Lop. */
+const struct test_case test_cases[] =
+ {
+ {.input = ".:", },
+ {.input = "0.0.0.0",
+ .ipv4_ok = true,
+ .ipv4_expected = {0, 0, 0, 0},
+ },
+ {.input = "0.:", },
+ {.input = "00", },
+ {.input = "0000000", },
+ {.input = "00000000000000000", },
+ {.input = "092.", },
+ {.input = "10.0.301.2", },
+ {.input = "127.0.0.1",
+ .ipv4_ok = true,
+ .ipv4_expected = {127, 0, 0, 1},
+ },
+ {.input = "19..", },
+ {.input = "192.0.2.-1", },
+ {.input = "192.0.2.01", },
+ {.input = "192.0.2.1.", },
+ {.input = "192.0.2.1192.", },
+ {.input = "192.0.2.192.\377..", },
+ {.input = "192.0.2.256", },
+ {.input = "192.0.2.27",
+ .ipv4_ok = true,
+ .ipv4_expected = {192, 0, 2, 27},
+ },
+ {.input = "192.0.201.", },
+ {.input = "192.0.261.", },
+ {.input = "192.0.2\256", },
+ {.input = "192.0.\262.", },
+ {.input = "192.062.", },
+ {.input = "192.092.\256", },
+ {.input = "192.0\2562.", },
+ {.input = "192.192.0.2661\031", },
+ {.input = "192.192.00n2.1.", },
+ {.input = "192.192.2.190.", },
+ {.input = "192.255.255.2555", },
+ {.input = "192.92.219\023.", },
+ {.input = "192.\260.2.", },
+ {.input = "1:1::1:1",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x0, 0x1, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1
+ },
+ },
+ {.input = "2", },
+ {.input = "2.", },
+ {.input = "2001:db8:00001::f", },
+ {.input = "2001:db8:10000::f", },
+ {.input = "2001:db8:1234:5678:abcd:ef01:2345:67",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x12, 0x34, 0x56, 0x78,
+ 0xab, 0xcd, 0xef, 0x1, 0x23, 0x45, 0x0, 0x67
+ },
+ },
+ {.input = "2001:db8:1234:5678:abcd:ef01:2345:6789:1", },
+ {.input = "2001:db8:1234:5678:abcd:ef01:2345::6789", },
+ {.input = "2001:db8::0",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
+ },
+ },
+ {.input = "2001:db8::00",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
+ },
+ },
+ {.input = "2001:db8::1",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1
+ },
+ },
+ {.input = "2001:db8::10",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x10
+ },
+ },
+ {.input = "2001:db8::19",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x19
+ },
+ },
+ {.input = "2001:db8::1::\012", },
+ {.input = "2001:db8::1::2\012", },
+ {.input = "2001:db8::2",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2
+ },
+ },
+ {.input = "2001:db8::3",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x3
+ },
+ },
+ {.input = "2001:db8::4",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4
+ },
+ },
+ {.input = "2001:db8::5",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5
+ },
+ },
+ {.input = "2001:db8::6",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x6
+ },
+ },
+ {.input = "2001:db8::7",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x7
+ },
+ },
+ {.input = "2001:db8::8",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x8
+ },
+ },
+ {.input = "2001:db8::9",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x9
+ },
+ },
+ {.input = "2001:db8::A",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa
+ },
+ },
+ {.input = "2001:db8::B",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb
+ },
+ },
+ {.input = "2001:db8::C",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc
+ },
+ },
+ {.input = "2001:db8::D",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd
+ },
+ },
+ {.input = "2001:db8::E",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe
+ },
+ },
+ {.input = "2001:db8::F",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf
+ },
+ },
+ {.input = "2001:db8::a",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xa
+ },
+ },
+ {.input = "2001:db8::b",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xb
+ },
+ },
+ {.input = "2001:db8::c",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc
+ },
+ },
+ {.input = "2001:db8::d",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xd
+ },
+ },
+ {.input = "2001:db8::e",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xe
+ },
+ },
+ {.input = "2001:db8::f",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xf
+ },
+ },
+ {.input = "2001:db8::ff",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x20, 0x1, 0xd, 0xb8, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff
+ },
+ },
+ {.input = "2001:db8::ffff:2\012", },
+ {.input = "22", },
+ {.input = "2222@", },
+ {.input = "255.255.255.255",
+ .ipv4_ok = true,
+ .ipv4_expected = {255, 255, 255, 255},
+ },
+ {.input = "255.255.255.255\001", },
+ {.input = "255.255.255.25555", },
+ {.input = "2:", },
+ {.input = "2:a:8:EEEE::EEEE:F:EEE8:EEEE\034*:", },
+ {.input = "2:ff:1:1:7:ff:1:1:7.", },
+ {.input = "2f:0000000000000000000000000000000000000000000000000000000000"
+ "0000000000000000000000000000000000000000000000000000000000000000000000"
+ "0G01",
+ },
+ {.input = "429495", },
+ {.input = "5::5::", },
+ {.input = "6.6.", },
+ {.input = "992.", },
+ {.input = "::",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
+ },
+ },
+ {.input = "::00001", },
+ {.input = "::1",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1
+ },
+ },
+ {.input = "::10000", },
+ {.input = "::1:1",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x1
+ },
+ },
+ {.input = "::ff:1:1:7.0.0.1",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xff,
+ 0x0, 0x1, 0x0, 0x1, 0x7, 0x0, 0x0, 0x1
+ },
+ },
+ {.input = "::ff:1:1:7:ff:1:1:7.", },
+ {.input = "::ff:1:1:7ff:1:8:7.0.0.1", },
+ {.input = "::ff:1:1:7ff:1:8f:1:1:71", },
+ {.input = "::ffff:02fff:127.0.S1", },
+ {.input = "::ffff:127.0.0.1",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xff, 0xff, 0x7f, 0x0, 0x0, 0x1
+ },
+ },
+ {.input = "::ffff:1:7.0.0.1",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0xff, 0xff, 0x0, 0x1, 0x7, 0x0, 0x0, 0x1
+ },
+ },
+ {.input = ":\272", },
+ {.input = "A:f:ff:1:1:D:ff:1:1::7.", },
+ {.input = "AAAAA.", },
+ {.input = "D:::", },
+ {.input = "DF8F", },
+ {.input = "F::",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x0, 0xf, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
+ },
+ },
+ {.input = "F:A:8:EEEE:8:EEEE\034*:", },
+ {.input = "F:a:8:EEEE:8:EEEE\034*:", },
+ {.input = "F:ff:100:7ff:1:8:7.0.10.1",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0x0, 0xf, 0x0, 0xff, 0x1, 0x0, 0x7, 0xff,
+ 0x0, 0x1, 0x0, 0x8, 0x7, 0x0, 0xa, 0x1
+ },
+ },
+ {.input = "d92.", },
+ {.input = "ff:00000000000000000000000000000000000000000000000000000000000"
+ "00000000000000000000000000000000000000000000000000000000000000000001",
+ },
+ {.input = "fff2:2::ff2:2:f7",
+ .ipv6_ok = true,
+ .ipv6_expected = {
+ 0xff, 0xf2, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0,
+ 0x0, 0x0, 0xf, 0xf2, 0x0, 0x2, 0x0, 0xf7
+ },
+ },
+ {.input = "ffff:ff:ff:fff:ff:ff:ff:", },
+ {.input = "\272:", },
+ {NULL}
+ };
+
+static int
+do_test (void)
+{
+ for (size_t i = 0; test_cases[i].input != NULL; ++i)
+ run_one_test (test_cases + i);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-leaks.c b/resolv/tst-leaks.c
index b97c0648fd..5715f1ba34 100644
--- a/resolv/tst-leaks.c
+++ b/resolv/tst-leaks.c
@@ -1,5 +1,5 @@
/* Tests for res_query in libresolv
- Copyright (C) 2003-2016 Free Software Foundation, Inc.
+ Copyright (C) 2003-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/resolv/tst-leaks2.c b/resolv/tst-leaks2.c
index 3e9c4a2dc7..6a1fd6aa9c 100644
--- a/resolv/tst-leaks2.c
+++ b/resolv/tst-leaks2.c
@@ -1,5 +1,5 @@
/* Tests for res_init in libresolv
- Copyright (C) 2004-2016 Free Software Foundation, Inc.
+ Copyright (C) 2004-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
diff --git a/resolv/tst-no-libidn2.c b/resolv/tst-no-libidn2.c
new file mode 100644
index 0000000000..590696e3fa
--- /dev/null
+++ b/resolv/tst-no-libidn2.c
@@ -0,0 +1,2 @@
+/* Compiled into an empty shared object. Used by
+ tst-resolv-ai_idn-nolibidn2 to disable libidn2. */
diff --git a/resolv/tst-ns_name.c b/resolv/tst-ns_name.c
new file mode 100644
index 0000000000..970c3d6d15
--- /dev/null
+++ b/resolv/tst-ns_name.c
@@ -0,0 +1,438 @@
+/* Test ns_name-related functions.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* This test program processes the tst-ns_name.data file. */
+
+#include <ctype.h>
+#include <resolv.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xstdio.h>
+
+/* A byte buffer and its length. */
+struct buffer
+{
+ unsigned char *data;
+ size_t length;
+};
+
+/* Convert a base64-encoded string to its binary representation. */
+static bool
+base64_to_buffer (const char *base64, struct buffer *result)
+{
+ /* "-" denotes an empty input. */
+ if (strcmp (base64, "-") == 0)
+ {
+ result->data = xmalloc (1);
+ result->length = 0;
+ return true;
+ }
+
+ size_t size = strlen (base64);
+ unsigned char *data = xmalloc (size);
+ int ret = b64_pton (base64, data, size);
+ if (ret < 0 || ret > size)
+ return false;
+ result->data = xrealloc (data, ret);
+ result->length = ret;
+ return true;
+}
+
+/* A test case for ns_name_unpack and ns_name_ntop. */
+struct test_case
+{
+ char *path;
+ size_t lineno;
+ struct buffer input;
+ size_t input_offset;
+ int unpack_result;
+ struct buffer unpack_output;
+ int ntop_result;
+ char *ntop_text;
+};
+
+/* Deallocate the buffers associated with the test case. */
+static void
+free_test_case (struct test_case *t)
+{
+ free (t->path);
+ free (t->input.data);
+ free (t->unpack_output.data);
+ free (t->ntop_text);
+}
+
+/* Extract the test case information from a test file line. */
+static bool
+parse_test_case (const char *path, size_t lineno, const char *line,
+ struct test_case *result)
+{
+ memset (result, 0, sizeof (*result));
+ result->path = xstrdup (path);
+ result->lineno = lineno;
+ result->ntop_result = -1;
+ char *input = NULL;
+ char *unpack_output = NULL;
+ int ret = sscanf (line, "%ms %zu %d %ms %d %ms",
+ &input, &result->input_offset,
+ &result->unpack_result, &unpack_output,
+ &result->ntop_result, &result->ntop_text);
+ if (ret < 3)
+ {
+ printf ("%s:%zu: error: missing input fields\n", path, lineno);
+ free (input);
+ return false;
+ }
+ if (!base64_to_buffer (input, &result->input))
+ {
+ printf ("%s:%zu: error: malformed base64 input data\n", path, lineno);
+ free (input);
+ free (unpack_output);
+ free (result->ntop_text);
+ return false;
+ }
+ free (input);
+
+ if (unpack_output == NULL)
+ result->unpack_output = (struct buffer) { NULL, 0 };
+ else if (!base64_to_buffer (unpack_output, &result->unpack_output))
+ {
+ printf ("%s:%zu: error: malformed base64 unpack data\n", path, lineno);
+ free (result->input.data);
+ free (unpack_output);
+ free (result->ntop_text);
+ return false;
+ }
+ free (unpack_output);
+
+ /* At this point, all allocated buffers have been transferred to
+ *result. */
+
+ if (result->input_offset > result->input.length)
+ {
+ printf ("%s:%zu: error: input offset %zu exceeds buffer size %zu\n",
+ path, lineno, result->input_offset, result->input.length);
+ free_test_case (result);
+ return false;
+ }
+ if (result->unpack_result < -1)
+ {
+ printf ("%s:%zu: error: invalid unpack result %d\n",
+ path, lineno, result->unpack_result);
+ free_test_case (result);
+ return false;
+ }
+ if (result->ntop_result < -1)
+ {
+ printf ("%s:%zu: error: invalid ntop result %d\n",
+ path, lineno, result->ntop_result);
+ free_test_case (result);
+ return false;
+ }
+
+ bool fields_consistent;
+ switch (ret)
+ {
+ case 3:
+ fields_consistent = result->unpack_result == -1;
+ break;
+ case 5:
+ fields_consistent = result->unpack_result != -1
+ && result->ntop_result == -1;
+ break;
+ case 6:
+ fields_consistent = result->unpack_result != -1
+ && result->ntop_result != -1;
+ break;
+ default:
+ fields_consistent = false;
+ }
+ if (!fields_consistent)
+ {
+ printf ("%s:%zu: error: wrong number of fields: %d\n",
+ path, lineno, ret);
+ free_test_case (result);
+ return false;
+ }
+ return true;
+}
+
+/* Format the buffer as a hexadecimal string and write it to standard
+ output. */
+static void
+print_hex (const char *label, struct buffer buffer)
+{
+ printf (" %s ", label);
+ unsigned char *p = buffer.data;
+ unsigned char *end = p + buffer.length;
+ while (p < end)
+ {
+ printf ("%02X", *p & 0xFF);
+ ++p;
+ }
+ putchar ('\n');
+}
+
+/* Run the test case specified in *T. */
+static void
+run_test_case (struct test_case *t)
+{
+ /* Test ns_name_unpack. */
+ unsigned char *unpacked = xmalloc (NS_MAXCDNAME);
+ int consumed = ns_name_unpack
+ (t->input.data, t->input.data + t->input.length,
+ t->input.data + t->input_offset,
+ unpacked, NS_MAXCDNAME);
+ if (consumed != t->unpack_result)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong result from ns_name_unpack\n"
+ " expected: %d\n"
+ " actual: %d\n",
+ t->path, t->lineno, t->unpack_result, consumed);
+ return;
+ }
+ if (consumed != -1)
+ {
+ if (memcmp (unpacked, t->unpack_output.data,
+ t->unpack_output.length) != 0)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong data from ns_name_unpack\n",
+ t->path, t->lineno);
+ print_hex ("expected:", t->unpack_output);
+ print_hex ("actual: ",
+ (struct buffer) { unpacked, t->unpack_output.length });
+ return;
+ }
+
+ /* Test ns_name_ntop. */
+ char *text = xmalloc (NS_MAXDNAME);
+ int ret = ns_name_ntop (unpacked, text, NS_MAXDNAME);
+ if (ret != t->ntop_result)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong result from ns_name_top\n"
+ " expected: %d\n"
+ " actual: %d\n",
+ t->path, t->lineno, t->ntop_result, ret);
+ return;
+ }
+ if (ret != -1)
+ {
+ if (strcmp (text, t->ntop_text) != 0)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong data from ns_name_ntop\n",
+ t->path, t->lineno);
+ printf (" expected: \"%s\"\n", t->ntop_text);
+ printf (" actual: \"%s\"\n", text);
+ return;
+ }
+
+ /* Test ns_name_pton. Unpacking does not check the
+ NS_MAXCDNAME limit, but packing does, so we need to
+ adjust the expected result. */
+ int expected;
+ if (t->unpack_output.length > NS_MAXCDNAME)
+ expected = -1;
+ else if (strcmp (text, ".") == 0)
+ /* The root domain is fully qualified. */
+ expected = 1;
+ else
+ /* The domain name is never fully qualified. */
+ expected = 0;
+ unsigned char *repacked = xmalloc (NS_MAXCDNAME);
+ ret = ns_name_pton (text, repacked, NS_MAXCDNAME);
+ if (ret != expected)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong result from ns_name_pton\n"
+ " expected: %d\n"
+ " actual: %d\n",
+ t->path, t->lineno, expected, ret);
+ return;
+ }
+ if (ret >= 0
+ && memcmp (repacked, unpacked, t->unpack_output.length) != 0)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong data from ns_name_pton\n",
+ t->path, t->lineno);
+ print_hex ("expected:", t->unpack_output);
+ print_hex ("actual: ",
+ (struct buffer) { repacked, t->unpack_output.length });
+ return;
+ }
+
+ /* Test ns_name_compress, no compression case. */
+ if (t->unpack_output.length > NS_MAXCDNAME)
+ expected = -1;
+ else
+ expected = t->unpack_output.length;
+ memset (repacked, '$', NS_MAXCDNAME);
+ {
+ enum { ptr_count = 5 };
+ const unsigned char *dnptrs[ptr_count] = { repacked, };
+ ret = ns_name_compress (text, repacked, NS_MAXCDNAME,
+ dnptrs, dnptrs + ptr_count);
+ if (ret != expected)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong result from ns_name_compress\n"
+ " expected: %d\n"
+ " actual: %d\n",
+ t->path, t->lineno, expected, ret);
+ return;
+ }
+ if (ret < 0)
+ {
+ TEST_VERIFY (dnptrs[0] == repacked);
+ TEST_VERIFY (dnptrs[1] == NULL);
+ }
+ else
+ {
+ if (memcmp (repacked, unpacked, t->unpack_output.length) != 0)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong data from ns_name_compress\n",
+ t->path, t->lineno);
+ print_hex ("expected:", t->unpack_output);
+ print_hex ("actual: ", (struct buffer) { repacked, ret });
+ return;
+ }
+ TEST_VERIFY (dnptrs[0] == repacked);
+ if (unpacked[0] == '\0')
+ /* The root domain is not a compression target. */
+ TEST_VERIFY (dnptrs[1] == NULL);
+ else
+ {
+ TEST_VERIFY (dnptrs[1] == repacked);
+ TEST_VERIFY (dnptrs[2] == NULL);
+ }
+ }
+ }
+
+ /* Test ns_name_compress, full compression case. Skip this
+ test for invalid names and the root domain. */
+ if (expected >= 0 && unpacked[0] != '\0')
+ {
+ /* The destination buffer needs additional room for the
+ offset, the initial name, and the compression
+ reference. */
+ enum { name_offset = 259 };
+ size_t target_offset = name_offset + t->unpack_output.length;
+ size_t repacked_size = target_offset + 2;
+ repacked = xrealloc (repacked, repacked_size);
+ memset (repacked, '@', repacked_size);
+ memcpy (repacked + name_offset,
+ t->unpack_output.data, t->unpack_output.length);
+ enum { ptr_count = 5 };
+ const unsigned char *dnptrs[ptr_count]
+ = { repacked, repacked + name_offset, };
+ ret = ns_name_compress
+ (text, repacked + target_offset, NS_MAXCDNAME,
+ dnptrs, dnptrs + ptr_count);
+ if (ret != 2)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong result from ns_name_compress"
+ " (2)\n"
+ " expected: 2\n"
+ " actual: %d\n",
+ t->path, t->lineno, ret);
+ return;
+ }
+ if (memcmp (repacked + target_offset, "\xc1\x03", 2) != 0)
+ {
+ support_record_failure ();
+ printf ("%s:%zu: error: wrong data from ns_name_compress"
+ " (2)\n"
+ " expected: C103\n",
+ t->path, t->lineno);
+ print_hex ("actual: ",
+ (struct buffer) { repacked + target_offset, ret });
+ return;
+ }
+ TEST_VERIFY (dnptrs[0] == repacked);
+ TEST_VERIFY (dnptrs[1] == repacked + name_offset);
+ TEST_VERIFY (dnptrs[2] == NULL);
+ }
+
+ free (repacked);
+ }
+ free (text);
+ }
+ free (unpacked);
+}
+
+/* Open the file at PATH, parse the test cases contained in it, and
+ run them. */
+static void
+run_test_file (const char *path)
+{
+ FILE *fp = xfopen (path, "re");
+ char *line = NULL;
+ size_t line_allocated = 0;
+ size_t lineno = 0;
+
+ while (true)
+ {
+ ssize_t ret = getline (&line, &line_allocated, fp);
+ if (ret < 0)
+ {
+ if (ferror (fp))
+ {
+ printf ("%s: error reading file: %m\n", path);
+ exit (1);
+ }
+ TEST_VERIFY (feof (fp));
+ break;
+ }
+
+ ++lineno;
+ char *p = line;
+ while (isspace (*p))
+ ++p;
+ if (*p == '\0' || *p == '#')
+ continue;
+
+ struct test_case test_case;
+ if (!parse_test_case (path, lineno, line, &test_case))
+ {
+ support_record_failure ();
+ continue;
+ }
+ run_test_case (&test_case);
+ free_test_case (&test_case);
+ }
+ free (line);
+ xfclose (fp);
+}
+
+static int
+do_test (void)
+{
+ run_test_file ("tst-ns_name.data");
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-ns_name.data b/resolv/tst-ns_name.data
new file mode 100644
index 0000000000..890a89a976
--- /dev/null
+++ b/resolv/tst-ns_name.data
@@ -0,0 +1,548 @@
+# Test input for ns_name_unpack and ns_name_ntop.
+# Copyright (C) 2017-2018 Free Software Foundation, Inc.
+# This file is part of the GNU C Library.
+#
+# The GNU C Library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# The GNU C Library is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with the GNU C Library; if not, see
+# <http://www.gnu.org/licenses/>.
+
+# This file contains test input and expected output for the
+# ns_name_unpack and ns_name_ntop functions. Empty lines and comments
+# (lines starting with #) are ignored. Test data lines have the
+# following format:
+#
+# INPUT INPUT-OFFSET UNPACK-RESULT UNPACK-OUTPUT NTOP-RESULT NTOP-OUTPUT
+#
+# INPUT, UNPACK-OUTPUT are base64-encoded binary blobs. INPUT-OFFSET,
+# UNPACK-RESULT, NTOP-RESULT are signed integers. NTOP-OUTPUT is an
+# ASCII string (without spaces). If UNPACK-RESULT or NTOP-RESULT are
+# -1, the fields after that are missing (-1 is an error code, so the
+# output buffer is undefined).
+
+# First some manually-crafted test cases.
+
+# bytes-1
+AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgEvATABMQEyATMBNAE1ATYBNwE4ATkBOgE7ATwBPQE+AT8BQAFBAUIBQwFEAUUBRgFHAUgBSQFKAUsBTAFNAU4BTwFQAVEBUgFTAVQBVQFWAVcBWAFZAVoBWwFcAV0BXgFfAWABYQFiAWMBZAFlAWYBZwFoAWkBagFrAWwBbQFuAW8BcAFxAXIBcwF0AXUBdgF3AXgBeQF6AXsBfAF9AX4BfwGAAYEBggGDAYQBhQGGAYcBiAGJAYoBiwGMAY0BjgGPAZABkQGSAZMBlAGVAZYBlwGYAZkBmgGbAZwBnQGeAZ8BoAGhAaIBowGkAaUBpgGnAagBqQGqAasBrAGtAa4BrwGwAbEBsgGzAbQBtQG2AbcBuAG5AboBuwG8Ab0BvgG/AcABwQHCAcMBxAHFAcYBxwHIAckBygHLAcwBzQHOAc8B0AHRAdIB0wHUAdUB1gHXAdgB2QHaAdsB3AHdAd4B3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QH+Af8A 0 -1
+# bytes-1a
+AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgEvATABMQEyATMBNAE1ATYBNwE4ATkBOgE7ATwBPQE+AT8A 0 129 AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgEvATABMQEyATMBNAE1ATYBNwE4ATkBOgE7ATwBPQE+AT8A 233 \000.\001.\002.\003.\004.\005.\006.\007.\008.\009.\010.\011.\012.\013.\014.\015.\016.\017.\018.\019.\020.\021.\022.\023.\024.\025.\026.\027.\028.\029.\030.\031.\032.!.\".#.\$.%.&.'.\(.\).*.+.,.-.\../.0.1.2.3.4.5.6.7.8.9.:.\;.<.=.>.?
+# bytes-1b
+AUABQQFCAUMBRAFFAUYBRwFIAUkBSgFLAUwBTQFOAU8BUAFRAVIBUwFUAVUBVgFXAVgBWQFaAVsBXAFdAV4BXwFgAWEBYgFjAWQBZQFmAWcBaAFpAWoBawFsAW0BbgFvAXABcQFyAXMBdAF1AXYBdwF4AXkBegF7AXwBfQF+AX8A 0 129 AUABQQFCAUMBRAFFAUYBRwFIAUkBSgFLAUwBTQFOAU8BUAFRAVIBUwFUAVUBVgFXAVgBWQFaAVsBXAFdAV4BXwFgAWEBYgFjAWQBZQFmAWcBaAFpAWoBawFsAW0BbgFvAXABcQFyAXMBdAF1AXYBdwF4AXkBegF7AXwBfQF+AX8A 133 \@.A.B.C.D.E.F.G.H.I.J.K.L.M.N.O.P.Q.R.S.T.U.V.W.X.Y.Z.[.\\.].^._.`.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.{.|.}.~.\127
+# bytes-1c
+AYABgQGCAYMBhAGFAYYBhwGIAYkBigGLAYwBjQGOAY8BkAGRAZIBkwGUAZUBlgGXAZgBmQGaAZsBnAGdAZ4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8A 0 129 AYABgQGCAYMBhAGFAYYBhwGIAYkBigGLAYwBjQGOAY8BkAGRAZIBkwGUAZUBlgGXAZgBmQGaAZsBnAGdAZ4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8A 320 \128.\129.\130.\131.\132.\133.\134.\135.\136.\137.\138.\139.\140.\141.\142.\143.\144.\145.\146.\147.\148.\149.\150.\151.\152.\153.\154.\155.\156.\157.\158.\159.\160.\161.\162.\163.\164.\165.\166.\167.\168.\169.\170.\171.\172.\173.\174.\175.\176.\177.\178.\179.\180.\181.\182.\183.\184.\185.\186.\187.\188.\189.\190.\191
+# bytes-1d
+AcABwQHCAcMBxAHFAcYBxwHIAckBygHLAcwBzQHOAc8B0AHRAdIB0wHUAdUB1gHXAdgB2QHaAdsB3AHdAd4B3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QH+Af8A 0 129 AcABwQHCAcMBxAHFAcYBxwHIAckBygHLAcwBzQHOAc8B0AHRAdIB0wHUAdUB1gHXAdgB2QHaAdsB3AHdAd4B3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QH+Af8A 320 \192.\193.\194.\195.\196.\197.\198.\199.\200.\201.\202.\203.\204.\205.\206.\207.\208.\209.\210.\211.\212.\213.\214.\215.\216.\217.\218.\219.\220.\221.\222.\223.\224.\225.\226.\227.\228.\229.\230.\231.\232.\233.\234.\235.\236.\237.\238.\239.\240.\241.\242.\243.\244.\245.\246.\247.\248.\249.\250.\251.\252.\253.\254.\255
+# bytes-4
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaWwRcXV5fBGBhYmMEZGVmZwRoaWprBGxtbm8EcHFycwR0dXZ3BHh5ensEfH1+fwSAgYKDBISFhocEiImKiwSMjY6PBJCRkpMElJWWlwSYmZqbBJydnp8EoKGiowSkpaanBKipqqsErK2urwSwsbKzBLS1trcEuLm6uwS8vb6/BMDBwsMExMXGxwTIycrLBMzNzs8E0NHS0wTU1dbXBNjZ2tsE3N3e3wTg4eLjBOTl5ucE6Onq6wTs7e7vBPDx8vME9PX29wT4+fr7BPz9/v8A 0 -1
+# bytes-4a
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 185 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+# bytes-4b
+BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8A 0 81 BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8A 85 \@ABC.DEFG.HIJK.LMNO.PQRS.TUVW.XYZ[.\\]^_.`abc.defg.hijk.lmno.pqrs.tuvw.xyz{.|}~\127
+# bytes-4c
+BICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUlZaXBJiZmpsEnJ2enwSgoaKjBKSlpqcEqKmqqwSsra6vBLCxsrMEtLW2twS4ubq7BLy9vr8A 0 81 BICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUlZaXBJiZmpsEnJ2enwSgoaKjBKSlpqcEqKmqqwSsra6vBLCxsrMEtLW2twS4ubq7BLy9vr8A 272 \128\129\130\131.\132\133\134\135.\136\137\138\139.\140\141\142\143.\144\145\146\147.\148\149\150\151.\152\153\154\155.\156\157\158\159.\160\161\162\163.\164\165\166\167.\168\169\170\171.\172\173\174\175.\176\177\178\179.\180\181\182\183.\184\185\186\187.\188\189\190\191
+# bytes-4d
+BMDBwsMExMXGxwTIycrLBMzNzs8E0NHS0wTU1dbXBNjZ2tsE3N3e3wTg4eLjBOTl5ucE6Onq6wTs7e7vBPDx8vME9PX29wT4+fr7BPz9/v8A 0 81 BMDBwsMExMXGxwTIycrLBMzNzs8E0NHS0wTU1dbXBNjZ2tsE3N3e3wTg4eLjBOTl5ucE6Onq6wTs7e7vBPDx8vME9PX29wT4+fr7BPz9/v8A 272 \192\193\194\195.\196\197\198\199.\200\201\202\203.\204\205\206\207.\208\209\210\211.\212\213\214\215.\216\217\218\219.\220\221\222\223.\224\225\226\227.\228\229\230\231.\232\233\234\235.\236\237\238\239.\240\241\242\243.\244\245\246\247.\248\249\250\251.\252\253\254\255
+# bytes-63
+PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0/fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8P72+v8DBwsPExcbHyMnKy8zNzs/Q0dLT1NXW19jZ2tvc3d7f4OHi4+Tl5ufo6err7O3u7/Dx8vP09fb3+Pn6+wT8/f7/AA== 0 -1
+# bytes-63a
+PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9PgE/AA== 0 67 PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9PgE/AA== 171 \000\001\002\003\004\005\006\007\008\009\010\011\012\013\014\015\016\017\018\019\020\021\022\023\024\025\026\027\028\029\030\031\032!\"#\$%&'\(\)*+,-\./0123456789:\;<=>.?
+# bytes-63b
+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fgF/AA== 0 67 P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fgF/AA== 71 \@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~.\127
+# bytes-63c
+P4CBgoOEhYaHiImKi4yNjo+QkZKTlJWWl5iZmpucnZ6foKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vgG/AA== 0 67 P4CBgoOEhYaHiImKi4yNjo+QkZKTlJWWl5iZmpucnZ6foKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vgG/AA== 258 \128\129\130\131\132\133\134\135\136\137\138\139\140\141\142\143\144\145\146\147\148\149\150\151\152\153\154\155\156\157\158\159\160\161\162\163\164\165\166\167\168\169\170\171\172\173\174\175\176\177\178\179\180\181\182\183\184\185\186\187\188\189\190.\191
+# bytes-63d
+P8DBwsPExcbHyMnKy8zNzs/Q0dLT1NXW19jZ2tvc3d7f4OHi4+Tl5ufo6err7O3u7/Dx8vP09fb3+Pn6+/z9/gH/AA== 0 67 P8DBwsPExcbHyMnKy8zNzs/Q0dLT1NXW19jZ2tvc3d7f4OHi4+Tl5ufo6err7O3u7/Dx8vP09fb3+Pn6+/z9/gH/AA== 258 \192\193\194\195\196\197\198\199\200\201\202\203\204\205\206\207\208\209\210\211\212\213\214\215\216\217\218\219\220\221\222\223\224\225\226\227\228\229\230\231\232\233\234\235\236\237\238\239\240\241\242\243\244\245\246\247\248\249\250\251\252\253\254.\255
+# compression-loop
+wAA= 0 -1
+# compression-loop-2
+wALAAA== 0 -1
+# empty
+- 0 -1
+# root
+AA== 0 1 AA== 2 .
+# truncated-compression
+wA== 0 -1
+# www
+A3d3dwA= 0 5 A3d3dwA= 4 www
+# www-truncated
+A3d3dw== 0 -1
+# www-truncated-2
+A3d3 0 -1
+# www.example.com
+5jrGq8kVxMt3ZS3RA3d3dwdleGFtcGxlA2NvbQA= 12 17 A3d3dwdleGFtcGxlA2NvbQA= 16 www.example.com
+# www.example.com-answer
+5jrGq8kVxMt3ZS3RA3d3dwdleGFtcGxlA2NvbQAAAQABwAw= 33 2 A3d3dwdleGFtcGxlA2NvbQA= 16 www.example.com
+# www.example.com-answer-truncated
+5jrGq8kVxMt3ZS3RA3d3dwdleGFtcGxlA2NvbQAAAQABwA== 33 -1
+# www.example.com-truncated
+5jrGq8kVxMt3ZS3RA3d3dwdleGFtcGw= 12 -1
+# www1.example.com-answer
+5jrGq8kVxMt3ZS3RA3d3dwdleGFtcGxlA2NvbQAAAQABBHd3dzHAEA== 33 7 BHd3dzEHZXhhbXBsZQNjb20A 17 www1.example.com
+
+# Then test cases derived from the above by American Fuzzy Lop (AFL).
+BAABAgMEBAUGBwQICQoLAAwN 0 16 BAABAgMEBAUGBwQICQoLAA== 51 \000\001\002\003.\004\005\006\007.\008\009\010\011
+PwABAgMEBQYHCAmztLUAABYXGBmInAoLDA0ODyQRNDU2NwE5Ojs8PT4/PwkKCwwNDg8kSwoLDA0ODyQpKSkpKSkpPT4/VTAxMjM0NDY3AYeLjCspCSkpKSkpKSkpKSkpZCcoKSorLC0uPD0+Pz9AQUJDREVGLzAxMjM0NDY3AYoEAKytrq8= 0 -1
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2ADwBAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2ADwBAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAA 618 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000<\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\000\001X+66666vvvvvv\@\@\@\000\000
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AA8BAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AA8BAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAA 621 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\015\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\000\001X+66666vvvvvv\@\@\@\000\000
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjbJNjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAAAQAb 0 -1
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NskAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NskAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAA 624 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.6\201\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\000\001X+66666vvvvvv\@\@\@\000\000
+BAABAgMEBAUGBwQICQoLBBINDg8QAAAAEwQUFRYXBBgZGhsEHB0eNjY2AAA2NjY2Njw2ATYYNkUAAAIQ//9/TExMTExMTExMTExMTExMTExMTExMTENMTBMTExNqEykTlhMTEyYLAAEUFAAABjY2NjYAAAE2NhwAAAABAAABBDb/fwAAAzY2NgX//wU2NgD7SDYkNjk5OTk5OTk5OTk5OTk5OTk5OTk5PTY0pDY2NjY2NiQAAAE2Nn82cXZ2dnZ2dnZ20Coq0DPQ0P/QM9DQ//9//9AAAAHSu9DRkNAABgAA/xQUAAAGfzYkNjY0Nks2AAQeVTb/AAABNn////8= 0 -1
+BAABAgMEBAUGBwQICQoLBBINDg8EAAAQAAQUFRYXBBgZGhsEHB0eNjY2AAA2NjY2Njw2ATYYNkUAAAIQ//9/TExMTExMTExMTExMTExMTExMTExMTENMTBMTExNqEykTlhMTEyYLAAEUFAAABjY2NjYAAAE2NhwAAAABAAABBDb/fwAAAzY2NgX//wU2NgD7SDYkNjk5OTk5OTk5OTk5OTk5OTk5OTk5PTY0pDY2NjY2NiQAAAE2Nn82cXZ2dnZ2dnZ20Coq0DPQ0P/QM9DQ//9//9AAAAHSu9DRkNAABgAA/xQUAAAGfzYkNjY0Nks2AAQeVTb/AAABNn////8= 0 -1
+AgIhIiMEJCUkAScBKAEpASoBKwEsAS0BLgExATgBOQE6IDsBASoBKwEsAS0BLgE3ATgBOQE6IDsBPAE9AT4BPw0BDgEPARABEQESARMBFAEBDgEPARABEQESARMBFCEhISEhISEhISEhISEhIX4hISEhISEhISEhARcFGAEZARoBGwEcAR0BASYBJwEoASkBKjwBPQE+AT8NAQ4BDwEQAREBEgETARQBFwUYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBAAACQCsBLAEtAS4BJwEoAUgBKgErASwBLQEuATsBPAE9AT4BPwA= 0 242 AgIhIiMEJCUkAScBKAEpASoBKwEsAS0BLgExATgBOQE6IDsBASoBKwEsAS0BLgE3ATgBOQE6IDsBPAE9AT4BPw0BDgEPARABEQESARMBFAEBDgEPARABEQESARMBFCEhISEhISEhISEhISEhIX4hISEhISEhISEhARcFGAEZARoBGwEcAR0BASYBJwEoASkBKjwBPQE+AT8NAQ4BDwEQAREBEgETARQBFwUYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBAAACQCsBLAEtAS4BJwEoAUgBKgErASwBLQEuATsBPAE9AT4BPwA= 607 \002!.#\004\$%\$\001'\001\(\001\)\001*\001+\001,\001-\001\.\0011\0018\0019\001:\032\;\001\001*.+.,.-.\..7.8.9.:.\;\001<\001=\001>\001?\013\001\014\001\015\001\016\001\017\001\018\001\019\001\020\001\001\014\001\015\001\016\001.\001\018\001\019\001\020!!!!!!!!!!!.!!!~!!!!!!!!!!\001\023\005\024\001\025\001\026\001\027\001\028\001\029\001\001&\001'.\(.\).*.\001=\001>\001?\013\001\014\001\015\001\016\001\017\001\018\001\019\001\020\001\023\005\024\001\025\001\026\001\027\001\028\001\029\001\030\001\031\001\032\001!\001\"\001#\001\$\001%\001&\001'\001\(\001\000\000.\@+.,.-.\..'.\(.H.*.+.,.-.\..\;.<.=.>.?
+wMAAAcDAwMDAQAA2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2iTY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAUYUwB82Nn7s7OzsEBQUDDY2NgAAATY2NjZYNjYyNk02NlEAEQEANjYABf//BUU2OTY2NiU9PT09NgAAAfI//3Y2AAABNjY0NgAAAYA2PRAA+/v7+/v7+/v///8= 16 -1
+AwAAJ8AAISEhISEhISEhISEhISEhfiEhISEhISEhISG7u5CjAA== 0 -1
+AhIAAlBINQAAATU1FTo/SEhIAwMDAwMFRTY5NgA2JT09PQEfNjY8NjYkFTY0NjYyNjY2NjYADDY2QksAAAEBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgD//gABNjY2PDY2JBUAfg== 68 -1
+AQQBAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAFdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4ASEhISEhISEhISEhISEhIX4hISEhISEhISEhuQG6AbsBvAG9Ab4BvwHAAdwBwgHDAcQBxQHGAQ0BDgEPARABEQESARMBFAEVARYBFwEYARkBGiEhuQG6AbsBvAG9Ab4BvwHAAdwBwgHDAcQBxQHGAQ3xDQEPARABEQESARMBFAEVARYBFwEYARkBGgEbARwBXQEeAZ8BoAGhAaIBowGkAaUBpgGnAagBqQGqAasBrAGtAa4BrwGwAbEBsgGzAbQBtQG2AbcBuAEhISEBqgGrAawBrQGuAa8BsAGxASEhISEhISEhISEhISEhISEhISEhIX4hISEhISEhISEhEhISEhISEhISAAABEhISEhISEhICAgICAgICAgICAgICIssBzAHNAc4BzwHQAdEB0gHTAdQB1QHWASPHAcgByf9/AAABzAHNAc4BzwHQAdEB0gHTg9QB1QHWARISEhISEhISEhISEhISEhIREhISEhISEhISEgAAAH8SAAABEhISEhISEhICAgICAgICAgICAgICIssBzAHNAc4BzwHQAdEB0gHTAdQB1QHWASMELyTrJwQIKSsrACw= 0 -1
+AQA= 0 -1
+AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHcAd0V3gHfAeAB4QHiAc8B0AHRAdIB0wHUAdUB1gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QD+ 0 -1
+AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHcAd0B3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9Af4B/wA= 0 -1
+BOgDAwgINjY2NjY2NjY2NjY2NjY2NjY2NgAAASY2NjY2NjZAAAAANjY2NjY2NgAAAAE2NjY2NjY2NjY2Ng82NjY2NjY2NjYhNis2RhQ2Nv9///82NjY2NjY2NjY2Nlc2QDY2NjYAAAE2NiM2NjY2NoE2NjY2Np5CPAAhNhM2NjY2NjY2Np42PAAYNhM2NjY2NjY2NgA2NjY2NjY2NjY2NvA2tzY2NjY2NjY2NjY2NjY2NjY2NjY2Njk2NjYxNjY2NjY2Nv9/NjY2NhY2NjY2NgAAATY2NjY2NjaeNjwAGDY2NjY2NjY2FDYAgAAANgAAATY2NjY2NjY2NjYBNgAAATY2 0 255 BOgDAwgINjY2NjY2NjY2NjY2NjY2NjY2NgAAASY2NjY2NjZAAAAANjY2NjY2NgAAAAE2NjY2NjY2NjY2Ng82NjY2NjY2NjYhNis2RhQ2Nv9///82NjY2NjY2NjY2Nlc2QDY2NjYAAAE2NiM2NjY2NoE2NjY2Np5CPAAhNhM2NjY2NjY2Np42PAAYNhM2NjY2NjY2NgA2NjY2NjY2NjY2NvA2tzY2NjY2NjY2NjY2NjY2NjY2NjY2Njk2NjYxNjY2NjY2Nv9/NjY2NhY2NjY2NgAAATY2NjY2NjaeNjwAGDY2NjY2NjY2FDYAgAAANgAAATY2NjY2NjY2NjYBNgAA 412 \232\003\003\008.66666666.6666666666\000\000\001&666666\@\000\000\0006666666\000\000\000\00166666666666\0156666666.6!6+6F\02066\255\127\255\25566666666666W6\@6666\000\000\00166#66666\12966666\158B<\000!6.66666666\1586<\000\0246\0196666.666\00066666666666\2406\183666666666666666666666966616666666\255\1276.66\02266666\000\000\0016666666\1586<\000\02466666666\0206\000\128\000\0006\000\000\0016666666666\0016\000
+AhIAAlBIAABISEhIUz4AAAE1FTU1LTU1LTW2NTU1NQAAATU1FTo/SEhISEhISEhISEhISEhISEhISEhISAABAABISCZIUw== 68 -1
+AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgE3ATgBOQE6ATsBPAE9AT4BPwA= 0 113 AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgE3ATgBOQE6ATsBPAE9AT4BPwA= 217 \000.\001.\002.\003.\004.\005.\006.\007.\008.\009.\010.\011.\012.\013.\014.\015.\016.\017.\018.\019.\020.\021.\022.\023.\024.\025.\026.\027.\028.\029.\030.\031.\032.!.\".#.\$.%.&.'.\(.\).*.+.,.-.\..7.8.9.:.\;.<.=.>.?
+BOgAAAEDAwgINjY2NgAAAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2NDZYBAX//wU2NjY0NgAAAQAAAYA2NhY2Njbn0NDQ0NDQ0NA2NjY2NjY2NjY2NgAAAAEENjY2NjY2NjY2NjY2NgAAAAEAG0tsS0tLS0tLSwE2vh9GFDY2NjYAADY2JDY2NDY2NjY2NjY2NjY2NjY2NjY2JDY2f3Z2dnZ2dnZ2dnZ2dnZ2dkE2ATYeBAX//wU2NjY0NgAACQAAAYA2NhY2NjbQ0NDQ0NDQ0NAz0NDQ0NDQ0NDQ0NCQ0AAUFAAAARQUNjY2NjY2Nlg2NjY2TSE2UQARAQAAATY2 0 255 BOgAAAEDAwgINjY2NgAAAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2NDZYBAX//wU2NjY0NgAAAQAAAYA2NhY2Njbn0NDQ0NDQ0NA2NjY2NjY2NjY2NgAAAAEENjY2NjY2NjY2NjY2NgAAAAEAG0tsS0tLS0tLSwE2vh9GFDY2NjYAADY2JDY2NDY2NjY2NjY2NjY2NjY2NjY2JDY2f3Z2dnZ2dnZ2dnZ2dnZ2dkE2ATYeBAX//wU2NjY0NgAACQAAAYA2NhY2NjbQ0NDQ0NDQ0NAz0NDQ0NDQ0NDQ0NCQ0AAUFAAAARQUNjY2NjY2Nlg2NjY2TSE2UQARAQAA 572 \232\000\000\001.\003\008\008.666\000\000\000\192\0316\128\00066\$\021666\0216\000\004666666666646X\004\005\255\255\00566646\000\000\001\000\000\001\12866.666\231\208\208\208\208\208\208\208\2086666666666.\000\000\000\001\0046666666666666\000\000\000\001\000\027KlKKKKKKK\0016\190\031F\0206666\000\00066\$664666.6666666666666\$66\127vvvvvvvvvvvvvvvA6\0016\030\004\005\255\255\00566646\000\000\009\000\000\001\128.6\022666\208\208\208\208\208\208\208\208\2083\208\208\208\208\208\208\208\208\208\208\208\144\208\000\020\020\000\000\001\020\0206666666X6666M!6Q\000\017.\000
+AQABAwEJAQoYARkBGmwbARwHGgEeAc0BAAAB0AAAA+gB0w== 0 -1
+AUABQwFEAUUBRgFPAVABUQFSAVMBVAFVAVYBVwFYAVkBWgFbAVwBXwFgAWEBYgFjAWQBZQFmAWcBaAFpAWoBawFsAW0BbgFvAXABcQFyAXMBdAF1AXYBdwF4AXkBegF7AXwBfQF+AX8A 0 105 AUABQwFEAUUBRgFPAVABUQFSAVMBVAFVAVYBVwFYAVkBWgFbAVwBXwFgAWEBYgFjAWQBZQFmAWcBaAFpAWoBawFsAW0BbgFvAXABcQFyAXMBdAF1AXYBdwF4AXkBegF7AXwBfQF+AX8A 109 \@.C.D.E.F.O.P.Q.R.S.T.U.V.W.X.Y.Z.[.\\._.`.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z.{.|.}.~.\127
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAA 618 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\1276X+66666vvvvvvvv\255\011\000
+AYABnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+ 0 -1
+BOgAAAEDAwgINjY2NgAAAMAfNjZkAAAAAAEAFPY2HjY2NDYMAAEABAEAAAE2NgAAATb7IPvz+/sAAAFCRDYkDzI0NjY2NjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTY2FTYABDk2NgAAATY2NjY2Nhw0NlgAIDY2/zY+NjY2NjYAADYAAPs2DAEAAAH0wB82NjY2 0 146 BOgAAAEDAwgINjY2NgAAAMAfNjZkAAAAAAEAFPY2HjY2NDYMAAEABAEAAAE2NgAAATb7IPvz+/sAAAFCRDYkDzI0NjY2NjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTY2FTYABDk2NgAAATY2NjY2Nhw0NlgAIDY2/zY+NjY2NjYAADYAAPs2DAEAAAH0NjY0NgwAAQAEAQAAATY2AAABNvsg+/P7+wAAAUJENiQPMjQ2NjY2NjY2NgAQNjY2WDY2NjY2NjY2AAABAAE2NjZFNjYVNgAEOTY2AAABNjY2NjY2HDQ2WAAgNjb/Nj42NjY2NgAANgAA+zYMAQAA 607 \232\000\000\001.\003\008\008.666\000\000\000\192\03166d\000\000\000\000\001\000\020\2466\0306646\012\000\001\000\004\001\000\000\00166\000\000\0016\251\032\251\243\251\251\000\000\001BD6\$\015.466666666\000\016666X66666666\000\000\001\000\001666E66\0216\000\004966\000\000\001666666.46X\000\03266\2556>66666\000\0006\000\000\2516\012\001\000\000\001\244.646\012\000\001\000\004\001\000\000\00166\000\000\0016\251\032\251\243\251\251\000\000\001BD6\$\0152466666666\000\016666X666666.6\000\000\001\000\001666E66\0216\000\004966\000\000\001666666\02846X\000\03266\2556>66666\000\0006\000\000\2516\012\001\000
+AcAB3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QH+ 0 -1
+BOgAAAENAwgINjY2NgAAAMAfNjY2NjY2NgAQNjY2WDY2NjY2NjY2APP2FgE2NjZFNjYVNgAENjY2NjY2NjY2NjQ2WDY2NjY2NiUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlNjY2NjY2NjYAAAABBB82NgAAATY2NiQVNjQ2NjY2NjY2NjY2NjY2NgAAAAEENgAAATY2NjY2NgAAATY2NjY2NjY2AAAAAQQ2NjY2NjY2NjY2NjY2AAAAAQAbS2xLS0tLS0tLATa+HQABNjY2AFA2NiQgNjQ2NjY2NlE2NjY2NjY2NjY2Nho2Nn92dnZ2dpZ2dnZ2dkE2AQAAAQAAARY2 0 255 BOgAAAENAwgINjY2NgAAAMAfNjY2NjY2NgAQNjY2WDY2NjY2NjY2APP2FgE2NjZFNjYVNgAENjY2NjY2NjY2NjQ2WDY2NjY2NiUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlJSUlNjY2NjY2NjYAAAABBB82NgAAATY2NiQVNjQ2NjY2NjY2NjY2NjY2NgAAAAEENgAAATY2NjY2NgAAATY2NjY2NjY2AAAAAQQ2NjY2NjY2NjY2NjY2AAAAAQAbS2xLS0tLS0tLATa+HQABNjY2AFA2NiQgNjQ2NjY2NlE2NjY2NjY2NjY2Nho2Nn92dnZ2dpZ2dnZ2dkE2AQAAAQAA 460 \232\000\000\001.\003\008\0086666\000\000\000\192\0316.66666\000\016666X66666666\000\243\246\022\001666E66\0216\000\004666666666646X666666%.%%%%%%%%%%%%%%%%%%%%%%%%66666666\000\000\000\001\004.66\000\000\001666\$\0216466666666666666\000\000\000\001\004.\000\000\001666666\000\000\00166666666\000\000\000\001\0046666666666666\000\000\000\001\000\027KlKKKKKKK\001.\190\029\000\001666\000P66\$\0326466666Q66666666666\02666\127vvvvv\150vvvvvA6\001\000\000\001\000
+BAABAgMEERITBBQVFhceHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaWwRcXV5fBGBhYmMEZGVmZwRoaWprBGxtbm8EcHFycwR0dXZ3BHh5ensEfH1+fwSAgYKDBISFhocEiImKiwSMjY6PBJCRkpMElJWWlwSYmZqbBJydnp8EoKGiowQ= 0 -1
+BOgAAAEDAwgIFjY2NgAAAMAfNjY2NjYkFTY0NjY2NjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTY2FTYABDY2NjY2NjY2NjY0Nlg2NjY2NjY2NgAAATY2NgAAAADAHzY2NjY2JAkJCf9/CQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkVNjQ2NjY2NjY2NjY2NjY2NgAAAAEENjY2NjY2NjY2NjY2NgAAAAEAG0tsS0tLS0tLSwE2vh9GFDY2NjYAADY2JDY2NDY2NjY2NjY2NjY2NjY2NiQ2Nn92dnZ2dnZ2dnZ2dnZ2dnZBNgE2HgQAQP82NjY2NDYAAAEAAAGA 0 255 BOgAAAEDAwgIFjY2NgAAAMAfNjY2NjYkFTY0NjY2NjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTY2FTYABDY2NjY2NjY2NjY0Nlg2NjY2NjY2NgAAATY2NgAAAADAHzY2NjY2JAkJCf9/CQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkJCQkVNjQ2NjY2NjY2NjY2NjY2NgAAAAEENjY2NjY2NjY2NjY2NgAAAAEAG0tsS0tLS0tLSwE2vh9GFDY2NjYAADY2JDY2NDY2NjY2NjY2NjY2NjY2NiQ2Nn92dnZ2dnZ2dnZ2dnZ2dnZBNgE2HgQAQP82NjY2NDYAAAEA 526 \232\000\000\001.\003\008\008.666\000\000\000\192\03166666\$\0216466666.66\000\016666X66666666\000\000\001\000\001666E66\0216\000\004666666666646X66666666\000\000.6.6\000\000\000\000\192\03166666\$\009\009\009\255\127\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\009\021646666666.666666\000\000\000\001\0046666666666666\000\000\000\001\000\027KlKKKKKKK\0016\190\031F\0206666\000\00066\$.64666666666666666\$66\127vvvvvvvvvvvvvvvA6\0016\030\004\000\@\255666646\000\000\001
+AQABBwEIAQkBCgELAQwBZAEOAegB6QHqAesB7AHtAe4B7wHwAfEB8gHzAfQB9QH2AfcB+AH5AfoB+wH8Af0B/gH/AA== 0 67 AQABBwEIAQkBCgELAQwBZAEOAegB6QHqAesB7AHtAe4B7wHwAfEB8gHzAfQB9QH2AfcB+AH5AfoB+wH8Af0B/gH/AA== 162 \000.\007.\008.\009.\010.\011.\012.d.\014.\232.\233.\234.\235.\236.\237.\238.\239.\240.\241.\242.\243.\244.\245.\246.\247.\248.\249.\250.\251.\252.\253.\254.\255
+AQAB3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QFAAP8A 0 67 AQAB3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QFAAA== 163 \000.\223.\224.\225.\226.\227.\228.\229.\230.\231.\232.\233.\234.\235.\236.\237.\238.\239.\240.\241.\242.\243.\244.\245.\246.\247.\248.\249.\250.\251.\252.\253.\@
+AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGAEVFhcEGDoaGwQLHR4fDTUpIhkEJDoaGwQUIx4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CAjsA 0 255 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGAEVFhcEGDoaGwQLHR4fDTUpIhkEJDoaGwQUIx4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CAjsA 781 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\004\008\002\002\002\002.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\001\021\022\023\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$.\026\027\004\020#\030\031&5\)\"\025\004\$\$\000\000\002\000\@\002\016\"\002\016\@\002\016\"\002\016\"\002\016\@\002\016\"\002\016\031\004\032\)\"#\004\$\$\000\000\002\000\@\002\016\"\002.\@\002\016\"\002\016\"\006\004\008\002\@\002\002\002\254.\002\;
+YcAAAcDAwA3AAQAQFBQMNjY2AAABNjY2Hlg2NjY2PzY2UQARAQA2NktLS0sBFrsfRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PAFLATa+H0YUwB82Nn7s7OwAAAEB7OHsFAD/ADY0NjYyNjY2NjY9PT0BNjY2AAAAAQA2NDY2MjInNhgYGBgYGBgYGBgYGBgYGBgYGBgYGBg2NgAQNjYAEDY2AAABQAAAAQAAAUsBNr4fRgEAHzY2fuzs7AAAAQHs4ewUNrY2NgAdNjQ2NjZBNj42NjY2NjY2TtDQ0JDQABQUFBS2NjU2Njo2WDY2NjYAAAHQ0DPQ0NDQ0NDQ0ND///8BABAUFAw2NjYAAAE2Ng== 16 255 NjYAAAE2NjYeWDY2NjY/NjZRABEBADY2S0tLSwEWux9GFDY2NjYAADY2WDZ2PDY2NjY2AAABAAE2NjY8AUsBNr4fRhTAHzY2fuzs7AAAAQHs4ewUAP8ANjQ2NjI2NjY2Nj09PQE2NjYAAAABADY0NjYyMic2GBgYGBgYGBgYGBgYGBgYGBgYGBgYGDY2ABA2NgAQNjYAAAFAAAABAAABSwE2vh9GAQAfNjZ+7OzsAAABAezh7BQ2tjY2AB02NDY2NkE2PjY2NjY2NjZO0NDQkNAAFBQUFLY2NTY2OjZYNjY2NgAAAdDQM9DQ0NDQ0NDQ0P///wEAEBQUDDY2NgAA 660 6\000\000\001666\030X6666?66Q\000\017\001\00066KKKK\001\022\187\031F\0206666\000\00066X6v<66666\000\000\001\000.6.6<\001K\0016\190\031F\020\192\03166~\236\236\236\000\000\001\001\236\225\236\020\000\255\0006466266666===\001666\000\000\000\001\000646.22'6\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\024\02466\000\01666\000\01666\000\000\001\@\000\000\001\000\000\001K\0016\190\031F\001\000.66~\236\236\236\000\000\001\001\236\225\236\0206\18266\000\02964666A6>666.666N\208\208\208\144\208\000\020\020\020\020\1826566:6X6666\000\000\001\208\2083\208\208\208\208\208\208\208\208\208\255\255\255\001\000\016\020\020\012666\000
+PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0/fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8P70= 0 -1
+AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIPAgKAAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISJBISAEASEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhICAgICAgICAgICAgICIiMELyTrJwQIKSorACw= 2 239 AgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICDwICgAICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEiQSEgBAEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISAgICAgICAgICAgICAiIjBC8k6ycECCkqKwA= 786 \002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002\128\002\002\002\002\002\002\002\002\002\002\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018.\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\$\018.\000\@\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018.\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018.\018\018\018\018\018\018\018\018\018\018\018\018\018\018\018\002\002\002.\002\002.\002\002.\002\002.\"#./\$\235'.\008\)*+
+PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9PgE/ 0 -1
+AQAh5ifGs8kVxMsAAAHRAAABdwdle2FtcGxlA2NvbQAAGgABBHd3dzHAEA== 0 -1
+P0BBQkNERUZHSElKS0xNTk9QUVJTVFVWV1hZWltcXV5fYGFiY2RlZmdoaWprbG1ub3BxcnN0dXZ3eHl6e3x9fgF/ 0 -1
+wMAAAcDgwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0s2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BHzY2PDY2JBU2NDY2MjY2NjY2AAw2NktLAAABARa+H0YUNjY2NgAANjZYNnY8NjY2NjYAAP4AATY2Njw2NiQVNgSzNqI2NjY2NgX//wVFNjk2PjYlPT09ATY2NgAAAAEANjQ2NjI2NjY2NgAQNjZLS0tAAAABSwE2vh9GFMAfNi5+7Ozs7AAAAezs7BQ2NjY2AAAAAAE2NjQ2NjZBNj42NjY2NjY2TtDQ0JDQABQUFBQ2NjU2NkM2WDY2NjZNNjZRABEBAA== 16 2 NjY2NgAQNjZLSzY2WDZ2PDY2NjY2AAABAAE2NjY8NjYkFTYEszaiNjY2NjYF//8FRTY5Nj42JT09PQEfNjY8NjYkFTY0NjYyNjY2NjYADDY2S0sAAAEBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAA/gABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Ln7s7OzsAAAB7OzsFDY2NjYAAAAAATY2NDY2NkE2PjY2NjY2NjZO0NDQkNAAFBQUFDY2NTY2QzZYNjY2Nk02NlEAEQEA 523 666\000\01666KK66X6v<66666\000\000\001\000\001666<66\$\0216\004\1796\16266666\005\255\255\005E696>6%.==\001\03166<66\$\0216466266666\000\01266KK\000\000\001\001\022\190\031F\0206666\000\00066X6v<66666\000\000\254\000\001666.66\$\0216\004\1796\16266666\005\255\255\005E696>6%===\001666\000\000\000\001\0006466266666\000\01666KKK\@\000\000\001K\001.\190\031F\020\192\0316\.~\236\236\236\236\000\000\001\236\236\236\0206666\000\000\000\000\001664666A6>6666666N\208\208\208\144\208\000\020\020.\02066566C6X6666M66Q\000\017\001
+P4CBgoOEhYaHiImKi4yNjo+QkZKTlJWWl5iZmpucnZ6foKGio6SlpqeoqaqrrK2ur7CxsrO0tba3uLm6u7y9vgG/ 0 -1
+P8DBwsPExcbHyMnKy8zNzs/Q0dLT1NXW19jZ2tvc3d7f4OHi4+Tl5ufo6err7O3u7/Dx8vP09fb3+Pn6+/z9/gH/ 0 -1
+A3c= 0 -1
+5jrGq8kVxMt3ZS3RA3d3dwdl 12 -1
+BAALBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9 64 -1
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0rBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0= 32 -1
+BAAEBQYHBAgJCgsEDA0ODwQQFBUWFysELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PQ== 16 -1
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 8 73 BgcECAkKCwQMDQ4PBBAREhMEFBUWFwQYGRobBBwdHh8EICEiIwQkJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/AA== 159 \007\004\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+hAA= 0 -1
+JAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2Nw== 0 -1
+FAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCsELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PQ== 0 -1
+DAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 DAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 224 \000\001\002\003\004\004\005\006\007\004\008\009.\011\004\012\013\014\015\004\016\017\018.\004\020\021\022\023\004\024\025\026\027\004\028\029\030\031\004\032!\".\004\$%&'\004\(\)*+\004,-\./\0040123\0044567\00489:\;\004<=>?
+BgABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BgABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 221 \000\001\002\003\004\004.\006\007\004\008\009.\011\004\012\013\014\015\004\016\017\018.\004\020\021\022\023\004\024\025\026\027\004\028\029\030\031\004\032!\".\004\$%&'\004\(\)*+\004,-\./\0040123\0044567\00489:\;\004<=>?
+BQABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BQABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 188 \000\001\002\003\004.\005\006\007\004.\009\010\011\004\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+BEABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BEABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 183 \@\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+BABBAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BABBAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 182 \000A\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+BAAhAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAAhAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 182 \000!\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+BAABIgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABIgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 183 \000\001\"\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+BAABAgMUBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXGwQcHR4fBCAhIiMEJCUmJwQoKSo= 0 -1
+BAABAgMMBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMMBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 209 \000\001\002\003.\004\005\006\007\004\008\009\010\011\004\012\013.\015\004\016\017\018\019\004\020\021\022\023\004\024\025.\027\004\028\029\030\031\004\032!\"#\004\$%&'\004\(\)*+\004,-\./.0123.4567.89:\;.<=>?
+BAABAgMA 0 6 BAABAgMA 17 \000\001\002\003
+BAABAgMEAAgJCg== 0 -1
+BAABAgMEBAUGBwYICQoLBAwNDg8EEAQYGRobBBwdHh8EICEiIwQrBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwA= 0 -1
+BAABAgMEBAUGBwQIKQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQIKQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 183 \000\001\002\003.\004\005\006\007.\008\)\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+BAABAgMEBAUGBwQICQoLFAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQICQoLFAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 209 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015\004\016\017\018\019\004\020\021\022\023\004\024\025\026\027\004.\029\030\031\004\032!\"#\004\$%&'\004\(\)*+\004,-\./\0040123.4567.89:\;.<=>?
+BAABAgMEBAUGBwQICQoLBAwNDg8AEA== 0 21 BAABAgMEBAUGBwQICQoLBAwNDg8A 68 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBRgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBRgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 200 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027\004.\029\030\031\004\032!\"#\004\$%&'\004\(\)*+\004,-\./\0040123.4567.89:\;.<=>?
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGjsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGjsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 183 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\;.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgIaIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgIaIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 187 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\162#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjJA== 0 -1
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjAA== 0 46 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjAA== 145 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgJCUmJw== 0 -1
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwAsLQ== 0 56 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwA= 158 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBA== 0 -1
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vADA= 0 61 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vAA== 164 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMA 0 66 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMA 169 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123
+BAABAgMEBAUGBwQICQoLBAwNDg8EEAQYGRobBBwdHh8EICEiIwQkJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwY8PQ== 0 -1
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8B 0 -1
+BAAEBQYHBAgJCgsEDA0ODwQQERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwA= 6 71 BAgJCgsEDA0ODwQQERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwA= 151 \008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 3 78 AgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 176 \003\004.\005\006\007\004.\009\010\011\004\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+NAABAgMEBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9 0 -1
+HAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9 0 -1
+CAABAgMEBAUGBwQICQoLBAwNDg8EEAQYGRobBBwdHh8EICEiIwQrBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwA= 0 -1
+AgABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 AgABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 185 \000\001.\003\004.\005\006\007\004.\009\010\011\004\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+BAABAgM0ERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0= 0 -1
+AQABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 AQABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 182 \000.\002.\004\004\005.\007\004\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+BAABAgMmBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMmBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 227 \000\001\002\003.\004\005\006\007\004\008\009\010\011\004\012\013\014\015\004\016\017\018\019\004\020\021\022\023\004\024\025\026\027\004\028\029\030\031\004\032!\".\004\$%&'\004\(\)*+\004,-\./\0040123\0044567\00489:\;\004<=>?
+BAQYGRobBBwdHh8EICEiIwQkJSYnBCgpKisELC0uHB0eHwQgISIjBCQlJicEKCkqKwQsLS45BDAxBCAhIiMEJAAB 0 -1
+BAABAgMEDA0ODwQQERITBBQVFhcEGBkaGwQcLx4fBCAhIiMEJCUmJwQoKyorBA== 0 -1
+BAABAiAEBAUGBwQICQoLBAxkAA8EEBEeHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDxvPj8A 0 66 BAABAiAEBAUGBwQICQoLBAxkAA8EEBEeHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDxvPj8A 131 \000\001\002\032.\004\005\006\007.\008\009\010\011.\012d\000\015.\016\017\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<o>?
+BAAkdXV1dR0pELsELC0uPBgZGhsEHgkJ2gEBAmQEBAeAABogBCkJCdonBBQVPUAEGBkaGwQpGgAEKAkJ2gQWJRfaGxITBAEVFgBAGCQwGwT5HClHuwQsLS48GBkaGwQpCQnKARKKBJ2dnZ2dnZ2dnRgsLUAEGCwtLgA= 2 -1
+BAABAgMEBEAADQ4PBBAREhMEFBUWFwQYGRobBAQgISIjBA8lJicczx4fBCAhIiMEJCUmLwQwMS8EMDEyMww0NTQ3BDg5GwQmJ/UnNjcEODkyMww0NzY3BDg5GwQmJ/UnNjcEODk6OwQ6OwQ8PT4/AA== 0 112 BAABAgMEBEAADQ4PBBAREhMEFBUWFwQYGRobBAQgISIjBA8lJicczx4fBCAhIiMEJCUmLwQwMS8EMDEyMww0NTQ3BDg5GwQmJ/UnNjcEODkyMww0NzY3BDg5GwQmJ/UnNjcEODk6OwQ6OwQ8PT4/AA== 261 \000\001\002\003.\004\@\000\013.\015\004\016\017\018\019\004\020\021\022\023\004\024\025.\027\004\004\032!\"#\004\015%&'\028\207\030\031\004\032!\"#\004\$%&/.01/\004.123\0124547\00489\027\004&'\245'67\0048923\0124767\00489\027\004&'\245'67\00489:\;\004:\;.<=>?
+BAABAgMEBAUiIwQkJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEOAYHBAgJCoAEDA0ODwQQERITBBQFFhcEGBkaGwQcHR4fBKAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwA= 0 110 BAABAgMEBAUiIwQkJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEOAYHBAgJCoAEDA0ODwQQERITBBQFFhcEGBkaGwQcHR4fBKAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwA= 222 \000\001\002\003.\004\005\"#.\$%&'.\(\)*+.,-\./.0123.4567.8\006\007\004.\009\010\128\004\012\013\014\015.\016\017\018\019.\020\005\022\023.\024\025\026\027.\028\029\030\031.\160!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+BCorBCwtLjL79Pv7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+3sEPD0VFhcEGBka0yYMHR4mBCAhIiO0ELS0trTFtLS0tLS09rS0tCsELC0uLQAEAAB/AAA= 4 82 LC0uMvv0+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7ewQ8PRUWFwQYGRrTJgwdHiYEICEiI7QQtLS2tMW0tLS0tLT2tLS0KwQsLS4tAAQAAH8AAA== 270 -\.2\251\244\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251\251{\004<=\021\022\023\004\024\025\026\211&\012\029.&\004\032!\"#\180\016\180\180\182\180\197\180\180\180\180\180\180\246\180\180\180+\004,-\.-\000.\000\000\127\000
+BAABAh0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dAwQEBQYHBAgJCgsEDP0NDwQQERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJwQoKTY3BDg4OjsEPD0+PwA= 0 98 BAABAh0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dAwQEBQYHBAgJCgsEDP0NDwQQERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJwQoKTY3BDg4OjsEPD0+PwA= 321 \000\001\002\029.\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029.\003\004\004\005\006\007\004\008\009\010\011\004\012\253\013\015\004\016\017\018\019\004\020\021\022\023\004\024\025.\027\004\028\029\030\031\004\032!\"#\004\$%&'\004\(\)67\00488:\;.<=>?
+BAABAgMEBAUGBwQAAAEABAwNDhQEEBESEwQUNBYXBAcH5wYHogcHBw0HBwcHBwcAEAcHBwcigDUzNjcEODk6OwQ8UT4/AA== 0 70 BAABAgMEBAUGBwQAAAEABAwNDhQEEBESEwQUNBYXBAcH5wYHogcHBw0HBwcHBwcAEAcHBwcigDUzNjcEODk6OwQ8UT4/AA== 200 \000\001\002\003.\004\005\006\007.\000\000\001\000.\012\013\014\020.\016\017\018\019.\0204\022\023.\007\007\231\006.\162\007\007\007\013\007\007.\007\007\007\000\016\007\007.\007\"\1285367.89:\;.<Q>?
+DQ4EAAHlDQQEBQYBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBBAgJAA4PAwAAGRobBCchHB0eHwQgISIjBCQlJiciIwQkJSYnBCj+3vH+/u7+/v7+BCQlJichIiME/h7//t7+3/7+/v7+/v7+/v7+BAg/AA== 0 118 DQ4EAAHlDQQEBQYBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBBAgJAA4PAwAAGRobBCchHB0eHwQgISIjBCQlJiciIwQkJSYnBCj+3vH+/u7+/v7+BCQlJichIiME/h7//t7+3/7+/v7+/v7+/v7+BAg/AA== 354 \014\004\000\001\229\013\004\004\005\006\001\001\001.\001.\001.\001.\001.\001.\001.\001.\001.\001.\001.\001.\001.\004.\009\000\014\015\003\000\000\025.\027\004'!\028\029\030\031\004\032!\"#\004\$%&'\"#\004\$%&'\004.\254\222\241\254\254\238\254\254\254\254\004\$%&'!\"#\004\254\030\255\254\222\254\223\254\254\254\254\254\254\254\254\254\254\254\004\008?
+BAAIAgMEBwQsLS4vBC0xCAkKCwQMDQ4PfxA3BDgEAAgCAwQHBDwtLjIzBDQ1NggJCgsEDA0OD38QNwQ/OTotLkYELTEyNggJCgsEDA0OD38QNwQ4BAAIAgMEBwQsLS4vBC0xMjMENDU2CAkKCwQ5OjsEPEg+Pw== 0 -1
+BAABAgMEBAUGBwLrCQoFBgcD6wkKCwQMDQ7//xAREhMEFBUWFwQYGRob 0 -1
+BAAP/wAXBBgZGhsEHB0eHwQOIZgAIvQJ//8WGRcXFxcXFxcXFxwlF/oXICEiEAxAABcXFxcXFxcXFxcX/xcXFxccJQxAABcXFxcXFxcX 0 -1
+DAAB/AMEBAUGBwQICQoLAwxADg8EEBESEwQkJSYnBCgpKisELC1ADg8EBgcECAxADg8TBBQiIwQkJSY5OjsEPD0+ 0 -1
+BH8PEhMEIn4EABD/BCEiIwQkJSYADg8EBEwSEwQiIwQADf8EAXUjBA0ABCIjBAAQ/wQhIiNVDQ4PBgQPEhMEFCMk+gAA+i4AAAADQAAAAC4uLi4uLi5PLi4uLi4uLi4jAAACAAAO 0 101 BH8PEhMEIn4EABD/BCEiIwQkJSYADg8EBEwSEwQiIwQADf8EAXUjBA0ABCIjBAAQ/wQhIiNVDQ4PBgQPEhMEFCMk+gAA+i4AAAADQAAAAC4uLi4uLi5PLi4uLi4uLi4jAAACAAA= 289 \127\015\018\019.\"~\004\000.\255\004!\"#\004\$%&\000\014\015\004\004L\018.\004\"#\004\000\013\255\004\001u#\004\013\000\004\"#\004\000.\255\004!\"#U\013\014\015\006\004\015\018\019\004\020.\$\250\000\000\250\.\000\000\000\003\@\000\000\000\.\.\.\.\.\.\.O\.\.\.\.\.\.\.\.#\000\000\002\000
+BAAYGRoCAgICAgICAgICAgIC 0 -1
+BBwBAhwBBQYAABAACgsEDA0OFwMUBAUGAAAQAAoLBAwNDicEKD8qKwQsMjMENA== 0 -1
+BAABAvsEBDQmNjcEAEA6O6GhoZ2hoaGhoakhoaGhoaEEPD0FHQcECAkKCwB/DQ4uBBAREhMEFBUWFwQYGAACAAAdHh8EICljAAAAADEySwQ0NTY3BABAOjsEPD1APwQ8PT4= 0 -1
+BP9/AgMEBAUGBwQICQoLBAwNDg8EEBESEwQEGRobBBwdHh8EICEkJSYnMzMzMzMzMzMzMzMzMysELC0uLwQwMTIzBDQ1NjcEODktOwQ8PT4/AA== 0 -1
+DQ4PBAgICgtADA0ODwQICQoLAAD//w8EBF4GBwwABF4GBwwNBg8EBBMEBv8ICQoDQAQTBgcEDwQICdsLQAwzBDRONjcEOA== 12 -1
+BAABAgMEBDAxMjMENCwtLi8EBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgAAIAAHF2hHyEiIwQkJTEnBCgpKisELC0uLwQwMTIzBDQsLS4vBDAxMjMENDU2NwQ4OTpkNjcEODk6OwQ8PQ== 0 -1
+A+cBAgMEBCkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKQcECAkKISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OVc7BDw9PgA= 0 -1
+BAABAhERAwQEBQYHBCEJCAghCQgICAgJCAgI7REICAAICAgICAiICAgICAgICAgICAgICAoLBAwNDg8EBhESEx0UFRYXfyX/JwQoKSorBCwtLi8EMDEyMwQ0NTw9Pg== 0 -1
+BAABAgMEBQUG5gMI5ycLBAwNDg8EyxG6EykRHQEBAQEBAQEBAQEBAQEBAQEBAQEBAQF/auUs 0 -1
+CgsjFSQlJicEKCkqKwQsNDQAEDcUFRYX/wAAABsEHB0bBBwdHh8EICEiIxUkAAAbFhcEMTIzBDQAEBsEHB0eHwQgMwQ0NQ== 0 -1
+BAABAgMEBAUGBwQI7AoLBAwNDicEEBESEwQUFRYXBAYZGhsEHB0eIgQgISIjAj4/AA== 0 49 BAABAgMEBAUGBwQI7AoLBAwNDicEEBESEwQUFRYXBAYZGhsEHB0eIgQgISIjAj4/AA== 143 \000\001\002\003.\004\005\006\007.\008\236\010\011.\012\013\014'.\016\017\018\019.\020\021\022\023.\006\025\026\027.\028\029\030\".\032!\"#.>?
+BBABAgMsLS4A/zA0MvoAAPo2NwQ4PD03PwAEJwQoKR0eHwQg//8aGwABHR4fBCA2IiMEJCUmJwQoKQACEu4rLS4vBDCysn8ENDU2NwQ4ORUWFwQgISIjBCSyBDQ1NjcEODkVFhcGGBkaGwQwMDAwMCoqKioqKioqKiogKioqKioqKioqKioqKioqJSYnBCgpHR4fBCD///+APT5BAA== 0 -1
+BBABggMEBAUG6wQICQoLBAxuBBQtLiBQMwQzNTY5BDgeOTsEUFEENDUpNwQ4ADkEMDFQKhcELC0uIAQwMVAzBAQzNTY0NQ== 0 -1
+GQABAgMEBAUGBAIWCwQL8Q8EChESEwYUFRYXpQIDBAQFBgQIFgsEC/EPBAoREhMGFBYXpRgZGhvuHB0dHh7iPQ0ODwQQERITBhQV+gAAdHB0dOICBBwdQIAAKwQsLS6jvzA= 0 -1
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEDh0eHwQgISIjBAICAgICAgICAgICAgICAgICAgICAgICAjsEPD0= 0 -1
+BAABAgMEBAX0BgQICf9/BAwNEg8EEBESEwQUFRYXBBgZGhsEFB0eHwQgKSIjBCQk6ycECCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAX0BgQICf9/BAwNEg8EEBESEwQUFRYXBBgZGhsEFB0eHwQgKSIjBCQk6ycECCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 192 \000\001\002\003.\004\005\244\006.\008\009\255\127.\012\013\018\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\020\029\030\031.\032\)\"#.\$\$\235'.\008\)*+.,-\./.0123.4567.89:\;.<=>?
+BAABAGQEBAUGBwQICQouLwQwMTIzBDQAgAAASzk6OwQ8PT4EGBkaGwQcHR4fBCAhIyMKJCUmJwQoKSo4BCYtLi8EMDEyMuI0NTYEJi0uLwQwMTIzBDQAAAABAAA6OwQ8PT4/BDcEODk6Oys8PT4/BA== 0 -1
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESKQQUFRYXBBgZGigEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQICQoLBAwNDg8EEBESKQQUFRYXBBgZGigEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 181 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\).\020\021\022\023.\024\025\026\(.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+BAABAgICAgICAgICLhwEMDEyMwICAgICAgQUFRYXAgICAgICAgICAgICAgICAgICAgICAgICAgICAi4cBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgICAgICAgICLhwEMDEyMwICAgICAgQUFRYXAgICAgICAgICAgICAgICAgICAgICAgICAgICAi4cBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 191 \000\001\002\002.\002\002.\002\002.\.\028.0123.\002\002.\002\002.\020\021\022\023.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\.\028.0123.4567.89:\;.<=>?
+BAABAgMEBAUGBwQICQoLBAwNDgICAgICAicEKCkqKwQsLS4vBDACAgICAgICAgICAicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAgMEBAUGBwQICQoLBAwNDgICAgICAicEKCkqKwQsLS4vBDACAgICAgICAgICAicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 168 \000\001\002\003.\004\005\006\007.\008\009\010\011.\012\013\014\002.\002\002.\002'.\(\)*+.,-\./.0\002\002\002.\002\002.\002\002.\002'.\(\)*+.,-\./.0123.4567.89:\;.<=>?
+BAAYDQ4PBBAREhMBjAMEBAUGDQ4PBBAREhMEFBUWEwQUFRYXBBgZGhsEkx0eHxobBJMdDB8EICEiIwQ2NDUEkx0eDg8EEBESEwQEGBkaGwSTHQ== 0 -1
+ZAENAWQBDQAA/w== 1 7 AQ0BZAENAA== 12 \013.d.\013
+BAQIIwoLDwQQEeQcPx4fBCAhIiMEJCUmJx8FIAQoKSorBCwhLi8EMB0yD6cQEcscPx4fBCA+IiMEJCUmJx8EFd4oKSorFCcEGSkqKwQsLTcEODk6OwQ8BwQYBxobBBwdHg/HEBES 3 -1
+wAADJRoVHignKiuALC1AAAAABCBNLn////97fwAcPj+A 0 -1
+BAARAgMEBAUGBwQICQrvAwgJCsAEDBcEGAQMDQ4PBBAdHh8EICEiIwQkJSYnBCgpKisELC0uLwQwMQAAEQIDBAQFBgcECAkK7wP/BDQ1NjcEODk6OwQ8PT4/ 0 -1
+BAABAgMEBAAGBwQICQoLBAwNDg8EEBESKAQUFRYXBBgZGhsEHB0eHwQgISIrBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwQ4OTo7BDw9AEAA 0 81 BAABAgMEBAAGBwQICQoLBAwNDg8EEBESKAQUFRYXBBgZGhsEHB0eHwQgISIrBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwQ4OTo7BDw9AEAA 185 \000\001\002\003.\004\000\006\007.\008\009\010\011.\012\013\014\015.\016\017\018\(.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"+.,-\./.0123.4567.89:\;.<=>?.89:\;.<=\000\@
+BAABAgMEBAUGBwQICQoPDwQQFBUWFwQYGRobAQEBAQEBAQEBBBwdHh8EICEiIwQkJSYnBCgpKisELC0uL////38zBDQ1NjcEPBA+P0A= 0 -1
+BA8EAgAsAID/////MjMEMjU2NwMEFgUEBf//9BEAHALNBAb/f0AA6iAEICEiIwQkJSYn+vr6+vr6BPYGACQICQoQAiADvQABEgMEBAUEBQYHBEAA6iAEICEiIwQkJSYn+vr6+vr6+vr6+vr0BBIdLC0u9gQwMSgMBwRkAAAgBEQAIAQgISI= 0 -1
+BAABAgMEBAUGBwQICQoLBBobBBwdHh8EICEiIwQkJSYnBCgpKisELDEyMwQ0NTY3BAACOjsEPHI+OwQ8PT4/AA== 0 64 BAABAgMEBAUGBwQICQoLBBobBBwdHh8EICEiIwQkJSYnBCgpKisELDEyMwQ0NTY3BAACOjsEPHI+OwQ8PT4/AA== 147 \000\001\002\003.\004\005\006\007.\008\009\010\011.\026\027\004\028.\030\031\004\032!\"#\004\$%&'\004\(\)*+\004,123\0044567\004\000.:\;.<r>\;.<=>?
+wAABAgMEERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJ/snKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwA= 0 -1
+BB4fBAQcKSkpKSkpKSkpKSkpKSkpKRMpKSkpBCAhDyMEJCUmJwQ= 0 -1
+AgAAAhAiAhAiFvQAzwACECICECIW9ADpFvQW9ADpA/QAzw== 0 33 AgAAAhAiAhAiFvQAzwACECICECIW9ADpFvQW9ADpA/QA 108 \000\000.\016\".\016\".\244\000\207\000\002\016\"\002\016\"\022\244\000\233\022\244\022\244\000\233\003\244
+BAABFwMEBAUWFwQYGRobBBwdHh8EICEiIwQkJSYnBCgpKisELDsuLwQgISIjBCQlJicEKCkqKwQsOy4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABFwMEBAUWFwQYGRobBBwdHh8EICEiIwQkJSYnBCgpKisELDsuLwQgISIjBCQlJicEKCkqKwQsOy4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 147 \000\001\023\003.\004\005\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,\;\./.\032!\"#.\$%&'.\(\)*+.,\;\./.0123.4567.89:\;.<=>?
+BAABAQEBAQEBAQEBAQoL9gwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJieuDCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 81 BAABAQEBAQEBAQEBAQoL9gwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJieuDCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 214 \000\001\001\001.\001.\001.\001.\001.\011\246\012\013\014\015\004\016\017\018.\004\020\021\022\023\004\024\025\026\027\004\028\029\030\031\004\032!\".\004\$%&'\174\012\)*+\004,-\./\0040123\0044567\00489:\;\004<=>?
+BBgZKhsEHIAAHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMgICAgICAgIC 0 -1
+PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0/fn+AgYKDhIWGh4iJiouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8P70= 64 -1
+PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0Afg== 0 129 PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyQlJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0A 235 \000\001\002\003\004\005\006\007\008\009\010\011\012\013\014\015\016\017\018\019\020\021\022\023\024\025\026\027\028\029\030\031\032!\"#\$%&'\(\)*+,-\./0123456789:\;<=>.?\@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}
+PwAhIiMFJSZZKAPoKzQtLi0wMTIzSTU2Nzg5OjsSPT4/PwECy8vLy+fnntTn5wQBBgcILy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vLy8vL38jBSUmWSgD6Cs0LS4tMDEyMzRGR0hJSktMTYODgwUGBwgJCgsMDQ4PEBETFEAADw== 0 -1
+wACQkAQAJiYmJiYmJiYmJiYi 0 -1
+AgBAAhAiAhAiFvQAzwACECICECIW9ADpFvQW9ADpA/QAzw== 0 33 AgBAAhAiAhAiFvQAzwACECICECIW9ADpFvQW9ADpA/QA 106 \000\@.\016\".\016\".\244\000\207\000\002\016\"\002\016\"\022\244\000\233\022\244\022\244\000\233\003\244
+AgAAAgEiAhAiFusCzwACECICZCIW9A/pFvQW9ADpAwACASICECIW6wLPAAIQDQJkIhb0D+kW9Bb0AOkDJQA= 0 62 AgAAAgEiAhAiFusCzwACECICZCIW9A/pFvQW9ADpAwACASICECIW6wLPAAIQDQJkIhb0D+kW9Bb0AOkDJQA= 200 \000\000.\001\".\016\".\235\002\207\000\002\016\"\002d\"\022\244\015\233\022\244\022\244\000\233\003\000.\001\".\016\".\235\002\207\000\002\016\013\002d\"\022\244\015\233\022\244\022\244\000\233\003%
+AgABAQEBAQEBAQIBAQEBAQEBAQEBAQ== 0 -1
+AgACAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgL0 0 -1
+AgAAAhAiAQEBCQEBAQACENQBAQEBAQEBAQEBAWQBAAEBAgEBAQEBKSkp 0 -1
+AgABAQEBAQEBAQEBAQECAQACAAACECIBAQEBAQEBAQEBAQEBAQE= 0 -1
+AgAAAhAiAgAAAhAiAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQIBVwEBAQEBAQEBAQECAVcBAQEBAQEBAQEBAQECAVcBAQEBAQEBFAE= 0 -1
+BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwTgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8A 0 81 BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwTgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8A 88 \@ABC.DEFG.HIJK.LMNO.PQRS.TUVW.XYZ[.\\]^_.\224abc.defg.hijk.lmno.pqrs.tuvw.xyz{.|}~\127
+BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawBsbQ== 0 56 BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawA= 57 \@ABC.DEFG.HIJK.LMNO.PQRS.TUVW.XYZ[.\\]^_.`abc.defg.hijk
+BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fj8A 0 81 BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fj8A 82 \@ABC.DEFG.HIJK.LMNO.PQRS.TUVW.XYZ[.\\]^_.`abc.defg.hijk.lmno.pqrs.tuvw.xyz{.|}~?
+PwABAgMEBQYHCAmztLUAABYXGBmInAoLDA0ODyQRNDU2NwE5Ojs8PT4/PwkKCwwNDg8kSwoLDA0ODyQpKSkpKSkpPT4/VTAxMjM0NDY3AYeLjKqObB0eHyB9KSkpKSkpKWQnKCkqKykJKSkpKSkpKSkpKSlkJygpKissLS48PT4/P0BBQkNERUYvMDEyMzQ0NjcBigQArK2urw== 0 -1
+PwABAgMEBQYHCAkKCwwNDg8QERITFBUWFxgZGhscHR4fICEiIyTsJicoKSorLC0uLzAxMjM0NTY3ODk6Ozw9Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNLVVZXWFlaW1xdXl9gYWJjZGVmZ2hpMDAwMDEwMDAwMDAwME0wMDAwMDAwMDAwMDAwMDAwMGprbG1ub3BxcnN0dXZ3eHl6ewh9P35/gIGCg4SFhoeIiYo7PD0+Pz9AQUJLTE1OT1BRUouMjY6PkJGSk5SVlpeYmZqbnJ2en6ChoqMgpaanqKmqq6ytrq+wsbKztLW2t7i5uru8P70= 0 -1
+KCgoKCgoKDkQgAQwQDJDxsbGyP9EKsbG1sbGxsbGxsbGyP8qxkAqKioqKioqKMbGzcbG1v8qKsbG1sbGxsbGxsbGyP8qKkAqKioqKioqQSoqACgTExMTExMTExMTExMTExMTExMTExMTExMTExMTKioMKioqKir/ACroAyoq 0 -1
+BAwDAwMDA+gCAwMDAwMDAwMDAwP6A+gCAwMDAwMDAwMDAwP6AAA= 0 38 BAwDAwMDA+gCAwMDAwMDAwMDAwP6A+gCAwMDAwMDAwMDAwP6AAA= 121 \012\003\003\003.\003\232\002.\003\003\003.\003\003\003.\003\003\250.\232\002\003.\003\003\003.\003\003\003.\003\250\000
+BAABAh0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dAwQEBQYHBAgJCgsEDP0NDwQQERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJwQoKTY3BDg4OjsEPD0+P8A= 0 -1
+//8FDgMEBwQsLS4nBC0AEwIQAAcAAH/fMjMENDU2CAkKTy4gAB8ANgQsLS4vBAcAAH/fMjMENDU2CCAAHwA2BCwtLi8eBC4gAB8ANgQsIAAfAC4vBH8QHgQ/OTpPLiCVlZWVlZWVlZWVlZWVlZWVlZWV 5 -1
+FgAAEAAnBCgpKisELC0uEdkuEQYDBCEJCAghCQgICBgJCAgIAwIICAAICAgIAAkICCEJCAgIGAgICO0RCAgACAYIFAgICIYICAgICO0RCAgACAYIFAgPBAYREhMdag== 0 -1
+BA8ICAgEBAUG6wQICQoLBAxuJSY2BBAAAAAEFC0uIFAzBDM1NjkEOB45OwRQUgQ0NSk3BDgAOQQ1NjkEOB45OwRQUQQ0NSk3BDA0UCoX 0 -1
+PwABFwMEenp6enp6enp6enp6enp6enp6enp6enp6enp6enp6IyQlJicoKSorLC0uLzAxMjM0ACAzODk6Ozw4Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaAVxdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0Afg== 0 129 PwABFwMEenp6enp6enp6enp6enp6enp6enp6enp6enp6enp6IyQlJicoKSorLC0uLzAxMjM0ACAzODk6Ozw4Pj8/QEFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFlaAVxdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0A 159 \000\001\023\003\004zzzzzzzzzzzzzzzzzzzzzzzzzzzzzz#\$%&'\(\)*+,-\./01234\000\032389:\;<8>.?\@ABCDEFGHIJKLMNOPQRSTUVWXYZ\001\\]^_`abcdefghijklmnopqrstuvwxyz{|}
+PwDuAQMEBQYHCAl8fHx8fHx8fHx8fHx8fHx8fHx8fHx8ICEiIyQlJjU2Nzg5Ojs8ICEiIyQlJjU2Nzg5Ojs8PT4/P0BBQkNEVHx8fHx8fHx8fHx8fHx8fHx8fHx8fCAhVVZXWFlaW1xdXl9gABBjZGVwcXJzdHV2QAAAAHt8fQB+ 0 128 PwDuAQMEBQYHCAl8fHx8fHx8fHx8fHx8fHx8fHx8fHx8ICEiIyQlJjU2Nzg5Ojs8ICEiIyQlJjU2Nzg5Ojs8PT4/P0BBQkNEVHx8fHx8fHx8fHx8fHx8fHx8fHx8fCAhVVZXWFlaW1xdXl9gABBjZGVwcXJzdHV2QAAAAHt8fQA= 190 \000\238\001\003\004\005\006\007\008\009||||||||||||||||||||||\032!\"#\$%&56789:\;<\032!\"#\$%&56789:\;<=.??\@ABCDT|||||||||||||||||||||\032!UVWXYZ[\\]^_`\000\016cdepqrstuv\@\000\000\000{|}
+wACQmAQA 0 -1
+ARABIQEiAYABJAElASYBJwEoASkBKgEaARsBHAEdAR4BHwEgASEBIgGAASQBJQEmAScBKAEpASsBLAEtAS4BNwE4 0 -1
+AQABAwEEAQUBBgEnASgBKQEqASkBKgErASwBLQEuATcBOAE5AToBOwE8AT0BKwEsAS0BLgE3ATgBOQE6ATsBPAE9 0 -1
+A98BAgMEBCkpKCkpKSkpKSkpKSkpBikmKSkrKSkpICkpKSkpKQEnBCgpKSkpKSkpKSkGKSYpJDMENA== 0 -1
+A2QBAgMEBCkpKSkpKSkpKSkpKSkpKQQEKSkpKSkpKSkpKSkpKSkpKSkMKSkpKSkpKSkpKSkpKSkpKCkHBAgJCiFAKSkpKSkpKSkpKSkpKQcEKSkpKSkpKSkpKTcEODlXOwQ= 0 -1
+BBABAgMsLS4A/yoqMgUAAH82NwQ1NjcEODwVFhcGGBkaG/0vEQYYIgQoKQACEu4rLS4vBDCysioqKiAqKio2MC4wKioqKioEIEciIwQkCCYnKQoCEu4rLS4vBDCysgRFKQACEu4rAwAAfyoqICoCEu4rLS4BADCysioqKiAqKioqJSoqKioqKioqEiolJicEPCk= 0 -1
+AUABRQFGAU8BUAFRAVIBUwFUAVUBVgFXAVgBWQFaAVsBXAFfAWABYQFiAWMBZAFlAWYBZwFoAWkBagFrAWwBbQFuAW8BcAFxAXIBcwF0AXUBdgF3AXgBeQF6AXsBfAF9AX4BfwA= 64 37 AW4BbwFwAXEBcgFzAXQBdQF2AXcBeAF5AXoBewF8AX0BfgF/AA== 39 n.o.p.q.r.s.t.u.v.w.x.y.z.{.|.}.~.\127
+BAAEBQYHBAgJCgsEDA0ODwQQERITBBQVFhcEGBkaGwQcHSEiIwQkJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChoqMEpKWmpwSoqao= 32 -1
+BAAEBQYHBAgJCgsEDA0kJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChoqMEpKWmpwSoqao= 8 -1
+BAABAgMEBAUGBwQICQocHR4fBCAhIiMEJCUsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaWwRcXV5fBGBhYmMEZGVmZwRoaWprBGxtHh8EICEiIwQkJSYnBCgpKisELC0uLwSAgYKDBISFhocEiImKiwSMjY6PBJCRkpMElJWWlwSYmZqbBJydnp8EoKGiowSkpaanBKipqqsErK2urwSwsbI= 0 -1
+BAAEBQYHBAgJCgsEDA0kJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEgAA6OwQ8PT4/BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgNTY3BDg5OjsEPD0+PwRAQUJDBERFRkcEdHV2dwR4eXp7BHx9fn8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChoqMEpKWmpwSoqao= 8 -1
+BAAEBQYHBAgJCgsEDA0kJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT5fBGBhYGMEZGVmZwRoaWprBGxtbm8EcHFycwR0dVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8EgIGCgwSEhYaHBIiJiosEjJGOjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChoqMEpKWmpwSoqao= 8 -1
+BOgCAwMD+gPoAgMDAwMDAwMDAwMD+gAMAwMDAwPoF+gCAwMDAwMDA+ICAwP6AAADAwMDAwMDAwMDA/oD6AIDAwMDAwMDAw== 0 -1
+BOj6A+gCAwMDAwMDAwMDAwP6AAwDAwMDA+gX6AIDAwMDAwMD4gIDA/oAAAMDAwMDAwMDAwMD+gToAgMDA/oD6AIDAwMDAwMDAwMDA/oADAMDAwMD6BfoAgMDAwMDAwPiAgMD+gAAAwMDAwMDAwMDAwP6A+gCAwMDAwMDAwMSAwP6A+gCAwM= 0 -1
+BOj6A+gCAwMDAwAMAwMDAwPoF+gCAwMDAwMDA+LwAwP6AAADAQMDA/oD6AIDAwPoF+gCAwMDAwMDA+LwAwMDAwMD+gMDAwMDAwMDAwMD+gAMAwMDAwPoF+gCAwMDAwMDA+LwAwP6AAADAwMDAwMDAwMDA/oD6AIDAwMDAwMDAwMDAw== 0 -1
+BOgDAwgICAgICAgICAgICAgICAgICAgBCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICHQICAgICAEICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIdAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI 0 -1
+BOgCFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFQMDAwMDAwMJ+gPoAgPwAgM= 0 -1
+GxsbGxsAGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsVGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbAxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGyYbGxsbGxsbGxsbGxsbGxsbGxsb 27 -1
+BOgCAwMD+gPoAgMDAwMADAMDAwMD6BAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAE6AQDAwP6A+gC 0 -1
+BOgCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC 0 -1
+BOgDAwgIDAgICAjvCAgICAgIAgjCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCAMLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwuXCwsLCwsLCwsLCwsLCwsLCwsLCwsK6wsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCssLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCqMLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwggICAEICAgIf3QICAgICAEICAfwCAgICAgIB+8IEwgIgAgICB8ICAgICBgICAgICAgSCAgICAgICAgICAgICAgfJoAICAgICAgICACAAAAF/+kFCH8ICAgICAgICAgICHQICAgICJwIwqrCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwtLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCpcLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsIICAgBCAgICH90CAgICAgBCAgH8AgICAgICAfvCAgICIAICAgfCAgICAgYCAgICAgIEggICAgICAgICAgICAgH8AgICAgIAQgIB/AICAgICAgICAgICAjwCAgIHwgICAgIGAgICAgICBIICAgICAgICCAACAgICAgICAgICAjeCAgICAgICAgICAgICAgFHyYICAgICAgICAgAgAAABf/pCFpaWlpaWlp6WlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWggICAgBCAgH8AgICAgICAgICAgICPAICAgfCAgICAgYCAgICAgIEggICAgICAgICAgICAgICAgICAgICN4ICAgICAgICAgICAgICAUfJggICAgICAgICACAAAAF/+kIWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpahoaGhoaGhoaGkIaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGf4aGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGhoaGWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaWlpaTlpaWlpaWlpaWlpaWlpaWlpaWlpaWggICAEICAfwCAgI///CwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwsLCwgAACAgH8AgICP//AAAICAgI+QcICAgICAUICAgICAgICAgICAgICAgICAgICAgICAgICAgI//8AAAgICAgICAgICAgIBQgICAgICAgICAgICAkICAgICAgICAgICAgIDA== 0 -1
+BOgDAwgIFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcCFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXAAADFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFwgI 0 -1
+BOg6OjoIOjo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Mzo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo6Ojo= 0 -1
+BOgDAwQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAgQEBAQEBA== 0 -1
+BOgDAwgINjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjaeNjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Np42NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY= 0 -1
+AQABAQECAQcBCAEJAQoBCwEMAQECAQsBDAENAQ4BDwEQAREBEgETARQBFQEWARkBGgEbARwBHQEeAR8BIAEjASQBJQEmAScBKAEpASoBKwEsAS0BLgE3ATgBOQE6ATsBPAE9AT4BPw0BDgEPARABEQESARMBFAEXBRgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgE3ATgBOQE6ATsBPAE9AT4BPwA= 0 185 AQABAQECAQcBCAEJAQoBCwEMAQECAQsBDAENAQ4BDwEQAREBEgETARQBFQEWARkBGgEbARwBHQEeAR8BIAEjASQBJQEmAScBKAEpASoBKwEsAS0BLgE3ATgBOQE6ATsBPAE9AT4BPw0BDgEPARABEQESARMBFAEXBRgBGQEaARsBHAEdAR4BHwEgASEBIgEjASQBJQEmAScBKAEpASoBKwEsAS0BLgE3ATgBOQE6ATsBPAE9AT4BPwA= 387 \000.\001.\002.\007.\008.\009.\010.\011.\012.\001.\001\011.\012.\013.\014.\015.\016.\017.\018.\019.\020.\021.\022.\025.\026.\027.\028.\029.\030.\031.\032.#.\$.%.&.'.\(.\).*.+.,.-.\..7.8.9.:.\;.<.=.>.?.\001\014\001\015\001\016\001\017\001\018\001\019\001.\001\023\005\024\001\025\001\026\001\027\001\028\001\029\001\030\001\031\001\032.!.\".#.\$.%.&.'.\(.\).*.+.,.-.\..7.8.9.:.\;.<.=.>.?
+AQABAQECAQMBBAEFAQYBJwEoASkBKgEpASoBAQIBOQE6ATsBKwEsAS0BLgE3ATgBOQE6ATsBLQEuATcBOAE5AToBOwE8AQ== 0 -1
+BAABAgMEAAAEAAQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BEBBQkMEREUwRwRISUtLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnaGiAAA= 0 241 BAABAgMEAAAEAAQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BEBBQkMEREUwRwRISUtLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnaGiAA== 438 \000\001\002\003.\000\000\004\000.\008\009\010\011.\012\013\014\015.\016\017\018\019.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?.\@ABC.DE0G.HIKK.LMNO.PQRS.TUVW.XYZ[.\\]^_.89:\027.<=>?.\@ABC.DE0G.HIKK.LMNO.PQRS.TUVW.XYZ[.\\]^_.`abc.defg.hijk.lm\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.\128\129\130\131.\132\133\134\135.\136\137\138\139.\140\141\142\143.\144\145\146\147.\148\149\150\151.\152\153\154\155.\156\157\161\162
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFRkcESElKSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EYGFiYwRkZWZnBGhpamsEbG0eHwQgISIjBCQlJicEKCkqKwQsLS4vBICBgoME+oWGhwSIOwQ8PQ== 0 -1
+BAABAgMEBAgJCgsEDA0gISIjMDEyMwQ0NTY3BDg5OjsEPD0iIwQkJSYnBD8pKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/BEBFRkcESElKSwRMTUNPBFBRUlsEVFVWVwRYWVpbBFxNXl8EYGFiYwRkZWZnBGhpamsEbG0eHwQgISIjBCQlJicEKCkqKwQsLScvBICBgoME+oWGhwSIiYqLBDQ1NjcEODk9Pj8E 0 -1
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmBwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFRkcESElKSwRMTU5PBFBRUlMEVFVWVwRYWVpbBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUOwQ8PQ== 0 -1
+AgAAAhBiAgAAAhAiAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQIBVwEBAQEBAQEBAQECAVcBAQEBAQEBAQEBAQECAVcBAQEBAQEBFAE= 0 -1
+AykpKSkpKSkpKQQEKSkpKSkpKSkpKSkpKSkpDCkMKSkuKSkpKSkpKSkpKSkpKCkG9QgJCiFAKSkpKSn/KSkpKSkAAAEpKQcEKSkpKSkpKSkpKSkpKSkpKQwpKSkpKSkpKSkpKTsEQAApKSkpKCkG9QgJCiFAKSkpKSn/KSkpKSkpKQcEKSkpKSkyKSkpKbckODlXOwRAAD4pBwQgHCkpKSkA 0 162 AykpKSkpKSkpKQQEKSkpKSkpKSkpKSkpKSkpDCkMKSkuKSkpKSkpKSkpKSkpKCkG9QgJCiFAKSkpKSn/KSkpKSkAAAEpKQcEKSkpKSkpKSkpKSkpKSkpKQwpKSkpKSkpKSkpKTsEQAApKSkpKCkG9QgJCiFAKSkpKSn/KSkpKSkpKQcEKSkpKSkyKSkpKbckODlXOwRAAD4pBwQgHCkpKSkA 365 \)\)\).\)\)\)\)\)\004\004\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\012\)\012\)\)\.\)\)\)\)\)\)\)\)\)\)\)\)\(.\006\245\008\009\010!\@\)\)\)\)\)\255\)\)\)\)\)\000\000\001\)\)\007\004\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\).\)\)\)\)\)\)\)\)\)\)\)\;.\@\000\)\).\)\(\)\006\245\008\009\010!\@\)\)\)\)\)\255\)\)\)\)\)\)\)\007\004\)\)\)\)\)2\)\)\)\)\183\$89W\;.\@\000>\).\004\032\028\)\)\)\)
+AgAAAhBiAQEBAQIQYgIiAQEBAQEBAQEBAQEBAQECAVcBAQEBAQEBAQEBAgFXAQEBAQEBAQEBAQEBAgFXAUEBAQEBAQECAVcBAQE= 0 -1
+AgBAAhAiAhBAAhAiAhATBAEVFhcEGBkaGwQUHR4fBCApIiMEJCTrJwQIKSorBAgJ/38EDA0SDwQQERITBBQVFhcEGBkaGwQUHR4fBCAp 0 -1
+AgAAAhBiAgAAAhAiAQEBAgFXAhBiAgAAAhABAQEBAQIBVwEBAQEBAQIQYgIAAAIQIgEBAQEBAQIBVwEBAgFXAQEBAQIBVwFBAQEBAQEBAgFXAQ== 0 -1
+AgBAAhAiAhBAAhAiAhAMDRIPBBAIEhMEARUWFwQYGRobBBQdHh8EICkiIwQkJAAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBgZGhsEFB0eHwQgKSIjBCQk6ycECCkAAAE= 0 108 AgBAAhAiAhBAAhAiAhAMDRIPBBAIEhMEARUWFwQYGRobBBQdHh8EICkiIwQkJAAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBgZGhsEFB0eHwQgKSIjBCQk6ycECCkA 344 \000\@.\016\".\016\@.\016\".\016\012.\018\015\004\016\008\018\019\004\001\021\022\023\004.\025\026\027\004\020\029\030\031\004\032\)\"#\004\$\$\000\000\002\000\@\002\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\025\026\027\004\020\029\030\031\004\032\)\"#\004\$\$\235'\004\008\)
+AgAfBCApJOsnBAgpKisELC0uLwQwQAIQIgIQQAIQIgIQIgYECAAAAQn/fwQMDRIPBBAIEhMEARUWFwQYGRobBBQdHh8EICkiIwQkJOsnBAgpKisELC0xMjMENDU2IgYECAn/fwQMDRIPBBAREhMEFBEWFwQYGRobBBQdHh8EICkiIwQvJOsnBAgpKisELC0uLwQwMTIzBDRCNjcEODk6OwQ8 0 -1
+AgBAAhAiAhBAAhAiAhAiAhAiBgQICR0eHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGBksLS6KBDAxMjMENDU2IgYECAn/fwQMDRIPBBAREhMEFBUQAAQYGRobBBQdHh8EICkiIwQkJOsnBAgpKisELC0uLwQwMTIzBDRCNjcEOHk6OwQ86ycECCkAAAEsLS4vBDAGBAgJ/38EDBAREhMEFBUQ 0 -1
+AgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBgZGhsEFB0eHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgJ/38EAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBgZGhsEFB0eHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGBkagAQUHR4fBCApIiMEJCTrJwQIKQAAAQw= 0 191 AgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBgZGhsEFB0eHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgJ/38EAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBgZGhsEFB0eHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGBkagAQUHR4fBCApIiMEJCTrJwQIKQA= 603 \000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\025\026\027\004\020\029\030\031\004\032\)\"#\004\$\$\000\000\002\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\025\026\027\004\020\029\030\031\004\032\)\"#\004\$\$\000\000\002\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\025\026\128\004\020\029\030\031\004\032\)\"#\004\$\$\235'\004\008\)
+AgAAAgBAAhAiAhBAAhAdHh8NNSkiGQQkJAAA/wBAAhAiAhBAAhAiAhAiBgQQIgIQQAIQIgIQHwQgKSIjBAQkAAACAEACEAACEEACECICBBAIEhMEARUWFwQYOhobBBQdHh8mNSkiGQQkJAAAAgBAAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQAAAIAQAIQIgIQQAIQIgIQIgYECAJAAgIC/gICOwA= 0 -1
+BAABAwMEAwjnJwsEDA0OHwTpASMBAQEBAQEBAADm 0 29 BAABAwMEAwjnJwsEDA0OHwTpASMBAQEBAQEBAAA= 88 \000\001\003\003.\003\008\231'.\004\012\013\014\031\004\233\001#\001\001.\001.\001.\000
+BAAAAQABAgMEBQAAAQU= 0 12 BAAAAQABAgMEBQAA 35 \000\000\001\000.\002.\004\005\000
+AQAcqAT1BQbmAwgAAAEEDA0ODwQAABHm/LkzKREyAQDo+w== 0 32 AQAcqAT1BQbmAwgAAAEEDA0ODwQAABHm/LkzKREyAQA= 110 \000.\168\004\245\005\006\230\003\008\000\000\001\004\012\013\014\015\004\000\000\017\230\252\1853\)\0172\001
+AgICAgICAgICAgICAgIAAAF/ 0 16 AgICAgICAgICAgICAgIAAA== 45 \002\002.\002\002.\002\002.\002\002.\002\000
+BBwcHAwcHBwcHBwc9KgMAQEBQBwcHBwcAcsRfX19fX76EwAAARw= 0 35 BBwcHAwcHBwcHBwc9KgMAQEBQBwcHBwcAcsRfX19fX76EwA= 113 \028\028\028\012.\028\028\028\028\028\028\244\168\012\001\001\001\@\028\028\028\028\028\001\203\017}}}}~\250\019
+BEAfPj4+HFBRUlMEVAAAASYmJiYmJiYmJiYmrSYVJiZnBGhpP2sAAABhYmMfZGUmJhgmJiYmJjImJiYmJiYmJiYmJiYmJiYmJiatJhUmJiZmZwRoaT9rACYmJiYmJq0mJiYmJmZnBGhpQAAAAQA= 0 108 BEAfPj4+HFBRUlMEVAAAASYmJiYmJiYmJiYmrSYVJiZnBGhpP2sAAABhYmMfZGUmJhgmJiYmJjImJiYmJiYmJiYmJiYmJiYmJiatJhUmJiZmZwRoaT9rACYmJiYmJq0mJiYmJmZnBGhpQAAA 172 \@\031>>.\028PQRS\004T\000\000\001&&&&&&&&&&&\173&\021&&g\004hi?k\000\000\000abc\031de&&\024&&&&&2&&&&&&&&&&&&.&&&&&\173&\021&&&fg\004hi?k\000&&&&&&\173&&&&&fg\004hi\@\000
+BOgD6wcINjY2NjY2MzY2NjY2NgD2ABA2UDY2NjY2NjY2NjY2NjY2JDY2NjYAAP//AAA2AAABNgAQNlg2NjaHNjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjYAgAAAKDY2zjY2Np42NjY2Njb/////6DY2QzY2NjYgAQA2 0 125 BOgD6wcINjY2NjY2MzY2NjY2NgD2ABA2UDY2NjY2NjY2NjY2NjY2JDY2NjYAAP//AAA2AAABNgAQNlg2NjaHNjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjYAgAAAKDY2zjY2Np42NjY2Njb/////6DY2QzY2NjYgAQA= 225 \232\003\235\007.66666636.6666\000\246\000\0166P66666666666666\$6666\000\000\255\255\000\0006\000\000\0016\000\0166X666\135666666.6666666666666666666666\000\128\000\000\(66\206666\158666666\255\255\255\255\23266C6666\032\001
+BCYmJiYmNjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2EhISEhISEhISEhISEhISEhISEhISEhISEhI2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Nhw2njY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2HTY2NjZINjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjaeNjY2NjY2NjY2NjY2NjY2NjY2NjY2NiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmJiYmNjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2Ng== 0 -1
+BOgAAAEDAwgINjY2NgAAAMAfNjY2NjYkFTY0NjY2NjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTY2FTYABDY2NjY2NjY2NjY0Nlg2NjY2NjY2NgAAATY2NgAAAADAHzY2NjY2JBU2NDY2NjY2NjY2NjY2NjY2AAAAAQQ2NjY2NjY2NjY2NjY2AAAAAQAbS2xLS0tLS0tLATa+H0YUNjY2NgAANjYkNjY0NjY2NjY2NjY2NjY2NjY2NjYkNjZ/dnZ2dnZ2dnZ2dnZ2dnZ2QTYBNh4EAED/NjY2NjQ2AAABAAABgDY2FjY2NtDQ0NDQ0NDQ0DPQ0NDQ0NDQ0NDQ0JDQABQUFBQ2NjY2NjY2WDY2NjZNNjZRABEBAAABNiU9PT09NgBAAAGANj0QAPv7+/v7+/v7+/sg+/v7+0JEAAABNjYyNjY= 0 -1
+BOgDAwgINjZWNhU2NgE2NjY2NjY2NjY2NjY2UjY2AzY2NjY2NjY2NjYlNkk2NjY2NjY2NjY2NiIiIiIiIkAiNugDNjY2NjY2NjY2NjZDNjY2NpiYmDY2NjYiICIiIiIiIiIiIiIiIiJJNjY2NjY2NjY2NjYiIiIiIiJAIjboAzYiIiIiIiIiIiIiIiI2NjY2NjY2NjZkNjY2NjY2NjZNNgAAATY2NjYCAAQANjY2NgAQAIAAADY= 0 180 BOgDAwgINjZWNhU2NgE2NjY2NjY2NjY2NjY2UjY2AzY2NjY2NjY2NjYlNkk2NjY2NjY2NjY2NiIiIiIiIkAiNugDNjY2NjY2NjY2NjZDNjY2NpiYmDY2NjYiICIiIiIiIiIiIiIiIiJJNjY2NjY2NjY2NjYiIiIiIiJAIjboAzYiIiIiIiIiIiIiIiI2NjY2NjY2NjZkNjY2NjY2NjZNNgAAATY2NjYCAAQANjY2NgAQAIAA 299 \232\003\003\008.66V6\02166\001.666666666666R66\0036666666666%6I66666666666\"\"\"\"\"\"\@\"6\232\003666.6666666C6666\152\152\1526666\"\032\"\"\"\"\"\"\"\"\"\"\"\"\"I66666666666\"\"\"\"\"\"\@\".\232\0036\"\"\"\"\"\"\"\"\"\"\"\"666666666d66666666M6\000\000\0016666\002\000\004\0006666\000\016\000\128
+BOgAATY2NjY2fwA2NjY2NjY2NjY2NjY2NjY2NjY2Njb/ADY2NjY2NjY2NjY5NjY2AAAAgFQ2NjY2NjY2NjY2UzY2NjY2tzY2NjY2NjY2NjY2NjY2NjY2NjY2NgAAATY2O0o2NjY2NjY2NjY2NjY2NjYAEDY2OTY2NgAAAIBUNjY2NjY2NjY2NjY2NjY2/zY2NlU2NjY2NjY2NjY2NjY2Nis2NgABAACA/zY2NjY2NjY2NjY2Np42NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2IjY2NjY2IDY2NjY2NjY2NjY2NjY2NjY2IjY2NjY2IDY2NjY2NjY2NjY2IzY2NjY2NjY2NjY2NjZINjY2NjYTDAwMDAwMDAwMDAYMDAwMDAwMDAwMDAwMDDY2NjY2JTY2NjY2NjY2NjY2Np42NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY= 0 -1
+BOgAAAABAAgINjY2NgAAAMAQNjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTY2FTY2NjY2NjQ2WDY2NjY2NjY2AAABNjY2AAD/8cAfNjY2NjYkFTYUNjY2NjY2NjY2NgAAAAEENjY2NjY2NjY2NjY2NgAAAAEAG0tsS0tLS0tLSwE2vh9GFAAAATYAADY2JDY2NDY2NjY2NjY2NnZ2dnZ2QTYBNh4EAED/NjY2NjQ2AAABAAABgDY2FjY2NtDQ0NDQ0NDQ0DPQ0NDQ0NDQ0EDQ0JDQABQUFBQ2NjY2NjY2WDY2NjZNNjZRABEBAAABNjY2RTY5NjY2JT09PT02ADY0NgAAAYA2PRAA+/v7+/v7+w== 0 -1
+BOgDCAg2NjY2AAAAwB82NjY2NiQVNjQ2NjY2NjY2NgAQNgAAATY2NjY2NjY2AAABAAE2NjZFNjYVNgAENjY2NjY2JzY2NjQ2WDY2NjY2NjY2AAABNjY2AAAAAMAfNjY2NjYkFTY0NjY2NjY2NjY2NjY2NjYAAAABBDY2NjY2NjY2NjY2NjYAAAABABtLbEtLS0tLS0sBAAABRhQ2gDY2AAA2NiQ2NjQ2NjY2NjY2NjY2NjY2NjY2NiQ2Nn92dnZ2dnZ2dnZ2dnZ2dnZBNgE2HgQAQP82NjY2NDYAAAEAAAGANhkWNjY20NDQ0NDQ0NDQM9DQ0NDQ0NDQ0NDQkNAAFBQUFDY2NjY2NjZYNjY2Nk02NlEAEQEAAAEjNjZFNjk2NjYlPT09VDYAQP82NjY2NDYAAAGANj0QAPv7+/v7+/v7+/sg+/v7+0JEAAABNgsLCwsLCwsLCwsLCwsLCws= 0 -1
+wMAAAcDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Nn7s7OzsEBQUDDY2NgAAATY2NjZYNjY2Nk02NlEAEQEANjYABf//BUU2OTY2NiU9PT09NgAAAfI//3Y2AAABNjY0NgAAAYA2PRAA+/v7+/v7+/v///8= 16 -1
+BOgAAGQB4ggISTY2NgAEQMAAAAAAATY2NjY6JDY2NgAQNjZKWDYgNjY2AAA2NjY2Njw2ATYYNkUAAAIQ//9/TExMTExMTExMTExMTExMTExMTExMTENMTBMTExMTEykTExMTEyYLAAEUFAAABjY2NjYAAAE2NhwAAAABAAABBDY2NtAAAzY2NgX//wU2NgD7SDYkNjk5OTk5OTk5OTk5OTk5OTk5OTk5PTY0NjY2NjY2NiQAAAE2Nn82cXZ2dnZ2dnZ20Coq0DPQ0P/QM9DQ//9//9AAAAHSu9DRkNAABgAA/xQUAAAGfzYkNjY0Nks2AAQeVTb/Nn////82TENMTBMTExMTEykTExMTEyYTACATNjYmfwLuAaMYAAABgDY2SlggIDY2NiQAAAE2Nn82cXZ2dnZ2dnZ20Co2Pk4ABQABADcyNjY= 0 -1
+BOgAAGQB4ggISTY2NgBEQMAAAADOzs7Ozs6wzs7O//9/TExMTExMTExMTExMTExMTExMTExMTENMTBMTEwAAARMTEy0T1NTU1NTU1NTU1NTU1NTU1NTU1NTU1NQcExMTJgsAARQeAAAGNzY2WAAAATY2HAAAAAEAAAEENhY20AADNjY2Bf//BTY2APtIACQ2OTk5OTk5OTk5OTk5OTk5OTk5OTk9NjQ2NjY2NjY2GwAAATY2fzZxdnZ2dnZ2dnbQKirQM9DQ/9Az0ND//3//0AAA5tK70NGQ0AAGAAD/FBQAEAB/NiQ2NjQ2SzY0NjY2NjY2NiRVNv82f+4BoxgAAAGANjZKVSAgNjY2JAAAATY1fzZxdnZ2dnZ2dnbQKjY+TeYFACEANzI2OTk9NjQ2NjY2NjY2GwAAATY2fzZxdnZ2dnZ2dnY= 0 -1
+AgACAgICAgACAgICAgLXAgICAgICAuEBAgICAgICAgICAgICAgICAgICAgICAgICAgICAAL0 0 52 AgACAgICAgACAgICAgLXAgICAgICAuEBAgICAgICAgICAgICAgICAgICAgICAgICAgICAA== 153 \000\002.\002\002.\000\002.\002\002.\002\215.\002\002.\002\002.\225\001.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002
+AgwAAhAiAgAAAhAiAQECAVcBAQEBAQEBAQEBAgFXAQEBAQEBAQEBAQEBAgFXAQEBAQA= 0 50 AgwAAhAiAgAAAhAiAQECAVcBAQEBAQEBAQEBAgFXAQEBAQEBAQEBAQEBAgFXAQEBAQA= 120 \012\000.\016\".\000\000.\016\".\001.\001W.\001.\001.\001.\001.\001.\001W.\001.\001.\001.\001.\001.\001.\001W.\001.\001
+AgAAAhAiAgAAAhAiAQECAVcBAQEBAQEBAQEBAgFXAQEBAQEBARQBAQEBAQIBAQEBAQEBAQIBSgEBAQEBAQEBAQEBAQEBAgFXAVcBAQEBAQEBAQEBAQEAAAEC 0 87 AgAAAhAiAgAAAhAiAQECAVcBAQEBAQEBAQEBAgFXAQEBAQEBARQBAQEBAQIBAQEBAQEBAQIBSgEBAQEBAQEBAQEBAQEBAgFXAVcBAQEBAQEBAQEBAQEA 208 \000\000.\016\".\000\000.\016\".\001.\001W.\001.\001.\001.\001.\001.\001W.\001.\001.\001.\020.\001.\001.\002.\001.\001.\001.\001.\001J.\001.\001.\001.\001.\001.\001.\001.\001W.W.\001.\001.\001.\001.\001.\001
+BAAEBQYHBAgJCg4PBBAREhMEFBUWFwQYGRobBBwdHh8EICEiIwQkJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/GEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChoi0EpKWmpwSoqaqrBKytrq8EsLGyswS0tba3BLi5ursEvL3BwgAA 8 225 CQoODwQQERITBBQVFhcEGBkaGwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PxhAQUJDBERFRkcESElKSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EYGFiYwRkZWZnBGhpamsEbG1ubwRwcXJzBHR1dncEeHl6ewR8fX5/BICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUlZaXBJiZmpsEnJ2enwSgoaItBKSlpqcEqKmqqwSsra6vBLCxsrMEtLW2twS4ubq7BLy9wcIA 520 \010\014\015\004\016\017\018\019\004.\021\022\023\004\024\025\026\027\004\028\029\030\031\004\032!\"#\004\$.&'\004\(\)*+\004,-\./\0040123\0044567\00489:\;\004<=>?\024\@ABC.DEFG.HIJK.LMNO.PQRS.TUVW.XYZ[.\\]^_.`abc.defg.hijk.lmno.pqrs.tuvw.xyz{.|}~\127.\128\129\130\131.\132\133\134\135.\136\137\138\139.\140\141\142\143.\144\145\146\147.\148\149\150\151.\152\153\154\155.\156\157\158\159.\160\161\162-.\164\165\166\167.\168\169\170\171.\172\173\174\175.\176\177\178\179.\180\181\182\183.\184\185\186\187.\188\189\193\194
+AgAAAhBiAgAAAhAiAQECEGICAQIBVwEBAhBiAgAAAhAiAVcBAgFXAQECAVcBAQEBAgFXAAAB 0 52 AgAAAhBiAgAAAhAiAQECEGICAQIBVwEBAhBiAgAAAhAiAVcBAgFXAQECAVcBAQEBAgFXAA== 116 \000\000.\016b.\000\000.\016\".\001.\016b.\001\002.W.\001.\016b.\000\000.\016\".W.\002.W.\001.\001W.\001.\001.\001W
+AgAfBCApIiMEJAgpKisELC0uLwQwQAIQIgIQQAIQIgIQIgYECAAAAQn/fwQMDRIPBBAIEhMEiRUWFwQYGRobBBQdHh8EICkiIwQkJOsnBAgpKisELC0uLwQwMTIzBDQ1NiIGBAgJ/38EDA0SDwQQERITBBQRFhcEGBkaGwQUHR4fBCApIiMELyTrJwQIKSorACw= 0 145 AgAfBCApIiMEJAgpKisELC0uLwQwQAIQIgIQQAIQIgIQIgYECAAAAQn/fwQMDRIPBBAIEhMEiRUWFwQYGRobBBQdHh8EICkiIwQkJOsnBAgpKisELC0uLwQwMTIzBDQ1NiIGBAgJ/38EDA0SDwQQERITBBQRFhcEGBkaGwQUHR4fBCApIiMELyTrJwQIKSorAA== 432 \000\031.\032\)\"#.\$\008\)*.\004,-\./\0040\@\002\016\"\002\016\@\002\016\"\002\016\"\006\004\008\000\000\001\009\255\127\004\012\013\018\015\004\016\008\018\019\004\137\021\022.\004\024\025\026\027\004\020\029\030\031\004\032\)\"#\004\$\$\235'\004\008\).+\004,-\./\0040123\004456\"\006\004\008\009\255\127\004\012\013\018\015\004\016\017\018\019\004\020\017\022\023\004\024\025\026\027.\020\029\030\031.\032\)\"#./\$\235'.\008\)*+
+AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgIQIgYECAn/fwQMDRIPBBAIEhMEARUWFwQYFB0eHyY1KSIZBCQkAAACDkACECICEEACECICECICEEACECICEB8EICkiIwQkJAAAAgBAAhAiAhBAAhAiAhAAAA== 0 202 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgIQIgYECAn/fwQMDRIPBBAIEhMEARUWFwQYFB0eHyY1KSIZBCQkAAACDkACECICEEACECICECICEEACECICEB8EICkiIwQkJAAAAgBAAhAiAhBAAhAiAhAAAA== 593 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\020\029\030\031&5\)\"\025\004\$\$\000\000\002\014\@\002\016\"\002.\@\002\016\"\002\016\"\002\016\@\002\016\"\002\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\".\016\@.\016\".\016\000
+AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CADsA 0 232 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CAA== 664 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\128\000\000\0005\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\004\008\002\002\002\002.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\020\029\030\031&5\)\"\025\004\$\$\000\000\002\000\@.\016\".\016\@.\016\".\016\".\016\@.\016\".\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\002\@\002\002.\254\002
+AgAAAhBiAgAAAhAiAQECAVcBAQIBVwIQYgIAAAIQYgIAAAIQIgEBAgFXAQECAVcCEGICAAACEAECAAACEGICAAACECIBAQIBVwEBAgFXAhBiAgAAAhBiAgAAAhAiAQECAVcBAQIBVwIQYgIAAAIQAQIBVwAAAQ== 0 116 AgAAAhBiAgAAAhAiAQECAVcBAQIBVwIQYgIAAAIQYgIAAAIQIgEBAgFXAQECAVcCEGICAAACEAECAAACEGICAAACECIBAQIBVwEBAgFXAhBiAgAAAhBiAgAAAhAiAQECAVcBAQIBVwIQYgIAAAIQAQIBVwA= 278 \000\000.\016b.\000\000.\016\".\001.\001W.\001.\001W.\016b.\000\000.\016b.\000\000.\016\".\001.\001W.\001.\001W.\016b.\000\000.\016\001.\000\000.\016b.\000\000.\016\".\001.\001W.\001.\001W.\016b.\000\000.\016b.\000\000.\016\".\001.\001W.\001.\001W.\016b.\000\000.\016\001.\001W
+AQAfBCApIiMEJCTrJ3//BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBf//KwQsLS4vBAAAAQAAAQ== 0 177 AQAfBCApIiMEJCTrJ3//BQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBf//KwQsLS4vBAAAAQAA 598 \000.\004\032\)\"#\004\$\$\235'\127\255\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\005\005\005.\005\005\255\255+.,-\./.\000\000\001\000
+AgAABgYGBgYcBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBAYGBgYGBgYGBgYGBgQGBgYGBgYGBgYGBgYGBgYGBkAGBgYQBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGZAYGBgYGBgYGsgYGBgYGBgYGBgYGBgYFBgYGBgYGBgYGBgYGGgYGBgYGBgYGBgYGBhMGBgYGBgAgBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgboIR4fBCApIiMELyTrJwQIKSorACw= 0 241 AgAABgYGBgYcBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBAYGBgYGBgYGBgYGBgQGBgYGBgYGBgYGBgYGBgYGBkAGBgYQBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGZAYGBgYGBgYGsgYGBgYGBgYGBgYGBgYFBgYGBgYGBgYGBgYGGgYGBgYGBgYGBgYGBhMGBgYGBgAgBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgboIR4fBCApIiMELyTrJwQIKSorAA== 821 \000\000.\006\006\006\006\028\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\004\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\@.\006\006\016\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006d\006\006\006.\006\006\006\006\178\006.\006\006\006\006\006\006.\006\006\006\006\005\006.\006\006\006\006\006\006.\006\006\006\026\006\006.\006\006\006\006\006\006.\006\006\019\006\006\006.\006\000\032\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\232!\030\031.\032\)\"#./\$\235'.\008\)*+
+AgAfBCApIiMEJCTrJwQIKSqrBCwtLi8EMEECAB8EBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcGBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcOBwcHBwczMzMaOzMzMzMzMzMzMzMzMwcHBwcHBwcHBwcHBwcHBwcHBw4HBwcHBwcHIQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHFwcHBwcHBwcHBwcHBwIQIgcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcHBwcHBwcHAhAiAhAiBi4vAAABBDAx+X8EDA0SDxAiAhAiBi4vBDAxKjMENDU2IgYECAn5fwQMDRIPBCozBAcHBwcHBwcHBwcHBwcHBwcQERITBBQREkAAARYXMzMzMzMzMzMRMzMzMzMzM/9/EwQUERYXBBgkGhsEFB0CECIGBAgJ+X8EDCcSDwQQERITBEAAFhbogAAAGwQUHQAQMwQ0MX/+//8ICQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHDgcHBwcHBwchBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcHBwcHBwcHBwcHfwAEJDQdAhAiAhBAAhAiAhAiEkAAARYXBBgZGhsEFB0gHwAzMzM= 0 -1
+AgQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAQQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBOUDBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBATlAwQEBAQEBAQEBAQEBAQAAA== 0 165 AgQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAAAAQQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBOUDBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBATlAwQEBAQEBAQEBAQEBAQA 554 \004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\000\000.\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\229\003\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\004.\004\004\004\229.\004\004\004.\004\004\004\004.\004\004\004\004
+AgICAgICAgICAgICAgICAg8CAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICIiMELyTrJwQIKSorACw= 2 119 AgICAgICAgICAgICAgIPAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiIjBC8k6ycECCkqKwA= 337 \002\002.\002\002.\002\002.\002\002.\002\015.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\"#./\$\235'.\008\)*+
+BAABAgMEAAAEAAQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BEBBQkMEREV/RwRISUtLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbR42BCAhIiMEJCUmJwQoKSorBCwtLi8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChogAA 0 246 BAABAgMEAAAEAAQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BEBBQkMEREV/RwRISUtLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbR42BCAhIiMEJCUmJwQoKSorBCwtLi8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChogAA 455 \000\001\002\003.\000\000\004\000.\008\009\010\011.\012\013\014\015.\016\017\018\019.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?.\@ABC.DE0G.HIKK.LMNO.PQRS.TUVW.XYZ[.\\]^_.89:\027.<=>?.\@ABC.DE\127G.HIKK.LMNO.PQRS.TUVW.XYZ[.\\]^_.`abc.defg.hijk.lm\0306.\032!\"#.\$%&'.\(\)*+.,-\./.\128\129\130\131.\132\133\134\135.\136\137\138\139.\140\141\142\143.\144\145\146\147.\148\149\150\151.\152\153\154\155.\156\157\158\159.\160\161\162\000
+BAABAgMEAAAEAAQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BEBBQkMEREUwRwRISUtLBExNTk8EUFFSUwRUVVZXBEJZWlsEXF1eXwRgNTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BJSVlpcEmJmamwScnaGiAAA= 0 241 BAABAgMEAAAEAAQICQoLBAwNDg8EEBESEwQcHR4fBCAhIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BEBBQkMEREUwRwRISUtLBExNTk8EUFFSUwRUVVZXBEJZWlsEXF1eXwRgNTY3BDg5OjsEPD0+PwRAQUJDBERFMEcESElLSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EODk6GwQ8PT4/BJSVlpcEmJmamwScnaGiAA== 370 \000\001\002\003.\000\000\004\000.\008\009\010\011.\012\013\014\015.\016\017\018\019.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>?.\@ABC.DE0G.HIKK.LMNO.PQRS.TUVW.XYZ[.\\]^_.89:\027.<=>?.\@ABC.DE0G.HIKK.LMNO.PQRS.TUVW.BYZ[.\\]^_.`567.89:\;.<=>?.\@ABC.DE0G.HIKK.LMNO.PQRS.TUVW.XYZ[.\\]^_.89:\027.<=>?.\148\149\150\151.\152\153\154\155.\156\157\161\162
+EMDAwMDANjYAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAA= 0 146 EMDAwMDANjYAAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAAA= 475 \192\192\192\192\19266\000\003\003\003\003\003\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\003.\003\003\000
+AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFQACAEACECICEEACECICECICEEACEBYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQWAAIAQAIQIgIQQAIQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CADs= 0 253 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFQACAEACECICEEACECICECICEEACEBYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQWAAIAQAIQIgIQQAIQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CAA== 715 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\000.\000\@.\016\".\016\@.\016\".\016\".\016\@.\016\022.\004\024:\026\027\004\011\128\000\000\0005\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\004\008\002\002\002\002.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\020\029\030\031&5\)\"\025\004\$\$\022\000\002\000\@.\016\".\016\@.\016\".\016\".\016\@.\016\".\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\002\@\002\002.\254\002
+AgAfBCApIiMEJCTrJwQIKSqrBCwtLi8EMEECAB8EBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwYHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBw4HBwcHBzMzMxo7MzMzMzMzMzMzMzMzBwcHBwcHBwcHBwcHBwcHBwcHDgcHBwcHBwchBwcHBwcHBwcHBwcF//8FBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcHBwcHBwcHAhAiBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBxcHBwcHBwMHBwcHBwcCECICECIGLi8AAAEEMDH5fwQMDRIPECICECIGLi8EMDEqMwQ0NTYiBgQICfl/BAwNEg8EKjMEBwcHBwcHB8XFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBgcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHDgcHBwcHMzMzGjszMzMzMzMzMzMzMzMHBwcHBwcHBwcHBwcHBwcHBwcOBwcHBwcHByEHBwcHBwcHBwcHBwX//wUHBwcHBwcHBwcHBwcHBwcHBxcHBwcHBwcHBwcHBwcCECIHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHFwcHBwcHAwcHBwcHBwIQIgIQIgYuLwAAAQQwMfl/BAwNEg8QIgIQIgYuLwQwMSozBDQ1NiIGBAgJ+X8EDA0SDwQqMwQHBwcHBwcHxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFBwcHBwcHBwcHEBESEwQUERJAAAEWFzMzMzMzMzMzETMzMzMzMzP/fxMEFBEWFwQYJBobBBQdAhAiBgQICfl/BAwnEg8EEBESEwRAABYW6IAAABsEFB0AEDMENDF//v//CAkHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBw4HBwcHBwcHIQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHFwcHBwcHBwcHBwfFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcUHBwcH 0 -1
+BB8BAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pl8EYGFgYwRkZWZnBGhpamsEbG1ubwRwcXJzBHR1VlcEWFlaWwRcXV5fBGBhYmMEZGVmZwRoaWprBGxtbm8EcHFycwR0dXZ3BHh5ensEfH1+fwSAgYKDBISFhocAAAGK 8 163 BgcECAkKCwQMDQ4PBBAREhMEFBUWFwQYGRobBBwdHh8EICEiIwQkJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT5fBGBhYGMEZGVmZwRoaWprBGxtbm8EcHFycwR0dVZXBFhZWlsEXF1eXwRgYWJjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHV2dwR4eXp7BHx9fn8EgIGCgwSEhYaHAA== 277 \007\004\008\009\010\011.\012\013\014\015.\016\017\018\019.\020\021\022\023.\024\025\026\027.\028\029\030\031.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<=>_.`a`c.defg.hijk.lmno.pqrs.tuVW.XYZ[.\\]^_.`abc.defg.hijk.lmno.pqrs.tuvw.xyz{.|}~\127.\128\129\130\131.\132\133\134\135
+AhI1AAABNTUVOj9ISEhISEhISEhISEhISAMDAwMDAwMTAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDCAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzYAPRAA+/v7+/v7+wMDAwMDAwMDAwMDAwAAAQMDAwMDAwMDAwMDAwADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMOAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzYAAAGA 68 -1
+AhIAAlBINQAAATU1FTo/SEhISEhIAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMFRTY5Nj42JT09PQEfNjY8NjYkFTY0NjYyNjY2NjYADDY2S0sAAAEBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAA/gABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2Mh02NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Ln7s7OzsAAAB7OzsFDY2NjYAAAAAATY2NDY2NkE2PjY2NjY2NjZO0NDQkNAAFBQUFDY2NTY2QzZYNjY2Nk02NlEAEQEANjY07Ozs7AAA 68 -1
+BCAhIiMEJCUmJwQoKSorBCwtLi8EMDEFGAEfASABIQEiASMBJAEnASgBKQEqASsBLAEtAS4BNwE4ATkBOiA7ATwBPQE+AT8NAQ4BDwEQAREBEgETARQBFwUYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBKQEqASsBLAEtAS4BJwEoAUgBKgErASwBLQEuATsBPAE9AT4BPwA= 0 161 BCAhIiMEJCUmJwQoKSorBCwtLi8EMDEFGAEfASABIQEiASMBJAEnASgBKQEqASsBLAEtAS4BNwE4ATkBOiA7ATwBPQE+AT8NAQ4BDwEQAREBEgETARQBFwUYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBKQEqASsBLAEtAS4BJwEoAUgBKgErASwBLQEuATsBPAE9AT4BPwA= 293 \032!\"#.\$%&'.\(\)*+.,-\./.01\005\024.\031.\032.!.\".#.\$.'.\(.\).*.+.,.-.\..7.8.9.:.\;\001<\001=\001>\001?\013\001\014\001\015\001\016\001\017\001\018\001\019\001\020\001\023\005\024\001\025\001\026.\027.\028.\029.\030.\031.\032.!.\".#.\$.%.&.'.\(.\).*.+.,.-.\..'.\(.H.*.+.,.-.\..\;.<.=.>.?
+AX8CAAAA 0 6 AX8CAAAA 14 \127.\000\000
+AgIAAAEC 0 4 AgIAAA== 9 \002\000
+AQAAZA== 0 3 AQAA 5 \000
+AQWhQEBAQAAAAQ== 1 7 BaFAQEBAAA== 13 \161\@\@\@\@
+JB4kJDUkJCQkJCQkJCQCNCQC/yQkJCQkJAAAASQkJAAkHgcAgAA= 0 38 JB4kJDUkJCQkJCQkJCQCNCQC/yQkJCQkJAAAASQkJAAkHgcAgAA= 95 \030\$\$5\$\$\$\$\$\$\$\$\$\0024\$\002\255\$\$\$\$\$\$\000\000\001\$\$\$\000\$\030\007\000\128
+AQABAwEiAQUBBgEHAQgBCQEKAQsBDAENAQ4BDwESARMBFAEVARYBFwEYARkBGgEbARwBHRABEQESARMBFAEVARYBFwEYARkBGgEbARwBHQEeAZ8BoAGhAaIBowGkAaUBpgGnAagBqQGqAasBrAGtAa4BrwGwAbEBsgGzAbQBtQG2AbcBuAG5AboBuwG8Ab0BvgG/AcABwQHCAcMBxAHFAcYBxwHIAckBygHLAcwBzQHOAc8B0AHRAdIB0wHUAdUB1gHXAdgB2QHaAdsB3AHdAd4B3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QH+Af8A 0 -1
+AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHcAd0V3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9AP4= 0 253 AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHcAd0V3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9AA== 660 \000.\001.\002.\003.\004.\005.\006.\007.\008.\009.\010.\011.\012.\013.\014.\015.\016.\017.\018.\019.\020.\021.\022.\023.\024.\025.\026.\027.\028.\029.\030.\159.\160.\161.\162.\163.\164.\165.\166.\167.\168.\169.\170.\171.\172.\173.\174.\175.\176.\177.\178.\179.\180.\181.\182.\183.\184.\185.\186.\187.\188.\189.\190.\191.\192.\193.\194.\195.\196.\197.\198.\199.\200.\201.\202.\203.\204.\205.\206.\207.\208.\209.\210.\211.\212.\213.\214.\215.\216.\217.\218.\219.\220.\221.\222\001\223\001\224\001\225\001\226\001\227\001\228\001\229\001\230\001\231\001\232.\233.\234.\235.\236.\237.\238.\239.\240.\241.\242.\243.\244.\245.\246.\247.\248.\249.\250.\251.\252.\253
+AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHUAd0B3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9AQEA/wA= 0 255 AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8BEAERARIBEwEUARUBFgEXARgBGQEaARsBHAEdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHUAd0B3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9AQEA 635 \000.\001.\002.\003.\004.\005.\006.\007.\008.\009.\010.\011.\012.\013.\014.\015.\016.\017.\018.\019.\020.\021.\022.\023.\024.\025.\026.\027.\028.\029.\030.\159.\160.\161.\162.\163.\164.\165.\166.\167.\168.\169.\170.\171.\172.\173.\174.\175.\176.\177.\178.\179.\180.\181.\182.\183.\184.\185.\186.\187.\188.\189.\190.\191.\192.\193.\194.\195.\196.\197.\198.\199.\200.\201.\202.\203.\204.\205.\206.\207.\208.\209.\210.\211.\212.\213.\214.\215.\216.\217.\218.\219.\212.\221.\222.\223.\224.\225.\226.\227.\228.\229.\230.\231.\232.\233.\234.\235.\236.\237.\238.\239.\240.\241.\242.\243.\244.\245.\246.\247.\248.\249.\250.\251.\252.\253.\001
+AgAADABAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsmCx0eHw01KSIZBCQkAAD/AEACEBgCEEACECICECIGBBAiAhBAAgIQIgYECAICAgICECICEEACECICECIGBAgJIgICAhAiAhBAAhAiAhAiBgQICf9/BAwNIA8EEAgSEwQBFRYXBBgBFRYXBBg6GhsECx0eEA01KSIZBCQ6NSkiGQQkJAAAAgBAAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQOAAIAQAIQIgIQQAIQIgIQIgYECAJAAgIC/gICOwA= 0 239 AgAADABAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsmCx0eHw01KSIZBCQkAAD/AEACEBgCEEACECICECIGBBAiAhBAAgIQIgYECAICAgICECICEEACECICECIGBAgJIgICAhAiAhBAAhAiAhAiBgQICf9/BAwNIA8EEAgSEwQBFRYXBBgBFRYXBBg6GhsECx0eEA01KSIZBCQ6NSkiGQQkJAAAAgBAAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQOAAIAQAIQIgIQQAIQIgIQIgYECAJAAgIC/gICOwA= 793 \000\000.\000\@\002\016\"\002\016\@\002\016\"\002.\"\006\004\008\009\255\127\004\012\013\018\015\004\016\008\018.\004\001\021\022\023\004\024:\026\027&\011\029\030\031\0135\)\".\004\$\$\000\000\255\000\@\002\016\024\002\016\@\002\016\"\002\016\"\006\004\016\"\002.\@\002\002\016\"\006\004\008\002\002\002\002\002\016\"\002.\@\002\016\"\002\016\"\006\004\008\009\"\002\002\002\016.\002\016\@\002\016\"\002\016\"\006\004\008\009\255\127\004\012\013\032\015\004\016\008\018\019\004\001\021\022\023\004\024\001\021.\023\004\024:\026\027\004\011\029\030\016\0135\)\"\025\004\$:5\)\".\004\$\$\000\000\002\000\@\002\016\"\002\016\@\002\016\"\002\016\"\002\016\@\002\016.\002\016\031\004\032\)\"#\004\$\$\014\000\002\000\@\002\016\"\002\016\@\002\016\"\002\016\"\006\004\008\002\@\002.\002\254.\002\;
+BOgDAwgINjY2NjY2NjY2PAA3NhM2NjY2NjY2Nkk2NjY2NjZAAAAANjk2NjY2NgAAAAFANjY2NjY2NjY2Ng82NjY8ADc2EzY2NjY2NjY2ADY2NjY2NjY2NjY28Da3NjY2NjbwNrc2NjY2NjY8ADc2EzY2NjY2NjY2NjY2NvA2tzY2NjYaAAE2NiM2NjY2NoE2NjY2NqVCPAAhNhM2NjY2NjY2Np42O/oYNhM2MjY2NjY2NgA2NjYAAAHwNrc2NjY2NjY2NjY2NjY2NjY2NjY2NjY5NjY2MTY2NjY2Njb/fzY2AAE2NjZ/PjZUnjY8ABg2NjY2Nj5SNhQ+AICAADYAAAE2 0 255 BOgDAwgINjY2NjY2NjY2PAA3NhM2NjY2NjY2Nkk2NjY2NjZAAAAANjk2NjY2NgAAAAFANjY2NjY2NjY2Ng82NjY8ADc2EzY2NjY2NjY2ADY2NjY2NjY2NjY28Da3NjY2NjbwNrc2NjY2NjY8ADc2EzY2NjY2NjY2NjY2NvA2tzY2NjYaAAE2NiM2NjY2NoE2NjY2NqVCPAAhNhM2NjY2NjY2Np42O/oYNhM2MjY2NjY2NgA2NjYAAAHwNrc2NjY2NjY2NjY2NjY2NjY2NjY2NjY5NjY2MTY2NjY2Njb/fzY2AAE2NjZ/PjZUnjY8ABg2NjY2Nj5SNhQ+AICAADYA 419 \232\003\003\008.66666666.<\00076\01966666666I666666\@\000\000\0006966666\000\000\000\001\@6666666666\015666<\00076.66666666\0006666666666.\2406\18366666\2406\183666666<\00076\019666666666666\2406\1836666\026\000\00166#66666\1296.666\165B<\000!6\01966666666\1586\;\250\0246\01962666666\000666\000\000\001\2406\18366666666666.666666666966616666666\255\12766\000\001666\127>6T\1586<\000\02466666>R6\020>\000\128\128\0006
+BOgDAwgINjY2NjY2NjY2NjYAAH//NgAAf/8XAjZ/UV5eIAAXFxcXFxcXFxcXFwI2fzZeAAABXiAAATYAAEVkNgAANjY2NjY2NgABQDY2NjYyNjYjQzb/fxN1Njb8NjaeQjwAIVkTNjY2Nfs2NjaeNFnkGDITNjY2Njb/HDf/fzY2NgAAAf///382VzY2NgA2NjY2NjY2NjY2NjY2AAAANjb/////NgAAAFw2f////zY2NjE2NjY2//82/382NjYAAAH///9/ZAABNjY2NjY2Np5eXl4RATYAAEVkNgAANjY2NjY2NgABQDY2NgABNg== 0 236 BOgDAwgINjY2NjY2NjY2NjYAAH//NgAAf/8XAjZ/UV5eIAAXFxcXFxcXFxcXFwI2fzZeAAABXiAAATYAAEVkNgAANjY2NjY2NgABQDY2NjYyNjYjQzb/fxN1Njb8NjaeQjwAIVkTNjY2Nfs2NjaeNFnkGDITNjY2Njb/HDf/fzY2NgAAAf///382VzY2NgA2NjY2NjY2NjY2NjY2AAAANjb/////NgAAAFw2f////zY2NjE2NjY2//82/382NjYAAAH///9/ZAABNjY2NjY2Np5eXl4RATYAAEVkNgAANjY2NjY2NgABQDY2NgA= 544 \232\003\003\008.66666666.66\000\000\127\2556\000\000\127\255\023\0026\127Q^^\032\000\023\023\023\023\023\023\023\023\023\023\023\0026\1276^\000\000\001^\032\000\0016\000\000Ed6\000\000666.666\000\001\@6666266#C6\255\127\019u66\25266\158B<\000!Y\0196665\251666\1584Y\228\0242\01966666\255\028.\255\127666\000\000\001\255\255\255\1276W666\0006666666666666\000\000\00066\255\255\255\2556\000\000\000\\6\127\255\255\25566616.66\255\2556\255\127666\000\000\001\255\255\255\127d\000\0016666666\158^^^\017\0016\000\000Ed6\000\0006666666\000\001\@666
+AykpKSkpKSkpKQQEKSkpKSkpKSkpKSkpKSkpDAAAASkMKSkuKSkpKSkpKSkpKSkpKCkG9QgJfyFAKSkpKSn/KSkpKSkAAAEpKQcEKSkpKSkpKSkpKSkpKSkpKQwpKSkpKSkpKSkpKSkpKQwpDCkpLikpKSkpKSkpKSkpKSkpKSkpKTsEQAIpKSkpKCkG9QgJCiFAKSkpKSn/KSkpKUUpKQcEKSkpKSkyKSkpKbckODlXOwRAAD4pBwQgKSkpKQAAEAA= 0 191 AykpKSkpKSkpKQQEKSkpKSkpKSkpKSkpKSkpDAAAASkMKSkuKSkpKSkpKSkpKSkpKCkG9QgJfyFAKSkpKSn/KSkpKSkAAAEpKQcEKSkpKSkpKSkpKSkpKSkpKQwpKSkpKSkpKSkpKSkpKQwpDCkpLikpKSkpKSkpKSkpKSkpKSkpKTsEQAIpKSkpKCkG9QgJCiFAKSkpKSn/KSkpKUUpKQcEKSkpKSkyKSkpKbckODlXOwRAAD4pBwQgKSkpKQA= 441 \)\)\).\)\)\)\)\)\004\004\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\012\000\000\001\)\012\)\)\.\)\)\)\)\)\)\)\)\)\).\)\(\)\006\245\008\009\127!\@\)\)\)\)\)\255\)\)\)\)\)\000\000\001\)\)\007\004\)\)\)\)\)\)\)\)\)\)\)\)\).\)\)\012\)\)\)\)\)\)\)\)\)\)\)\)\)\)\012\)\012\)\)\.\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\).\004\@\002\)\)\)\)\(\)\006\245\008\009\010!\@\)\)\)\)\)\255\)\)\)\)E\)\)\007\004\)\)\)\)\)2\)\)\)\)\183\$89W\;\004\@\000>\)\007\004\032\)\)\)\)
+BAABFwMBBRYXBBgZGhsEHB0eAAAAACIjBCQlJicEKCkqKwQsOy4vBCAhIiMEJCUmJwQoKSorBCw7Li8EBAQFFhcEGBkaGwQcHR4AAAAAIiMEJCUmJwQoKSorBCw7Li8EICEiIwQkJSYnBCgpKisELDsuLwQwMTIzBDQ1NjcEODk6OwQ8PT5BAA== 0 136 BAABFwMBBRYXBBgZGhsEHB0eAAAAACIjBCQlJicEKCkqKwQsOy4vBCAhIiMEJCUmJwQoKSorBCw7Li8EBAQFFhcEGBkaGwQcHR4AAAAAIiMEJCUmJwQoKSorBCw7Li8EICEiIwQkJSYnBCgpKisELDsuLwQwMTIzBDQ1NjcEODk6OwQ8PT5BAA== 309 \000\001\023\003.\005.\023\004\024\025\026\027\004\028\029\030\000\000\000\000\"#\004\$%&'\004.\)*+\004,\;\./\004\032!\"#\004\$%&'\004\(\)*+\004,\;\./\004\004\004\005\022\023\004\024\025\026\027\004.\029\030\000\000\000\000\"#\004\$%&'\004\(\)*+\004,\;\./\004\032!\"#.\$%&'.\(\)*+.,\;\./.0123.4567.89:\;.<=>A
+PwDuAQMEBQYHCAl8fHx8fHx8fHx8fHx8fHx8fHx8fHx8ICEiIyQlJjU2Nzg5Ojs8ICEiIyQlJjU2Nzg5Ojs8PT4/P0BBQkNEVHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8ICEiIyQlJjU2Nzg5Ojs8ICEiIyQlJjU2Nzg5Ojs8PT4/P0BBQkNEVCEiIyQlJjU2Nzg5Ojs8ICEiIyQlJiAhVVZXWFlaW1xdXl9gABBjZGVwcXJzdHV2QAAAfA== 0 188 PwDuAQMEBQYHCAl8fHx8fHx8fHx8fHx8fHx8fHx8fHx8ICEiIyQlJjU2Nzg5Ojs8ICEiIyQlJjU2Nzg5Ojs8PT4/P0BBQkNEVHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8fHx8ICEiIyQlJjU2Nzg5Ojs8ICEiIyQlJjU2Nzg5Ojs8PT4/P0BBQkNEVCEiIyQlJjU2Nzg5Ojs8ICEiIyQlJiAhVVZXWFlaW1xdXl9gABBjZGVwcXJzdHV2QAA= 261 \000\238\001\003\004\005\006\007\008\009||||||||||||||||||||||\032!\"#\$%&56789:\;<\032!\"#\$%&56789:\;<=.??\@ABCDT||||||||||||||||||||||||||\032!\"#\$%&56789:\;<\032!\"#\$%&56789:.<=>??\@ABCDT!\"#\$%&56789:\;<\032!\"#\$%&\032!UVWXYZ[\\]^_`\000\016cdepqrstuv\@
+PwDuKSkpKSkpKSkpRikpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpIikpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKRYpKSlyc3R1dkAAAAB7 0 149 PwDuKSkpKSkpKSkpRikpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpIikpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKRYpKSlyc3R1dkAAAAA= 297 \000\238\)\)\)\)\)\)\)\)\)F\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\".\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\).\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\)\022\)\)\)rstuv\@\000\000
+PwDuHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHQAAAR0dHR0dHR0dHR0dHR0+HR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHQAAAR0dHR0dHR0dHR0dHR0+HR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0UHR0dHR0dHR0dHR0BAwAAAQT9BQcICXx8fHx8fHx8AAABAHx8fHx8IAB8 0 245 PwDuHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHQAAAR0dHR0dHR0dHR0dHR0+HR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHQAAAR0dHR0dHR0dHR0dHR0+HR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0UHR0dHR0dHR0dHR0BAwAAAQT9BQcICXx8fHx8fHx8AAABAHx8fHx8IAA= 910 \000\238\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\000\000\001\029\029\029\029\029\029\029\029\029\029\029\029\029>\029\029\029\029\029\029\029\029\029\029.\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029.\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\000\000\001\029\029\029.\029\029\029\029\029\029\029\029\029>\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029.\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029.\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\020\029\029\029\029\029\029\029\029\029\029.\001\003\000\000\001\004\253\005\007\008\009||||||||\000\000\001\000|||||\032
+AQAAAAEgAAAA8Q8iAhAiAAABDkQICf9/BAAAAAEQCGNjL39jY2NjeHhvY2NjRwEVFjcEGDpaFwQLgAD//3//IgIAAAEQABCAAP//f/8iAhAAEBCb9BYfBENBh6AA+vr6FNkEAAQIZP8zAA== 100 6 BAhk/zMA 11 \008d\2553
+AgAAAgAAAAEiAg== 0 7 AgAAAgAAAA== 18 \000\000.\000\000
+AgAAAgBAAhAiAhBAAhAiAhAiBgQIDf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaIiMEBCQAAAIAQAIQAAIfQAIQIgIQIgYECAIChgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEAIECIiAEACECICECIGBAgCQAICAv4CAA== 0 250 AgAAAgBAAhAiAhBAAhAiAhAiBgQIDf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaIiMEBCQAAAIAQAIQAAIfQAIQIgIQIgYECAIChgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEAIECIiAEACECICECIGBAgCQAICAv4CAA== 754 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\013\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\128\000\000\0005\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\"#\004\004\$\000\000\002\000\@\002\016\000\002\031\@\002\016\".\016\".\004\008\002\002\134\002.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\020\029\030\031&5\)\"\025\004\$\$\016\"\002\016\".\016\@.\016\".\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\"\"\000\@\002\016\".\016\".\004\008\002\@\002\002.\254\002
+AQABAwEiAQcBCAEJAQoBCwEMAQ0BDgEPARIBEwEUARUBFgEXARgBGQEaARsBHAEdEAERARIBEwEUARUBFgEXAX0BGQEaARsBHAEdAR4BnwGgAaEBAAA= 0 86 AQABAwEiAQcBCAEJAQoBCwEMAQ0BDgEPARIBEwEUARUBFgEXARgBGQEaARsBHAEdEAERARIBEwEUARUBFgEXAX0BGQEaARsBHAEdAR4BnwGgAaEBAAA= 230 \000.\003.\".\007.\008.\009.\010.\011.\012.\013.\014.\015.\018.\019.\020.\021.\022.\023.\024.\025.\026.\027.\028.\029.\001\017\001\018\001\019\001\020\001\021\001\022\001\023\001}.\025.\026.\027.\028.\029.\030.\159.\160.\161.\000
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sNNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAARU2ClA2NtDO09DQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dgAA//92dnb/CwAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sNNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAARU2ClA2NtDO09DQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dgAA//92dnb/CwAA 633 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0136\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\001\0216\010P66\208\206\211\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\1276X+66666v\000\000\255\255vvv\255\011\000
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQsNjYAAdDQkAAAFBQUFDY2gH82WCs2NjY2NnZ2dnZ2dnZ2/wsAAAEAGw== 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQsNjYAAdDQkAAAFBQUFDY2gH82WCs2NjY2NnZ2dnZ2dnZ2/wsAAAEA 615 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020,66\000\001\208\208\144\000\000\020\020\020\02066\128\1276X+66666vvvvvvvv\255\011\000\000\001
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QAAAAAAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QAAAAAAA 625 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\000\001X+66666vvvvvv\@\000\000\000\000
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEAAAAAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEAAAAAA 623 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\000\001X+66666vvvvvv\@\@\000\000\000
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAAAAA 621 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\000\001X+66666vvvvvv\@\@\@\000\000
+BAABAgMEBAUGBwQICQoLBBINDg8EEBESEwQUFRYXBBgZGhsEHB0eNjY2AAA2NjY2Njw2ATYYNkUAAAIQ//9/TExMTExMTExMTExMTExMTExMTExMTENMTBMTExNqEykTlhMTEyYLAAEUFAAABjY2NjYAAAE2NhwAAAABAAABBDb/fwAAAzY2NgX//wU2NgD7SDYkNjk5OTk5OTk5OTk5OTk5OTk5OTk5PTY0pDY2NjY2NiQAAAE2Nn82cXZ2dnZ2dnZ20Coq0DPQ0P/QM9DQ//9//9AAAAHSu9DRkNAABgAA/xQUAAAGfzYkNjY0Nks2AAQeVTb/AAABNn////8= 0 -1
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAQAAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAAAFYKzY2NjY2dnZ2dnZ2QEBAQAAA 619 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\000\001X+66666vvvvvv\@\@\@\@\000
+ISEhISEhISEhISEhISEhISEhISEAA+gAISEhISEhISEhISEhISEhGiEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhISEhIYAhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhIRAhISEhISEhISEhISEhISEhISEhISEhISEhIYAhISEhISEpcnN0dXZAAA== 33 205 ISEhISEhGiEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhISEhIYAhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhIRAhISEhISEhISEhISEhISEhISEhISEhISEhIYAhISEhISEpcnN0dXZAAA== 218 !!!!!\026!!!!!!!!!!!C!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!!!!!!!~!!!!!!!!!!!.!\128!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!C!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!~!!!!!!!!!!\016!!!!!!.!!!!!!!!!!!!!!!!!!!\128!!!!!!\)rstuv\@
+AQABAQEAAAEBBBswGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbBhsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsVGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGyobGxsbGxsbGxsbGxsbGxsbGxsbzs7Ozs7Ozs7Ozs4bGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsmGxsbGhsbGxsbNRsbGxsbGxsbGw== 0 7 AQABAQEAAA== 15 \000.\001.\000
+AQABAQECAQMbGwAAARsbGxsbGzobGyAbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbG2kbGxsbFRsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGwMbGxsbGxsbGxsbGxsbGxsbGxsbGxsiGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxvfGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsmGxsbGxsbGxsbGxsbGxsbGxsbGw== 0 -1
+AQABAQECAQMBBAEFAQYBB+sIAQkBCgELxwwBDQEOAQEXJwEoAT42JT09PTYfNjY8NjYkFTY0NjYyAAABNjY2NjYADDY2S0sAAAEBFr4fRhQ2NjY2AAA2Nlg2iTw2HDY2NgAA/gABRDY2TjY2JBA2BLM2ojY2NjY2Bf8AG0Q2OTZNNiU9PT0BNlM2AAAAAQA2NDY2MjY2NjYyJjY2NjYAEDY2S0tLQAAAAUsBNr4fRhTDHzbAQDYufuzs7OwAAAHs7OwUNjY2NgAAAH//NjY0NjY2QTYAAAE+NjY2NjY2Nk7W0NCQ0AAUFBQUGjY1UzZDNlh/NjY2TTY2UQARAQA= 0 -1
+AQABAQECAQMBBAEFAAABBwEIAQkBCgELAQwBDQEOAQ8BECABIQEiASMBJAElASYBJwEoAAw2NktLAAABARa+/kYkFTY0NjYyNjY2NjYADDY2S0sAAAEBFr7+RhQ2NjY2AAA2Nlg0djw2NjY2NgAA/t4BNjY2PDY2MxU2AbM2ojY2NjY2Bf82NjYAEDY2S0tLQAAAAUt//74fRhTANjQ2NiQ2NjY2NgAQNjZLAAABfvPs7OwAAAHs7OwUNjY2NgAAAAABNjY0NjY2QTY+NjY2NjY2Nk7Q1NCQ0AAUFBQUNjY1NjZDNlg2NjY2TTY2UQARAQA= 0 13 AQABAQECAQMBBAEFAA== 30 \000.\001.\002.\003.\004.\005
+AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8CAgICAgICAoAAAgICAAABAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC 0 42 AQABAQECAQMBBAEFAQYBBwEIAQkBCgELAQwBDQEOAQ8CAgICAgICAoAA 107 \000.\001.\002.\003.\004.\005.\006.\007.\008.\009.\010.\011.\012.\013.\014.\015.\002\002.\002\002.\002\128
+BOgAAAEDAwgINjY2NgAAAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2NDZYBAX//wU2NjY0NgAANjYWNjY259DQ0NDQ0NDQNjY2ABtLbEtLS0tLS0sBNr4fRhQ2NjY2AAA2NiQ2NjQ2NjY2NjY2NjY2NjY2NjY2NiQ2Nn92dnZ2dnZ2doF2dnZ2dnZBNgE2HgQF//8FNjY2NDYAAAkAAAGANjYWNjY20NDQ0NDQ0NDQf9DQ0NDQ0NDQ0NDQkNAAFBQAAAEUFDY2NjY2NjZYNjY2Nk0hNlEAEQEAAAE2Ng== 0 -1
+BOgAAAEDAwgINjY2AAABNgAAAMAAAADAHzaAADY2JBU2NjYVNgAENjw2NjY2NjY2BAX//+fQ0NDQ0NDQ0DY4NjY2NjY2NjY2AAAAAQQ2NjY2NjY2NjY2NjY2AAAAAQAbS2xLS0tLS0tLATa+H0YUNjY2NgAANjYgNjY0NjY2NjY2NjY0NjY2NjY2NvoAAPp/dnZ2dnZ2dnZ2dnZ2dnaAQTYBNh4EBf//BTY20NDQ0NDQ0NB2dnZ2dnZ2dnZ2QTYB0NDQ0DPQ0NDQ0ND///+A0JDQABQUAAAaNk0hNlEAEQEAAAE2Ng== 0 -1
+BOgAAAEDAwgINjY2NeYAAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2NDZYBAH//wU2NjY0NgAAAQDoAYA2NhY2Njbn0NDQ0DY2NjY2Fk//AAAAAAABABtLbEtLS0tLSwAAAQQ2NjQ2NjY2Nic2NjY2NjY2NgABAAA2Nn92dnZ2dnZ2dnZ2dnZ2dnZBNgE2HgQF//8FNjY2NDYAADY2NjY2Fk//AAAAAAABABtLbEtLS0sJAAABgDY2FjY2NtDQ0NDQ0NDQ0DPQw9DQ0NDQ0NDQ0JDQABQUAAABFBQ2NjY2NjY2aTY2NjZNITZAABEBAAABNjY= 0 88 BOgAAAEDAwgINjY2NeYAAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2NDZYBAH//wU2NjY0NgAAAQDoAYA2NhY2Njbn0NDQ0DY2NjY2Fk//AAAAAAABAA== 217 \232\000\000\001.\003\008\008.665\230\000\000\192\0316\128\00066\$\021666\0216\000\004666666666646X\004\001\255\255\00566646\000\000\001\000\232\001\12866.666\231\208\208\208\20866666\022O\255\000\000\000\000\000\001
+BOgAAAEDAwgINjY2AAABAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2NDZYBAX//wU2NjY0NgAAAQAAAYA2NhY2Njbn0NDQ0NDQ0NA2NjY2NjY2NjY2NgAAAAEENjY2NjY2NjY2NjY2NgAAAAEAG0tsS0tLS0tLSwE2vh9GFDY2NjY2AAAAAQQ2NjY2NjY2NjY2NjY2NjY2NjY2JDY2f3Z2dnZ2dnZ2dnZ2dnZ2dkE2ATYeBAX//wU2NjY0NgAACQAAAYA2NhY2NjbQ0NDQ0NDQ0NAz0NDQ0NDQ0NDQ0NCQ0AAUFAAAARQUNjY2NjY2Nlg2NjY2TSE2UQARAQAAATY2 0 255 BOgAAAEDAwgINjY2AAABAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2NDZYBAX//wU2NjY0NgAAAQAAAYA2NhY2Njbn0NDQ0NDQ0NA2NjY2NjY2NjY2NgAAAAEENjY2NjY2NjY2NjY2NgAAAAEAG0tsS0tLS0tLSwE2vh9GFDY2NjY2AAAAAQQ2NjY2NjY2NjY2NjY2NjY2NjY2JDY2f3Z2dnZ2dnZ2dnZ2dnZ2dkE2ATYeBAX//wU2NjY0NgAACQAAAYA2NhY2NjbQ0NDQ0NDQ0NAz0NDQ0NDQ0NDQ0NCQ0AAUFAAAARQUNjY2NjY2Nlg2NjY2TSE2UQARAQAA 583 \232\000\000\001.\003\008\008.66\000\000\001\000\192\0316\128\00066\$\021666\0216\000\004666666666646X\004\005\255\255\00566646\000\000\001\000\000\001\12866.666\231\208\208\208\208\208\208\208\2086666666666.\000\000\000\001\0046666666666666\000\000\000\001\000\027KlKKKKKKK\0016\190\031F\02066666\000\000\000\001\00466666.6666666666666\$66\127vvvvvvvvvvvvvvvA6\0016\030\004\005\255\255\00566646\000\000\009\000\000\001\128.6\022666\208\208\208\208\208\208\208\208\2083\208\208\208\208\208\208\208\208\208\208\208\144\208\000\020\020\000\000\001\020\0206666666X6666M!6Q\000\017.\000
+BOgAAGQAAAA2AAAAwB82gAA2NoAANjYkFTY2NhU2IAQ2NjY2NjY2NjY2NDYAAAFYBAX//wA2NjY0Nu//NTY2AAAAAQQ2NjY2////fzY0NiMAG0tsS2RLS0tLSwEAAAE2vh9GFDY2NjYAAAE2dnZ2dnZ2dnZ2dgAAAUE+ATYeBAX//wU2NjY0NgAACQAAaWlpaWlpaWlpaWnzaWlpaWn/f2lpaWlpaWlYNjY2Nk0hHVEAEQEAAAE2Ng== 0 6 BOgAAGQA 14 \232\000\000d
+BOgAAAEDAwgINjY2NgAAAMAfNoAANjYkFTY2NhU2AAQ2NjY2NjY2NjY2PSIjBCQlJicEPykqFQQsLS4uBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEVGRwRISUpLBExNQ08EUFFSWwRUVVZXBFhZWlsEXE1eXwRgYWJjBGRlZmcEaGlqawRsbR4fBCAhIiMEJCUmJwQoKSorBCwtJy8EgIGCgwT6hYaHBIiJiosENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwQ= 0 -1
+AAABBOgAAEFAA+gYAAA2TgD/8sAQAAAAATAkAAABAAE2AwAAdj52ATT/YTk5GVQ5Ad42QCL7/zA= 0 1 AA== 2 .
+wMAAAcDgwMDANjY2NgAAGsAfNjY8NjYkFTo0NjYyNjY2NjYAEDY2S0s2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2NiU9PT0BHzY2FDY2NjYAADY2WDZ2PDY2NjY2AAD+AAE2NjY8NjYkFTYEszaiNjY2NjYF//8FRTY5Nj42JT09PQEAAAABADY0NjYyNjY2NjYAEDY2S0tLQABAAUsBNr4fRhQ2////fyQVNgTAHzYufuwp7OwAAAHs7OwUNjY2NgAAAAAAAAE0NjYAAAE+NjY2NjY2Nk7Q0NCQ0AsUFBQUNjY1NjZDNlg2NjY2TTY2UQD//wVFNjk2PjYlPT09AR82NhQ2NjY2AAA2Nlg2djw2NjY2NgAA/gABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NjY2Bf//BUU2OTY+NiU9PT0BAAAAAQA2gAAAADY2NjY2ABA2NktLS0AAAAFLATa+H0YUNv///38kFTYEwB82Ln7s7OzsAAAB7OzsFDY2NhEBAA== 16 2 NjY2NgAQNjZLSzY2WDZ2PDY2NjY2AAABAAE2NjY8NjYkFTYEszaiNjY2JT09PQEfNjYUNjY2NgA= 98 666\000\01666KK66X6v<66666\000\000\001\000\001666<66\$\0216\004\1796\162666%===\001\03166\0206666
+wMgAAcDgwMDANjY2NgAAGsAfNmY8NjY2QzZYNjY2NjY2NjYAAAE2S0s2NgFK4za+H0YUwB82Ln7s7OzsAAAB7BDsFDY2NjYAAAAAAf//NDZKNjZBNj42NjY2gDY2TtDQQTY+NjY2NjY2Nk7Q4tCQ0AAUFP////81NjZDNlg2Nhc2TTY2UQARAQA= 39 -1
+wMAAAcDgwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0s2OFg2djw2NjY2NgAAAQABNjY2PDY2QDY1NjZDNgAAAVhAADY2TTY2UQARAQA= 16 -1
+wMAAAcDgwMDANjY2NgAAGsAfNjY8NjY2cjY2NjY2ABA2NktLS0AAAAFLATYAAAEUwB82Ln7s7OzsAAAB7OzsFDY2NjYAAAAAATY2NDY2NkE2PjY2NjY2NjZOHzY2PDY2JBU2NDY2MjY2NjY2AAw2NktLAAABARa+H0YUNjY2NgAANjZYNnY8NjY2NjYAAP4AATY2Njw2NiQVNgSzNjY2cjY2NjY2ABA2NktLS0AAAAFLATYAAAEUwB82Ln7s7OzsAAAB7OzsFDY2NjYAAAAAATY2NDY2NkE2PjY2NjY2NjZO0NDQkNAAFBQUFDY2NTY2QzZYNjY2Nk02NlEAEQEA 16 -1
+wKoAAcDgwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0s2Nlg2djw2NjY2NkAAAQABNjY2PAAAARU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BHzY2PDY2JBU2AAABMjY2NjY2AAw2NktLAAABARa+AAABNjY2NgAANjZYNnY8NjY2NjYAAP4AATY2Njw2NiQVJgSzNqI2NjY2NgX//wVFNjk2PjYlPT09ATY2NgAAAAEANjQ2NjI2NjY2NgAQNjZLgABAAAABSwE2vh9GFMAfNi5+7Ozs7AAAAezs7BQ2NjY2AAAAAAE2NjQ2NjZBNj42NjY2NjY2TtDQ0JDQABQUFBQ2NjU2NkM2WDY2NjZNQDZRABEBAA== 16 2 NjY2NgAQNjZLSzY2WDZ2PDY2NjY2QAABAAE2NjY8AAABFTYEszaiNjY2NjYF//8FRTY5Nj42JT09PQEfNjY8NjYkFTYAAAEyNjY2NjYADDY2S0sAAAEBFr4AAAE2NjY2AAA2Nlg2djw2NjY2NgAA/gABNjY2PDY2JBUmBLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NkuAAEAAAAFLATa+H0YUwB82Ln7s7OzsAAAB7OzsFDY2NjYAAAAAATY2NDY2NkE2PjY2NjY2NjZO0NDQkNAAFBQUFDY2NTY2QzZYNjY2Nk1ANlEAEQEA 548 666\000\01666KK66X6v<66666\@\000\001\000\001666<\000\000\001\0216\004\1796\16266666\005\255\255\005E696>6%.==\001\03166<66\$\0216\000\000\001266666\000\01266KK\000\000\001\001\022\190\000\000\0016666\000\00066X6v<66666\000\000\254\000\001666.66\$\021&\004\1796\16266666\005\255\255\005E696>6%===\001666\000\000\000\001\0006466266666\000\01666K\128\000\@\000\000\001K\001.\190\031F\020\192\0316\.~\236\236\236\236\000\000\001\236\236\236\0206666\000\000\000\000\001664666A6>6666666N\208\208\208\144\208\000\020\020.\02066566C6X6666M\@6Q\000\017\001
+P8DBwsPExcbHyMnKy8zNzs/Q0dLT1NXe3+AbGxsbGxsbGxsbGxsbGxsbGxsbGyMbGxsbGxsbGxsbGxsbGxsbGxsbGxsbFRsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGwMbGxsbGxsbGxsbGxsbGxvW19jZ2tvc3d7f4BsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsVGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbAxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGyYbGxsbGxsbGxsbGxsbGxsbGxsb 0 -1
+wMAAAcDAf////zY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjZLS0tLSwEWAZ8BoAGhAaIBowGkAaUBpgGxAagBqQGqAasBrAGtAa4BrwGwAbEBsgGzAbQBtQG2AbcBuAG5AboBuwG8Ab0BvgG/AcABwQHCAcMBxAHFAcYBxwHIAckBygHLAcwBzQHOAc8B0AHRAdIB0wHUAdUB1gHXAdgB2QHaAdsB3AHdFd4B3wHgAeEB4gHjAeQB5QHmAecB6AHpAeoB6wHsAe0B7gHvAfAB8QHyAfMB9AH1AfYB9wH4AfkB+gH7AfwB/QD+ 16 2 NjY2NktLS0tLARYBnwGgAaEBogGjAaQBpQGmAbEBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugG7AbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHcAd0V3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9AA== 588 666KKKKK\001\022\001\159\001\160\001\161\001\162\001\163\001\164\001\165\001\166\001\177\001\168\001\169\001\170\001\171\001\172\001\173\001\174\001\175\001\176\001\177\001\178\001\179\001\180.\181.\182.\183.\184.\185.\186.\187.\188.\189.\190.\191.\192.\193.\194.\195.\196.\197.\198.\199.\200.\201.\202.\203.\204.\205.\206.\207.\208.\209.\210.\211.\212.\213.\214.\215.\216.\217.\218.\219.\220.\221.\222\001\223\001\224\001\225\001\226\001\227\001\228\001\229\001\230\001\231\001\232.\233.\234.\235.\236.\237.\238.\239.\240.\241.\242.\243.\244.\245.\246.\247.\248.\249.\250.\251.\252.\253
+BA8EAgAsAID/////MjMEMjU2NwMEFgUEBf//9BEAHP/NBAb/f0AA6iAEICEiIwQkJTon+vr6+vr6BPYGACQICQoQAgAAAQABEgMEBAUEBQYHBEAA6iDkHyEiIwQkJSYn+vr6+vr6+vr6+vr0BBIdLC0u9gQwMSgMBwRkAAAgBEQAIAQgISI= 0 -1
+BGQEAgAsAP//8/QQHALNBAb/9P+AFgAEBf//9AAQHALNBAb/9POAIAAiI/r6BgX2BgAkAAABCGQKEAIgBDYl+vr6fwAAAAAEIAAiI/r6BgX2BgAkAAABCGQKEAIgBDYlJif5+/rZ+voE9gYAJAhkChACIAO9AAESGQQEBQQFAwb/fwB/AAAELS72p6enp6enp6enp6enp6cgBJKSkqlxkiAhIg== 0 -1
+BA8EAgAsAID/////LzMEMjU2NwMEFgUEBf//9BEAHALNBAb/f0AA6iAEICEiIwQkJSYn+vr6+gYHBEAA6iAEICEiIwQkJSYn+vr6+vr6+vr6fwABAAAdLC0u9gQwMSgMBwRkAAAgBBwAIAQgISI= 0 -1
+BA8EAgAsAID/////MjMEMjU2NwMEJAUAAAH/9BD+HALNBAb/f0AA6iAEICEiIwQkJSYn+voX+vr6BPYGIwQkJSYnABDa+vr6+vr6AAAAgBIdLC0u9gQwMSgMBwRkAAAgBEQAIAQgISI= 0 99 BA8EAgAsAID/////MjMEMjU2NwMEJAUAAAH/9BD+HALNBAb/f0AA6iAEICEiIwQkJSYn+voX+vr6BPYGIwQkJSYnABDa+vr6+vr6AAAAgBIdLC0u9gQwMSgMBwRkAAAgBEQA 306 \015\004\002\000.\000\128\255\255\255\25523\0042567\003\004\$\005\000\000\001\255\244\016\254\028\002\205\004\006\255\127\@\000\234\032\004\032!\"#\004\$%&.\250\250\023\250\250\250\004\246\006#\004\$%&'\000\016\218\250\250\250\250\250\250\000\000\000\128\018\029,-\.\246\00401\(\012.\004d\000\000\032\004D
+73//AO4D9YDuBPOA/0QgIAogChk= 8 -1
+BA8EAgAsAARAAOogBAIhIiMEJCUmJ/r6+vr6+vr68QT2AQAAAQkKEAIgA70AARIDBAQFBOjMBwRAAOogBAIhIiMEJCUmJ/r6+gAAAfr6+vr6+vr69AT5HSw9LvYEMC8AAAAAAQAAIAZEACAEICEi 0 -1
+BAABAgMEBAUGBwQICQocHR4fBCAhIiMEJCUsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaMgRcXV5fBGBhYmMEZGVmZwRoaWprBGxtHh8EICEiIwQkJSYnBCgpKgAAAS0uLwSAgYKDBISFhocEiImKiwSMi46PBJCRkpMElJWWlwSYmZqbBJydnp8EoKGiggSkpaanBKipqqsErK2urwSwsbI= 0 126 BAABAgMEBAUGBwQICQocHR4fBCAhIiMEJCUsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaMgRcXV5fBGBhYmMEZGVmZwRoaWprBGxtHh8EICEiIwQkJSYnBCgpKgAA 207 \000\001\002\003.\004\005\006\007.\008\009\010\028.\030\031\004\032!\"#\004\$%,-\./\0040123\0044567\00489:\;.<=>?.\@ABC.DEFG.HIJK.LMNO.PQRS.TUVW.XYZ2.\\]^_.`abc.defg.hijk.lm\030\031.\032!\"#.\$%&'.\(\)*\000
+BAABAgL8BAUGBwQICQoAAAEfBCAhIjMEJCUsLS4vBDAxMjMENDU2NwQ4OTo7BDw9BFRVVmYEWFlaWwRcAAACBGBhYmMMZGVmZwRoAAABaWprBGxtHh8EICEiIwQkJSYnBCgpKisELC0uLwSYs5qbBISdhocEiImKiwSMjY6PBJCRkpMElJWWlwSYs5qbBJydnp8EoKGiowSkpab//6jLqqsErK2urwSwsbI= 0 -1
+Ig== 0 -1
+AAABAAAEBAUGBwQICQocHR4fBCAhIiMEJCUsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaWwRcXV5fBGBhYmMEZGVmZwRoaWprBGxtHh8EICEiIwQkJSYnBCgpKisELC0uLwSAgYKDBISFhocEiImBiwSMjY6PBJCRkpMElJWWlwSYmZqbBKOkpaanqKmqq6ytrq+wsbKztLW2t7i5uru8WL0= 0 1 AA== 2 .
+BAAcAgMEBAUGBwQICQocHR4fBCAhIiMEJDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 -1
+ACA= 2 -1
+BOgCFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFQUVFRUVFRUVFRUVFRUVFRUVFRQVFRUVFRUVFQAAARUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRU5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5OTk5FRUVFRUVFRUVFRU3FRUDAwMDAwMDAAABCfoD6AID8AID 0 -1
+BOgCFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFfQVFRUVFRQV+RUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRU2FRUVFRUVBQUFBQUFBRUVFS0VFX//FRUVFRUVFRUVFQX//wUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRX6FBUVFRUVFRUVFRUAAAEVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFREVFRUVBQUVFRUVFRUVFRUVFRUVFRUVFRUVFfoUFRUVFRUVFRUVFQAAARUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVFRUVERUVFRUFBQUFBQUFBQUFBQUFBQUFBQUFBQQsLS4vBAAAAQAAAQ== 0 -1
+BOgCFRUVFRUVFRUVFQAAAS8AAAEEMDH5fwQMDRIPECICECIGLi8EMDEqMwQ0NTYiBgQICfl+/AwNEg8EKjMEBwcHBwcHB8XFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFhcXFxcXFxcXFxcXFxcXFxcXFxcXFxQAAAAHFyMXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFwMXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxQcHBwcHBykHBwcHBwcHBwcHBwcHBwcIBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBgcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHDgcHBwcHMzMzGjszMzMzMzMzMzMzMzMHBwcHBwcHBwcHBwcHBxYHBwcOBwcHBwcHByEHBwcHBwcHBwcHBwX//wUHBwcHBwcHBwcHBwcHBwcHBxcHBwcHBwcHBwcHBwcCECIHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHFwcHBwcHAwcHBwcHBwIQIgIQIgYuLwAAAQQwMfl/BAwNEg8QIgIQIgYuLwQwMQMzBDQ1NiIGBAgJ+X8EDA0SDwQqMwQHBwcHBwcHxcXlxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcU3CCkqqwQsLS4vBDBBAgAAAQAfBAcHBwcHBwcHB+wGBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBweHBwcHBwcHBwcHBwcHBwcHBwcHcnJycnJycnJycnJycnJycnJycnJycldycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycgcHBwczMzMaOzMzMzMzMzMzMzMzMwcHBwcHBxYHBwcHBwcHBwcHBw4HBwcHBwcHIQcHBwcHBwcHBwcHBf//BQcHBwcHBwcHBwcHBwcHBwcHFwcHBwcHAAAAZAcHBwIQIgcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcDBwcHBwcHAhAiAhAiBi4vAAABBDAx+X8EDA0SDxAiAhAiBi4vBDAxKjMENDU2IgYECAn5fvwMDRIPBCozBAcHBwcHBwfFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcUAAAABxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFBwcHBwcHKQcHBwcHBwcHBwcHBwcHBwgHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcGBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcOBwcHBwczMzMaOzMzMzMzMzMzMzMzMwcHBwcHBwcHBwcHBwcHFgcHBw4HBwcHBwcHIQcHBwcHBwcHBwcHBf//BQcHBwcHBwcHBwcBBwcHIgcHFwcHBwcHBwcHBwcHBwIQIgcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHDQcXBwcHBwcDBwcHBwcHAhAiAhAiBi4vAAABBDAx+X8EDA0SDxAiAhAiBi4vBDAxAzMENDU2IgYECAn5fwQMDRIPBCozBAcHBwcHBwfFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxebFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXF//9//8XFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcUHBwcHBwcHBwcHB3JycnJycnJychYXMzMzMzMzMzMRMzMzMzMzM/9/EwQUERYXBBgkGhsEFB0CECIGBAgJ+X8EDCcSDwQQERITBEAAFhbogAAAGwQUHQAaMwQ0MX/+//8ICQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHDgcHBwcHBwchBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBygHBwcHIAAHBwcHBwcHBwcHBwcXBwcHBwcHBwcHB8XFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcW3xcXFxcXFxcXFxcXFxcXFxcXFxcXFxQcHBwc= 0 -1
+BBwcHAwcHBwcHBw+9KgLAQEBQBwcHBwcwsI2Nv////82NjY2NjY2AAAAAQAjZyw2AAQ2NjY2Ngk2NjY2NIBYNgAQAcw2NjY0/zZLaUtLATa+dnZ2dh9GNjY2NjY2NjYAAAABABtn6gABbEsxS0tpS0sBNr52dnZ2H0Y1ADY2NgAANjYkNjY0LRAAATY2NjYZNjZPNjY2RzYkNk/pEIAAdnZ2dnZ2dv8LAED/NjY2NgAAAQABAAABAAEAgAAAATY2CjYJNjY2NjSAWDYAEAHMNjY2NP82S2lLSwE2vnZ2dnYfRjY2NjY2NjY2AAAAAQAbZ+oAAWxLMUtLaUtLATa+dnZ2dh9GNQA2NjYAADY2JDY2NC0QAAE2NjY2GTY2TzY2Nkc2JDZP6RCAAHZ2dnZ2dnY2AAHQ0JAABf//BRQ/NoABAAABWCs2NjY2//92VHaRdkBAQAAAAAAAAQAjZyw2AAQ2NjY2Ngk2NjYyNIAAAQAb 0 -1
+AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfAhBAAgQgKRcjBAQkAAACAEACEAACEEACECICECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGBQdHh8mNSkiGQQkJAAAAg5AAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQAAAIAQAIQIgIQQAIQIgIQAAA= 0 206 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfAhBAAgQgKRcjBAQkAAACAEACEAACEEACECICECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGBQdHh8mNSkiGQQkJAAAAg5AAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQAAAIAQAIQIgIQQAIQIgIQAAA= 626 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\016\@.\004\032.\023#\004\004\$\000\000\002\000\@\002\016\000\002\016\@\002\016\"\002\016\"\002\016\"\006\004\008\009\255\127\004\012\013\018\015\004\016\008\018\019.\001\021\022\023.\024\020\029\030.&5\)\"\025\004\$\$\000\000\002\014\@\002\016\"\002\016\@\002\016\"\002\016\"\002\016\@\002\016\".\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\".\016\@.\016\".\016\000
+AgAAAuZAAhAiAhBAAhAiAhAiBgQICf9/BAwNAAABEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBAAABQAAAEACECQB8kACECIC8iEGBBAiAhBAAhAiAhAff////yMEByQAAAIAAAABQO0PAAIQQAIQDwIQImAQIh4ECAn/AR8mNSkiGQQkJAAAgiJAZBAiAhAAAAEigBACEAIQIgAAAgBAAhAAAA== 0 64 AgAAAuZAAhAiAhBAAhAiAhAiBgQICf9/BAwNAAABEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBAAABQAAAA== 202 \000\000.\230\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\000\000\001\018\015\004\016\008\018\019\004.\021.\023\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\000\000\005\000\000
+BICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUBJiZmpsEnJ2enwSgoaKjBKSlpqcEqKmqq1RVVldYWZWWlwSYmZqbBJydnp8EoKGiowSkpaanBKipqqtUVVZXWFlaW1xdXl9gYWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXp7fH0Afg== 0 -1
+EgEABIAQABABAIOKAAAB6mtsAaurqwHqa2xtbauri6ChoqMAAAABPVxNP0ABAAEsBf//BQABT20AHgFo6OpzbG2rq6uJb3BxZBZ+ 0 -1
+AQAAAIMFhIWGhweaiYqLBIyNjo7ykKcAgP//hpaDBISFhocEATY2NjY0hiABADY2NiMAgAAAAAABNjY2NjY2NjZ+AAAAAAAhHxtn6gABbEt2AAAAQBgzNjYAADY2JDY2NP9/ATY2NjY2FTYVTzYAQDY2JACAAAyAGQB2dnZ0dn//Yv8AAAE2NjY0Nt3d3d3d3d0AAAHd3cfd3d3d3d3diosEpI0AIAEAAQB4AAABNjYK3d3d3d3d3d3d3d3d3f3H3cft3d3d3d3diisEpI2PBJCnAID//4aWgwSEhYaHBIiOjwAAAbMgABYWFhYWFgAAARY2fXZ2dgAAAQAb 0 3 AQAA 5 \000
+BICBgoMEhIWGhwSHiYqLBIyNjo8EkJGSkwQAAAGXBJiZmpsEnJ02AAAAAAsBZxU2AAQ2GjYAAQltbW1tbW1tbW1tbW1tbTY2NjY0gFg2ABABNjY2l5sEnJ02AAAAAAABZxU2AAQ2GjY2NgSYmZqbBJydNgAAAAAAAWcVNgA2NP82NjY2AAAA3gM/NjY2NjY2NjY2NjY2AAAAAQAbZ+oACmxLS0tLaUtLATa+dnaSdh9GFAA2AAABNjT/fzY2NjY2NhVDNk82ABAAACQ2Nv//gAB2dmX///9//wsAAAEiQP82NjYAAAFnFTY0NgHQ0NAz0NDi0NC9EAAA+y0UFAB2AAHQ0JAAABQUZAAAAIABAAABWCs2NjY2NnZ2dnZ2dkABAAAAAAEAGw== 0 41 BICBgoMEhIWGhwSHiYqLBIyNjo8EkJGSkwQAAAGXBJiZmpsEnJ02AAA= 133 \128\129\130\131.\132\133\134\135.\135\137\138\139.\140\141\142\143.\144\145\146\147.\000\000\001\151.\152\153\154\155.\156\1576\000
+BICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUlZaXBJiZmpsEnJ02AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADe/3//NjY2NjY2NjYVNjY2NjYAAAABABtqampqbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2BAAVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/LDY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY3gAEAAAFYKzY2NjY2dnZ2dnZ2QAAAAAAAAQAb 237 1 AA== 2 .
+BGQDAwgINjZWNhU2NgE2NjY2NjY2NjYlNkk2NjY2NjY2NjY2NiIiIiIiLyIiIi8EMBQyMwQ0NTY3BDg5LTsEPD0+PwA= 0 -1
+AAEAAQ== 0 1 AA== 2 .
+BOgDAwgINjZWNhU2NgE2NjY2NjY2NjY2NjY2UjY2AzY2NjY2NjY2NjYlNkk2NjY2NjY2NjY2NiIiIjYAAEVkNgAANjY2NjY2NgABQDY2NjYyNjYjQzb/fxN1Njb8NjaeQjwAIVkTNjY2Nfs2NjaeNFnkGDITNjY2NjbvHDf/fzY2NgAAAf///382VzY2NgA2NjY2NjY2NjY2NjY2BQAANjb/////NgAAAFw2f////zY2NjE2NjY2//82/382NjYAAAH///9/ZAABNjY2NjY2Np5eXl4RATYAAEVkNgAANjY2NjY2NgABQDY2NgABNg== 0 236 BOgDAwgINjZWNhU2NgE2NjY2NjY2NjY2NjY2UjY2AzY2NjY2NjY2NjYlNkk2NjY2NjY2NjY2NiIiIjYAAEVkNgAANjY2NjY2NgABQDY2NjYyNjYjQzb/fxN1Njb8NjaeQjwAIVkTNjY2Nfs2NjaeNFnkGDITNjY2NjbvHDf/fzY2NgAAAf///382VzY2NgA2NjY2NjY2NjY2NjY2BQAANjb/////NgAAAFw2f////zY2NjE2NjY2//82/382NjYAAAH///9/ZAABNjY2NjY2Np5eXl4RATYAAEVkNgAANjY2NjY2NgABQDY2NgA= 460 \232\003\003\008.66V6\02166\001.666666666666R66\0036666666666%6I66666666666\"\"\"6\000\000Ed6\000\000666.666\000\001\@6666266#C6\255\127\019u66\25266\158B<\000!Y\0196665\251666\1584Y\228\0242\01966666\239\028.\255\127666\000\000\001\255\255\255\1276W666\0006666666666666\005\000\00066\255\255\255\2556\000\000\000\\6\127\255\255\25566616.66\255\2556\255\127666\000\000\001\255\255\255\127d\000\0016666666\158^^^\017\0016\000\000Ed6\000\0006666666\000\001\@666
+ATY= 0 -1
+BOgDAwgINjZWAAABNgE2NjY2NjY2NjY2NjY2UjY2AzY2NjY2NjY2NjYlNkk2NjY2Ni02PTY2NiIiIjYAAEVkNgAANjY2NjY2NgABQDY2NjYyNjYjQzb/fxN1Njb8NjaeQgAAATwAIVkTNjY2Nfs2NjaeNFnkGDITNjY2Izb/HDf/f1Q2NgAAAQAAF4AA/382VzY2NgA2NjY2NjY2NjY2NjY2AAAANmT/////FgAAAQAANjb/////NgAAAFw2f////zY2NjE2NjY2//82//9/ZAABNjY2NjY2Np5eXl4RATYAADY2NjY2NjY2NlI2NgM2NjY2NjY2NjY2JTZJNjY2NjYAAAE2NjYiIiI2AABFZDYAADY2NjY2NjYAAUA2NjY2MjY2I0M2/38TdTY2/DY2nkIAAAE8ACFZEzY2NjX7NjY2njRZ5BgyEzY2NjY2/xw3/382NjYAAAEAAAGAAP9/Nlc2NjYANjY2NjY2NjY2NjY2NgAAADY2/////wAAAAEAADY2/////zYAAABcNn////82NjYxNjY2NjY2NgABQDY2NgABNg== 0 -1
+BAFXAAIEAg== 2 -1
+BOgDAwgINjZWNhU2NgE2NjY2NjY2NjY2NjY2UjY2EzY2NjY2NjY2NjYlNkk2NjY2NjY2NjY2NiIiIiIiIkAiNugDNjY2NjY2NjY2NjZDNjY2NpiYmDY2NjYiICIiIiIiIiIiIiIiIiJJNjY2NjY2NjY2NjYiIiIiIiJAIjboAzYiIiIiIiIiIiIiIiI2NjY2JzY2NjZkZAAANjY2NjY2NjY2NjYiIiIiIiJAIjboAzYiIiIiIiIiIiIiIgA2NjY2TV8EYGFiYwRkZWZnBGhpamsEbG0eNgQgISIjBCQlJicEKCkqKwQsLS4vBICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUlZaXBJiZmpsEnJ2enwSgoaIAAA== 0 -1
+7I2NjY2NjY2NjY2NjQACjY2NjY2NjY2NjY2NjY2NjY2NAAKNjY2NjY2NjY6NjY2NjY2NjY2Nm42NjY2NjY2NjY2NjWyNjY2NjY2kjY2NjY2NjY2NjTY2NjY2PQAAATY2RDY2U1I2NgAAAQM2NjY2Nvc2dnbQKjYQTfgFACEANzI2OekAABA2NjY2EABxGwAAATY2AAABAHZ2dnZ29g== 0 -1
+BOgAATY2NjY2fwDiNjY2NjY2NjY2NgAAATY2NjY2NjYmNjb/ADY2NjY2AwAAAQT9BQcICXx8fHx8fHx8AAABAHx8fHx8IAB8 0 61 BOgAATY2NjY2fwDiNjY2NjY2NjY2NgAAATY2NjY2NjYmNjb/ADY2NjY2AwAAAQT9BQcICXx8fHx8fHx8AA== 123 \232\000\0016.666\127\000\2266666666666\000\000\0016666666&66\255\00066666\003\000\000\001\004\253\005\007\008\009||||||||
+wMAAAcDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNgAQwMAAAcDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABPjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Nn7s7OzsEBQUDDY2NgAAATY2NjZYNjY2Nk02NlEAEQEANjYABf//BUU2OTY2NiU9PT09NgAAAV8//3Y2AAABNjY0NgAAAYA2PRAANjYAAAABADY0NjYyNjY2NjYAEDY2S0tLQAAAAUsBNr4fRhTAHzY2fuzs7OwQFBQMNjY2AAABNjY2Nlg2NjY2TTY2UQARAQA2NgAF//8FRTY5NjY2JT09PT02AAABXz//djYAAAE2NjQ2AAABgDY9EAD7+/v76fv7+////w== 16 -1
+wMAAAcDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUX/gDY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Nn7s7OzsEBQUDDY2NgAAATY2NjZYNjYkNk02f/8AEQEANjYABf//BUU2OTY2NiU9PT09NgAAAfI//3Y2AAgBNjY0NgAAAYA2PRAA+/v7+/v7+/v///8= 16 -1
+BAABAgMEBAUGBwQICQoLBBINDg8EEBESEwQUFRYXBBgZGhsEHB0eNjY2AAA2NjY2Njw2ATYYNkUAAAIQ//9/TExMTExMTExMTExMTExMTExMTExMTENMTBMTExNqEykTlhMTEyYLAAEUFAAABjY2NjYAAAE2NhwAAAABAAABBDb/fwAAAzYAAQX//wU2NgD7SDYkNjk5OTk5OTk5OTk5OTk5OTk5OTk5PTY0pjY2NjY2NiQAAAE2Nn82cXZ2dnZ2dnZ20Coq0DPQ0P/QM9DQ//9//9AAAAHSu9DRkNAABgAA/xQUAAAGfzYkNjY0Nks2AAQeVTb/AAABNn////8= 0 -1
+xcXFxcXFxcXFxcXFxcXFxcXFxcXFxRDAwExMaExMTExMHzY7TTY2JBU2NDY2MjY2NjY2AxA2NktLS0tLwDY2NjYAABrAHzY2MzYQAN4HBzc2ATY2AxA2NktLS0tLwDY2NjYAABrAHzY2NjY2NjYWvh8AAAFGFDA2NjYAADY2WDZ2PDY2NjY2ADY2NjY2NjYAAAE2NjY2NgMQNjZLS0tLS8A2NjY2AAAawB82NjY2NgCAAAA2NjYuLi4uLi4uLi4hLi4uLi4uLi4uLi4uLi4uNjY2NjY2NjY2ozY2NjZENiU2njY2NjY2NjY2NjY2NjY2FzY2NgAA 197 48 Li4uLi4uLi4uLjY2NjY2NjY2NqM2NjY2RDYlNp42NjY2NjY2NjY2NjY2Nhc2NjYA 65 \.\.\.\.\.\.\.\.\.666666666\1636666D6%6\15866666666666666\023666
+ASY= 0 -1
+AAEAIA== 0 1 AA== 2 .
+BBABggMEBAAABBABggMEBAUG6wQICQoLBAxuBBQtLiBQMwQzNVEENDUpNwQ4ADkEMDFQKhcELC0uIAQwMVAzBAQzNTY0NQ== 0 -1
+AAAAGxsfGxv51ED/ACBk/vYbGxsbGxsbWRsbBQAbGxwbEAAAAAEb/QEAgACYAAEbGxsbGxtAG9EbJhsbAAAAGwMbJhsbAAAABwAg0rBpaWlpaWlpaWlpaWJpaWlpaQAAAAAAAQAAHSmJGw== 27 -1
+AACrq6r/7Q== 0 1 AA== 2 .
+BAABAgLgAeEBgADjAeQB6QHqAesB8wH0AfUB9gH3AfgB+QH6AfsB/AEaAv4= 0 -1
+/38AAAEAAAHj/CGaygAEAAA= 0 -1
+BAABAgICAgICAgICLhwEMDEzAiMEABD/BCEiI1UNDg8GBA81/QQUIyT6AAD6LgAAAANAAAAALi4uLi4uLk8uLi4uLi4uLiMAAAIAAA4= 0 -1
+BAABAgICAgICAgICLhwEMDEyMwICAgICAgQUFRYXAgICAgICAnWAAAAABCIjBACQ/wQhIiNVDQ4PBgQPCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoKCgoSEwQUIyT6AAD6LgAAAANAAAAALi4uLi48Lk8uLi4uLi4uLiMAAAIAAA4= 0 40 BAABAgICAgICAgICLhwEMDEyMwICAgICAgQUFRYXAgICAgICAnWAAA== 106 \000\001\002\002.\002\002.\002\002.\.\028.0123.\002\002.\002\002.\020\021\022\023.\002\002.\002\002.u\128
+BAABAgICAgICAgICLhwEMDEyMwIGBgYGBgYkBgICAgICBBQVFhcCAgICAgICdSMEDQAEIgAAARD/BCEiI1UNDg8GBA8SEwQDIyT6AAD6LgAAAANAAAAALi4uLi4uLk8uLi4uLi4uLiMAAAIAAA4= 0 77 BAABAgICAgICAgICLhwEMDEyMwIGBgYGBgYkBgICAgICBBQVFhcCAgICAgICdSMEDQAEIgAAARD/BCEiI1UNDg8GBA8SEwQDIyT6AAA= 228 \000\001\002\002.\002\002.\002\002.\.\028.0123.\006\006.\006\006\006\$\006\002.\002\002.\004\020.\022\023\002\002\002\002\002\002\002u#\004\013\000\004\"\000\000\001\016\255.!\"#U.\014\015\006\004\015\018\019\004\003#\$\250\000
+d3gXBf//BUcQp0CAAAABfx4= 2 -1
+ZAABAgICAgICZS3RA3d3dwdleGFtcIhlA2NvbQAAAQABwAw= 0 -1
+Af8= 0 -1
+BAABAgICAgICAgICLhwEMDEyMwICAgICAgICAgICAgICAgICAgICAgICAgICLhwEMDEyMwQ0NXYBdwF4AXkBegF7AXwBfQF+ATZuAW8BcAFxAXIBcwF0AXUBdgF3Af8BeQF6AXsBfAF9AX4BfwA= 0 110 BAABAgICAgICAgICLhwEMDEyMwICAgICAgICAgICAgICAgICAgICAgICAgICLhwEMDEyMwQ0NXYBdwF4AXkBegF7AXwBfQF+ATZuAW8BcAFxAXIBcwF0AXUBdgF3Af8BeQF6AXsBfAF9AX4BfwA= 228 \000\001\002\002.\002\002.\002\002.\.\028.0123.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\002.\002\..\0040123\00445v\001w\001x\001y\001z\001{\001|\001}\001~\0016n.o.p.q.r.s.t.u.v.w.\255.y.z.{.|.}.~.\127
+BAABAAABAwgINjY2NgAAAMAfNjZkAAAAAAEAFPY2HjY2NPoAAPoABAEAAAE2NgAAATb7IPvz+/sAAAFCAAABRDYkDzI0NjY2NjY2NjYAAAABNlg2Nv9/NjY2NgAAAQA2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2/zY+NjY2NjYAADYA/wA2DAEAAQH0wB82NjY2 0 -1
+ABAAFwMfExQVFhcYGRobHB0eHyAhIiMkJSYnKCkqKywtLi8wMTIzNDU2Nzg5Ojs8PT4BPw== 0 1 AA== 2 .
+hBABAgMAAAERCf//hBABAgMsARAAAAFkCQsADwAQANRMAACEMAECAwAAAAABHQEBKUIK 0 -1
+AAFAAGQpCgo= 0 1 AA== 2 .
+BBABAAABf/8BCQEBAQACENQBAQEBAQEBAQEBAWQBAAEBAgEBAQEBKSkp 0 -1
+BBABAgMsLUcBCQEBAQACENQBAQEBAQEBAQEBAWQBAAEBAgEkAQEBKSkp 0 -1
+BBABAgMsLS4A/zA0MvoAAPo2NwQ4PD03PwAEJwRZWVlZWVlZWVlZGwABHR4fBCA2IiMEJCUmJwQoKQACEu4rLS4v9y+ysn8ENDU2NwQ4ORUWFwQgISIjBCSyBDQ1Nh0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHQAAAR0dHR0dHR0dHR0dHR0+HR0dHR0dHR0dDx0dHR0dHR0dHR0dHR0FHR0dHR0dHR0dHR0dHR0dFR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0UHR0dHR0dHR0dHQAAAR0BAwAAAQT9BQcICXy0BDB8fHx8AAABAHx8fHx8IAB8 0 222 BBABAgMsLS4A/zA0MvoAAPo2NwQ4PD03PwAEJwRZWVlZWVlZWVlZGwABHR4fBCA2IiMEJCUmJwQoKQACEu4rLS4v9y+ysn8ENDU2NwQ4ORUWFwQgISIjBCSyBDQ1Nh0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHQAAAR0dHR0dHR0dHR0dHR0+HR0dHR0dHR0dDx0dHR0dHR0dHR0dHR0FHR0dHR0dHR0dHR0dHR0dFR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0UHR0dHR0dHR0dHQAAAR0BAwAA 709 \016\001\002\003.-\.\000\255042\250\000\000\25067\0048<=7?\000\004'\004YYYYYYYYYY\027\000\001\029\030\031\004\0326\"#.\$%&'.\(\)\000\002.\238+-\./\247/\178\178\127\0044567\00489.\022\023\004\032!\"#\004\$\178\004456\029\029\029\029\029\029\029.\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\000\000\001\029\029\029\029\029\029\029\029\029\029.\029\029>\029\029\029\029\029\029\029\029\029\015\029\029\029\029\029\029\029\029\029\029\029\029\029\005\029\029.\029\029\029\029\029\029\029\029\029\029\029\029\021\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029\029.\029\029\029\029\029\029\029\029\029\029\029\020\029\029\029\029\029\029\029\029\029\029\000\000\001\029\001\003\000
+4BABAgMsLTw9Nz8ABCcWFwQYGRobBBwdHh8EICEiIwA= 0 -1
+BAABAgMEBAUGBwQICQoLBAwNDgICAgICAicEKCkqqwQsLS4vBDACAi0uLwQwAgICAgICEAICAgICBCgpKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/AA== 0 -1
+BAABAgMEBAUGBwQICQoLBAwNDgICAgICAicEKCkqKwQsLS4vBDACAgICAgICAgABADY2JzY2NjQ2WDY2NoAAAAA2AAABNjY2AAAAAMAfNjY2NjYkFTY0NjY2NjY2NjY2NjY2NjYAAAABBDY2NjY2NjY2NjY2NjYAAAABABtLbEtLS0tLS0sBAAABRhQ2gDY2NjY2NjY2NjY2NjY2NjY2NiQ2Nn92dnZ2dnZ2dnZ2dnZ2AXZBNgE2HgQAQP82NjY2NDYAAAEAAAGANhkWNjY20NDQ0NDQ0NDQM9DQ0NDQ0NDQ0NDQkNAAFBQUFDY2NjY2NjZYNjY2Nk02NlEAEQEAAAEjNjZFNjk2NjYlPT09VDYAQP82NjY2NDYAAAGANj0QAPsAAAH7AAAAZPv7+/sg+/v7+0JEAAABNgsLCwsLCwsLCwsLCwsLCwuYCwsLCwsLCwsLCws= 0 -1
+AQLAAA== 0 -1
+BAABAgMEBAUGBwQEDA2ADwQQBBgZGhsEHB0hIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFRkcESElKSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EYGFiYwRkZWZnBGhpamsEbG1ubwRwcXJzBHR1dncEeHl6ewR8fX5/BICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUlZaXBJiZmpsEnJ2enwSgoaKjBKSlpqcAAAGqqwSsra6vBLCxsrME 0 195 BAABAgMEBAUGBwQEDA2ADwQQBBgZGhsEHB0hIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+PwRAQUJDBERFRkcESElKSwRMTU5PBFBRUlMEVFVWVwRYWVpbBFxdXl8EYGFiYwRkZWZnBGhpamsEbG1ubwRwcXJzBHR1dncEeHl6ewR8fX5/BICBgoMEhIWGhwSIiYqLBIyNjo8EkJGSkwSUlZaXBJiZmpsEnJ2enwSgoaKjBKSlpqcA 415 \000\001\002\003.\004\005\006\007.\004\012\013\128.\004\016\004\024\025\026\027\004\028\029!\"#\004\$.&'\004\(\)*+\004,-\./\0040123\0044567\00489:\;\004<=>?\004\@ABC.DEFG.HIJK.LMNO.PQRS.TUVW.XYZ[.\\]^_.`abc.defg.hijk.lmno.pqrs.tuvw.xyz{.|}~\127.\128\129\130\131.\132\133\134\135.\136\137\138\139.\140\141\142\143.\144\145\146\147.\148\149\150\151.\152\153\154\155.\156\157\158\159.\160\161\162\163.\164\165\166\167
+GxsAAAEbGxsbGxsbGxsbAxsbGxsbGxsbGxsYIBsbGxsbGxs2GxsbGxsbGxsbCxsbGxsbGxsbGxsbFRsbGxsbGxubGxs3GxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsUGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGx8DGxsbGxsbAAEbGxsbGxsAAAHqGxsa+gAbGxsbGxsbGxsXGxsbGxsbG4AbGxsbGxsbGxsbGxsbGxsbGxsbGxv7GxsbGxsbGxsbGxsbGxsbGxsbGxs0G/waGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbJh8bGxsEGxsbGxsbGzEbGxsbAPoAAPo= 155 -1
+BBgfKgAA 0 6 BBgfKgAA 14 \024\031*\000
+wMAAAAABAcDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2MzYAEDY2S0tLABBQNktLS0tLATY2/+I2Nlg2djw2NjYAAAE2KQAAAf+ANjY2PDY2MRU2BLMF9AAB//8FRTYAEDY2S0tLQAAAAUsQNr4fRhTAHzY2fuwAAAHsrOwQAAABJBQMNjYAABAANjY2LVg2NjY2NiQVNjQ2NjI2NkMzNgAQNjZLS0s2JUU2HzM2ABA2NktLS0tLARu+H0YUNgABgDY9ARa+H0YUNjYQAPv7+/v7+/v7//8b 16 1 AA== 2 .
+wMAAAcDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Nn7s7OzsEBQUDDY2NgAAATY2NjZYNjY2Nk02NlEAEQEANjYABf//BUU2OTY2NiU9PT09NgAAAfJAFXaANj0QAPv7+/v7+/v7//// 16 -1
+wMAAAcDAwMDANjY2NgAAGtgfNjY8NjYkFTY0NgAAAGQ2NjYAEDY2S0tLS0sBFr4fADaiNjY2NjYF//8FRTY5Nj42JT09PQE2NjYAAAABADY0NncyNjY2NjYAEDY2S0tLQAAAAUsBNr4fRhTAHzY2QOzs7OwQFBQMNjYQAAABNjY2Nlg2NjY2TTY2UQARAQA2NgAF//8FRTY5NjYqJT09PT02AAAB8j//djYAAAE2NjQ2AAABgDY9EAD7+/v7+/v7+////w== 16 -1
+wMAAAcDAwMA2JBU2NDY2MjY2NjY2ABA2NjY2NjYAADY2WDZ2PDY2NjZLS0tLSwEWvh9GFDZFNjYAADY2WDZ2PDY2NjY2AAABAAE2NjY8NjYkFTYEszaiNjY9NjYF//8FRTY5Nj42JT09PQE2NjYAAAABADY0NjYyNjY2NjYAECc2S0tLQAAAAUsBNr4fRhTAHzY2fuzs7OwQFDY2Nlg2JDY2TTY2UQARAQA2NgAF//8FRTY5NjY2JT09PT02AAAB8j//djYAAAE2NjQ2AAABgDY9EAAAAAH7+/v7+/v7+////w== 16 -1
+wMAAAcDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ogAENgAQAAD/BWM2OTY+NCU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YQwB82Nn7s7OzsEBQUDDY2NgAAATY2NjZYNjY2Nk02NlEAEQEANjb4Bf//BUU2OTY2NiVEPT09NgAAAfI//3Y2AAABNjY0NgAAAYA2PRAA+/v7+/oAAPr///8= 16 2 NjY2NgAQNjZLS0tLSwEWvh9GFDY2NjYAADY2WDZ2PDY2NjY2AAABAAE2NjY8NjYkFTYEszaiAAQ2ABAAAA== 127 666\000\01666KKKKK\001\022\190\031F\0206666\000\00066X6v<66666\000\000\001\000\001666<66\$\0216\004\1796\162\000.6\000\016\000
+wMDzAMDAwMDANjY2NgAAGsAfNjY8NjYkFTY0NjYyNjY2NjYAEDY2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2NgAAAQABNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Nn7s7Ow9PT09NgAAAewQFBQMNjY2AAABNjY2Nlg2NjY2TTY2UQARAQA2NgAF//8FRTY5NjY2JT09PT02AAAB8j//djYAAAE2GjQ2AAABgDY9EAD7+/v7+/v7+/9k/w== 16 -1
+wMAAAcDAwMDANjY2NgA2S0tLS0sBFr4fRhQ2NjY2AAA2Nlg2djw2NjY2BLM2ojY2Bf//BUU4OTY+NiU9PT0BNjY2AAAAAQAuNDY2YjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Nn7s7OzsEBQUDDY2NgAAATQ2NjZYNjY2Nk02NlEAEQEANugDBf//BUU2OTY2NiU9PT09NgAAAfI//3ZCAAABNjY0NjY2NgAAAYA2PRAA+/v7+/v7+/v/ABA= 16 -1
+wMAAAcDAwMDANjYEHB0eHwQgISIjBCQlJicAKCkqKwQsLS4vBAkJCQkJCQkJCQkJAAABCQkJCQkJCQkJCQkJCTAxMjP+MzU2NwQ4OTo7BDw9 16 11 BCAhIiMEJCUmJwA= 15 \032!\"#.\$%&'
+AX8= 0 -1
+AQ== 1 -1
+wMAAAcDAwMDANjY2NgAbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbwxsbGxsbGxsbGxsbGxsbGxsCGxsbGxsbGxsbGxsbGxsbGxsVGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxkbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbAxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGyYbEBsbGxsbGxsbGxsbGxsbGxsb 16 -1
+wMAAAQAAAcYEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYX6hcZGhsEHB0eBwcHBwcHBwcHB/cHBwcHBwcHBwcfBCAhIvIAASMEJCUmEAQoKSorBCwtLi8AMA== 16 53 CgsEDA0ODwQQERITBBQVFhfqFxkaGwQcHR4HBwcHBwcHBwcH9wcHBwcHBwcHBx8EICEi8gA= 188 \011\004\012\013\014\015\004\016\017\018.\004\020\021\022\023\234\023\025\026\027\004\028\029\030\007\007\007\007\007.\007\007\007\007\247\007\007.\007\007\007\007\007\007\031.\032!\"\242
+AgAfBCApIiMEJCTrJwQIKSqrBCwtLi8EMEECAB8EBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwYHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBw4HBwcHBzMzMxo7MzMzMzMzMzMzMzMzBwcHBwcHBwcHBwcHBwcHBwcHDgcHBwcHBwchBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcHBwcHBwcHAhAiBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBxcHBwcHBwcHBwcHBwcCECICECIGLi8AAAEEMDH5fwQMDRIPECICECIGLi8EMDEqMwQ0NTYiBgQICfl/BAwNEg8EKjMEBwcHBwcHBwcHBwcHBwcHBxAREhMEFBESQAABFhczMzMzMzMzMxEzMzMzMzMz/38TBBQRFhcEGCQaGwQUHQIQIgYECAn5fwQMJxIPBBAREhMEQAAWFuiAAAAbBBQdABAzBDQxf/7//wgJBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcOBwcHBwcHByEHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBxcHBwcHBwcHBwcHBwcHBwd/AAQkNB0CECICEEACECICECISQAABFhcEGBkaGwQUHSAfADMzMw== 0 -1
+AAEAEP8AAQD3 0 1 AA== 2 .
+AegDCAg2HzY2AAAAwB82NjY2NiQVNjQ2NjY2NjY2NgAQNgAAATY2NjY2NjY2AAABAAE2NjZFNjYVNgAENjY2NjY2JzY2NjQ2WDY2NjY2NjY2AAABNjY2AAAAAMAfNjbj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+Pj4+M2NjYkFTY0NjY2NjY2NjY2NjY2NjYAAAABBDY2NjY2NjY2NjY2NjYAAAABABtLbEtLS0tLS0sBAAABRhQ2gDY2AAA2NiQ2NjQ2NjY2NjY2NjY2NjY2NjY2NiQ2Nn92dnZ2dnZ2dnZ2dnZ2dnZBNgE2HgQAQP82NjY2NDYAAAEAAAGANhkWNjY20NDQ0NDQ0NDQM9DQ0NDQ0NDQ0NDQkNAAFBQUFDY2NjY2NjZYNjY2Nk02NlEAEQEAAAEjNjZFNjk2NjYlPT09VDYAQP82NjY2NDYAAAGANj0QAPv7+/v7+/v7+/sg+/v7+0JEAAABNgsLCwsLCwsLCwsLCwsLCws= 0 -1
+Bf//BcDAwMDANjY2NgAAVwECAVcBAQIBVwEBAQECAVcAAA== 16 17 AQIBVwEBAgFXAQEBAQIBVwA= 34 \002.W.\001.\001W.\001.\001.\001W
+BAABAgMEBAUGBwSICQoLBAwA//wNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIj538lRicEKCkqKwQsLS4vBDAxMjMENDU2PgQ4OTo7BDwQPj8A 0 -1
+BAABAgMEBAUSEwQUFRYXBBgZGhsEHB0eOQQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw8Pj8A 0 66 BAABAgMEBAUSEwQUFRYXBBgZGhsEHB0eOQQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw8Pj8A 131 \000\001\002\003.\004\005\018\019.\020\021\022\023.\024\025\026\027.\028\029\0309.\032!\"#.\$%&'.\(\)*+.,-\./.0123.4567.89:\;.<<>?
+NwAAAAABAQQdIh8EICEiI/8QJSYnBCgpA+j4LBvrGx0eHwQgISKGBKQlJicEKP8qKwAAG4aGhgAQhoaGhoaGhoaGIh8EIICGhoY4PT5SAA== 0 -1
+AAABAgMEBAXrBgQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8A 0 1 AA== 2 .
+AAEBAgMEBAUGBwQICQoLBAwNBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEAgKSIjBAQkAAACAEACAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgIQIgYECAn/fwQMDRIPBBAIEhMEARUWFwQYOhobBBQdHh8mNSkiGQQkJAAAAg5AAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQAAAIAQAIQIgIQQAIQIgIQAAA= 0 1 AA== 2 .
+BAABAAABBAUGDQYECAn/fwAAARIPEBAJCgsEfwAAABMEByAACQoLBGQNEgkQEAgSEwQBFRYXBBg6Gv9/Hx0eHw01KSIZBCQkAAD/AEACECICEEACECLzDyIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAJkAAIQQAL+AgAQywIQIgYECAn/fyQkAAAAAAECDkACQCIAAAECEEACJiIBBCQkAAACAEACECJTENQCECICEAAA 0 -1
+5f8AAgAAAAEEBAX/ZAAICQoL5AwNBgQIgAAAAA38DgQQCBIZBCQcAAAAAUACEP9kAAgJECLtECL/D///AhBAAhAiAhAtBCApIiPpEgAAAAABAAIAQAAAAQJkAAIQCAAAEAAFACkJ/wL/fxcKGOoAAToa/wIcJ/R6enp6enp6enp6enp6enp6enp6enp6AAECA+gAAIACECICEAAA 0 -1
+A9YBAgMmAAABBwQIGQoACwQMCxQMDQ4AAAAA 0 -1
+lJWWogwA6P8A 0 -1
+wMAAAQBkn8CiNjY2NgAAGsAfNjY8yQAhEAACCSICAgIQIgIQQAA= 16 2 AhAiAhBAAA== 14 \016\".\016\@
+3g== 0 -1
+AQ== 0 -1
+AgAAAhBiAgAAAhAiAQECAVcBAQIBVwIQYgIAAAIQAQIBVwEBAhBiAgAAAhAiAVcBAgFXAQECAVcBAQEBAgFXAAAB 0 64 AgAAAhBiAgAAAhAiAQECAVcBAQIBVwIQYgIAAAIQAQIBVwEBAhBiAgAAAhAiAVcBAgFXAQECAVcBAQEBAgFXAA== 146 \000\000.\016b.\000\000.\016\".\001.\001W.\001.\001W.\016b.\000\000.\016\001.\001W.\001.\016b.\000\000.\016\".W.\002.W.\001.\001W.\001.\001.\001W
+AQABAwEJAQoYARkBGmwbARwHGgEeAc0BAAAB0AAAA+gB01NTAZ8= 0 -1
+wMAAAcD/AMAbAgICAgICAgIAAgICAgABAAA= 16 7 AgACAgICAA== 18 \000\002.\002\002
+BOgAAAEDAwgINjY2NgAAAMAfNjZkAAAAAAEAFPY2HjY2NDYMAAEABAEAAAE2NgAAATb7IAAAAfsAAAFCRDYkDzI0NjY2NjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTY2FTYABDk2NgAAATY2NjY2Nhw0NlgAIDY2/zY+NjY2NjYAADYAAPs2DAEAAAH0ATY2Njw2NiQVNgSzNqI2NjY2NgX//wVFNjk2PjYlPT09ATY2NgAAAAEANjQ2NjI2NjY2NgAQNjZLS0tAAAABSwE2vh9GFMAfNi5+7Ozs7AAAAezs7BQ2NjY2AAAAAAE2NjQ2GTZBNj42LTY2NjY2TtDQ0ID///8UFBQ2NjU2NkM2WDY2NjZNNjZRABEBAA== 0 -1
+BDY2KwAAAMAfNjZkAAAAAAAAFHY2HjY2NDYMAAEABAEAAAE2NgAAATb7IPvz+/sAAUsBNr4fRhTAHzYufuzs7OwAAAHs7OwUNgABQkQ2JA8yNDY2NjY2NjY2ABA2Nj1YNjY2NjY2NjYAAAEAATY2NkU2EzY2HDQ2WAAgNjb/Nj42NjY2NgAANgAA+zYMAQAA8PMBNjY2PDY2JBU2BLM2ojY2NjY2Bf//BUU2OTY+NiU9PT0BNjY2AOj/AAAyNDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Ln7s7OzsAAAB7OzsFDY2NjYAAAAg+/P7+wAAAUJENiQPMjQ2NjY2SDY2AAE2NjQ2NjZRQzZYNjY2Nk02NlEAEQEA 0 6 BDY2KwAA 8 66+\000
+BOgANvsE+/vZ+wAAAX////8AMjQ2DjY2NjY2NgAAAID//wEAWCD7T1ZYEzY2NjY2NjYAAAEAATY2NkU2NhU21dXn1dXVINXV1dXV1dXV1dXV1RDV1dXL1dXV1dUABDk2NgAAAv///4c2PjY2NlY2AAAfRhTAHwAAA+g2PDY2fuzs7OwVAAAAADY2UQAR9gA= 0 11 BOgANvsE+/vZ+wA= 31 \232\0006\251.\251\251\217\251
+BOgAAAEDAwgINjYxNgD/5MApIPvz+wAAAQFCRDYkHjY2NDYMAAE2NjY2NjYAEDY2Nlj7IPvz+/sAAAFCRDYkDzI0NjY2NjY2NjYAEDY2Nlg2EzY2NjY2NgAcAQABNjY2RTY2FTYABDk2NgAAATY2NjY2Nhw0NlgAIDY2/zY+NjY2NugDADYAAPs2DAEAAAH0ATY2NjwpNiQVNgSzG6I2NjY2NgX//wVFNjk2PjYlPT09ATY2NgAAAAEANjQ2NjI2NjYfNjZkAAAAAAEAFPY2HjY2NDYMAAEABAEAAAE2NgAAAezs7BQ2NjY2AAAAAAE2NjY2QzZYNjY2Nk02NlEAEQEA 0 202 BOgAAAEDAwgINjYxNgD/5MApIPvz+wAAAQFCRDYkHjY2NDYMAAE2NjY2NjYAEDY2Nlj7IPvz+/sAAAFCRDYkDzI0NjY2NjY2NjYAEDY2Nlg2EzY2NjY2NgAcAQABNjY2RTY2FTYABDk2NgAAATY2NjY2Nhw0NlgAIDY2/zY+NjY2NugDADYAAPs2DAEAAAH0ATY2NjwpNiQVNgSzG6I2NjY2NgX//wVFNjk2PjYlPT09ATY2NgAAAAEANjQ2NjI2NjYfNjZkAAAAAA== 455 \232\000\000\001.\003\008\008.616\000\255\228\192\)\032\251\243\251\000\000\001\001BD6\$\0306646\012\000\001666666\000\016666X\251\032\251\243\251\251\000\000\001BD6\$\015.466666666\000\016666X6\019666666\000\028\001\000\001666E66\0216\000\004966\000\000\001666666.46X\000\03266\2556>6666\232\003\0006\000\000\2516\012\001\000\000\001\244.6.6<\)6\$\0216\004\179\027\16266666\005\255\255\005E696>6%===\001666\000\000\000\001\00064662666\03166d\000\000\000
+BOgAAAEDAwgINjY2NgAAAMAfNjZkAAAAAAE2vh9GFMAfNi5+7AAAAezs7AAAAezs7BQ2NgEAFAEAJA8yNDY2NjY2NjY2ABA2NjZYNvQBNjY2PDY2JBU2BLM2ojY2NgAAATY2Bf//BUU2OTY+NiU9PT0BNjY2AAAAAQA2NDY2MjY2NjY2ABA2NktLS0AAAAFLATa+H0YUwB82Ln7s7OzsAAAB7OzsFDY2NjYAAAAAATY2NDY2NkE2PjY2NjY2NjZO0DZRABEBAA== 0 120 BOgAAAEDAwgINjY2NgAAAMAfNjZkAAAAAAE2vh9GFMAfNi5+7AAAAezs7AAAAezs7BQ2NgEAFAEAJA8yNDY2NjY2NjY2ABA2NjZYNvQBNjY2PDY2JBU2BLM2ojY2NgAAATY2Bf//BUU2OTY+NiU9PT0BNjY2AAAA 302 \232\000\000\001.\003\008\008.666\000\000\000\192\03166d\000\000\000\000\0016\190\031F\020\192\0316\.~\236\000\000\001\236\236\236\000\000\001\236\236\236\02066\001\000\020\001\000\$\01524666.6666\000\016666X6\244\001666<66\$\0216\004\1796\162666\000\000\00166\005\255\255\005E696>6%===\001666\000\000
+BOgAAAEDAwgINjY2NgAAAAEfNjZkAAAAAAEAFPY2HjY2NDYMAAEABAEAAAE2NgAAATb7IPvz+/t/AAFCRDYkDzI0NjY2NjY2NjYAEFY2Nlg2NjY2NjY2NgAAAQABWTY2RQAAATYABDk2NgAAATY2NjY2Nhw0NlgAIDY2/zY+NjY2NjYAADYAAPs2DAEAAAH0ATYVNjw2NiQVNgSzNqI2NjY2NgX//wVFNjk2PktLQAAAAUsBNr4fRhTAHzYufuzs7OwAAAHs7OwUNjY2NgAAAAABNjY0NjY2QTY+NjY2NjY2Nk7Q0NCQ0AAUFBQUNjY1NjZDNlg2NjY2TSE2UQARAQA= 0 -1
+BOgAAAEDAwgINjY2NgAAAMAfNjZkAAAAAAABAAEAFPY2HjY2NDYMAAEABAEAAPM2NgAAIzb7IPvz+/sAAAFCRDYkDzI0NjY2NjY2NjYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTa1FTYABDk2NgAAATY2NjY2Nhw0JlgAIDY2/zY+NjY2NjYAADYAAPs2DAEAAAH0ATY2Njw2NiQVNgSzNqI2NjY2NgX//wVFNjk2PjYlPT09ATY2NgAAAAEANjQ2NjI2NjY2NgAQNjZLS0tAAAABSwE2vh9GFMAeNi5+7Ozs7AAAgADs7BQ2NjY2AAAAAAE2NjQ2NjZBNj42NjY2NjY2TtDQ0JDQABQUFBQ2NjU2NkM2WDY2NjZNNDZRABEBAA== 0 -1
+BOgAAAEDAwgINjY2NgAA6R8fNjZkAAAAAAEAFPY2HjY2NDYMAAEABAEAAAE2NgAAATb7IPvz+wEBAAFCRDYkDzI0NjY2NjYAATYAEDY2Nlg2NjY2NjY2NgAAAQABNjY2RTYyFTYABDk2NgAAATY2NjY2Nhw0NlgAIDY2/w0NDQ0NDQ0NDQ0NNj42NgAAAQAANgAA+zYMAQAAAfQBNjY2PDY2JBU2BLM2ogX//wVFNjk2MjYlPT09ATY2MgAAAAEANjQ2NjI2NjY2NgAQNjZLS0tAAN8AAAEASwE2vh9GFMAfNi5+7Ozs7AAAAezs7BQ2NjY2AAAAAAE2NjQ2NjJBNj42NjY2NjY2TtDQ0JDQABQUFBTOUTU2NkM2WDY2NjZNNjZRABEBAA== 0 -1
+AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAjyEgQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACFyICECIGBBAiAhBAAoAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGAEVFhcEGDoaGwQL/x4fDTUpIhljJDoaGwQUIx4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIvIQIgIQQAIQIgAQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgAAAECAv4CAjsA 0 255 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAjyEgQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACFyICECIGBBAiAhBAAoAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGAEVFhcEGDoaGwQL/x4fDTUpIhljJDoaGwQUIx4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIvIQIgIQQAIQIgAQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgAAAECAv4CAjsA 780 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\242\018\004\001\021\022.\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\023\".\016\".\004\016\"\002\016\@.\128\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\004\008\002\002\002\002.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\001\021\022\023\004\024:\026\027\004\011\255\030\031\0135\)\"\025c\$.\026\027\004\020#\030\031&5\)\"\025\004\$\$\000\000\002\000\@\002\016\"\002\016\@\002\016\"\242\016\"\002\016\@\002\016\"\000\016\031\004\032\)\"#\004\$\$\000\000\002\000\@\002\016\"\002.\@\002\016\"\002\016\"\006\004\008\000\000\001\002\002\254.\002\;
+AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/GgwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGAEVFhcEGDoaGwQLHR4fDTUpIhkEJDoaGwQUIx4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIgIQIgIQJQIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CAjsA 0 255 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/GgwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgYECAICAgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGAEVFhcEGDoaGwQLHR4fDTUpIhkEJDoaGwQUIx4fJjUpIhkEJCQAAAIAQAIQIgIQQAIQIgIQIgIQJQIQIgIQHwQgKSIjBCQkAAACAEACECICEEACECICECIGBAgCQAICAv4CAjsA 780 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\026.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\004\008\002\002\002\002.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024\001\021\022\023\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$.\026\027\004\020#\030\031&5\)\"\025\004\$\$\000\000\002\000\@\002\016\"\002\016\@\002\016\"\002\016\"\002\016%\002\016\"\002\016\031\004\032\)\"#\004\$\$\000\000\002\000\@\002\016\"\002.\@\002\016\"\002\016\"\006\004\008\002\@\002\002\002\254.\002\;
+AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw3oAwAABCQkAAD/AEACECICEEACECICECIGBBAiAkACEAACEEACECICECIGBAgCAgICAhAiAiY1KSIZBCQkBgQICf9/BAwNEg8EEAgSEwQBFRYXBBgBFRYXBBg6GhsECx0eHw01KSIZBCQ6GhsEFCMAAAEMHyY1KSIZBCQkGwACAEACECHtEEACECICECICEEACECICEB8EIBwiIwQkJAAAAgBAAhAiAhBAAhAiAhAiBgQIAkACAgL+AgI7AA== 0 -1
+DGQAAADKBhgi////fxA33d3d3QECAA0B+/HWEAA43iABAQyAEM/V3d3d8d3d3d3d3d3/AN3d3d3dyADGA+gAIvgP8gbz9A3z9PX2ECIB7SIB7AX43d3d3egD/wDd3d3d3cjd3d3/AAD19hAiAefTAARFAPgB6UD7BCUB/AUjIf8= 16 -1
+rgGvAbABsQGyAbMBtAG1AbYBtwEBtgG3AbgBuboBuQG6AbsBvAG9Ab4= 0 -1
+6AU2 3 -1
+BAABAgMEBAUGBwQICQoLBAwNDg8EEBESEwQUFRYXBBgZGhsEHB0eHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxAwMDAwMDAwMDAwMDAwMCAwMDAwMDAwMDAwMDCAMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzYAPRAA+/v7+/v7+wMDAwMDAwMDAwMDAwAAAQMDAwMDAwMDAwMDAwADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwAAAQMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMOAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAzYAAAGA 3 -1
+IBJDAQAQAAAAOj9IWUhISGVIAwMA//8AACBIAwMAAAHsSDD//wAAAwMDAwMAf9z//wAAAQMDAQMDAwMLAwMDAAEDAwMDAwQDAAA= 68 5 AwMEAwA= 13 \003\004\003
+BOiACwBA/78AABA2NjYyZxVHAOY1NDYfNkg2NP82NgABNjY2NGcVRwDmNTQYHzY2NjT/NjY2NgAA/wADNjY2H8LCwkYUAFA2NgAAgH0AAAfzATY+BFCCwkYUADYAAAGANjYkNv9//wB/NjY2NjYUAAABNjZPNjYYPgQ5NjbQztDQ0NDQ0Mcz0NDi0NDQAAAA+xAN+TY2BwEBAIkAABQUFBQ2NoAHAH8A6AE2WCs2NjYZNnZ2knZ2dnZ2gAsAAAEAGw== 0 -1
+BOgA8r8fNFI2wsK+wsLCBABSUBYAAQAAFBuQAAAA7DUmNgAEAAA2EAABAAAUG5AAAAA2AAAA3gAAgOXQ0NDQM9DQAAABAAAAAeZ/NjY2NjZ2dn92dgE2dn92dgE2Jgr//QFQNsLCwsLCwh80f////8JQNsLCwsLCwh80Nk3CwsLCwsLCwsLCADY2+gAA+nZ2AAABSwE0vjYAAACA5dDQ0NAy/+EB0NAAAAEAAAAB5n82NjY2NjZ2f3Z2ATZ2CgAQAAE2NgDo/4Dl0NDQ0DPQ0AAAAQAAAABAztDQ0M12dv/2AAC5ubm5ubm5ubm5ubm5ubkBAUZUADY2ADI2JDY2NJAAAQAA 0 38 BOgA8r8fNFI2wsK+wsLCBABSUBYAAQAAFBuQAAAA7DUmNgAEAAA= 118 \232\000\242\191.4R6\194\194\190\194\194\194\004\000RP\022\000\001\000\000\020\027\144\000\000\000\2365&6\000\004\000
+BOgAAMAfNjY2wsJCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADe4TU2NjY2NjY2NjY2NjYAAAABABtn6gABbEsAAAFLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQAAUAADPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2AHZ2dnZ2dnb/CwAAAQAb 0 93 BOgAAMAfNjY2wsJCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADe4TU2NjY2NjY2NjY2NjYAAAABABtn6gABbEsA 216 \232\000\000\192.666\194\194B\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.66\00966664\128X6\000\016\00166664\2556666\000\000\000\222\2255666666666666\000\000\000\001\000\027g\234\000\001lK
+BOgAAMAfNjY2wvoAAPrCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0NjY2AAAA3gM2NjY2NjY2NjY2NjY2AAAAAQAbZ+oAAWxLS0tLaUtLATa+dnZ2dh9GFAA2NjYAADY2JDY2NP9/NjY2NjY2FTY2TzY2NjY2JDY2//+AAHZ2dnZ2dnb/CwBA/zY2NjY2NgA0NgAAAQABAIAAAAE2NgpQNjbQztDQ0NDQ0NAz0NDi0NDQAABA+xAUFDY2AAHQ0JAAABQUFBQ2NoABAH82WCs2NjY2NnZ2dnZ2dnZ2/wsAAAEAGw== 0 -1
+Z+oAASAAS0tLaUtLATa+AAAE6AAAwB82NjbCwsLCwsLCwsLCn8LCwsLCwjY2JBU2NDY2NjY2NjYAAAABABtnFTYABDY2NjY2CTY2NjY0gFg2ABABNl82NjT/NjY2NgABAN4DNjY2NjY2NjY2Njb6AAD6AP8AG2fqAAEgAEtLS2lLSwE2vnZ2dnYfRhQANjY2ACA2NiQ2NjT/fzY2NjY2NhU2Nk82NjY2NiQ2Nv//gAB2dnZ2dnb//3//QP+Dg4ODgzY2NjY0NgAAAQABAIAAAAE2NgpQNjYAAAHQNP9/NjY2NjY2FdA2WCs2NjY2NnZ2dnZ2anZ2/wsAAAEAGw== 27 -1
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngn/fzY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NlI2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngn/fzY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NlI2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAA 624 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\009\255\127664\128X6\000\016\00166664\2556666\000\000\000\222\003666666666R.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\1276X+66666vvvvvvvv\255\011\000
+BOgAAMBgYGBgYGBgYGBgYGBgYGBgYJ/Cs8LCwsLqNh0VNiE2NkI2NkM2AAAAEOkaZxU2AAQ2NlY2Ngk2lpaWlpaWlpaWlpaWlpaWHTY2IIBYNvQAAQAtATYiNn8AAAA2Nh02NjSAWDgALQE2NjZ/AOQANjY1///13gM2NjYFAGQAAwAAATY2NjZnFTYABDY2VjY2ZAD/f+//f4w2NjY2//82NjZQACAAHBwYHBwcHBwcHBwcAQB//xwcHBwcARAbZ+rwAWxLS3Z2djY2NP8QNjY2NjY2FTY2T3Z2dv8LAEAeNhQgf////xtn6vABbEtLdnZ2NjY0/xA2AdDQkAAAARTSFEAAAAABABs= 0 -1
+AAAAAQH/Hwb/AB7pAAAAAAAAAABAHyUlJSVWVlZfAP9/ADR3NjYjFBg2VTY29xQYNlU2NvdWVlZWVlYAAAFWVlZWVlZWVlZWVlZWVlZWVlZWVlZWVl8A/wAAEiKA//8C////AATnVwAAxxUAAAAB//++hhAEiDsEOD0= 9 1 AA== 2 .
+ATYkNjb/NiQgAF9fgF9XX184X71fX19fAF9fKysrfwBfAAABAHtfAwAAXwADAwMAAgMD/zYkIABfX19fAAABX19fOV+9X182NjYAAAEVaQAABgQ8PQ== 0 44 ATYkNjb/NiQgAF9fgF9XX184X71fX19fAF9fKysrfwBfAAABAHtfAwAAXwA= 86 6.66\2556\$\032\000__\128_W__8_\189____\000__+++\127\000_\000\000\001\000{_.\000\000_
+AOgAAMAfNjY2wsLCwsLCwuTiwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZwAAARU2AAQ2NjYAAAE2Ngk2NjY2NIBYNgAQAT02NjY0/zY2NjYAAADeAzY2NjY2NjY2NjYTNjbCwsLk4sKfwsLZwsLCNjYkFTY0NjY2NjY2NgAAABcAGwAAAQE2AAABNv+AhocEiDsEPD0= 0 1 AA== 2 .
+8A== 1 -1
+BCorBCwtLjL79Pv7/BX7+/v7+/v7+/v7+/v7+/v7+wcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcBBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwYHBwcHBwcHBwcHB9EHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBw4HBwcHBzMzMxo7MzMzMzMzMzMzMzMzBwcHBwcHBwcHBwcHBwcHBwcHDgcHBwcHBwchBwcHBwcHBwcHBwcF//8FBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcHBwcHBwcHAhAiBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHAAEEMDH5fwQMDRIAECICECIGLi8EMDEqMwQ0NTYiBgQICfl/BAwNEgB/KjMEBwcHBwcHB8XFxcXFxcXFx8XFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFAAABxcXFxcXFxcXFxcXFxcXFxQAAAcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFvcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwMHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBgcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHDgcHKgcHMzMzGjszMzMzMzMzMzMzMzMHBwcHBwcHBwcHBwcHBwcHAAABBwcOBwcHBwcHxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcUHBwcHBwcHBwcHBwcCECIHBwcHBwcHBwcHBwcHBwcHBwcHBwcHAAABBwcHFwcHBwcHAwcHBwcHBwIQIgIQIgYuLwAAAQQwMfl/BAwNEg8QIgIQIgYuLwQwMSozBDQ1NiIGBAgJ+X8EDA0SDwQqMwQHBwcHBwcHxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFscXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxbfFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxeHFxcXFxcXFxcXFxcXFxcXFxcXFxcXNxcXFxcXFxcXFxcXFxcXFxcXFxcXF28XFxcXFxcXFxcXFxcXFxcXVxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxQHFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxdTFxcXFxQcHBwcHBwcHBxAREhMEFBESQAABFjEzMzMzMzMzMxEzMzMzMzMz/38TBBQRFhcEGCQaGwQUHQIQIgYECAn5fwQMJxIPBBAREhMEQAAWFuiAAAAbBBQdABAzBDQxf/7//wgJBwcHBwcHBwcHBwcHBwcGBwcHBwcHBwcHBwcHBwcOB08HBwcHByEHBwcHBwcHBwcHBwcHBwcHBwcHCQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBxcHBwcHBwcHBwcHxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxfv7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7+/v7xcXFxcXFAMXFxcXFxcXFxQAAAcXFxcXFxcXFxcXFxcUHBwcH 15 -1
+AAABASIAwA4= 0 1 AA== 2 .
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2NjY2NjY0Ejc2NjYAAADeAzYAAAE2NjY2NjY2NjbeAzYAAAE2NjY2NiQ2NjT/fzY2NjY2NhU2Nk82NjY2NiQ2Nv//gAB2dnZ2dnZ2/wsAQP82NjY2NDYAAAEAAQCAAAABNjYLUDY20M7Q0NDQ0NDQM9DQ4tDQ/38AAAABFBQ2NgAB0NCQAAAUFBQUNjaAAQB/NlgrNjY2NjZ2dnZ2dnZ2dv8LAAABABs= 0 148 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2NjY2NjY0Ejc2NjYAAADeAzYAAAE2NjY2NjY2NjbeAzYAAAE2NjY2NiQ2NjT/fzY2NjY2NhU2Nk82NjY2NiQ2Nv//gAB2dnZ2dnZ2/wsAQP82NjY2NDYAAAEAAQCAAA== 340 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\0046666666664\0187666\000\000\000\222\0036\000\000\001666666666\222\0036\000\000\001666.6\$664\255\127666666\02166O66666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATYmNjY0/zY2NjYAAADeCDY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATYmNjY0/zY2NjYAAADeCDY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAA 618 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\0016&664\2556666\000\000\000\222\0086666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\1276X+66666vvvvvvvv\255\011\000
+NjYAAAF2ZAAAFwtAAAABgn//AAABA0SAgAABCALLFTZXLNDGAAAU/wABAAIAAAAAgAAAAQkiHBU2V0XQ0JAAABQD6DZPrQAAAQCAAAAAAAEBAAIcFTZXRdDQkAAAFKP/AAAAo5Ojo6O+o56jo6Ojo6Ojo6Ojo6Ojo6MAAAGjdtB/AAAUAAAnNjVA3gABNv8AAzb/AAABdnZ2dnb/CwD8AQAb 54 -1
+ARERERERES42wsLCwuKfwsLCwsLCNjYkFTYiNjY2NjZ2Ngk2NjY2NIBYNg4QATYF//8F/zYXNjYAAACAAzY2VjY2SjY2NjY2ADYAAAABABsAECcAARw2NjYnpxknJycAAABAAOUBHDY2NgAAAQAAEjY0/382NjZNFzYVNhZPNgABAACA//////8F/zYXNjYRAPLeAzY2NjY2NjY2JCw2//+AAHYAABABNgX//wX/Nhc2NhEA8t4DNjY2NjY2djPQ0OLQ0NAAAAD7EBQUHTblgNDQkAAQKBQUGw== 0 -1
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAqATY2NjY0/zY2NjYAAADeAzZPNjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAqATY2NjY0/zY2NjYAAADeAzZPNjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sBNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAATY2ClA2NtDO0NDQ0NDQ0DPQ0OLQ0NAAAAD7EBQUNjYAAdDQkAAAFBQUFDY2gAEAfzZYKzY2NjY2dnZ2dnZ2dnb/CwAA 615 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000*\00166664\2556666\000\000\000\222\0036O66666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0016\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\00166\010P66\208\206\208\208\208\208\208\208\208.\208\208\226\208\208\208\000\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\02066\128\001\000\1276X+66666vvvvvvvv\255\011\000
+BOhtAG0AAAA= 0 6 BOhtAG0A 11 \232m\000m
+MzY238LYnwCAf8LCbzY2th82bzY2thU2NDYANiQlJicEKAAAAAHpARA2NwQ4OAE7BD49Pj8A 4 -1
+BOgAAMAfNjY2wsJAwsLCwsLCwp/CNjY2NjYAAIABABtnFTYABDY2NjY2CTY2NjY0gGA2ABABNjY2NmcxNgAENjYjNjYnBCgpNjcEODg6OwQ8PT4/AA== 0 -1
+BOgAEACf1MLCwsLCNgABABtnFTYABjY2NjY2CTY2NjY0gFhZADg4OTsEPD0+PwA= 0 -1
+ZAGU0g== 0 -1
+AAEp 1 -1
+//9/A4o= 5 -1
+//8FDgMEBwQsLS4nBC0AEwIQAAcAAH/fMjMEAAABCAkKTy4gAB8ANgQsLS4vBAcAAH/fMjMENDU2CCAAHwA2BCwtLi8eBC4gAB8ANgQsIAAfAC4vBH8QHgQ/OTpPLiCVlZWVlZWVlZWVlZWVBwcHBwcHBwcHBwYHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBw4HBwcHBzMzMxo7MzMzMzMzMzMzMzMzBwcHBwcHBwcHBwcHBxgHBwcHDgcHBwcHBwchBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcHBwcHBwcHAhAiBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBxcHBwcHBw0HBwcHBwcCECICECIGLi8AAAEEMDH5fwQMDRIPECICECIGLi8EMDEqMwQ0NTYiBgQICfl/BAz/EQ8EKjMEBwcHBwcHBwcHBwcHBwcHBxAREhMEFBESQAABFhczMzMzMzMzMxEzMzMzMzMz/38TBBQRFhcEGCQaGwQUHQIQIgYECAn5fwQMJxIPBBAREhMEQAAWFuiAAAAbBBQdABAzBDQxf/7/FAgJBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcOBzMzMwcHBwcHBwcHBwcHBwcHBwcHBw4HBwcHBwcHIQcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHFwcHBwcHBwcHBwcHBwIQIgcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcNBwcHBwcHAhAiAhAiBi4vAAABBDAx+X8EDA0SDxAiAhAiBi4vBDAxKjMENDU2IgYECAn5hgQMDRIPBCozBAcHBwcHBwcHBwcHBwcHBwcQERITBBQREkAAARYXMzMzMzMzMzMRMzMzMzMzM/9/EwQUERYXBBgkGhsEFB0CECIGBAgJ+X8EDCcSBwcHBwcHBwcHBwcHBwcHBwcHBwcXBwcHBwcHBwcHBwcHBwcHfwAEJDQdAhAiAhBAAhAiAhAiEkAAARYXBBgZGhsEFB0gHwAzMzM= 5 -1
+BA8ICAgEBAUG6wQICQoLBAxuJSY2BBAAAAAEFC0uIFAzBDM1NjkEOB45OwQAAAE0NSk3BDgAOQQrNjkEOH////9QUQQ0KQIQIgYEECICEEACAhAiBgQIAgICAgIQIgIQQAIQIgIQIgYECAkiAgICkCICEEACECICECIGBAgJ/37hDA0gDwQQDRITBAEVFhcEGAEVFhcEGDoaGwQLHR4Q8TQpIhkEJDo1KSIZBCQkAAACAEAQQAIQIgIEECICEEACAhAiBgQIAgICAgIQIgIQQAIQIgIQIgYECAkiAgICECICBBAiAhBAAgIQIgYECAICAgICECICEEACECICECIGBAgJIgICApAiAhBAAhAiAhAiBgQICf9+4QwNIA8EEA0SEwQBFRYXBBgBFRYXBBg6GhsECx0eApAiAhBAAhAiAhAiBgQICf9+4QwNIA8EEA0SEwQBFRYXBBgBFRYXBBg6GhsECx0d/PEkJAAAAgBAEEACECICECIGBAgCHQICAv4QIgYECAJAAgIC/gICOwIQIgIQQAIQIgIQIgIQQAIQIgIQBAQgKSIjBCQkDgACAEACECICEEACECICEAAAASIGBAgCQAICAv4CAjsA 0 -1
+BAABAgMEERITBBQVFhceHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaWwRcXV5fBGBhYmMEZGVmZwRoaWprBGxtbm8EcHFycwR0dXZ3BHh5ensEfH1+fwSAgYKDBISFhocEiImKiwSMjY6PBJCRkpMElJWWlwSYmZqbBJydnp8EoKGiowSkpaanBKipqqsErK2urwSwsbKzBA== 0 -1
+BAABAgMEBAUGBwQAAAEABAwNDhQEEBESEwQUNBYXBAcH5wYHogcHByoHBwcHBwcHDQcHBwcHBwAQBwcHByKANTM2NwQ4OTo7BDxRPj8A 0 78 BAABAgMEBAUGBwQAAAEABAwNDhQEEBESEwQUNBYXBAcH5wYHogcHByoHBwcHBwcHDQcHBwcHBwAQBwcHByKANTM2NwQ4OTo7BDxRPj8A 226 \000\001\002\003.\004\005\006\007.\000\000\001\000.\012\013\014\020.\016\017\018\019.\0204\022\023.\007\007\231\006.\162\007\007\007*\007\007.\007\007\007\007\013\007\007.\007\007\007\000\016\007\007.\007\"\1285367.89:\;.<Q>?
+BAAJCgsEGA0ODwQQERIEBAUGDQ4PBBAREhMEFBUWEwQUFRYXBBgZGhsEkx0eHxobBJMdDB8EICEiIwQ2NDUEkx0eDg8EEBESEwQEGBkaGwSTHQ== 0 -1
+BAAEBQYHBAgJCgsEDA0kJSYnBCgpKisELC0uLwQwMTIzBDQ1NjcEgAA6OwQ8PT4/BEBBQkMEREVGRwRISUpLBExNTk8EUFFSUwRUVVZXBFhZWlsEXF1eXwRgNTY3BDg5OjsEPD0+PwRAQUJDBERFRkcEdHV2dwR4eXp7BHx9fn8EgIGCgwSEhYaHBIiJiosEjI2OjwSQkZKTBJSVlpcEmJmamwScnZ6fBKChoqMEpKWmpwSoqaqrBKytrq8EsLGyswQ= 8 -1
+BAAEBQYHBAgJCgsEDA0ODwQQBBgZGhsEHB0hIiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NTY3BDg5OjsEPD0+XwRgYWBjBGRlZmcEaGlqawRsbW5vBHBxcnMEdHVWVwRYWVpbBFxdXl8EYGFiYwRkZWZnBGhpamsEbG1ubwRwcXJzBHR1dncEeHl6ewR8fX5/BICBgoMEhIWGhwSIiYqLBIyRjo8EkJGSkwSUlZaXBJiZmpsEnJ2enwSgoaKjBKSlpqcEqKmqqwSsra6vBLCxsrME 8 -1
+AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgIQIgYECAn/fwQMDRIPBBAIEhMEARUWFwQYOhobBCY1KSIZBCQkAAACDkACECICEEACECICECICEEACECICEB8EICkiIwQkJAAAAgBAAhAiAhBAAhAiAhAAAA== 0 202 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgIQIgYECAn/fwQMDRIPBBAIEhMEARUWFwQYOhobBCY1KSIZBCQkAAACDkACECICEEACECICECICEEACECICEB8EICkiIwQkJAAAAgBAAhAiAhBAAhAiAhAAAA== 590 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004&5\)\"\025\004\$\$\000\000\002\014\@\002\016\"\002.\@\002\016\"\002\016\"\002\016\@\002\016\"\002\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\".\016\@.\016\".\016\000
+5h3eAgMEBAUGByQrCS0QAADy/38AzSoAAAFkLi8BLC0uL4AAAAEwMf///4ABQH8AQAAAAQAAY2QAZS8BLC1AZQAAAWVmZwQAAAFwZQBleARkZWZn6AP0//xwAAABYGRlAAAA5RAQAAABAQAAAAHw7uzs/+x/AEBlAPABgoMWEAD//w== 8 8 BgckKwktEAA= 17 \007\$+\009-\016
+BB8BAAAAAAEEBCEGBwAAAQQICQQhBgQICQoT2xMVAAABFhAoKRsuLwQwE9sTFQAAARYXBBgZMCsCAwQhPw== 8 6 BAQhBgcA 14 \004!\006\007
+BB8BAgMEBAUGCwQMDQ4PBAgIAQgICAgICAgICAcECAkKCwQMDQ4PBAgIAQgICAgICAgICAgICAgJCAgICAgICAgICAgICAgICAh0B/AICAgBCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAj/fwAACAgAAAAACHQAAAH/AAgICAg= 8 122 BgsEDA0ODwQICAEICAgICAgICAgHBAgJCgsEDA0ODwQICAEICAgICAgICAgICAgICQgICAgICAgICAgICAgICAgIdAfwCAgIAQgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgI/38AAAgIAAAAAAh0AAAB/wA= 427 \011\004\012\013\014\015.\008\008\001\008.\008\008\008\008\008\008\008\007.\008\009\010\011.\012\013\014\015.\008\008\001\008.\008\008\008\008\008\008\008\008.\008\008\009\008\008\008\008\008.\008\008\008\008\008\008\008\008.\008\008t\007\240\008\008\008.\008.\008\008\008\008\008\008\008\008.\008\008\008\008\008\008\008\008.\008\008\008\008\008\008\008\008.\008\008\008\255\127\000\000\008.\000\000\000\000\008t\000\000.\255
+AgAAAgBAAhAiAhBAAhAiAhAiBgQIDf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaIiMEBCQAAAIAQAIQAAIfQAIQIgIQIgYECAIChgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEAIECIiAEACECICECIGBAgCQAICAv4CADsA 0 250 AgAAAgBAAhAiAhBAAhAiAhAiBgQIDf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsEC4AAAAA1KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaIiMEBCQAAAIAQAIQAAIfQAIQIgIQIgYECAIChgICECICEEACECICECIGBAgJ/38EDA0SDwQQCBITBAEVFhcEGDoaGwQUHR4fJjUpIhkEJCQQIgIQIgIQQAIQIgIQHwQgKSIjBCQkAAACAEAIECIiAEACECICECIGBAgCQAICAv4CAA== 754 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\013\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\128\000\000\0005\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\"#\004\004\$\000\000\002\000\@\002\016\000\002\031\@\002\016\".\016\".\004\008\002\002\134\002.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\020\029\030\031&5\)\"\025\004\$\$\016\"\002\016\".\016\@.\016\".\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\"\"\000\@\002\016\".\016\".\004\008\002\@\002\002.\254\002
+ISEhISEhISEhISEhISEhISEhISEAA+gAISEhISEhISEhISEhISEhGiEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhISEhIYAhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhIRAhISEhISEhISEhISEhISEhISEhISEhISEhIYAhISEhISEpcnN0dXZAAAAAew== 33 205 ISEhISEhGiEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhISEhIYAhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhQyEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISEhISF+ISEhISEhISEhIRAhISEhISEhISEhISEhISEhISEhISEhISEhIYAhISEhISEpcnN0dXZAAA== 218 !!!!!\026!!!!!!!!!!!C!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!!!!!!!~!!!!!!!!!!!.!\128!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!C!!!!!!!!!!!!!!!!!!!!!.!!!!!!!!!!!!!!!~!!!!!!!!!!\016!!!!!!.!!!!!!!!!!!!!!!!!!!\128!!!!!!\)rstuv\@
+AUABQwFEAUUBRgFPAVABUQFSAVMBVAFVAVYBVwFYAVkPWgFbAVwBXwFgAWEBYgFjAWQBZQFmAWcBaAFpAWoBawFsAW0BbgFvAXABcQFyAXMBdAF1AXYBdwF4AXkBegF7AXwBfQF+NjY2NjYAAAABBB82NgAAATY2NiQVNjQ2NjY2NjY2NjY2NjY2NgAAAAEENgAAATY2NjY2NgAAATY2NjY2NjY2AAAAAQQ2NjY2NjY2NjY2NjY2AAAANjY2NjY2NjYAAAABBDY2NjY2NjY2NjY2NiQgNjQ2NjY2NlE2NjY2NjY2NjY2Nho2Nn92dnZ2dpZ2dnb//0E2AQAAAQAAARY2 0 -1
+BwEBQwBkAQABRgFPAVABUQFSAesBVAFVAVYBbAFYAVkBWgFbF1wBAAABXwFgAVQBYgFrAWQBZQFmAWcBaAFpAWoBawdsAV0BbfxvAVs2NgBQNjYkZDY0NiQAZjZRNjY2Nv9aAVsBWwFfAQBQtDY2NjY2/1o2ZjZRNrdENjYAAAQ2NjY2MP9aAAEENgAAATY22jY2PwAABDY2AAAAAQQ2Gf4BNkc2Nr5LS0tLAAABSwE2vh0AATY2NuxQNjYkZDY0JCQ2ZjZRNks2AAABNmRaAVsbXAFfAWAAYQFiAWP/////AAABAWYBNgEAAAEAAAEWNg== 0 -1
+AUABQvZEAUUBRgFPAVABUQFSAVMBVAFVAVYBVwFLS0tLS0tLATa+HQDxNRc2AFgBWWH/AXMXdAF1AZEBdwF4AXkBegF7AXwBZwFo7GkBagFrAWwAAAFuAW8BcAF/AXIBcwEAAAH1kAF3AXgBeQF6AXsBfAAAAQF9AX42NjY2AAABAAEEHzY2AAABNjY2JBVdXV1dXV1dXV02NDY2NjY2NjY2NjY2NjY2AAAAAAABAQQ2AAABNjY2NjY2AAABAAABNjY2NjY2NjYAAAABGjY2NjY2NjY2NjY2NjYAAAEPHh4eHh4eHh4eHh4eHh4A5B4eAAAAAQAbS2xLS0tLS0tLATa+HQDxNRc2AFA2NiQsNjQ2GzY2NlE2NjY2NjY2NjY2Af/pAAABFjY= 0 -1
+AAAAAQIAAAGgACABgAGDDKABJQ== 0 1 AA== 2 .
+AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgIQIgYECAn/fwQMDRIPBBAIEhMEARUWFwQYOhobBBQdHh8mNSkiGQQkJAAAAg5AAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQAAAIAQAIQIgIQQAIQIgIQAAA= 0 206 AgAAAgBAAhAiAhBAAhAiAhAiBgQICf9/BAwNEg8EEAgSEwQBFRYXBBg6GhsECx0eHw01KSIZBCQkAAD/AEACECICEEACECICECIGBBAiAhBAAhAiAhAfBCApIiMEBCQAAAIAQAIQAAIQQAIQIgIQIgIQIgYECAn/fwQMDRIPBBAIEhMEARUWFwQYOhobBBQdHh8mNSkiGQQkJAAAAg5AAhAiAhBAAhAiAhAiAhBAAhAiAhAfBCApIiMEJCQAAAIAQAIQIgIQQAIQIgIQAAA= 588 \000\000.\000\@.\016\".\016\@.\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\011\029\030\031\0135\)\"\025\004\$\$\000\000\255\000\@.\016\".\016\@.\016\".\016\".\004\016\"\002\016\@.\016\".\016\031.\032\)\"#.\004\$\000\000.\000\@.\016\000.\016\@.\016\".\016\".\016\".\004\008\009\255\127\004.\013\018\015\004\016\008\018\019\004\001\021\022.\004\024:\026\027\004\020\029\030\031&5\)\"\025\004\$\$\000\000\002\014\@.\016\".\016\@.\016\".\016\".\016\@.\016\".\016\031.\032\)\"#.\$\$\000\000.\000\@.\016\".\016\@.\016\".\016\000
+AgAABgYGBgYcBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgQGBgYGBgYGBgYGBgYEBgYGBgYGBgYGBgYGBAYGBgYGBgYGBgYGBgYGBgYGQAYG/xAGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgZkBgYGBgYGBgayBgYGBgYGBgYGBgYGBgUGBgYGBgYGBgYGBgYaBgYGBgYGBgYGBgYGEwYGBgYGACAGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBughHh8EICkiIwQvJOsnBAgpKisALA== 0 255 AgAABgYGBgYcBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgQGBgYGBgYGBgYGBgYEBgYGBgYGBgYGBgYGBAYGBgYGBgYGBgYGBgYGBgYGQAYG/xAGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgZkBgYGBgYGBgayBgYGBgYGBgYGBgYGBgUGBgYGBgYGBgYGBgYaBgYGBgYGBgYGBgYGEwYGBgYGACAGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBgYGBughHh8EICkiIwQvJOsnBAgpKisA 871 \000\000.\006\006\006\006\028\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\004\006\006\006\006.\006\006\006\006\006\006.\004\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\@.\006\255\016\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006d\006\006\006.\006\006\006\006\178\006.\006\006\006\006\006\006.\006\006\006\006\005\006.\006\006\006\006\006\006.\006\006\006\026\006\006.\006\006\006\006\006\006.\006\006\019\006\006\006.\006\000\032\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\006\006\006\006.\006\006\232!\030\031.\032\)\"#./\$\235'.\008\)*+
+BAABAgMEERITBBQVFtckHwQgISMjBCQlJicEKCkqKwQsLS4vBIAAMjMENDU2NwQ4/4A7BDw9Pj8EQEFCJwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaWwRcXV5fBDcEMzk6OwQ6WgQ8PT4/AA== 0 -1
+BAAB7gMEERITBBQVFhceHwQgIQgjBCQlJgQUFRYXBBgZGhsPHB0eHwQgIQAAAQ== 0 -1
+AABAAP//ERPyvwJEGB4bBBETNgQUFRPyvwJEGB4fGwQdEzYEKBUWFx4eHwQvHxgekwABDBsAASIjXl5eXl5eXl5eXl5eXl5eXiQ= 0 1 AA== 2 .
+LS4vBDAxMjMENDUAAAE2NwAEAAECAwTyERMEFBUWFx4fBCAhMiMEJCUmJwQoKSorBCwtLi8EMDEyMwQ0NQAAATY3BDg5OjsEPD0+PwRAQUJDBDlFRkcESEn//4AATU5PBFBRUlAEVFVWVwRYWVpbBFxdXl8EYGFiYwRkRmZnamsEbG1ubwRwcXJzBHR1dndpeHl6ewR8fX5/BICBgoMEhIWGEBAQEBAQEBAQEP///38QEBAQEBAQEBCA/xAQEBAQEBAQEBAQEAAAARAQEBAQAAToBAMDgAAAAfoD6AI= 44 -1
+BAABAgMEERITBBQVFhceHwQgISIjBCQlJicEKCkqKwQsLS4vBDAxMjMENDU2NwQ4OTo7BDw9Pj8EQEFCQwRERUZHBEhJSksETE1OTwRQUVJTBFRVVlcEWFlaWwRcXWRfBGBhYmMEZGVmZwRoaWprfwSAgYKDBISFhhAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAE6AQDAwP6A+gC 0 -1
+FA== 0 -1
+AQABAwEiAQcBCAEJAQoBCwEMAZ/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQATZxU2AAQ2Ni42Ngk2NjY2NIBYNgAQATY2NhM0/yI2NjYAAADeAzY2NjY2AAAAAQAbZ+oAAYNLS0tLaUtLATa+kHZ2dh9GFAA2NjYAADYDNjY2NjY2NjY2NjY2NgAAAAEAG2fqAAFsS0tLS2lLSwE2vnZ2dnYfRhQANjY2AAA2NiQ2NjT/fzbsNjY2NhU2NgAAATY2NiQ2Nv//gAB2dnZ2dnZ2/wsANiQ2NjT/fzbCwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NhM0/zY2NjYAAADeAzY2NjYwNjY2NjY2NjYAAAABABtnNjY2Ngk2NjY2NIBYNgAQATZANhM0/zY2NjYAAADeAzY2Njb/NjY2NjYAAAE2NjYAAAABABtn6gABbEtLS0tpS0sBNr6QdnZ2H0YUADY2NgAANgM2NoD///82NjY2NjY2AAAAAQAbZ+oAAWxLS0tLaUtLATkAAAG+dnZ2dh9GFAA2NjYAADY2JDY2NP9/NjY2NjY2FTY2AAABNjY2JDY2//+AAHZ2dnZ2dnb/NjY2AAQ2AAAAAQAbZxU2AAQAAAE2NjY2Ngk2NjY2NIBYNgAQATY2NhM0/zY2NjYAAADeAzY2NjYwNjY2NjY2NjYAAAABABtnNjYhNjYVNjZPNjY2NjYkNjb/34AAbXZ2dnZ2dv8L0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0bnR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0dHR0QJA6DY2NjY0NgAAAQABAIAAAAE2NgpQNjbQsSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKSkpKQEAGw== 0 -1
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sNNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAARU2ClA2NtDO09DQ0NDQ0DPQ0OLQ0AAgAAD7EBQUNjYAAdDQkAAAFBQUFMLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NgAAAQAb 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjY2NIBYNgAQATY2NjY0/zY2NjYAAADeAzY2NjY2NjY2NjY2NjYAAAABABtn6gABbEtLS0tpS0sNNr52dnZ2H0YUADY2NgAANjYkNjY0/382NjY2NjYVNjZPNjY2NjYkNjb//4AAdnZ2dnZ2dv8LAED/NjY2NjQ2AAABAAEAgAAAARU2ClA2NtDO09DQ0NDQ0DPQ0OLQ0AAgAAD7EBQUNjYAAdDQkAAAFBQUFMLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NgAA 655 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\00966664\128X6\000\016\00166664\2556666\000\000\000\222\0036666666666.66\000\000\000\001\000\027g\234\000\001lKKKKiKK\0136\190vvvv\031F\020\000666\000\00066\$664\255\127666666\02166O.6666\$66\255\255\128\000vvvvvvv\255\011\000\@\255666646\000\000\001\000\001\000\128\000\000\001\0216\010P66\208\206\211\208\208\208\208\208\208.\208\208\226\208\208\000\032\000\000\251\016\020\02066\000\001\208\208\144\000\000\020\020\020\020\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466\000
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AMXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxcXFxfr6+vr6xcUAAAEAG2cVNgAENjY2NjYJNjY2NjSAWDYAEAE2NjY2NP82NjY2AAAA3gM2Nrw2NjY2NjY2NjY2AAD8AAAbZ+oAAWxLS0tLaUtLDTa+dnZ2dh9GFAA2NjYAADY2JFE2NP9/NjY2NjY2FTY2TzY2NjY2JDY2//+AAHZ2dnZ2dnb/CwBA/zY2NjY0NgAAAQABAIAAAAEVNgpQNjbQztPQ3NDQ0NAz0NDi0NDQAAAA+xAUFDYAAAPo0JAAABQUFBQ2Ns0BAH82WCs2NjY2NnYAAP//dnZ2/wsAAAEAGw== 0 -1
+BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjYdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugHWEbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHUAd0B3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9AQEA/wA= 0 255 BOgAAMAfNjY2wsLCwsLCwsLCwp/CwsLCwsI2NiQVNjQ2NjY2NjY2AAAAAQAbZxU2AAQ2NjY2Ngk2NjYdAR4BnwGgAaEBogGjAaQBpQGmAacBqAGpAaoBqwGsAa0BrgGvAbABsQGyAbMBtAG1AbYBtwG4AbkBugHWEbwBvQG+Ab8BwAHBAcIBwwHEAcUBxgHHAcgByQHKAcsBzAHNAc4BzwHQAdEB0gHTAdQB1QHWAdcB2AHZAdoB2wHUAd0B3gHfAeAB4QHiAeMB5AHlAeYB5wHoAekB6gHrAewB7QHuAe8B8AHxAfIB8wH0AfUB9gH3AfgB+QH6AfsB/AH9AQEA 717 \232\000\000\192.666\194\194\194\194\194\194\194\194\194\194\159\194\194\194\194\194\19466\$\0216466666.6\000\000\000\001\000\027g\0216\000\00466666\009666\029\001\030\001\159\001\160\001\161\001\162\001\163\001\164\001\165\001\166\001\167\001\168\001\169\001\170\001\171\001\172\001\173.\174.\175.\176.\177.\178.\179.\180.\181.\182.\183.\184.\185.\186.\214.\188\001\189\001\190\001\191\001\192\001\193\001\194\001\195\001\196.\197.\198.\199.\200.\201.\202.\203.\204.\205.\206.\207.\208.\209.\210.\211.\212.\213.\214.\215.\216.\217.\218.\219.\212.\221.\222.\223.\224.\225.\226.\227.\228.\229.\230.\231.\232.\233.\234.\235.\236.\237.\238.\239.\240.\241.\242.\243.\244.\245.\246.\247.\248.\249.\250.\251.\252.\253.\001
+BOgAAMAfNjY2wsLCwsLCwsLCwp8EMDEFGAEfASABIQEiASMBJAEnASgBKQEqASsBLAEtAS4BNwE4ATkBOiA7ATwBPQE+AT8NAQ4A/gEQAREAAH//ARQBFwUYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBKQEqASvALMLCwsLCwsLCwp8EMDEFGAEfASABIQEiASMBJAEnASgBKQEqASsBLAEtAS4BNwE4ATkBOiA7ATwBPQE+AT8NAQ4A/gEQAREAAH//ARQBFwUYARkBGgEbARwBHQEeAR8BIAEhASIBIwEkASUBJgEnASgBKQEqASvALAEtAS4BJwEoAUgBKgErASwBLQEuATsBLQEuAScBKAFIASoBKwEsAS0BLgE7ATwBPQE+AT8A 0 -1
+BAABAgMEAAABBwQICQoLBBINDg8EEBESEwQUFRYXBBgZGhsEHB0eNjY2AAA2NjY2Njw2ATYYNkUAAAIQ//9/TExMTExMTExMTExMTExMTExMTExMTENMbxMTExNqEykTlhMTEyYLAAEUFAAABjY2NjYAUwE2NhwAAAABAAABBDb/fwAAAzY2NgX//wU2NgD7SDYkNjk5OTk5OTk5OTk5OTk5OTk5OTk5PTY0pDY2NjY2NiQAAAE2Nn82cXZ2dnZ2dnZ20Coq0DPQ0P/gM9DQ//9//9AAAAHSu9DRkNAABgAA/xQUAAAGfzYkNjY0Nks2AAQeVTb/AAABNn////8= 0 -1
+BAABAgMEBAgJCgsEDA0ODwQQERITBAQ0NTY3BDg5OjsEPD0iIwQkJSYnBD8pKisELC0uLwQwMTIzBDQ1NjcEODk6OwQ8PT4/BEBFRkcESElKSwRMTUNPBFBRUlsEVFVWVwRYWVpbBFxNXl8EYGFiYwRkZWZnBGhpamsEbG0eHwQgISIjBCQlJicEKCkqKwQsLScvBICBgoME+oWGhwSIiYqLBDQ1NjcEODk9Pj8EQEFCQw== 0 -1
+AgAAAhBiAgAAAhAiAQEBAgFXAhBiAgAAAhABAgFXAQECEGICAAACECIBVwEBAgFXAQEBAQIBVwAAAQ== 0 56 AgAAAhBiAgAAAhAiAQEBAgFXAhBiAgAAAhABAgFXAQECEGICAAACECIBVwEBAgFXAQEBAQIBVwA= 129 \000\000.\016b.\000\000.\016\".\001.\002.W.\016b.\000\000.\016\001.\001W.\001.\016b.\000\000.\016\".W.\001.\001W.\001.\001.\001W
+wMAAAcDAwMDANgMDAwMDAwMDA/oAAA== 16 5 AwMD+gA= 13 \003\003\250
diff --git a/resolv/tst-ns_name_compress.c b/resolv/tst-ns_name_compress.c
new file mode 100644
index 0000000000..c1262e0ec1
--- /dev/null
+++ b/resolv/tst-ns_name_compress.c
@@ -0,0 +1,76 @@
+/* Test ns_name_compress corner cases.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <resolv.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/support.h>
+
+/* Check that we can process names which fit into the destination
+ buffer exactly. See bug 21359. */
+static void
+test_exact_fit (const char *name, size_t length)
+{
+ unsigned char *buf = xmalloc (length + 1);
+ memset (buf, '$', length + 1);
+ enum { ptr_count = 5 };
+ const unsigned char *dnptrs[ptr_count] = { buf, };
+ int ret = ns_name_compress (name, buf, length,
+ dnptrs, dnptrs + ptr_count);
+ if (ret < 0)
+ {
+ support_record_failure ();
+ printf ("error: ns_name_compress for %s/%zu failed\n", name, length);
+ return;
+ }
+ if ((size_t) ret != length)
+ {
+ support_record_failure ();
+ printf ("error: ns_name_compress for %s/%zu result mismatch: %d\n",
+ name, length, ret);
+ }
+ if (buf[length] != '$')
+ {
+ support_record_failure ();
+ printf ("error: ns_name_compress for %s/%zu padding write\n",
+ name, length);
+ }
+ free (buf);
+}
+
+static int
+do_test (void)
+{
+ test_exact_fit ("abc", 5);
+ test_exact_fit ("abc.", 5);
+ {
+ char long_name[]
+ = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.";
+ TEST_VERIFY (strlen (long_name) == NS_MAXCDNAME - 1);
+ test_exact_fit (long_name, NS_MAXCDNAME);
+ long_name[sizeof (long_name) - 1] = '\0';
+ test_exact_fit (long_name, NS_MAXCDNAME);
+ }
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-ns_name_pton.c b/resolv/tst-ns_name_pton.c
new file mode 100644
index 0000000000..6640ed3021
--- /dev/null
+++ b/resolv/tst-ns_name_pton.c
@@ -0,0 +1,210 @@
+/* Tests for ns_name_pton.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <arpa/nameser.h>
+#include <array_length.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/test-driver.h>
+
+/* Bits which indicate which functions are supposed to report
+ success. */
+enum
+ {
+ hnok = 1,
+ dnok = 2,
+ mailok = 4,
+ ownok = 8,
+ allnomailok = hnok | dnok | ownok,
+ allok = hnok | dnok | mailok | ownok
+ };
+
+/* A string of 60 characters. */
+#define STRING60 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
+
+/* A string of 63 characters (maximum label length). */
+#define STRING63 STRING60 "zzz"
+
+/* A string of 60 bytes (non-ASCII). */
+#define STRING60OCT \
+ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \
+ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \
+ "\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377\377" \
+ "\377\377\377\377\377\377\377\377\377"
+
+/* A string of 63 bytes (non-ASCII). */
+#define STRING63OCT STRING60OCT "\377\377\377"
+
+/* A string of 60 bytes (non-ASCII, quoted decimal). */
+#define STRING60DEC \
+ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \
+ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \
+ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \
+ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \
+ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255" \
+ "\\255\\255\\255\\255\\255\\255\\255\\255\\255\\255"
+
+/* A string of 63 bytes (non-ASCII, quoted decimal). */
+#define STRING63DEC STRING60DEC "\\255\\255\\255"
+
+/* Combines a test name with the expected results. */
+struct test_case
+{
+ const char *dn;
+ const char *back; /* Expected test result converted using ns_name_ntop. */
+ bool fully_qualified; /* True if the domain name has a trailing dot. */
+};
+
+static const struct test_case tests[] =
+ {
+ { "", ".", false },
+ { ".", ".", true },
+ { "..", NULL, },
+ { "www", "www", false },
+ { "www.", "www", true },
+ { "www\\.", "www\\.", false },
+ { ".www", NULL, },
+ { ".www\\.", NULL, },
+ { "example.com", "example.com", false },
+ { "example.com.", "example.com", true },
+ { ".example.com", NULL, },
+ { ".example.com.", NULL, },
+ { "example\\.com", "example\\.com", false },
+ { "example\\.com.", "example\\.com", true },
+ { "example..", NULL, },
+ { "example..com", NULL, },
+ { "example..com", NULL, },
+ { "\\0", NULL, },
+ { "\\00", NULL, },
+ { "\\000", "\\000", false },
+ { "\\1", NULL, },
+ { "\\01", NULL, },
+ { "\\001", "\\001", false },
+ { "\\1x", NULL, },
+ { "\\01x", NULL, },
+ { "\\001x", "\\001x", false },
+ { "\\256", NULL, },
+ { "\\0641", "\\@1", false },
+ { "\\0011", "\\0011", false },
+ { STRING63, STRING63, false },
+ { STRING63 ".", STRING63, true },
+ { STRING63 "z", NULL, },
+ { STRING63 "\\.", NULL, },
+ { STRING60 "zz\\.", STRING60 "zz\\.", false },
+ { STRING60 "zz\\..", STRING60 "zz\\.", true },
+ { STRING63 "." STRING63 "." STRING63 "." STRING60 "z",
+ STRING63 "." STRING63 "." STRING63 "." STRING60 "z", false },
+ { STRING63 "." STRING63 "." STRING63 "." STRING60 "z.",
+ STRING63 "." STRING63 "." STRING63 "." STRING60 "z", true },
+ { STRING63 "." STRING63 "." STRING63 "." STRING60 "zz", NULL, },
+ { STRING63 "." STRING63 "." STRING63 "." STRING60 "zzz", NULL, },
+ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT "\377",
+ STRING63DEC "." STRING63DEC "." STRING63DEC "." STRING60DEC "\\255",
+ false },
+ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT "\377.",
+ STRING63DEC "." STRING63DEC "." STRING63DEC "." STRING60DEC "\\255",
+ true },
+ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT
+ "\377\377", NULL, },
+ { STRING63OCT "." STRING63OCT "." STRING63OCT "." STRING60OCT
+ "\377\377\377", NULL, },
+ { "\\", NULL, },
+ { "\\\\", "\\\\", false },
+ { "\\\\.", "\\\\", true },
+ { "\\\\\\", NULL, },
+ { "a\\", NULL, },
+ { "a.\\", NULL, },
+ { "a.b\\", NULL, },
+ };
+
+static int
+do_test (void)
+{
+ unsigned char *wire = xmalloc (NS_MAXCDNAME);
+ char *text = xmalloc (NS_MAXDNAME);
+ for (const struct test_case *test = tests; test < array_end (tests); ++test)
+ {
+ if (test_verbose)
+ printf ("info: testing domain name [[[%s]]]\n", test->dn);
+ int ret = ns_name_pton (test->dn, wire, NS_MAXCDNAME);
+ if (ret == -1)
+ {
+ if (test->back != NULL)
+ {
+ support_record_failure ();
+ printf ("error: unexpected decoding failure for [[%s]]\n",
+ test->dn);
+ }
+ /* Otherwise, we have an expected decoding failure. */
+ continue;
+ }
+
+ if (ret < -1 || ret > 1)
+ {
+ support_record_failure ();
+ printf ("error: invalid return value %d for [[%s]]\n",
+ ret, test->dn);
+ continue;
+ }
+
+ int ret2 = ns_name_ntop (wire, text, NS_MAXDNAME);
+
+ if (ret2 < 0)
+ {
+ support_record_failure ();
+ printf ("error: failure to convert back [[%s]]\n", test->dn);
+ }
+
+ if (test->back == NULL)
+ {
+ support_record_failure ();
+ printf ("error: unexpected success converting [[%s]]\n", test->dn);
+ if (ret2 >= 1)
+ printf ("error: result converts back to [[%s]]\n", test->dn);
+ continue;
+ }
+
+ if (strcmp (text, test->back) != 0)
+ {
+ support_record_failure ();
+ printf ("error: back-conversion of [[%s]] did not match\n",
+ test->dn);
+ printf ("error: expected: [[%s]]\n", test->back);
+ printf ("error: actual: [[%s]]\n", text);
+ }
+
+ if (ret != test->fully_qualified)
+ {
+ support_record_failure ();
+ printf ("error: invalid fully-qualified status for [[%s]]\n",
+ test->dn);
+ printf ("error: expected: %d\n", (int) test->fully_qualified);
+ printf ("error: actual: %d\n", ret);
+ }
+ }
+
+ free (text);
+ free (wire);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-p_secstodate.c b/resolv/tst-p_secstodate.c
new file mode 100644
index 0000000000..8d5faa2fa1
--- /dev/null
+++ b/resolv/tst-p_secstodate.c
@@ -0,0 +1,84 @@
+/* Test __p_secstodate compat symbol.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <limits.h>
+#include <resolv.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <shlib-compat.h>
+
+#if TEST_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_27)
+
+char *__p_secstodate (unsigned long int);
+compat_symbol_reference (libresolv, __p_secstodate, __p_secstodate, GLIBC_2_0);
+
+struct test
+{
+ /* Argument to __p_secstodate. */
+ unsigned long int in;
+ /* Expected output. */
+ const char *out;
+};
+
+static const struct test tests[] =
+ {
+ { 0UL, "19700101000000" },
+ { 12345UL, "19700101032545" },
+ { 999999999UL, "20010909014639" },
+ { 2147483647UL, "20380119031407" },
+ { 2147483648UL, "<overflow>" },
+ { 4294967295UL, "<overflow>" },
+# if ULONG_MAX > 0xffffffffUL
+ { 4294967296UL, "<overflow>" },
+ { 9999999999UL, "<overflow>" },
+ { LONG_MAX, "<overflow>" },
+ { ULONG_MAX, "<overflow>" },
+# endif
+ };
+
+static int
+do_test (void)
+{
+ int ret = 0;
+ for (size_t i = 0; i < array_length (tests); i++)
+ {
+ char *p = __p_secstodate (tests[i].in);
+ printf ("Test %zu: %lu -> %s\n", i, tests[i].in, p);
+ if (strcmp (p, tests[i].out) != 0)
+ {
+ printf ("test %zu failed", i);
+ ret = 1;
+ }
+ }
+ return ret;
+}
+
+#else
+
+static int
+do_test (void)
+{
+ return 77;
+}
+
+#endif
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-res_hconf_reorder.c b/resolv/tst-res_hconf_reorder.c
index 2ef7f073ca..a16a6b2112 100644
--- a/resolv/tst-res_hconf_reorder.c
+++ b/resolv/tst-res_hconf_reorder.c
@@ -1,6 +1,6 @@
/* BZ #17977 _res_hconf_reorder_addrs test.
- Copyright (C) 2015-2016 Free Software Foundation, Inc.
+ Copyright (C) 2015-2018 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -19,6 +19,7 @@
#include <errno.h>
#include <stdio.h>
+#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <dlfcn.h>
diff --git a/resolv/tst-res_hnok.c b/resolv/tst-res_hnok.c
new file mode 100644
index 0000000000..a000cfd895
--- /dev/null
+++ b/resolv/tst-res_hnok.c
@@ -0,0 +1,169 @@
+/* Tests for res_hnok and related functions.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <resolv.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/test-driver.h>
+
+/* Bits which indicate which functions are supposed to report
+ success. */
+enum
+ {
+ hnok = 1,
+ dnok = 2,
+ mailok = 4,
+ ownok = 8,
+ allnomailok = hnok | dnok | ownok,
+ allok = hnok | dnok | mailok | ownok
+ };
+
+/* A string of 60 characters. */
+#define STRING60 "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz"
+
+/* A string of 63 characters (maximum label length). */
+#define STRING63 STRING60 "zzz"
+
+/* Combines a test name with the expected results. */
+struct test_case
+{
+ const char *dn;
+ unsigned int result; /* Combination of the *ok flags. */
+};
+
+static const struct test_case tests[] =
+ {
+ { "", allok },
+ { ".", allok },
+ { "..", 0 },
+ { "www", allnomailok },
+ { "www.", allnomailok },
+ { "example", allnomailok },
+ { "example.com", allok },
+ { "www.example.com", allok },
+ { "www.example.com.", allok },
+ { "www-.example.com.", allok },
+ { "www.-example.com.", allok },
+ { "*.example.com", dnok | mailok | ownok },
+ { "-v", dnok },
+ { "-v.example.com", mailok | dnok },
+ { "**.example.com", dnok | mailok },
+ { "www.example.com\\", 0 },
+ { STRING63, allnomailok },
+ { STRING63 ".", allnomailok },
+ { STRING63 "\\.", 0 },
+ { STRING63 "z", 0 },
+ { STRING63 ".example.com", allok },
+ { STRING63 "." STRING63 "." STRING63 "." STRING60 "z", allok },
+ { STRING63 "." STRING63 "." STRING63 "." STRING60 "z.", allok },
+ { STRING63 "." STRING63 "." STRING63 "." STRING60 "zz", 0 },
+ { STRING63 "." STRING63 "." STRING63 "." STRING60 "zzz", 0 },
+ { "hostmaster@mail.example.com", dnok | mailok },
+ { "hostmaster\\@mail.example.com", dnok | mailok },
+ { "with whitespace", 0 },
+ { "with\twhitespace", 0 },
+ { "with\nwhitespace", 0 },
+ { "with.whitespace ", 0 },
+ { "with.whitespace\t", 0 },
+ { "with.whitespace\n", 0 },
+ { "with\\ whitespace", 0 },
+ { "with\\\twhitespace", 0 },
+ { "with\\\nwhitespace", 0 },
+ { "with.whitespace\\ ", 0 },
+ { "with.whitespace\\\t", 0 },
+ { "with.whitespace\\\n", 0 },
+ };
+
+/* Run test case *TEST with FUNC (named FUNCNAME) and report an error
+ if the result does not match the result flag at BIT. */
+static void
+one_test (const struct test_case *test, const char *funcname,
+ int (*func) (const char *), unsigned int bit)
+{
+ int expected = (test->result & bit) != 0;
+ int actual = func (test->dn);
+ if (actual != expected)
+ {
+ support_record_failure ();
+ printf ("error: %s (\"%s\"): expected=%d, actual=%d\n",
+ funcname, test->dn, expected, actual);
+ }
+}
+
+/* Run 255 tests using all the bytes from 1 to 255, surround the byte
+ with the strings PREFIX and SUFFIX, and check that FUNC (named
+ FUNCNAME) accepts only those bytes listed in ACCEPTED. */
+static void
+one_char (const char *prefix, const char *accepted, const char *suffix,
+ const char *funcname, int (*func) (const char *))
+{
+ for (int ch = 1; ch <= 255; ++ch)
+ {
+ char dn[1024];
+ snprintf (dn, sizeof (dn), "%s%c%s", prefix, ch, suffix);
+ int expected = strchr (accepted, ch) != NULL;
+ int actual = func (dn);
+ if (actual != expected)
+ {
+ support_record_failure ();
+ printf ("error: %s (\"%s\"): expected=%d, actual=%d\n",
+ funcname, dn, expected, actual);
+ }
+ }
+}
+
+#define LETTERSDIGITS \
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+
+#define PRINTABLE \
+ "!\"#$%&'()*+,/:;<=>?@[\\]^`{|}~"
+
+static int
+do_test (void)
+{
+ for (const struct test_case *test = tests; test < array_end (tests); ++test)
+ {
+ if (test_verbose)
+ printf ("info: testing domain name [[[%s]]] (0x%x)\n",
+ test->dn, test->result);
+ one_test (test, "res_hnok", res_hnok, hnok);
+ one_test (test, "res_dnok", res_dnok, dnok);
+ one_test (test, "res_mailok", res_mailok, mailok);
+ one_test (test, "res_ownok", res_ownok, ownok);
+ }
+
+ one_char
+ ("", LETTERSDIGITS "._", "", "res_hnok", res_hnok);
+ one_char
+ ("middle",
+ LETTERSDIGITS ".-_\\", /* "middle\\suffix" == "middlesuffix", so good. */
+ "suffix", "res_hnok", res_hnok);
+ one_char
+ ("middle",
+ LETTERSDIGITS ".-_" PRINTABLE,
+ "suffix.example", "res_mailok", res_mailok);
+ one_char
+ ("mailbox.middle",
+ LETTERSDIGITS ".-_\\",
+ "suffix.example", "res_mailok", res_mailok);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-res_use_inet6.c b/resolv/tst-res_use_inet6.c
new file mode 100644
index 0000000000..0170335741
--- /dev/null
+++ b/resolv/tst-res_use_inet6.c
@@ -0,0 +1,509 @@
+/* Basic functionality tests for inet6 option processing.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <ctype.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/check_nss.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+#include <support/xthread.h>
+
+/* Handle IPv4 reverse lookup responses. Product a PTR record
+ A-B-C-D.v4.example. */
+static void
+response_ptr_v4 (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ int bytes[4];
+ int offset = -1;
+ TEST_VERIFY (sscanf (qname, "%d.%d.%d.%d.in-addr.arpa%n",
+ bytes + 0, bytes + 1, bytes + 2, bytes + 3,
+ &offset) == 4);
+ TEST_VERIFY (offset == strlen (qname));
+ resolv_response_init (b, (struct resolv_response_flags) {});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
+ char *name = xasprintf ("%d-%d-%d-%d.v4.example",
+ bytes[3], bytes[2], bytes[1], bytes[0]);
+ resolv_response_add_name (b, name);
+ free (name);
+ resolv_response_close_record (b);
+}
+
+/* Handle IPv6 reverse lookup responses. Produce a PTR record
+ <32 hex digits>.v6.example. */
+static void
+response_ptr_v6 (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+
+ TEST_VERIFY_EXIT (strlen (qname) > 64);
+
+ char bytes[33];
+ for (int i = 0; i < 64; ++i)
+ if ((i % 2) == 0)
+ {
+ TEST_VERIFY (isxdigit ((unsigned char) qname[i]));
+ bytes[31 - i / 2] = qname[i];
+ }
+ else
+ TEST_VERIFY_EXIT (qname[i] == '.');
+ bytes[32] = '\0';
+
+ resolv_response_init (b, (struct resolv_response_flags) {});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
+ char *name = xasprintf ("%s.v6.example", bytes);
+ resolv_response_add_name (b, name);
+ free (name);
+ resolv_response_close_record (b);
+}
+
+/* Produce a response based on QNAME: Certain characters in the first
+ label of QNAME trigger the inclusion of resource records:
+
+ 'a' A record (IPv4 address)
+ 'q' AAAA record (quad A record, IPv6 address)
+ 'p' PTR record
+ 'm' record type must match QTYPE (no additional records)
+ '6' stop flag processing if QTYPE == AAAA
+
+ For 'a' and 'q', QTYPE is ignored for record type selection if 'm'
+ is not specified.
+
+ in-addr.arpa and ip6.arpa queries are handled separately in
+ response_ptr_v4 and response_ptr_v6. */
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ if (strstr (qname, ".in-addr.arpa") != NULL)
+ return response_ptr_v4 (ctx, b, qname, qclass, qtype);
+ else if (strstr (qname, ".ip6.arpa") != NULL)
+ return response_ptr_v6 (ctx, b, qname, qclass, qtype);
+
+ bool include_a = false;
+ bool include_aaaa = false;
+ bool include_match = false;
+ bool include_ptr = false;
+ for (const char *p = qname; *p != '.' && *p != '\0'; ++p)
+ {
+ if (*p == 'a')
+ include_a = true;
+ else if (*p == 'q')
+ include_aaaa = true;
+ else if (*p == 'm')
+ include_match = true;
+ else if (*p == 'p')
+ include_ptr = true;
+ else if (*p == '6' && qtype == T_AAAA)
+ break;
+ }
+ if (include_match)
+ {
+ if (qtype == T_A)
+ include_aaaa = false;
+ else if (qtype == T_AAAA)
+ include_a = false;
+ }
+
+ resolv_response_init (b, (struct resolv_response_flags) {});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ if (include_a)
+ {
+ char ipv4[4] = {192, 0, 2, 17};
+ resolv_response_open_record (b, qname, qclass, T_A, 0);
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
+ resolv_response_close_record (b);
+ }
+ if (include_aaaa)
+ {
+ char ipv6[16]
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+ resolv_response_open_record (b, qname, qclass, T_AAAA, 0);
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
+ resolv_response_close_record (b);
+ }
+ if (include_ptr)
+ {
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
+ resolv_response_add_name (b, "ptr-target.example");
+ resolv_response_close_record (b);
+ }
+}
+
+/* Test that getaddrinfo is not influenced by RES_USE_INET6. */
+static void
+test_gai (void)
+{
+ {
+ struct addrinfo hints =
+ {
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_STREAM,
+ .ai_protocol = IPPROTO_TCP,
+ };
+ struct addrinfo *ai;
+ int ret = getaddrinfo ("qam.example", "80", &hints, &ai);
+ check_addrinfo ("getaddrinfo AF_UNSPEC qam.example", ai, ret,
+ "address: STREAM/TCP 192.0.2.17 80\n"
+ "address: STREAM/TCP 2001:db8::1 80\n");
+ if (ret == 0)
+ freeaddrinfo (ai);
+ ret = getaddrinfo ("am.example", "80", &hints, &ai);
+ check_addrinfo ("getaddrinfo AF_UNSPEC am.example", ai, ret,
+ "address: STREAM/TCP 192.0.2.17 80\n");
+ if (ret == 0)
+ freeaddrinfo (ai);
+ ret = getaddrinfo ("qa.example", "80", &hints, &ai);
+ /* Combined A/AAAA responses currently result in address
+ duplication. */
+ check_addrinfo ("getaddrinfo AF_UNSPEC qa.example", ai, ret,
+ "address: STREAM/TCP 192.0.2.17 80\n"
+ "address: STREAM/TCP 192.0.2.17 80\n"
+ "address: STREAM/TCP 2001:db8::1 80\n"
+ "address: STREAM/TCP 2001:db8::1 80\n");
+ if (ret == 0)
+ freeaddrinfo (ai);
+ }
+ {
+ struct addrinfo hints =
+ {
+ .ai_family = AF_INET,
+ .ai_socktype = SOCK_STREAM,
+ .ai_protocol = IPPROTO_TCP,
+ };
+ struct addrinfo *ai;
+ int ret = getaddrinfo ("qam.example", "80", &hints, &ai);
+ check_addrinfo ("getaddrinfo AF_INET qam.example", ai, ret,
+ "address: STREAM/TCP 192.0.2.17 80\n");
+ if (ret == 0)
+ freeaddrinfo (ai);
+ ret = getaddrinfo ("am.example", "80", &hints, &ai);
+ check_addrinfo ("getaddrinfo AF_INET am.example", ai, ret,
+ "address: STREAM/TCP 192.0.2.17 80\n");
+ if (ret == 0)
+ freeaddrinfo (ai);
+ ret = getaddrinfo ("qa.example", "80", &hints, &ai);
+ check_addrinfo ("getaddrinfo AF_INET qa.example", ai, ret,
+ "address: STREAM/TCP 192.0.2.17 80\n");
+ if (ret == 0)
+ freeaddrinfo (ai);
+ }
+ {
+ struct addrinfo hints =
+ {
+ .ai_family = AF_INET6,
+ .ai_socktype = SOCK_STREAM,
+ .ai_protocol = IPPROTO_TCP,
+ };
+ struct addrinfo *ai;
+ int ret = getaddrinfo ("qa.example", "80", &hints, &ai);
+ check_addrinfo ("getaddrinfo (AF_INET6)", ai, ret,
+ "address: STREAM/TCP 2001:db8::1 80\n");
+ if (ret == 0)
+ freeaddrinfo (ai);
+ ret = getaddrinfo ("am.example", "80", &hints, &ai);
+ check_addrinfo ("getaddrinfo AF_INET6 am.example", ai, ret,
+ "error: No address associated with hostname\n");
+ if (ret == 0)
+ freeaddrinfo (ai);
+ ret = getaddrinfo ("qam.example", "80", &hints, &ai);
+ check_addrinfo ("getaddrinfo AF_INET6 qam.example", ai, ret,
+ "address: STREAM/TCP 2001:db8::1 80\n");
+ if (ret == 0)
+ freeaddrinfo (ai);
+ }
+}
+
+/* Test gethostbyaddr and getnameinfo. The results are independent of
+ RES_USE_INET6. */
+static void
+test_reverse (void)
+{
+ {
+ char ipv4[4] = { 192, 0, 2, 17 };
+ check_hostent ("gethostbyaddr AF_INET",
+ gethostbyaddr (ipv4, sizeof (ipv4), AF_INET),
+ "name: 192-0-2-17.v4.example\n"
+ "address: 192.0.2.17\n");
+ }
+ {
+ char ipv6[16]
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+ check_hostent ("gethostbyaddr AF_INET",
+ gethostbyaddr (ipv6, sizeof (ipv6), AF_INET6),
+ "name: 20010db8000000000000000000000001.v6.example\n"
+ "address: 2001:db8::1\n");
+ }
+
+ {
+ struct sockaddr_in addr =
+ {
+ .sin_family = AF_INET,
+ .sin_addr = { .s_addr = htonl (0xc0000211) },
+ .sin_port = htons (80)
+ };
+ char host[NI_MAXHOST];
+ char service[NI_MAXSERV];
+ int ret = getnameinfo ((struct sockaddr *) &addr, sizeof (addr),
+ host, sizeof (host), service, sizeof (service),
+ NI_NUMERICSERV);
+ TEST_VERIFY (ret == 0);
+ TEST_VERIFY (strcmp (host, "192-0-2-17.v4.example") == 0);
+ TEST_VERIFY (strcmp (service, "80") == 0);
+ }
+ {
+ char ipv6[16]
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+ struct sockaddr_in6 addr =
+ {
+ .sin6_family = AF_INET6,
+ .sin6_port = htons (80),
+ };
+ TEST_VERIFY (sizeof (ipv6) == sizeof (addr.sin6_addr));
+ memcpy (&addr.sin6_addr, ipv6, sizeof (addr.sin6_addr));
+ char host[NI_MAXHOST];
+ char service[NI_MAXSERV];
+ int ret = getnameinfo ((struct sockaddr *) &addr, sizeof (addr),
+ host, sizeof (host), service, sizeof (service),
+ NI_NUMERICSERV);
+ TEST_VERIFY (ret == 0);
+ TEST_VERIFY
+ (strcmp (host, "20010db8000000000000000000000001.v6.example") == 0);
+ TEST_VERIFY (strcmp (service, "80") == 0);
+ }
+}
+
+/* Test that gethostbyname2 is mostly not influenced by
+ RES_USE_INET6. */
+static void
+test_get2_any (void)
+{
+ check_hostent ("gethostbyname2 AF_INET am.example",
+ gethostbyname2 ("am.example", AF_INET),
+ "name: am.example\n"
+ "address: 192.0.2.17\n");
+ check_hostent ("gethostbyname2 AF_INET a.example",
+ gethostbyname2 ("a.example", AF_INET),
+ "name: a.example\n"
+ "address: 192.0.2.17\n");
+ check_hostent ("gethostbyname2 AF_INET qm.example",
+ gethostbyname2 ("qm.example", AF_INET),
+ "error: NO_ADDRESS\n");
+ check_hostent ("gethostbyname2 AF_INET q.example",
+ gethostbyname2 ("q.example", AF_INET),
+ "error: NO_RECOVERY\n");
+ check_hostent ("gethostbyname2 AF_INET qam.example",
+ gethostbyname2 ("qam.example", AF_INET),
+ "name: qam.example\n"
+ "address: 192.0.2.17\n");
+ check_hostent ("gethostbyname2 AF_INET qa.example",
+ gethostbyname2 ("qa.example", AF_INET),
+ "name: qa.example\n"
+ "address: 192.0.2.17\n");
+
+ check_hostent ("gethostbyname2 AF_INET6 qm.example",
+ gethostbyname2 ("qm.example", AF_INET6),
+ "name: qm.example\n"
+ "address: 2001:db8::1\n");
+ check_hostent ("gethostbyname2 AF_INET6 q.example",
+ gethostbyname2 ("q.example", AF_INET6),
+ "name: q.example\n"
+ "address: 2001:db8::1\n");
+ check_hostent ("gethostbyname2 AF_INET6 qam.example",
+ gethostbyname2 ("qam.example", AF_INET6),
+ "name: qam.example\n"
+ "address: 2001:db8::1\n");
+ check_hostent ("gethostbyname2 AF_INET6 qa.example",
+ gethostbyname2 ("qa.example", AF_INET6),
+ "name: qa.example\n"
+ "address: 2001:db8::1\n");
+ /* Additional AF_INET6 tests depend on RES_USE_INET6; see below. */
+
+ test_reverse ();
+}
+
+/* gethostbyname2 tests with RES_USE_INET6 disabled. */
+static void
+test_get2_no_inet6 (void)
+{
+ test_get2_any ();
+
+ check_hostent ("gethostbyname2 AF_INET6 am.example",
+ gethostbyname2 ("am.example", AF_INET6),
+ "error: NO_ADDRESS\n");
+ check_hostent ("gethostbyname2 AF_INET6 a.example",
+ gethostbyname2 ("a.example", AF_INET6),
+ "error: NO_RECOVERY\n");
+}
+
+/* gethostbyname2 tests with RES_USE_INET6 enabled. */
+static void
+test_get2_inet6 (void)
+{
+ test_get2_any ();
+
+ check_hostent ("gethostbyname2 AF_INET6 am.example",
+ gethostbyname2 ("am.example", AF_INET6),
+ "name: am.example\n"
+ "address: ::ffff:192.0.2.17\n");
+ check_hostent ("gethostbyname2 AF_INET6 a.example",
+ gethostbyname2 ("a.example", AF_INET6),
+ "error: NO_RECOVERY\n");
+}
+
+/* Collection of tests which assume no RES_USE_INET6 flag. */
+static void
+test_no_inet6 (void)
+{
+ check_hostent ("gethostbyname (\"a.example\")",
+ gethostbyname ("a.example"),
+ "name: a.example\n"
+ "address: 192.0.2.17\n");
+ check_hostent ("gethostbyname (\"qa.example\")",
+ gethostbyname ("qa.example"),
+ "name: qa.example\n"
+ "address: 192.0.2.17\n");
+ check_hostent ("gethostbyname (\"am.example\")",
+ gethostbyname ("am.example"),
+ "name: am.example\n"
+ "address: 192.0.2.17\n");
+ check_hostent ("gethostbyname (\"amp.example\")",
+ gethostbyname ("amp.example"),
+ "name: amp.example\n"
+ "address: 192.0.2.17\n");
+ check_hostent ("gethostbyname (\"qam.example\")",
+ gethostbyname ("qam.example"),
+ "name: qam.example\n"
+ "address: 192.0.2.17\n");
+ check_hostent ("gethostbyname (\"q.example\")",
+ gethostbyname ("q.example"),
+ "error: NO_RECOVERY\n");
+ check_hostent ("gethostbyname (\"qm.example\")",
+ gethostbyname ("qm.example"),
+ "error: NO_ADDRESS\n");
+ test_get2_no_inet6 ();
+ test_get2_no_inet6 ();
+ test_gai ();
+ test_get2_no_inet6 ();
+ test_get2_no_inet6 ();
+}
+
+static void *
+threadfunc (void *ignored)
+{
+ struct resolv_test *obj = resolv_test_start
+ ((struct resolv_redirect_config)
+ {
+ .response_callback = response
+ });
+
+ TEST_VERIFY ((_res.options & RES_USE_INET6) == 0);
+ test_no_inet6 ();
+
+ _res.options |= RES_USE_INET6;
+ check_hostent ("gethostbyname (\"a.inet6.example\")",
+ gethostbyname ("a.inet6.example"),
+ "error: NO_RECOVERY\n");
+ check_hostent ("gethostbyname (\"am.inet6.example\")",
+ gethostbyname ("am.inet6.example"),
+ "name: am.inet6.example\n"
+ "address: ::ffff:192.0.2.17\n");
+ check_hostent ("gethostbyname (\"qa.inet6.example\")",
+ gethostbyname ("qa.inet6.example"),
+ "name: qa.inet6.example\n"
+ "address: 2001:db8::1\n");
+ check_hostent ("gethostbyname (\"qam.inet6.example\")",
+ gethostbyname ("qam.inet6.example"),
+ "name: qam.inet6.example\n"
+ "address: 2001:db8::1\n");
+ check_hostent ("gethostbyname (\"q.inet6.example\")",
+ gethostbyname ("q.inet6.example"),
+ "name: q.inet6.example\n"
+ "address: 2001:db8::1\n");
+ check_hostent ("gethostbyname (\"qm.inet6.example\")",
+ gethostbyname ("qm.inet6.example"),
+ "name: qm.inet6.example\n"
+ "address: 2001:db8::1\n");
+ check_hostent ("gethostbyname (\"amp.inet6.example\")",
+ gethostbyname ("amp.inet6.example"),
+ "error: NO_RECOVERY\n");
+ check_hostent ("gethostbyname (\"qmp.inet6.example\")",
+ gethostbyname ("qmp.inet6.example"),
+ "name: qmp.inet6.example\n"
+ "address: 2001:db8::1\n");
+ check_hostent ("gethostbyname (\"ap.inet6.example\")",
+ gethostbyname ("ap.inet6.example"),
+ "error: NO_RECOVERY\n");
+ check_hostent ("gethostbyname (\"6ap.inet6.example\")",
+ gethostbyname ("6ap.inet6.example"),
+ "name: 6ap.inet6.example\n"
+ "address: ::ffff:192.0.2.17\n");
+ check_hostent ("gethostbyname (\"am6p.inet6.example\")",
+ gethostbyname ("am6p.inet6.example"),
+ "name: am6p.inet6.example\n"
+ "address: ::ffff:192.0.2.17\n");
+ check_hostent ("gethostbyname (\"qp.inet6.example\")",
+ gethostbyname ("qp.inet6.example"),
+ "name: qp.inet6.example\n"
+ "address: 2001:db8::1\n");
+ test_get2_inet6 ();
+ test_get2_inet6 ();
+ test_gai ();
+ test_get2_inet6 ();
+ test_get2_inet6 ();
+
+ TEST_VERIFY (_res.options & RES_USE_INET6);
+ _res.options &= ~RES_USE_INET6;
+ test_no_inet6 ();
+
+ resolv_test_end (obj);
+
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ resolv_test_init ();
+
+ /* Attempt to run on a non-main thread first. */
+ {
+ pthread_t thr = xpthread_create (NULL, threadfunc, NULL);
+ xpthread_join (thr);
+ }
+
+ /* Try the main thread next. */
+ threadfunc (NULL);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-ai_idn-common.c b/resolv/tst-resolv-ai_idn-common.c
new file mode 100644
index 0000000000..e7c4030e1c
--- /dev/null
+++ b/resolv/tst-resolv-ai_idn-common.c
@@ -0,0 +1,569 @@
+/* Common code for AI_IDN/NI_IDN tests.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Before including this file, TEST_USE_UTF8 must be defined to 1 or
+ 0, depending on whether a UTF-8 locale is used or a Latin-1
+ locale. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/check_nss.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+
+/* Name of the shared object for libidn2. */
+#define LIBIDN2_SONAME "libidn2.so.0"
+
+#if TEST_USE_UTF8
+/* UTF-8 encoding of "nämchen" (German for “namelet”). */
+# define NAEMCHEN "n\xC3\xA4mchen"
+
+/* UTF-8 encoding of "שם" (Hebrew for “name”). */
+# define SHEM "\xD7\xA9\xD7\x9D"
+
+/* UTF-8 encoding of "buße" (German for “penance”). This used to be
+ encoded as "busse" (“busses”) in IDNA2003. */
+# define BUSSE "bu\xC3\x9F""e"
+
+#else
+/* Latin-1 encodings, as far as they are available. */
+
+# define NAEMCHEN "n\xE4mchen"
+# define BUSSE "bu\xDF""e"
+
+#endif
+
+/* IDNA encoding of NAEMCHEN. */
+#define NAEMCHEN_IDNA "xn--nmchen-bua"
+
+/* IDNA encoding of NAEMCHEN "_zwo". */
+#define NAEMCHEN_ZWO_IDNA "xn--nmchen_zwo-q5a"
+
+/* IDNA encoding of SHEM. */
+#define SHEM_IDNA "xn--iebx"
+
+/* IDNA encoding of BUSSE. */
+#define BUSSE_IDNA "xn--bue-6ka"
+
+/* IDNA encoding of "שם1". */
+#define SHEM1_IDNA "xn--1-qic9a"
+
+/* Another IDNA name. */
+#define ANDERES_NAEMCHEN "anderes-" NAEMCHEN
+#define ANDERES_NAEMCHEN_IDNA "xn--anderes-nmchen-eib"
+
+/* Controls the kind of test data in a PTR lookup response. */
+enum gni_test
+ {
+ gni_non_idn_name,
+ gni_non_idn_cname_to_non_idn_name,
+ gni_non_idn_cname_to_idn_name,
+ gni_idn_name,
+ gni_idn_shem,
+ gni_idn_shem1,
+ gni_idn_cname_to_non_idn_name,
+ gni_idn_cname_to_idn_name,
+ gni_invalid_idn_1,
+ gni_invalid_idn_2,
+ };
+
+/* Called from response below. The LSB (first byte) controls what
+ goes into the response, see enum gni_test. */
+static void
+response_ptr (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b, const char *qname)
+{
+ int comp[4] = { 0 };
+ TEST_COMPARE (sscanf (qname, "%d.%d.%d.%d.in-addr.arpa",
+ &comp[0], &comp[1], &comp[2], &comp[3]), 4);
+ const char *next_name;
+ switch ((enum gni_test) comp[0])
+ {
+ /* First name in response is non-IDN name. */
+ case gni_non_idn_name:
+ resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
+ resolv_response_add_name (b, "non-idn.example");
+ resolv_response_close_record (b);
+ return;
+ case gni_non_idn_cname_to_non_idn_name:
+ resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
+ next_name = "non-idn-cname.example";
+ resolv_response_add_name (b, next_name);
+ resolv_response_close_record (b);
+ resolv_response_open_record (b, next_name, C_IN, T_PTR, 0);
+ resolv_response_add_name (b, "non-idn-name.example");
+ resolv_response_close_record (b);
+ return;
+ case gni_non_idn_cname_to_idn_name:
+ resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
+ next_name = "non-idn-cname.example";
+ resolv_response_add_name (b, next_name);
+ resolv_response_close_record (b);
+ resolv_response_open_record (b, next_name, C_IN, T_PTR, 0);
+ resolv_response_add_name (b, NAEMCHEN_IDNA ".example");
+ resolv_response_close_record (b);
+ return;
+
+ /* First name in response is IDN name. */
+ case gni_idn_name:
+ resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
+ resolv_response_add_name (b, "xn--nmchen-bua.example");
+ resolv_response_close_record (b);
+ return;
+ case gni_idn_shem:
+ resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
+ resolv_response_add_name (b, SHEM_IDNA ".example");
+ resolv_response_close_record (b);
+ return;
+ case gni_idn_shem1:
+ resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
+ resolv_response_add_name (b, SHEM1_IDNA ".example");
+ resolv_response_close_record (b);
+ return;
+ case gni_idn_cname_to_non_idn_name:
+ resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
+ next_name = NAEMCHEN_IDNA ".example";
+ resolv_response_add_name (b, next_name);
+ resolv_response_close_record (b);
+ resolv_response_open_record (b, next_name, C_IN, T_PTR, 0);
+ resolv_response_add_name (b, "non-idn-name.example");
+ resolv_response_close_record (b);
+ return;
+ case gni_idn_cname_to_idn_name:
+ resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
+ next_name = NAEMCHEN_IDNA ".example";
+ resolv_response_add_name (b, next_name);
+ resolv_response_close_record (b);
+ resolv_response_open_record (b, next_name, C_IN, T_PTR, 0);
+ resolv_response_add_name (b, ANDERES_NAEMCHEN_IDNA ".example");
+ resolv_response_close_record (b);
+ return;
+
+ /* Invalid IDN encodings. */
+ case gni_invalid_idn_1:
+ resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
+ resolv_response_add_name (b, "xn---.example");
+ resolv_response_close_record (b);
+ return;
+ case gni_invalid_idn_2:
+ resolv_response_open_record (b, qname, C_IN, T_PTR, 0);
+ resolv_response_add_name (b, "xn--x.example");
+ resolv_response_close_record (b);
+ return;
+ }
+ FAIL_EXIT1 ("invalid PTR query: %s", qname);
+}
+
+/* For PTR responses, see above. A/AAAA queries can request
+ additional CNAMEs in the response by include ".cname." and
+ ".idn-cname." in the query. The LSB in the address contains the
+ first byte of the QNAME. */
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ TEST_VERIFY_EXIT (qclass == C_IN);
+
+ for (const char *p = qname; *p != '\0'; ++p)
+ if (!(('0' <= *p && *p <= '9')
+ || ('a' <= *p && *p <= 'z')
+ || ('A' <= *p && *p <= 'Z')
+ || *p == '.' || *p == '-' || *p == '_'))
+ {
+ /* Non-ASCII query. Reply with NXDOMAIN. */
+ struct resolv_response_flags flags = { .rcode = 3 };
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+ return;
+ }
+
+ struct resolv_response_flags flags = { 0 };
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+
+ if (qtype == T_PTR)
+ {
+ response_ptr (ctx, b, qname);
+ return;
+ }
+
+ bool with_cname = strstr (qname, ".cname.") != NULL;
+ bool with_idn_cname = strstr (qname, ".idn-cname.") != NULL;
+
+ const char *next_name = qname;
+ if (with_cname)
+ {
+ next_name = "non-idn-cname.example";
+ resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
+ resolv_response_add_name (b, next_name);
+ resolv_response_close_record (b);
+ }
+ if (with_idn_cname)
+ {
+ next_name = ANDERES_NAEMCHEN_IDNA ".example";
+ resolv_response_open_record (b, qname, C_IN, T_CNAME, 0);
+ resolv_response_add_name (b, next_name);
+ resolv_response_close_record (b);
+ }
+
+ resolv_response_open_record (b, next_name, C_IN, qtype, 0);
+ switch (qtype)
+ {
+ case T_A:
+ {
+ char addr[4] = { 192, 0, 2, qname[0] };
+ resolv_response_add_data (b, &addr, sizeof (addr));
+ }
+ break;
+ case T_AAAA:
+ {
+ char addr[16]
+ = { 0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ qname[0] };
+ resolv_response_add_data (b, &addr, sizeof (addr));
+ }
+ default:
+ FAIL_EXIT1 ("invalid qtype: %d", qtype);
+ }
+ resolv_response_close_record (b);
+}
+
+/* Check the result of a getaddrinfo call. */
+static void
+check_ai (const char *name, int ai_flags, const char *expected)
+{
+ struct addrinfo hints =
+ {
+ .ai_flags = ai_flags,
+ .ai_family = AF_INET,
+ .ai_socktype = SOCK_STREAM,
+ };
+ struct addrinfo *ai;
+ char *query = xasprintf ("%s:80 AF_INET/0x%x", name, ai_flags);
+ int ret = getaddrinfo (name, "80", &hints, &ai);
+ check_addrinfo (query, ai, ret, expected);
+ if (ret == 0)
+ freeaddrinfo (ai);
+ free (query);
+}
+
+/* Run one getnameinfo test. FLAGS is automatically augmented with
+ NI_NUMERICSERV. */
+static void
+gni_test (enum gni_test code, unsigned int flags, const char *expected)
+{
+ struct sockaddr_in sin =
+ {
+ .sin_family = AF_INET,
+ .sin_port = htons (80),
+ .sin_addr = { htonl (0xc0000200 | code) }, /* 192.0.2.0/24 network. */
+ };
+ char host[1024];
+ char service[1024];
+ int ret = getnameinfo ((const struct sockaddr *) &sin, sizeof (sin),
+ host, sizeof (host), service, sizeof (service),
+ flags| NI_NUMERICSERV);
+ if (ret != 0)
+ {
+ if (expected == NULL)
+ TEST_COMPARE (ret, EAI_IDN_ENCODE);
+ else
+ {
+ support_record_failure ();
+ printf ("error: getnameinfo failed (code %d, flags 0x%x): %s (%d)\n",
+ (int) code, flags, gai_strerror (ret), ret);
+ }
+ }
+ else if (ret == 0 && expected == NULL)
+ {
+ support_record_failure ();
+ printf ("error: getnameinfo unexpected success (code %d, flags 0x%x)\n",
+ (int) code, flags);
+ }
+ else if (strcmp (host, expected) != 0 || strcmp (service, "80") != 0)
+ {
+ support_record_failure ();
+ printf ("error: getnameinfo test failure (code %d, flags 0x%x)\n"
+ " expected host: \"%s\"\n"
+ " expected service: \"80\"\n"
+ " actual host: \"%s\"\n"
+ " actual service: \"%s\"\n",
+ (int) code, flags, expected, host, service);
+ }
+}
+
+/* Tests for getaddrinfo which assume a working libidn2 library. */
+__attribute__ ((unused))
+static void
+gai_tests_with_libidn2 (void)
+{
+ /* No CNAME. */
+ check_ai ("non-idn.example", 0,
+ "address: STREAM/TCP 192.0.2.110 80\n");
+ check_ai ("non-idn.example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.110 80\n");
+ check_ai ("non-idn.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: non-idn.example\n"
+ "address: STREAM/TCP 192.0.2.110 80\n");
+
+ check_ai (NAEMCHEN ".example", 0,
+ "error: Name or service not known\n");
+ check_ai (NAEMCHEN ".example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (NAEMCHEN ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: " NAEMCHEN ".example\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+
+#if TEST_USE_UTF8
+ check_ai (SHEM ".example", 0,
+ "error: Name or service not known\n");
+ check_ai (SHEM ".example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (SHEM ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: " SHEM ".example\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (SHEM ".example", AI_IDN | AI_CANONNAME,
+ "flags: AI_CANONNAME AI_IDN\n"
+ "canonname: " SHEM_IDNA ".example\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (SHEM "1.example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (SHEM "1.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: " SHEM "1.example\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (SHEM "1.example", AI_IDN | AI_CANONNAME,
+ "flags: AI_CANONNAME AI_IDN\n"
+ "canonname: " SHEM1_IDNA ".example\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+#endif
+
+ /* Check that non-transitional mode is active. German sharp S
+ should not turn into SS. */
+ check_ai (BUSSE ".example", 0,
+ "error: Name or service not known\n");
+ check_ai (BUSSE ".example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (BUSSE ".example", AI_IDN | AI_CANONNAME,
+ "flags: AI_CANONNAME AI_IDN\n"
+ "canonname: " BUSSE_IDNA ".example\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (BUSSE ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: " BUSSE ".example\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+
+ /* Check that Unicode TR 46 mode is active. Underscores should be
+ permitted in IDNA components. */
+ check_ai (NAEMCHEN "_zwo.example", 0,
+ "error: Name or service not known\n");
+ check_ai (NAEMCHEN "_zwo.example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (NAEMCHEN "_zwo.example", AI_IDN | AI_CANONNAME,
+ "flags: AI_CANONNAME AI_IDN\n"
+ "canonname: " NAEMCHEN_ZWO_IDNA ".example\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (NAEMCHEN "_zwo.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: " NAEMCHEN "_zwo.example\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+
+ /* No CNAME, but already IDN-encoded. */
+ check_ai (NAEMCHEN_IDNA ".example", 0,
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (NAEMCHEN_IDNA ".example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (NAEMCHEN_IDNA ".example", AI_IDN | AI_CANONNAME,
+ "flags: AI_CANONNAME AI_IDN\n"
+ "canonname: " NAEMCHEN_IDNA ".example\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (NAEMCHEN_IDNA ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: " NAEMCHEN ".example\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (SHEM_IDNA ".example", 0,
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (SHEM_IDNA ".example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+ check_ai (SHEM_IDNA ".example", AI_IDN | AI_CANONNAME,
+ "flags: AI_CANONNAME AI_IDN\n"
+ "canonname: " SHEM_IDNA ".example\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+#if TEST_USE_UTF8
+ check_ai (SHEM_IDNA ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: " SHEM ".example\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+#else
+ check_ai (SHEM_IDNA ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: " SHEM_IDNA ".example\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+#endif
+
+ /* Invalid IDNA canonical name is returned as-is. */
+ check_ai ("xn---.example", AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_CANONIDN\n"
+ "canonname: xn---.example\n"
+ "address: STREAM/TCP 192.0.2.120 80\n");
+
+ /* Non-IDN CNAME. */
+ check_ai ("with.cname.example", 0,
+ "address: STREAM/TCP 192.0.2.119 80\n");
+ check_ai ("with.cname.example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.119 80\n");
+ check_ai ("with.cname.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: non-idn-cname.example\n"
+ "address: STREAM/TCP 192.0.2.119 80\n");
+
+ check_ai ("with.cname." NAEMCHEN ".example", 0,
+ "error: Name or service not known\n");
+ check_ai ("with.cname." NAEMCHEN ".example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.119 80\n");
+ check_ai ("with.cname." NAEMCHEN ".example", AI_IDN | AI_CANONNAME,
+ "flags: AI_CANONNAME AI_IDN\n"
+ "canonname: non-idn-cname.example\n"
+ "address: STREAM/TCP 192.0.2.119 80\n");
+ check_ai ("with.cname." NAEMCHEN ".example",
+ AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: non-idn-cname.example\n"
+ "address: STREAM/TCP 192.0.2.119 80\n");
+
+ /* IDN CNAME. */
+ check_ai ("With.idn-cname.example", 0,
+ "address: STREAM/TCP 192.0.2.87 80\n");
+ check_ai ("With.idn-cname.example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.87 80\n");
+ check_ai ("With.idn-cname.example", AI_IDN | AI_CANONNAME,
+ "flags: AI_CANONNAME AI_IDN\n"
+ "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
+ "address: STREAM/TCP 192.0.2.87 80\n");
+ check_ai ("With.idn-cname.example",
+ AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: " ANDERES_NAEMCHEN ".example\n"
+ "address: STREAM/TCP 192.0.2.87 80\n");
+
+ check_ai ("With.idn-cname." NAEMCHEN ".example", 0,
+ "error: Name or service not known\n");
+ check_ai ("With.idn-cname." NAEMCHEN ".example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.119 80\n");
+ check_ai ("With.idn-cname." NAEMCHEN ".example", AI_IDN | AI_CANONNAME,
+ "flags: AI_CANONNAME AI_IDN\n"
+ "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
+ "address: STREAM/TCP 192.0.2.119 80\n");
+ check_ai ("With.idn-cname." NAEMCHEN ".example",
+ AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: " ANDERES_NAEMCHEN ".example\n"
+ "address: STREAM/TCP 192.0.2.119 80\n");
+
+ /* Non-IDN to IDN CNAME chain. */
+ check_ai ("both.cname.idn-cname.example", 0,
+ "address: STREAM/TCP 192.0.2.98 80\n");
+ check_ai ("both.cname.idn-cname.example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.98 80\n");
+ check_ai ("both.cname.idn-cname.example", AI_IDN | AI_CANONNAME,
+ "flags: AI_CANONNAME AI_IDN\n"
+ "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
+ "address: STREAM/TCP 192.0.2.98 80\n");
+ check_ai ("both.cname.idn-cname.example",
+ AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: " ANDERES_NAEMCHEN ".example\n"
+ "address: STREAM/TCP 192.0.2.98 80\n");
+
+ check_ai ("both.cname.idn-cname." NAEMCHEN ".example", 0,
+ "error: Name or service not known\n");
+ check_ai ("both.cname.idn-cname." NAEMCHEN ".example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.98 80\n");
+ check_ai ("both.cname.idn-cname." NAEMCHEN ".example",
+ AI_IDN | AI_CANONNAME,
+ "flags: AI_CANONNAME AI_IDN\n"
+ "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
+ "address: STREAM/TCP 192.0.2.98 80\n");
+ check_ai ("both.cname.idn-cname." NAEMCHEN ".example",
+ AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: " ANDERES_NAEMCHEN ".example\n"
+ "address: STREAM/TCP 192.0.2.98 80\n");
+}
+
+/* Tests for getnameinfo which assume a working libidn2 library. */
+__attribute__ ((unused))
+static void
+gni_tests_with_libidn2 (void)
+{
+ gni_test (gni_non_idn_name, 0, "non-idn.example");
+ gni_test (gni_non_idn_name, NI_IDN, "non-idn.example");
+ gni_test (gni_non_idn_name, NI_NUMERICHOST, "192.0.2.0");
+ gni_test (gni_non_idn_name, NI_NUMERICHOST | NI_IDN, "192.0.2.0");
+
+ gni_test (gni_non_idn_cname_to_non_idn_name, 0, "non-idn-name.example");
+ gni_test (gni_non_idn_cname_to_non_idn_name, NI_IDN, "non-idn-name.example");
+
+ gni_test (gni_non_idn_cname_to_idn_name, 0, NAEMCHEN_IDNA ".example");
+ gni_test (gni_non_idn_cname_to_idn_name, NI_IDN, NAEMCHEN ".example");
+
+ gni_test (gni_idn_name, 0, NAEMCHEN_IDNA ".example");
+ gni_test (gni_idn_name, NI_IDN, NAEMCHEN ".example");
+ gni_test (gni_idn_shem, 0, SHEM_IDNA ".example");
+ gni_test (gni_idn_shem1, 0, SHEM1_IDNA ".example");
+#if TEST_USE_UTF8
+ gni_test (gni_idn_shem, NI_IDN, SHEM ".example");
+ gni_test (gni_idn_shem1, NI_IDN, SHEM "1.example");
+#else
+ gni_test (gni_idn_shem, NI_IDN, SHEM_IDNA ".example");
+ gni_test (gni_idn_shem1, NI_IDN, SHEM1_IDNA ".example");
+#endif
+
+ gni_test (gni_idn_cname_to_non_idn_name, 0, "non-idn-name.example");
+ gni_test (gni_idn_cname_to_non_idn_name, NI_IDN, "non-idn-name.example");
+
+ gni_test (gni_idn_cname_to_idn_name, 0, ANDERES_NAEMCHEN_IDNA ".example");
+ gni_test (gni_idn_cname_to_idn_name, NI_IDN, ANDERES_NAEMCHEN ".example");
+
+ /* Test encoding errors. */
+ gni_test (gni_invalid_idn_1, 0, "xn---.example");
+ gni_test (gni_invalid_idn_1, NI_IDN, "xn---.example");
+ gni_test (gni_invalid_idn_2, 0, "xn--x.example");
+ gni_test (gni_invalid_idn_2, NI_IDN, "xn--x.example");
+}
diff --git a/resolv/tst-resolv-ai_idn-latin1.c b/resolv/tst-resolv-ai_idn-latin1.c
new file mode 100644
index 0000000000..fb60f3261e
--- /dev/null
+++ b/resolv/tst-resolv-ai_idn-latin1.c
@@ -0,0 +1,50 @@
+/* Test getaddrinfo and getnameinfo with AI_IDN, NI_IDN (Latin-1).
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+
+#define TEST_USE_UTF8 0
+#include "tst-resolv-ai_idn-common.c"
+
+#include <locale.h>
+#include <support/xdlfcn.h>
+
+static int
+do_test (void)
+{
+ void *handle = dlopen (LIBIDN2_SONAME, RTLD_LAZY);
+ if (handle == NULL)
+ FAIL_UNSUPPORTED ("libidn2 not installed");
+
+ if (setlocale (LC_CTYPE, "en_US.ISO-8859-1") == NULL)
+ FAIL_EXIT1 ("setlocale: %m");
+
+ struct resolv_test *aux = resolv_test_start
+ ((struct resolv_redirect_config)
+ {
+ .response_callback = response,
+ });
+
+ gai_tests_with_libidn2 ();
+ gni_tests_with_libidn2 ();
+
+ resolv_test_end (aux);
+ xdlclose (handle);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-ai_idn-nolibidn2.c b/resolv/tst-resolv-ai_idn-nolibidn2.c
new file mode 100644
index 0000000000..7203c23f3c
--- /dev/null
+++ b/resolv/tst-resolv-ai_idn-nolibidn2.c
@@ -0,0 +1,151 @@
+/* Test getaddrinfo and getnameinfo without usable libidn2.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_USE_UTF8 1
+#include "tst-resolv-ai_idn-common.c"
+
+#include <locale.h>
+#include <support/xdlfcn.h>
+
+/* Tests for getaddrinfo. */
+static void
+gai_tests (void)
+{
+ /* No CNAME. */
+ check_ai ("non-idn.example", 0,
+ "address: STREAM/TCP 192.0.2.110 80\n");
+ check_ai ("non-idn.example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.110 80\n");
+ check_ai ("non-idn.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: non-idn.example\n"
+ "address: STREAM/TCP 192.0.2.110 80\n");
+
+ /* This gets passed over the network to the server, so it will
+ result in an NXDOMAIN error. */
+ check_ai (NAEMCHEN ".example", 0,
+ "error: Name or service not known\n");
+ /* Due to missing libidn2, this fails inside getaddrinfo. */
+ check_ai (NAEMCHEN ".example", AI_IDN,
+ "error: Parameter string not correctly encoded\n");
+ check_ai (NAEMCHEN ".example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "error: Parameter string not correctly encoded\n");
+
+ /* Non-IDN CNAME. */
+ check_ai ("with.cname.example", 0,
+ "address: STREAM/TCP 192.0.2.119 80\n");
+ check_ai ("with.cname.example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.119 80\n");
+ check_ai ("with.cname.example", AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: non-idn-cname.example\n"
+ "address: STREAM/TCP 192.0.2.119 80\n");
+
+ /* IDN CNAME. */
+ check_ai ("With.idn-cname.example", 0,
+ "address: STREAM/TCP 192.0.2.87 80\n");
+ check_ai ("With.idn-cname.example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.87 80\n");
+ check_ai ("With.idn-cname.example", AI_IDN | AI_CANONNAME,
+ "flags: AI_CANONNAME AI_IDN\n"
+ "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
+ "address: STREAM/TCP 192.0.2.87 80\n");
+ check_ai ("With.idn-cname.example",
+ AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
+ "address: STREAM/TCP 192.0.2.87 80\n");
+
+ /* Non-IDN to IDN CNAME chain. */
+ check_ai ("both.cname.idn-cname.example", 0,
+ "address: STREAM/TCP 192.0.2.98 80\n");
+ check_ai ("both.cname.idn-cname.example", AI_IDN,
+ "flags: AI_IDN\n"
+ "address: STREAM/TCP 192.0.2.98 80\n");
+ check_ai ("both.cname.idn-cname.example", AI_IDN | AI_CANONNAME,
+ "flags: AI_CANONNAME AI_IDN\n"
+ "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
+ "address: STREAM/TCP 192.0.2.98 80\n");
+ check_ai ("both.cname.idn-cname.example",
+ AI_IDN | AI_CANONNAME | AI_CANONIDN,
+ "flags: AI_CANONNAME AI_IDN AI_CANONIDN\n"
+ "canonname: " ANDERES_NAEMCHEN_IDNA ".example\n"
+ "address: STREAM/TCP 192.0.2.98 80\n");
+}
+
+/* Tests for getnameinfo. */
+static void
+gni_tests (void)
+{
+ /* All non-IDN an IDN results are the same due to lack of libidn2
+ support. */
+ for (int do_ni_idn = 0; do_ni_idn < 2; ++do_ni_idn)
+ {
+ int flags = 0;
+ if (do_ni_idn)
+ flags |= NI_IDN;
+
+ gni_test (gni_non_idn_name, flags, "non-idn.example");
+ gni_test (gni_non_idn_name, flags | NI_NUMERICHOST, "192.0.2.0");
+ gni_test (gni_non_idn_cname_to_non_idn_name, flags,
+ "non-idn-name.example");
+ gni_test (gni_non_idn_cname_to_idn_name, flags,
+ NAEMCHEN_IDNA ".example");
+ gni_test (gni_idn_name, flags, NAEMCHEN_IDNA ".example");
+ gni_test (gni_idn_cname_to_non_idn_name, flags, "non-idn-name.example");
+ gni_test (gni_idn_cname_to_idn_name, flags,
+ ANDERES_NAEMCHEN_IDNA ".example");
+
+ /* Test encoding errors. */
+ gni_test (gni_invalid_idn_1, flags, "xn---.example");
+ gni_test (gni_invalid_idn_2, flags, "xn--x.example");
+}
+}
+
+static int
+do_test (void)
+{
+ void *handle = xdlopen ("tst-no-libidn2.so", RTLD_LAZY);
+ {
+ /* Verify that this replaced libidn2. */
+ void *handle2 = xdlopen (LIBIDN2_SONAME, RTLD_LAZY | RTLD_NOLOAD);
+ TEST_VERIFY (handle2 == handle);
+ xdlclose (handle2);
+ }
+
+ if (setlocale (LC_CTYPE, "en_US.UTF-8") == NULL)
+ FAIL_EXIT1 ("setlocale: %m");
+
+ struct resolv_test *aux = resolv_test_start
+ ((struct resolv_redirect_config)
+ {
+ .response_callback = response,
+ });
+
+ gai_tests ();
+ gni_tests ();
+
+ resolv_test_end (aux);
+ xdlclose (handle);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-ai_idn.c b/resolv/tst-resolv-ai_idn.c
new file mode 100644
index 0000000000..df8203b14a
--- /dev/null
+++ b/resolv/tst-resolv-ai_idn.c
@@ -0,0 +1,49 @@
+/* Test getaddrinfo and getnameinfo with AI_IDN, NI_IDN (UTF-8).
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_USE_UTF8 1
+#include "tst-resolv-ai_idn-common.c"
+
+#include <locale.h>
+#include <support/xdlfcn.h>
+
+static int
+do_test (void)
+{
+ void *handle = dlopen (LIBIDN2_SONAME, RTLD_LAZY);
+ if (handle == NULL)
+ FAIL_UNSUPPORTED ("libidn2 not installed");
+
+ if (setlocale (LC_CTYPE, "en_US.UTF-8") == NULL)
+ FAIL_EXIT1 ("setlocale: %m");
+
+ struct resolv_test *aux = resolv_test_start
+ ((struct resolv_redirect_config)
+ {
+ .response_callback = response,
+ });
+
+ gai_tests_with_libidn2 ();
+ gni_tests_with_libidn2 ();
+
+ resolv_test_end (aux);
+ xdlclose (handle);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-basic.c b/resolv/tst-resolv-basic.c
new file mode 100644
index 0000000000..e607d24084
--- /dev/null
+++ b/resolv/tst-resolv-basic.c
@@ -0,0 +1,503 @@
+/* Test basic nss_dns functionality and the resolver test harness itself.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/check_nss.h>
+#include <support/format_nss.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+
+#define LONG_NAME \
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaax." \
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaay." \
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz." \
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaat"
+
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ TEST_VERIFY_EXIT (qname != NULL);
+
+ /* The "t." prefix can be used to request TCP fallback. */
+ bool force_tcp;
+ if (strncmp ("t.", qname, 2) == 0)
+ force_tcp = true;
+ else
+ force_tcp = false;
+ const char *qname_compare;
+ if (force_tcp)
+ qname_compare = qname + 2;
+ else
+ qname_compare = qname;
+ enum {www, alias, nxdomain, long_name, nodata} requested_qname;
+ if (strcmp (qname_compare, "www.example") == 0)
+ requested_qname = www;
+ else if (strcmp (qname_compare, "alias.example") == 0)
+ requested_qname = alias;
+ else if (strcmp (qname_compare, "nxdomain.example") == 0)
+ requested_qname = nxdomain;
+ else if (strcmp (qname_compare, LONG_NAME) == 0)
+ requested_qname = long_name;
+ else if (strcmp (qname_compare, "nodata.example") == 0)
+ requested_qname = nodata;
+ else
+ {
+ support_record_failure ();
+ printf ("error: unexpected QNAME: %s\n", qname);
+ return;
+ }
+ TEST_VERIFY_EXIT (qclass == C_IN);
+ struct resolv_response_flags flags = {.tc = force_tcp && !ctx->tcp};
+ if (requested_qname == nxdomain)
+ flags.rcode = 3; /* NXDOMAIN */
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+ if (requested_qname == nxdomain || flags.tc)
+ return;
+
+ resolv_response_section (b, ns_s_an);
+ switch (requested_qname)
+ {
+ case www:
+ case long_name:
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
+ break;
+ case alias:
+ resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
+ resolv_response_add_name (b, "www.example");
+ resolv_response_close_record (b);
+ resolv_response_open_record (b, "www.example", qclass, qtype, 0);
+ break;
+ case nodata:
+ return;
+ case nxdomain:
+ FAIL_EXIT1 ("unreachable");
+ }
+ switch (qtype)
+ {
+ case T_A:
+ {
+ char ipv4[4] = {192, 0, 2, 17};
+ ipv4[3] += requested_qname + 2 * ctx->tcp + 4 * ctx->server_index;
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
+ }
+ break;
+ case T_AAAA:
+ {
+ char ipv6[16]
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+ ipv6[15] += requested_qname + 2 * ctx->tcp + 4 * ctx->server_index;
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
+ }
+ break;
+ default:
+ support_record_failure ();
+ printf ("error: unexpected QTYPE: %s/%u/%u\n",
+ qname, qclass, qtype);
+ }
+ resolv_response_close_record (b);
+}
+
+static void
+check_h (const char *name, int family, const char *expected)
+{
+ if (family == AF_INET)
+ {
+ char *query = xasprintf ("gethostbyname (\"%s\")", name);
+ check_hostent (query, gethostbyname (name), expected);
+ free (query);
+ }
+ {
+ char *query = xasprintf ("gethostbyname2 (\"%s\", %d)", name, family);
+ check_hostent (query, gethostbyname2 (name, family), expected);
+ free (query);
+ }
+
+ bool too_small = true;
+ for (unsigned int offset = 0; offset < 8; ++offset)
+ for (unsigned int size = 1; too_small; ++size)
+ {
+ char *buf = xmalloc (offset + size);
+ too_small = false;
+
+ struct hostent hostbuf;
+ struct hostent *result;
+ int herror;
+ if (family == AF_INET)
+ {
+ char *query = xasprintf ("gethostbyname (\"%s\") %u/%u",
+ name, offset, size);
+ int ret = gethostbyname_r
+ (name, &hostbuf, buf + offset, size, &result, &herror);
+ if (ret == 0)
+ {
+ h_errno = herror;
+ check_hostent (query, result, expected);
+ }
+ else if (ret == ERANGE)
+ too_small = true;
+ else
+ {
+ errno = ret;
+ FAIL_EXIT1 ("gethostbyname_r: %m");
+ }
+ free (query);
+ memset (buf, 0, offset + size);
+ }
+ char *query = xasprintf ("gethostbyname2 (\"%s\", %d) %u/%u",
+ name, family, offset, size);
+ int ret = gethostbyname2_r
+ (name, family, &hostbuf, buf + offset, size, &result, &herror);
+ if (ret == 0)
+ {
+ h_errno = herror;
+ check_hostent (query, result, expected);
+ }
+ else if (ret == ERANGE)
+ too_small = true;
+ else
+ {
+ errno = ret;
+ FAIL_EXIT1 ("gethostbyname_r: %m");
+ }
+ free (buf);
+ free (query);
+ }
+}
+
+static void
+check_ai_hints (const char *name, const char *service,
+ struct addrinfo hints, const char *expected)
+{
+ struct addrinfo *ai;
+ char *query = xasprintf ("%s:%s [%d]/0x%x", name, service,
+ hints.ai_family, hints.ai_flags);
+ int ret = getaddrinfo (name, service, &hints, &ai);
+ check_addrinfo (query, ai, ret, expected);
+ if (ret == 0)
+ freeaddrinfo (ai);
+ free (query);
+}
+
+static void
+check_ai (const char *name, const char *service,
+ int family, const char *expected)
+{
+ return check_ai_hints (name, service,
+ (struct addrinfo) { .ai_family = family, },
+ expected);
+}
+
+/* Test for bug 21295: getaddrinfo used to discard address information
+ instead of merging it. */
+static void
+test_bug_21295 (void)
+{
+ /* The address order is unpredictable. There are two factors which
+ contribute to that: The stub resolver does not perform proper
+ response matching for A/AAAA queries (an A response could be
+ associated with an AAAA query and vice versa), and without
+ namespaces, system configuration could affect address
+ ordering. */
+ for (int do_tcp = 0; do_tcp < 2; ++do_tcp)
+ {
+ const struct addrinfo hints =
+ {
+ .ai_family = AF_INET6,
+ .ai_socktype = SOCK_STREAM,
+ .ai_flags = AI_V4MAPPED | AI_ALL,
+ };
+ const char *qname;
+ if (do_tcp)
+ qname = "t.www.example";
+ else
+ qname = "www.example";
+ struct addrinfo *ai = NULL;
+ int ret = getaddrinfo (qname, "80", &hints, &ai);
+ TEST_VERIFY_EXIT (ret == 0);
+
+ const char *expected_a;
+ const char *expected_b;
+ if (do_tcp)
+ {
+ expected_a = "flags: AI_V4MAPPED AI_ALL\n"
+ "address: STREAM/TCP 2001:db8::3 80\n"
+ "address: STREAM/TCP ::ffff:192.0.2.19 80\n";
+ expected_b = "flags: AI_V4MAPPED AI_ALL\n"
+ "address: STREAM/TCP ::ffff:192.0.2.19 80\n"
+ "address: STREAM/TCP 2001:db8::3 80\n";
+ }
+ else
+ {
+ expected_a = "flags: AI_V4MAPPED AI_ALL\n"
+ "address: STREAM/TCP 2001:db8::1 80\n"
+ "address: STREAM/TCP ::ffff:192.0.2.17 80\n";
+ expected_b = "flags: AI_V4MAPPED AI_ALL\n"
+ "address: STREAM/TCP ::ffff:192.0.2.17 80\n"
+ "address: STREAM/TCP 2001:db8::1 80\n";
+ }
+
+ char *actual = support_format_addrinfo (ai, ret);
+ if (!(strcmp (actual, expected_a) == 0
+ || strcmp (actual, expected_b) == 0))
+ {
+ support_record_failure ();
+ printf ("error: %s: unexpected response (TCP: %d):\n%s\n",
+ __func__, do_tcp, actual);
+ }
+ free (actual);
+ freeaddrinfo (ai);
+ }
+}
+
+/* Run tests which do not expect any data. */
+static void
+test_nodata_nxdomain (void)
+{
+ /* Iterate through different address families. */
+ int families[] = { AF_UNSPEC, AF_INET, AF_INET6, -1 };
+ for (int i = 0; families[i] >= 0; ++i)
+ /* If do_tcp, prepend "t." to the name to trigger TCP
+ fallback. */
+ for (int do_tcp = 0; do_tcp < 2; ++do_tcp)
+ /* If do_nxdomain, trigger an NXDOMAIN error (DNS failure),
+ otherwise use a NODATA response (empty but successful
+ answer). */
+ for (int do_nxdomain = 0; do_nxdomain < 2; ++do_nxdomain)
+ {
+ int family = families[i];
+ char *name = xasprintf ("%s%s.example",
+ do_tcp ? "t." : "",
+ do_nxdomain ? "nxdomain" : "nodata");
+
+ if (family != AF_UNSPEC)
+ {
+ if (do_nxdomain)
+ check_h (name, family, "error: HOST_NOT_FOUND\n");
+ else
+ check_h (name, family, "error: NO_ADDRESS\n");
+ }
+
+ const char *expected;
+ if (do_nxdomain)
+ expected = "error: Name or service not known\n";
+ else
+ expected = "error: No address associated with hostname\n";
+
+ check_ai (name, "80", family, expected);
+
+ struct addrinfo hints =
+ {
+ .ai_family = family,
+ .ai_flags = AI_V4MAPPED | AI_ALL,
+ };
+ check_ai_hints (name, "80", hints, expected);
+ hints.ai_flags |= AI_CANONNAME;
+ check_ai_hints (name, "80", hints, expected);
+
+ free (name);
+ }
+}
+
+static int
+do_test (void)
+{
+ struct resolv_test *aux = resolv_test_start
+ ((struct resolv_redirect_config)
+ {
+ .response_callback = response,
+ });
+
+ check_h ("www.example", AF_INET,
+ "name: www.example\n"
+ "address: 192.0.2.17\n");
+ check_h ("alias.example", AF_INET,
+ "name: www.example\n"
+ "alias: alias.example\n"
+ "address: 192.0.2.18\n");
+ check_h ("www.example", AF_INET6,
+ "name: www.example\n"
+ "address: 2001:db8::1\n");
+ check_h ("alias.example", AF_INET6,
+ "name: www.example\n"
+ "alias: alias.example\n"
+ "address: 2001:db8::2\n");
+ check_h (LONG_NAME, AF_INET,
+ "name: " LONG_NAME "\n"
+ "address: 192.0.2.20\n");
+
+ check_ai ("www.example", "80", AF_UNSPEC,
+ "address: STREAM/TCP 192.0.2.17 80\n"
+ "address: DGRAM/UDP 192.0.2.17 80\n"
+ "address: RAW/IP 192.0.2.17 80\n"
+ "address: STREAM/TCP 2001:db8::1 80\n"
+ "address: DGRAM/UDP 2001:db8::1 80\n"
+ "address: RAW/IP 2001:db8::1 80\n");
+ check_ai_hints ("www.example", "80",
+ (struct addrinfo) { .ai_family = AF_UNSPEC,
+ .ai_flags = AI_CANONNAME, },
+ "flags: AI_CANONNAME\n"
+ "canonname: www.example\n"
+ "address: STREAM/TCP 192.0.2.17 80\n"
+ "address: DGRAM/UDP 192.0.2.17 80\n"
+ "address: RAW/IP 192.0.2.17 80\n"
+ "address: STREAM/TCP 2001:db8::1 80\n"
+ "address: DGRAM/UDP 2001:db8::1 80\n"
+ "address: RAW/IP 2001:db8::1 80\n");
+ check_ai ("alias.example", "80", AF_UNSPEC,
+ "address: STREAM/TCP 192.0.2.18 80\n"
+ "address: DGRAM/UDP 192.0.2.18 80\n"
+ "address: RAW/IP 192.0.2.18 80\n"
+ "address: STREAM/TCP 2001:db8::2 80\n"
+ "address: DGRAM/UDP 2001:db8::2 80\n"
+ "address: RAW/IP 2001:db8::2 80\n");
+ check_ai_hints ("alias.example", "80",
+ (struct addrinfo) { .ai_family = AF_UNSPEC,
+ .ai_flags = AI_CANONNAME, },
+ "flags: AI_CANONNAME\n"
+ "canonname: www.example\n"
+ "address: STREAM/TCP 192.0.2.18 80\n"
+ "address: DGRAM/UDP 192.0.2.18 80\n"
+ "address: RAW/IP 192.0.2.18 80\n"
+ "address: STREAM/TCP 2001:db8::2 80\n"
+ "address: DGRAM/UDP 2001:db8::2 80\n"
+ "address: RAW/IP 2001:db8::2 80\n");
+ check_ai (LONG_NAME, "80", AF_UNSPEC,
+ "address: STREAM/TCP 192.0.2.20 80\n"
+ "address: DGRAM/UDP 192.0.2.20 80\n"
+ "address: RAW/IP 192.0.2.20 80\n"
+ "address: STREAM/TCP 2001:db8::4 80\n"
+ "address: DGRAM/UDP 2001:db8::4 80\n"
+ "address: RAW/IP 2001:db8::4 80\n");
+ check_ai ("www.example", "80", AF_INET,
+ "address: STREAM/TCP 192.0.2.17 80\n"
+ "address: DGRAM/UDP 192.0.2.17 80\n"
+ "address: RAW/IP 192.0.2.17 80\n");
+ check_ai_hints ("www.example", "80",
+ (struct addrinfo) { .ai_family = AF_INET,
+ .ai_flags = AI_CANONNAME, },
+ "flags: AI_CANONNAME\n"
+ "canonname: www.example\n"
+ "address: STREAM/TCP 192.0.2.17 80\n"
+ "address: DGRAM/UDP 192.0.2.17 80\n"
+ "address: RAW/IP 192.0.2.17 80\n");
+ check_ai ("alias.example", "80", AF_INET,
+ "address: STREAM/TCP 192.0.2.18 80\n"
+ "address: DGRAM/UDP 192.0.2.18 80\n"
+ "address: RAW/IP 192.0.2.18 80\n");
+ check_ai_hints ("alias.example", "80",
+ (struct addrinfo) { .ai_family = AF_INET,
+ .ai_flags = AI_CANONNAME, },
+ "flags: AI_CANONNAME\n"
+ "canonname: www.example\n"
+ "address: STREAM/TCP 192.0.2.18 80\n"
+ "address: DGRAM/UDP 192.0.2.18 80\n"
+ "address: RAW/IP 192.0.2.18 80\n");
+ check_ai (LONG_NAME, "80", AF_INET,
+ "address: STREAM/TCP 192.0.2.20 80\n"
+ "address: DGRAM/UDP 192.0.2.20 80\n"
+ "address: RAW/IP 192.0.2.20 80\n");
+ check_ai ("www.example", "80", AF_INET6,
+ "address: STREAM/TCP 2001:db8::1 80\n"
+ "address: DGRAM/UDP 2001:db8::1 80\n"
+ "address: RAW/IP 2001:db8::1 80\n");
+ check_ai_hints ("www.example", "80",
+ (struct addrinfo) { .ai_family = AF_INET6,
+ .ai_flags = AI_CANONNAME, },
+ "flags: AI_CANONNAME\n"
+ "canonname: www.example\n"
+ "address: STREAM/TCP 2001:db8::1 80\n"
+ "address: DGRAM/UDP 2001:db8::1 80\n"
+ "address: RAW/IP 2001:db8::1 80\n");
+ check_ai ("alias.example", "80", AF_INET6,
+ "address: STREAM/TCP 2001:db8::2 80\n"
+ "address: DGRAM/UDP 2001:db8::2 80\n"
+ "address: RAW/IP 2001:db8::2 80\n");
+ check_ai_hints ("alias.example", "80",
+ (struct addrinfo) { .ai_family = AF_INET6,
+ .ai_flags = AI_CANONNAME, },
+ "flags: AI_CANONNAME\n"
+ "canonname: www.example\n"
+ "address: STREAM/TCP 2001:db8::2 80\n"
+ "address: DGRAM/UDP 2001:db8::2 80\n"
+ "address: RAW/IP 2001:db8::2 80\n");
+ check_ai (LONG_NAME, "80", AF_INET6,
+ "address: STREAM/TCP 2001:db8::4 80\n"
+ "address: DGRAM/UDP 2001:db8::4 80\n"
+ "address: RAW/IP 2001:db8::4 80\n");
+
+ check_h ("t.www.example", AF_INET,
+ "name: t.www.example\n"
+ "address: 192.0.2.19\n");
+ check_h ("t.alias.example", AF_INET,
+ "name: www.example\n"
+ "alias: t.alias.example\n"
+ "address: 192.0.2.20\n");
+ check_h ("t.www.example", AF_INET6,
+ "name: t.www.example\n"
+ "address: 2001:db8::3\n");
+ check_h ("t.alias.example", AF_INET6,
+ "name: www.example\n"
+ "alias: t.alias.example\n"
+ "address: 2001:db8::4\n");
+ check_ai ("t.www.example", "80", AF_UNSPEC,
+ "address: STREAM/TCP 192.0.2.19 80\n"
+ "address: DGRAM/UDP 192.0.2.19 80\n"
+ "address: RAW/IP 192.0.2.19 80\n"
+ "address: STREAM/TCP 2001:db8::3 80\n"
+ "address: DGRAM/UDP 2001:db8::3 80\n"
+ "address: RAW/IP 2001:db8::3 80\n");
+ check_ai ("t.alias.example", "80", AF_UNSPEC,
+ "address: STREAM/TCP 192.0.2.20 80\n"
+ "address: DGRAM/UDP 192.0.2.20 80\n"
+ "address: RAW/IP 192.0.2.20 80\n"
+ "address: STREAM/TCP 2001:db8::4 80\n"
+ "address: DGRAM/UDP 2001:db8::4 80\n"
+ "address: RAW/IP 2001:db8::4 80\n");
+ check_ai ("t.www.example", "80", AF_INET,
+ "address: STREAM/TCP 192.0.2.19 80\n"
+ "address: DGRAM/UDP 192.0.2.19 80\n"
+ "address: RAW/IP 192.0.2.19 80\n");
+ check_ai ("t.alias.example", "80", AF_INET,
+ "address: STREAM/TCP 192.0.2.20 80\n"
+ "address: DGRAM/UDP 192.0.2.20 80\n"
+ "address: RAW/IP 192.0.2.20 80\n");
+ check_ai ("t.www.example", "80", AF_INET6,
+ "address: STREAM/TCP 2001:db8::3 80\n"
+ "address: DGRAM/UDP 2001:db8::3 80\n"
+ "address: RAW/IP 2001:db8::3 80\n");
+ check_ai ("t.alias.example", "80", AF_INET6,
+ "address: STREAM/TCP 2001:db8::4 80\n"
+ "address: DGRAM/UDP 2001:db8::4 80\n"
+ "address: RAW/IP 2001:db8::4 80\n");
+
+ test_bug_21295 ();
+ test_nodata_nxdomain ();
+
+ resolv_test_end (aux);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-binary.c b/resolv/tst-resolv-binary.c
new file mode 100644
index 0000000000..e7e6d87994
--- /dev/null
+++ b/resolv/tst-resolv-binary.c
@@ -0,0 +1,120 @@
+/* Test handling of binary domain names with res_send.
+ Copyright (C) 2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <resolv.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/resolv_test.h>
+
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ TEST_COMPARE (qclass, C_IN);
+ TEST_COMPARE (qtype, T_TXT);
+ TEST_VERIFY (strlen (qname) <= 255);
+
+ struct resolv_response_flags flags = { 0 };
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, qname, qclass, T_TXT, 0x12345678);
+ unsigned char qnamelen = strlen (qname);
+ resolv_response_add_data (b, &qnamelen, 1);
+ resolv_response_add_data (b, qname, qnamelen);
+ resolv_response_close_record (b);
+}
+
+static int
+do_test (void)
+{
+ struct resolv_test *aux = resolv_test_start
+ ((struct resolv_redirect_config)
+ {
+ .response_callback = response,
+ });
+
+ for (int b = 0; b <= 255; ++b)
+ {
+ unsigned char query[] =
+ {
+ b, b, /* Transaction ID. */
+ 1, 0, /* Query with RD flag. */
+ 0, 1, /* One question. */
+ 0, 0, 0, 0, 0, 0, /* The other sections are empty. */
+ 1, b, 7, 'e', 'x', 'a', 'm', 'p', 'l', 'e', 0,
+ 0, T_TXT, /* TXT query. */
+ 0, 1, /* Class IN. */
+ };
+ unsigned char response[512];
+ int ret = res_send (query, sizeof (query), response, sizeof (response));
+
+ char expected_name[20];
+ /* The name is uncompressed in the query, so we can reference it
+ directly. */
+ TEST_VERIFY_EXIT (ns_name_ntop (query + 12, expected_name,
+ sizeof (expected_name)) >= 0);
+ TEST_COMPARE (ret,
+ (ssize_t) sizeof (query)
+ + 2 /* Compression reference. */
+ + 2 + 2 + 4 + 2 /* Type, class, TTL, RDATA length. */
+ + 1 /* Pascal-style string length. */
+ + strlen (expected_name));
+
+ /* Mark as answer, with recursion available, and one answer. */
+ query[2] = 0x81;
+ query[3] = 0x80;
+ query[7] = 1;
+
+ /* Prefix of the response must match the query. */
+ TEST_COMPARE (memcmp (response, query, sizeof (query)), 0);
+
+ /* The actual answer follows, starting with the compression
+ reference. */
+ unsigned char *p = response + sizeof (query);
+ TEST_COMPARE (*p++, 0xc0);
+ TEST_COMPARE (*p++, 0x0c);
+
+ /* Type and class. */
+ TEST_COMPARE (*p++, 0);
+ TEST_COMPARE (*p++, T_TXT);
+ TEST_COMPARE (*p++, 0);
+ TEST_COMPARE (*p++, C_IN);
+
+ /* TTL. */
+ TEST_COMPARE (*p++, 0x12);
+ TEST_COMPARE (*p++, 0x34);
+ TEST_COMPARE (*p++, 0x56);
+ TEST_COMPARE (*p++, 0x78);
+
+ /* RDATA length. */
+ TEST_COMPARE (*p++, 0);
+ TEST_COMPARE (*p++, 1 + strlen (expected_name));
+
+ /* RDATA. */
+ TEST_COMPARE (*p++, strlen (expected_name));
+ TEST_COMPARE (memcmp (p, expected_name, strlen (expected_name)), 0);
+ }
+
+ resolv_test_end (aux);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-canonname.c b/resolv/tst-resolv-canonname.c
new file mode 100644
index 0000000000..3f0e68b0f8
--- /dev/null
+++ b/resolv/tst-resolv-canonname.c
@@ -0,0 +1,313 @@
+/* Test _nss_dns_getcanonname_r corner cases.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <gnu/lib-names.h>
+#include <netdb.h>
+#include <nss.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+
+/* _nss_dns_getcanonname_r is not called during regular operation
+ because nss_dns directly provides a canonical name, so we have to
+ test it directly. The function pointer is initialized by do_test
+ below. */
+static enum nss_status
+(*getcanonname) (const char *name, char *buffer, size_t buflen,
+ char **result, int *errnop, int *h_errnop);
+
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ int code;
+ {
+ char *tail;
+ if (sscanf (qname, "code%d.%ms", &code, &tail) != 2
+ || strcmp (tail, "example") != 0)
+ FAIL_EXIT1 ("error: invalid QNAME: %s\n", qname);
+ free (tail);
+ }
+
+ switch (code)
+ {
+ case 1:
+ resolv_response_init (b, (struct resolv_response_flags) {});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, "www.example", qclass, qtype, 0);
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
+ resolv_response_close_record (b);
+ break;
+ case 2:
+ resolv_response_init (b, (struct resolv_response_flags) {});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ if (qtype == T_AAAA)
+ {
+ resolv_response_open_record (b, "www.example", qclass, qtype, 0);
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
+ resolv_response_close_record (b);
+ for (int i = 0; i < 30000; ++i)
+ resolv_response_add_data (b, "", 1);
+ }
+ break;
+ case 3:
+ resolv_response_init (b, (struct resolv_response_flags) {});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ if (qtype == T_AAAA)
+ {
+ resolv_response_open_record (b, "www.example", qclass, qtype, 0);
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
+ resolv_response_close_record (b);
+ }
+ else
+ {
+ for (int i = 0; i < 30000; ++i)
+ resolv_response_add_data (b, "", 1);
+ }
+ break;
+ case 4:
+ resolv_response_init (b, (struct resolv_response_flags) {});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
+ resolv_response_add_name (b, "www.example");
+ resolv_response_close_record (b);
+ resolv_response_open_record (b, "www.example", qclass, qtype, 0);
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
+ resolv_response_close_record (b);
+ break;
+ case 5:
+ resolv_response_init (b, (struct resolv_response_flags) {});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
+ resolv_response_add_name (b, "www.example");
+ resolv_response_close_record (b);
+ resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
+ resolv_response_add_name (b, "www1.example");
+ resolv_response_close_record (b);
+ resolv_response_open_record (b, "www1.example", qclass, qtype, 0);
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
+ resolv_response_close_record (b);
+ break;
+ case 6:
+ resolv_response_init (b, (struct resolv_response_flags) {});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
+ resolv_response_add_name (b, "www.example");
+ resolv_response_close_record (b);
+ resolv_response_open_record (b, qname, qclass, 46 /* RRSIG */, 0);
+ resolv_response_add_name (b, ".");
+ resolv_response_close_record (b);
+ resolv_response_open_record (b, "www.example", qclass, qtype, 0);
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
+ resolv_response_close_record (b);
+ break;
+ case 102:
+ if (!ctx->tcp)
+ {
+ resolv_response_init (b, (struct resolv_response_flags) {.tc = true});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ }
+ else
+ {
+ resolv_response_init
+ (b, (struct resolv_response_flags) {.ancount = 1});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
+ size_t to_fill = 65535 - resolv_response_length (b)
+ - 2 /* length, "n" */ - 2 /* compression reference */
+ - 2 /* RR type */;
+ for (size_t i = 0; i < to_fill; ++i)
+ resolv_response_add_data (b, "", 1);
+ resolv_response_close_record (b);
+ resolv_response_add_name (b, "n.example");
+ uint16_t rrtype = htons (T_CNAME);
+ resolv_response_add_data (b, &rrtype, sizeof (rrtype));
+ }
+ break;
+ case 103:
+ /* NODATA repsonse. */
+ resolv_response_init (b, (struct resolv_response_flags) {});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ break;
+ case 104:
+ resolv_response_init (b, (struct resolv_response_flags) {.ancount = 1});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ /* No RR metadata. */
+ resolv_response_add_name (b, "www.example");
+ break;
+ case 105:
+ if (qtype == T_A)
+ {
+ resolv_response_init (b, (struct resolv_response_flags) {});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ /* No data, trigger AAAA query. */
+ }
+ else
+ {
+ resolv_response_init
+ (b, (struct resolv_response_flags) {.ancount = 1});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ /* No RR metadata. */
+ resolv_response_add_name
+ (b, "long-name-exceed-previously-initialized-buffer.example");
+ }
+ break;
+ case 106:
+ resolv_response_init (b, (struct resolv_response_flags) {.ancount = 1});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ /* No RR metadata. */
+ resolv_response_add_name (b, "www.example");
+ resolv_response_add_data (b, "\xff\xff", 2);
+ break;
+ case 107:
+ if (qtype == T_A)
+ {
+ resolv_response_init (b, (struct resolv_response_flags) {});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ /* No data, trigger AAAA query. */
+ }
+ else
+ {
+ resolv_response_init
+ (b, (struct resolv_response_flags) {.ancount = 1});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ /* No RR metadata. */
+ resolv_response_add_name (b, "www.example");
+ resolv_response_add_data (b, "\xff\xff", 2);
+ }
+ break;
+ default:
+ FAIL_EXIT1 ("error: invalid QNAME: %s (code %d)\n", qname, code);
+ }
+}
+
+static void
+check (int code, const char *expected)
+{
+ char qname[200];
+ snprintf (qname, sizeof (qname), "code%d.example", code);
+ char *result;
+ enum nss_status status;
+ {
+ enum { buffer_size = 4096 };
+ char *buffer = xmalloc (buffer_size);
+ char *temp_result;
+ int temp_errno;
+ int temp_herrno;
+ status = getcanonname
+ (qname, buffer, buffer_size, &temp_result, &temp_errno, &temp_herrno);
+ if (status == NSS_STATUS_SUCCESS)
+ result = xstrdup (temp_result);
+ else
+ {
+ errno = temp_errno;
+ h_errno = temp_herrno;
+ }
+ free (buffer);
+ }
+
+ if (status == NSS_STATUS_SUCCESS)
+ {
+ if (expected != NULL)
+ {
+ if (strcmp (result, expected) != 0)
+ {
+ support_record_failure ();
+ printf ("error: getcanonname (%s) failed\n", qname);
+ printf ("error: expected: %s\n", expected);
+ printf ("error: actual: %s\n", result);
+ free (result);
+ return;
+ }
+ }
+ else
+ {
+ support_record_failure ();
+ printf ("error: getcanonname (%s) unexpected success\n", qname);
+ printf ("error: actual: %s\n", result);
+ free (result);
+ return;
+ }
+ free (result);
+ }
+ else
+ {
+ if (expected != NULL)
+ {
+ support_record_failure ();
+ printf ("error: getcanonname (%s) failed\n", qname);
+ printf ("error: expected: %s\n", expected);
+ return;
+ }
+ }
+}
+
+
+static int
+do_test (void)
+{
+ void *nss_dns_handle = dlopen (LIBNSS_DNS_SO, RTLD_LAZY);
+ if (nss_dns_handle == NULL)
+ FAIL_EXIT1 ("could not dlopen %s: %s", LIBNSS_DNS_SO, dlerror ());
+ {
+ const char *func = "_nss_dns_getcanonname_r";
+ void *ptr = dlsym (nss_dns_handle, func);
+ if (ptr == NULL)
+ FAIL_EXIT1 ("could not look up %s: %s", func, dlerror ());
+ getcanonname = ptr;
+ }
+
+ struct resolv_test *aux = resolv_test_start
+ ((struct resolv_redirect_config)
+ {
+ .response_callback = response,
+ });
+
+ check (1, "www.example");
+ check (2, "www.example");
+ check (3, "www.example");
+ check (4, "www.example");
+ check (5, "www1.example");
+
+ /* This should really result in "www.example", but the fake RRSIG
+ record causes the current implementation to stop parsing. */
+ check (6, NULL);
+
+ for (int i = 102; i <= 107; ++i)
+ check (i, NULL);
+
+ resolv_test_end (aux);
+
+ TEST_VERIFY (dlclose (nss_dns_handle) == 0);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-edns.c b/resolv/tst-resolv-edns.c
new file mode 100644
index 0000000000..3f2367ca57
--- /dev/null
+++ b/resolv/tst-resolv-edns.c
@@ -0,0 +1,532 @@
+/* Test EDNS handling in the stub resolver.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+#include <support/test-driver.h>
+#include <support/xthread.h>
+
+/* Data produced by a test query. */
+struct response_data
+{
+ char *qname;
+ uint16_t qtype;
+ struct resolv_edns_info edns;
+};
+
+/* Global array used by put_response and get_response to record
+ response data. The test DNS server returns the index of the array
+ element which contains the actual response data. This enables the
+ test case to return arbitrary amounts of data with the limited
+ number of bits which fit into an IP addres.
+
+ The volatile specifier is needed because the test case accesses
+ these variables from a callback function called from a function
+ which is marked as __THROW (i.e., a leaf function which actually is
+ not). */
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+static struct response_data ** volatile response_data_array;
+volatile static size_t response_data_count;
+
+/* Extract information from the query, store it in a struct
+ response_data object, and return its index in the
+ response_data_array. */
+static unsigned int
+put_response (const struct resolv_response_context *ctx,
+ const char *qname, uint16_t qtype)
+{
+ xpthread_mutex_lock (&mutex);
+ ++response_data_count;
+ /* We only can represent 2**24 indexes in 10.0.0.0/8. */
+ TEST_VERIFY (response_data_count < (1 << 24));
+ response_data_array = xrealloc
+ (response_data_array, sizeof (*response_data_array) * response_data_count);
+ unsigned int index = response_data_count - 1;
+ struct response_data *data = xmalloc (sizeof (*data));
+ *data = (struct response_data)
+ {
+ .qname = xstrdup (qname),
+ .qtype = qtype,
+ .edns = ctx->edns,
+ };
+ response_data_array[index] = data;
+ xpthread_mutex_unlock (&mutex);
+ return index;
+}
+
+/* Verify the index into the response_data array and return the data
+ at it. */
+static struct response_data *
+get_response (unsigned int index)
+{
+ xpthread_mutex_lock (&mutex);
+ TEST_VERIFY_EXIT (index < response_data_count);
+ struct response_data *result = response_data_array[index];
+ xpthread_mutex_unlock (&mutex);
+ return result;
+}
+
+/* Deallocate all response data. */
+static void
+free_response_data (void)
+{
+ xpthread_mutex_lock (&mutex);
+ size_t count = response_data_count;
+ struct response_data **array = response_data_array;
+ for (unsigned int i = 0; i < count; ++i)
+ {
+ struct response_data *data = array[i];
+ free (data->qname);
+ free (data);
+ }
+ free (array);
+ response_data_array = NULL;
+ response_data_count = 0;
+ xpthread_mutex_unlock (&mutex);
+}
+
+#define EDNS_PROBE_EXAMPLE "edns-probe.example"
+
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ TEST_VERIFY_EXIT (qname != NULL);
+
+ const char *qname_compare = qname;
+
+ /* The "formerr." prefix can be used to request a FORMERR response on the
+ first server. */
+ bool send_formerr;
+ if (strncmp ("formerr.", qname, strlen ("formerr.")) == 0)
+ {
+ send_formerr = true;
+ qname_compare = qname + strlen ("formerr.");
+ }
+ else
+ {
+ send_formerr = false;
+ qname_compare = qname;
+ }
+
+ /* The "tcp." prefix can be used to request TCP fallback. */
+ bool force_tcp;
+ if (strncmp ("tcp.", qname_compare, strlen ("tcp.")) == 0)
+ {
+ force_tcp = true;
+ qname_compare += strlen ("tcp.");
+ }
+ else
+ force_tcp = false;
+
+ enum {edns_probe} requested_qname;
+ if (strcmp (qname_compare, EDNS_PROBE_EXAMPLE) == 0)
+ requested_qname = edns_probe;
+ else
+ {
+ support_record_failure ();
+ printf ("error: unexpected QNAME: %s (reduced: %s)\n",
+ qname, qname_compare);
+ return;
+ }
+ TEST_VERIFY_EXIT (qclass == C_IN);
+ struct resolv_response_flags flags = { };
+ flags.tc = force_tcp && !ctx->tcp;
+ if (!flags.tc && send_formerr && ctx->server_index == 0)
+ /* Send a FORMERR for the first full response from the first
+ server. */
+ flags.rcode = 1; /* FORMERR */
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+ if (flags.tc || flags.rcode != 0)
+ return;
+
+ if (test_verbose)
+ printf ("info: edns=%d payload_size=%d\n",
+ ctx->edns.active, ctx->edns.payload_size);
+
+ /* Encode the response_data object in multiple address records.
+ Each record carries two bytes of payload data, and an index. */
+ resolv_response_section (b, ns_s_an);
+ switch (requested_qname)
+ {
+ case edns_probe:
+ {
+ unsigned int index = put_response (ctx, qname, qtype);
+ switch (qtype)
+ {
+ case T_A:
+ {
+ uint32_t addr = htonl (0x0a000000 | index);
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
+ resolv_response_add_data (b, &addr, sizeof (addr));
+ resolv_response_close_record (b);
+ }
+ break;
+ case T_AAAA:
+ {
+ char addr[16]
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ index >> 16, index >> 8, index};
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
+ resolv_response_add_data (b, &addr, sizeof (addr));
+ resolv_response_close_record (b);
+ }
+ }
+ }
+ break;
+ }
+}
+
+/* Update *DATA with data from ADDRESS of SIZE. Set the corresponding
+ flag in SHADOW for each byte written. */
+static struct response_data *
+decode_address (const void *address, size_t size)
+{
+ switch (size)
+ {
+ case 4:
+ TEST_VERIFY (memcmp (address, "\x0a", 1) == 0);
+ break;
+ case 16:
+ TEST_VERIFY (memcmp (address, "\x20\x01\x0d\xb8", 4) == 0);
+ break;
+ default:
+ FAIL_EXIT1 ("unexpected address size %zu", size);
+ }
+ const unsigned char *addr = address;
+ unsigned int index = addr[size - 3] * 256 * 256
+ + addr[size - 2] * 256
+ + addr[size - 1];
+ return get_response (index);
+}
+
+static struct response_data *
+decode_hostent (struct hostent *e)
+{
+ TEST_VERIFY_EXIT (e != NULL);
+ TEST_VERIFY_EXIT (e->h_addr_list[0] != NULL);
+ TEST_VERIFY (e->h_addr_list[1] == NULL);
+ return decode_address (e->h_addr_list[0], e->h_length);
+}
+
+static struct response_data *
+decode_addrinfo (struct addrinfo *ai, int family)
+{
+ struct response_data *data = NULL;
+ while (ai != NULL)
+ {
+ if (ai->ai_family == family)
+ {
+ struct response_data *new_data;
+ switch (family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *pin = (struct sockaddr_in *) ai->ai_addr;
+ new_data = decode_address (&pin->sin_addr.s_addr, 4);
+ }
+ break;
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *pin = (struct sockaddr_in6 *) ai->ai_addr;
+ new_data = decode_address (&pin->sin6_addr.s6_addr, 16);
+ }
+ break;
+ default:
+ FAIL_EXIT1 ("invalid address family %d", ai->ai_family);
+ }
+ if (data == NULL)
+ data = new_data;
+ else
+ /* Check pointer equality because this should be the same
+ response (same index). */
+ TEST_VERIFY (data == new_data);
+ }
+ ai = ai->ai_next;
+ }
+ TEST_VERIFY_EXIT (data != NULL);
+ return data;
+}
+
+/* Updated by the main test loop in accordance with what is set in
+ _res.options. */
+static bool use_edns;
+static bool use_dnssec;
+
+/* Verify the decoded response data against the flags above. */
+static void
+verify_response_data_payload (struct response_data *data,
+ size_t expected_payload)
+{
+ bool edns = use_edns || use_dnssec;
+ TEST_VERIFY (data->edns.active == edns);
+ if (!edns)
+ expected_payload = 0;
+ if (data->edns.payload_size != expected_payload)
+ {
+ support_record_failure ();
+ printf ("error: unexpected payload size %d (edns=%d)\n",
+ (int) data->edns.payload_size, edns);
+ }
+ uint16_t expected_flags = 0;
+ if (use_dnssec)
+ expected_flags |= 0x8000; /* DO flag. */
+ if (data->edns.flags != expected_flags)
+ {
+ support_record_failure ();
+ printf ("error: unexpected EDNS flags 0x%04x (edns=%d)\n",
+ (int) data->edns.flags, edns);
+ }
+}
+
+/* Same as verify_response_data_payload, but use the default
+ payload. */
+static void
+verify_response_data (struct response_data *data)
+{
+ verify_response_data_payload (data, 1200);
+}
+
+static void
+check_hostent (struct hostent *e)
+{
+ TEST_VERIFY_EXIT (e != NULL);
+ verify_response_data (decode_hostent (e));
+}
+
+static void
+do_ai (int family)
+{
+ struct addrinfo hints = { .ai_family = family };
+ struct addrinfo *ai;
+ int ret = getaddrinfo (EDNS_PROBE_EXAMPLE, "80", &hints, &ai);
+ TEST_VERIFY_EXIT (ret == 0);
+ switch (family)
+ {
+ case AF_INET:
+ case AF_INET6:
+ verify_response_data (decode_addrinfo (ai, family));
+ break;
+ case AF_UNSPEC:
+ verify_response_data (decode_addrinfo (ai, AF_INET));
+ verify_response_data (decode_addrinfo (ai, AF_INET6));
+ break;
+ default:
+ FAIL_EXIT1 ("invalid address family %d", family);
+ }
+ freeaddrinfo (ai);
+}
+
+enum res_op
+{
+ res_op_search,
+ res_op_query,
+ res_op_querydomain,
+ res_op_nsearch,
+ res_op_nquery,
+ res_op_nquerydomain,
+
+ res_op_last = res_op_nquerydomain,
+};
+
+static const char *
+res_op_string (enum res_op op)
+{
+ switch (op)
+ {
+ case res_op_search:
+ return "res_search";
+ case res_op_query:
+ return "res_query";
+ case res_op_querydomain:
+ return "res_querydomain";
+ case res_op_nsearch:
+ return "res_nsearch";
+ case res_op_nquery:
+ return "res_nquery";
+ case res_op_nquerydomain:
+ return "res_nquerydomain";
+ }
+ FAIL_EXIT1 ("invalid res_op value %d", (int) op);
+}
+
+/* Call libresolv function OP to look up PROBE_NAME, with an answer
+ buffer of SIZE bytes. Check that the advertised UDP buffer size is
+ in fact EXPECTED_BUFFER_SIZE. */
+static void
+do_res_search (const char *probe_name, enum res_op op, size_t size,
+ size_t expected_buffer_size)
+{
+ if (test_verbose)
+ printf ("info: testing %s with buffer size %zu\n",
+ res_op_string (op), size);
+ unsigned char *buffer = xmalloc (size);
+ int ret = -1;
+ switch (op)
+ {
+ case res_op_search:
+ ret = res_search (probe_name, C_IN, T_A, buffer, size);
+ break;
+ case res_op_query:
+ ret = res_query (probe_name, C_IN, T_A, buffer, size);
+ break;
+ case res_op_nsearch:
+ ret = res_nsearch (&_res, probe_name, C_IN, T_A, buffer, size);
+ break;
+ case res_op_nquery:
+ ret = res_nquery (&_res, probe_name, C_IN, T_A, buffer, size);
+ break;
+ case res_op_querydomain:
+ case res_op_nquerydomain:
+ {
+ char *example_stripped = xstrdup (probe_name);
+ char *dot_example = strstr (example_stripped, ".example");
+ if (dot_example != NULL && strcmp (dot_example, ".example") == 0)
+ {
+ /* Truncate the domain name. */
+ *dot_example = '\0';
+ if (op == res_op_querydomain)
+ ret = res_querydomain
+ (example_stripped, "example", C_IN, T_A, buffer, size);
+ else
+ ret = res_nquerydomain
+ (&_res, example_stripped, "example", C_IN, T_A, buffer, size);
+ }
+ else
+ FAIL_EXIT1 ("invalid probe name: %s", probe_name);
+ free (example_stripped);
+ }
+ break;
+ }
+ TEST_VERIFY_EXIT (ret > 12);
+ unsigned char *end = buffer + ret;
+
+ HEADER *hd = (HEADER *) buffer;
+ TEST_VERIFY (ntohs (hd->qdcount) == 1);
+ TEST_VERIFY (ntohs (hd->ancount) == 1);
+ /* Skip over the header. */
+ unsigned char *p = buffer + sizeof (*hd);
+ /* Skip over the question. */
+ ret = dn_skipname (p, end);
+ TEST_VERIFY_EXIT (ret > 0);
+ p += ret;
+ TEST_VERIFY_EXIT (end - p >= 4);
+ p += 4;
+ /* Skip over the RNAME and the RR header, but stop at the RDATA
+ length. */
+ ret = dn_skipname (p, end);
+ TEST_VERIFY_EXIT (ret > 0);
+ p += ret;
+ TEST_VERIFY_EXIT (end - p >= 2 + 2 + 4 + 2 + 4);
+ p += 2 + 2 + 4;
+ /* The IP address should be 4 bytes long. */
+ TEST_VERIFY_EXIT (p[0] == 0);
+ TEST_VERIFY_EXIT (p[1] == 4);
+ /* Extract the address information. */
+ p += 2;
+ struct response_data *data = decode_address (p, 4);
+
+ verify_response_data_payload (data, expected_buffer_size);
+
+ free (buffer);
+}
+
+static void
+run_test (const char *probe_name)
+{
+ if (test_verbose)
+ printf ("\ninfo: * use_edns=%d use_dnssec=%d\n",
+ use_edns, use_dnssec);
+ check_hostent (gethostbyname (probe_name));
+ check_hostent (gethostbyname2 (probe_name, AF_INET));
+ check_hostent (gethostbyname2 (probe_name, AF_INET6));
+ do_ai (AF_UNSPEC);
+ do_ai (AF_INET);
+ do_ai (AF_INET6);
+
+ for (int op = 0; op <= res_op_last; ++op)
+ {
+ do_res_search (probe_name, op, 301, 512);
+ do_res_search (probe_name, op, 511, 512);
+ do_res_search (probe_name, op, 512, 512);
+ do_res_search (probe_name, op, 513, 513);
+ do_res_search (probe_name, op, 657, 657);
+ do_res_search (probe_name, op, 1199, 1199);
+ do_res_search (probe_name, op, 1200, 1200);
+ do_res_search (probe_name, op, 1201, 1200);
+ do_res_search (probe_name, op, 65535, 1200);
+ }
+}
+
+static int
+do_test (void)
+{
+ for (int do_edns = 0; do_edns < 2; ++do_edns)
+ for (int do_dnssec = 0; do_dnssec < 2; ++do_dnssec)
+ for (int do_tcp = 0; do_tcp < 2; ++do_tcp)
+ for (int do_formerr = 0; do_formerr < 2; ++do_formerr)
+ {
+ struct resolv_test *aux = resolv_test_start
+ ((struct resolv_redirect_config)
+ {
+ .response_callback = response,
+ });
+
+ use_edns = do_edns;
+ if (do_edns)
+ _res.options |= RES_USE_EDNS0;
+ use_dnssec = do_dnssec;
+ if (do_dnssec)
+ _res.options |= RES_USE_DNSSEC;
+
+ char *probe_name = xstrdup (EDNS_PROBE_EXAMPLE);
+ if (do_tcp)
+ {
+ char *n = xasprintf ("tcp.%s", probe_name);
+ free (probe_name);
+ probe_name = n;
+ }
+ if (do_formerr)
+ {
+ /* Send a garbage query in an attempt to trigger EDNS
+ fallback. */
+ char *n = xasprintf ("formerr.%s", probe_name);
+ gethostbyname (n);
+ free (n);
+ }
+
+ run_test (probe_name);
+
+ free (probe_name);
+ resolv_test_end (aux);
+ }
+
+ free_response_data ();
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-network.c b/resolv/tst-resolv-network.c
new file mode 100644
index 0000000000..4b862d57e6
--- /dev/null
+++ b/resolv/tst-resolv-network.c
@@ -0,0 +1,303 @@
+/* Test getnetbyname and getnetbyaddr.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/check_nss.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+static void
+send_ptr (struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype,
+ const char *alias)
+{
+ resolv_response_init (b, (struct resolv_response_flags) {});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
+ resolv_response_add_name (b, alias);
+ resolv_response_close_record (b);
+}
+
+static void
+handle_code (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype,
+ int code)
+{
+ switch (code)
+ {
+ case 1:
+ send_ptr (b, qname, qclass, qtype, "1.in-addr.arpa");
+ break;
+ case 2:
+ send_ptr (b, qname, qclass, qtype, "2.1.in-addr.arpa");
+ break;
+ case 3:
+ send_ptr (b, qname, qclass, qtype, "3.2.1.in-addr.arpa");
+ break;
+ case 4:
+ send_ptr (b, qname, qclass, qtype, "4.3.2.1.in-addr.arpa");
+ break;
+ case 5:
+ /* Test multiple PTR records. */
+ resolv_response_init (b, (struct resolv_response_flags) {});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
+ resolv_response_add_name (b, "127.in-addr.arpa");
+ resolv_response_close_record (b);
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
+ resolv_response_add_name (b, "0.in-addr.arpa");
+ resolv_response_close_record (b);
+ break;
+ case 6:
+ /* Test skipping of RRSIG record. */
+ resolv_response_init (b, (struct resolv_response_flags) { });
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
+ resolv_response_add_name (b, "127.in-addr.arpa");
+ resolv_response_close_record (b);
+
+ resolv_response_open_record (b, qname, qclass, 46 /* RRSIG */, 0);
+ {
+ char buf[500];
+ memset (buf, 0x3f, sizeof (buf));
+ resolv_response_add_data (b, buf, sizeof (buf));
+ }
+ resolv_response_close_record (b);
+
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
+ resolv_response_add_name (b, "0.in-addr.arpa");
+ resolv_response_close_record (b);
+ break;
+ case 7:
+ /* Test CNAME handling. */
+ resolv_response_init (b, (struct resolv_response_flags) { });
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
+ resolv_response_add_name (b, "cname.example");
+ resolv_response_close_record (b);
+ resolv_response_open_record (b, "cname.example", qclass, T_PTR, 0);
+ resolv_response_add_name (b, "4.3.2.1.in-addr.arpa");
+ resolv_response_close_record (b);
+ break;
+
+ case 100:
+ resolv_response_init (b, (struct resolv_response_flags) { .rcode = 0, });
+ resolv_response_add_question (b, qname, qclass, qtype);
+ break;
+ case 101:
+ resolv_response_init (b, (struct resolv_response_flags)
+ { .rcode = NXDOMAIN, });
+ resolv_response_add_question (b, qname, qclass, qtype);
+ break;
+ case 102:
+ resolv_response_init (b, (struct resolv_response_flags) {.rcode = SERVFAIL});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ break;
+ case 103:
+ /* Check response length matching. */
+ if (!ctx->tcp)
+ {
+ resolv_response_init (b, (struct resolv_response_flags) {.tc = true});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ }
+ else
+ {
+ resolv_response_init (b, (struct resolv_response_flags) {.ancount = 1});
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
+ resolv_response_add_name (b, "127.in-addr.arpa");
+ resolv_response_close_record (b);
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
+ resolv_response_add_name (b, "example");
+ resolv_response_close_record (b);
+
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
+ size_t to_fill = 65535 - resolv_response_length (b)
+ - 2 /* length, "n" */ - 2 /* compression reference */
+ - 2 /* RR type */;
+ for (size_t i = 0; i < to_fill; ++i)
+ resolv_response_add_data (b, "", 1);
+ resolv_response_close_record (b);
+ resolv_response_add_name (b, "n.example");
+ uint16_t rrtype = htons (T_PTR);
+ resolv_response_add_data (b, &rrtype, sizeof (rrtype));
+ }
+ break;
+ default:
+ FAIL_EXIT1 ("invalid QNAME: %s (code %d)", qname, code);
+ }
+}
+
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ int code;
+ if (strstr (qname, "in-addr.arpa") == NULL)
+ {
+ char *tail;
+ if (sscanf (qname, "code%d.%ms", &code, &tail) != 2
+ || strcmp (tail, "example") != 0)
+ FAIL_EXIT1 ("invalid QNAME: %s", qname);
+ free (tail);
+ handle_code (ctx, b, qname, qclass, qtype, code);
+ }
+ else
+ {
+ /* Reverse lookup. */
+ int components[4];
+ char *tail;
+ if (sscanf (qname, "%d.%d.%d.%d.%ms",
+ components, components + 1, components + 2, components + 3,
+ &tail) != 5
+ || strcmp (tail, "in-addr.arpa") != 0)
+ FAIL_EXIT1 ("invalid QNAME: %s", qname);
+ free (tail);
+ handle_code (ctx, b, qname, qclass, qtype, components[3]);
+ }
+}
+
+static void
+check_reverse (int code, const char *expected)
+{
+ char *query = xasprintf ("code=%d", code);
+ check_netent (query, getnetbyaddr (code, AF_INET), expected);
+ free (query);
+}
+
+/* Test for CVE-2016-3075. */
+static void
+check_long_name (void)
+{
+ struct xmemstream mem;
+ xopen_memstream (&mem);
+
+ char label[65];
+ memset (label, 'x', 63);
+ label[63] = '.';
+ label[64] = '\0';
+ for (unsigned i = 0; i < 64 * 1024 * 1024 / strlen (label); ++i)
+ fprintf (mem.out, "%s", label);
+
+ xfclose_memstream (&mem);
+
+ check_netent ("long name", getnetbyname (mem.buffer),
+ "error: NO_RECOVERY\n");
+
+ free (mem.buffer);
+}
+
+static int
+do_test (void)
+{
+ struct resolv_test *obj = resolv_test_start
+ ((struct resolv_redirect_config)
+ {
+ .response_callback = response
+ });
+
+ /* Lookup by name, success cases. */
+ check_netent ("code1.example", getnetbyname ("code1.example"),
+ "alias: 1.in-addr.arpa\n"
+ "net: 0x00000001\n");
+ check_netent ("code2.example", getnetbyname ("code2.example"),
+ "alias: 2.1.in-addr.arpa\n"
+ "net: 0x00000102\n");
+ check_netent ("code3.example", getnetbyname ("code3.example"),
+ "alias: 3.2.1.in-addr.arpa\n"
+ "net: 0x00010203\n");
+ check_netent ("code4.example", getnetbyname ("code4.example"),
+ "alias: 4.3.2.1.in-addr.arpa\n"
+ "net: 0x01020304\n");
+ check_netent ("code5.example", getnetbyname ("code5.example"),
+ "alias: 127.in-addr.arpa\n"
+ "alias: 0.in-addr.arpa\n"
+ "net: 0x0000007f\n");
+ check_netent ("code6.example", getnetbyname ("code6.example"),
+ "alias: 127.in-addr.arpa\n"
+ "alias: 0.in-addr.arpa\n"
+ "net: 0x0000007f\n");
+ check_netent ("code7.example", getnetbyname ("code7.example"),
+ "alias: 4.3.2.1.in-addr.arpa\n"
+ "net: 0x01020304\n");
+
+ /* Lookup by name, failure cases. */
+ check_netent ("code100.example", getnetbyname ("code100.example"),
+ "error: NO_ADDRESS\n");
+ check_netent ("code101.example", getnetbyname ("code101.example"),
+ "error: HOST_NOT_FOUND\n");
+ check_netent ("code102.example", getnetbyname ("code102.example"),
+ "error: TRY_AGAIN\n");
+ check_netent ("code103.example", getnetbyname ("code103.example"),
+ "error: NO_RECOVERY\n");
+
+ /* Lookup by address, success cases. */
+ check_reverse (1,
+ "name: 1.in-addr.arpa\n"
+ "net: 0x00000001\n");
+ check_reverse (2,
+ "name: 2.1.in-addr.arpa\n"
+ "net: 0x00000002\n");
+ check_reverse (3,
+ "name: 3.2.1.in-addr.arpa\n"
+ "net: 0x00000003\n");
+ check_reverse (4,
+ "name: 4.3.2.1.in-addr.arpa\n"
+ "net: 0x00000004\n");
+ check_reverse (5,
+ "name: 127.in-addr.arpa\n"
+ "alias: 0.in-addr.arpa\n"
+ "net: 0x00000005\n");
+ check_reverse (6,
+ "name: 127.in-addr.arpa\n"
+ "alias: 0.in-addr.arpa\n"
+ "net: 0x00000006\n");
+ check_reverse (7,
+ "name: 4.3.2.1.in-addr.arpa\n"
+ "net: 0x00000007\n");
+
+ /* Lookup by address, failure cases. */
+ check_reverse (100,
+ "error: NO_ADDRESS\n");
+ check_reverse (101,
+ "error: HOST_NOT_FOUND\n");
+ check_reverse (102,
+ "error: TRY_AGAIN\n");
+ check_reverse (103,
+ "error: NO_RECOVERY\n");
+
+ check_long_name ();
+
+ resolv_test_end (obj);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-qtypes.c b/resolv/tst-resolv-qtypes.c
new file mode 100644
index 0000000000..b207e82fc4
--- /dev/null
+++ b/resolv/tst-resolv-qtypes.c
@@ -0,0 +1,185 @@
+/* Exercise low-level query functions with different QTYPEs.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <resolv.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/check_nss.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+#include <support/test-driver.h>
+#include <support/xmemstream.h>
+
+/* If ture, the response function will send the actual response packet
+ over TCP instead of UDP. */
+static volatile bool force_tcp;
+
+/* Send back a fake resource record matching the QTYPE. */
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ if (force_tcp && ctx->tcp)
+ {
+ resolv_response_init (b, (struct resolv_response_flags) { .tc = 1 });
+ resolv_response_add_question (b, qname, qclass, qtype);
+ return;
+ }
+
+ resolv_response_init (b, (struct resolv_response_flags) { });
+ resolv_response_add_question (b, qname, qclass, qtype);
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
+ resolv_response_add_data (b, &qtype, sizeof (qtype));
+ resolv_response_close_record (b);
+}
+
+static const char domain[] = "www.example.com";
+
+static int
+wrap_res_query (int type, unsigned char *answer, int answer_length)
+{
+ return res_query (domain, C_IN, type, answer, answer_length);
+}
+
+static int
+wrap_res_search (int type, unsigned char *answer, int answer_length)
+{
+ return res_query (domain, C_IN, type, answer, answer_length);
+}
+
+static int
+wrap_res_querydomain (int type, unsigned char *answer, int answer_length)
+{
+ return res_querydomain ("www", "example.com", C_IN, type,
+ answer, answer_length);
+}
+
+static int
+wrap_res_send (int type, unsigned char *answer, int answer_length)
+{
+ unsigned char buf[512];
+ int ret = res_mkquery (QUERY, domain, C_IN, type,
+ (const unsigned char *) "", 0, NULL,
+ buf, sizeof (buf));
+ if (type < 0 || type >= 65536)
+ {
+ /* res_mkquery fails for out-of-range record types. */
+ TEST_VERIFY_EXIT (ret == -1);
+ return -1;
+ }
+ TEST_VERIFY_EXIT (ret > 12); /* DNS header length. */
+ return res_send (buf, ret, answer, answer_length);
+}
+
+static int
+wrap_res_nquery (int type, unsigned char *answer, int answer_length)
+{
+ return res_nquery (&_res, domain, C_IN, type, answer, answer_length);
+}
+
+static int
+wrap_res_nsearch (int type, unsigned char *answer, int answer_length)
+{
+ return res_nquery (&_res, domain, C_IN, type, answer, answer_length);
+}
+
+static int
+wrap_res_nquerydomain (int type, unsigned char *answer, int answer_length)
+{
+ return res_nquerydomain (&_res, "www", "example.com", C_IN, type,
+ answer, answer_length);
+}
+
+static int
+wrap_res_nsend (int type, unsigned char *answer, int answer_length)
+{
+ unsigned char buf[512];
+ int ret = res_nmkquery (&_res, QUERY, domain, C_IN, type,
+ (const unsigned char *) "", 0, NULL,
+ buf, sizeof (buf));
+ if (type < 0 || type >= 65536)
+ {
+ /* res_mkquery fails for out-of-range record types. */
+ TEST_VERIFY_EXIT (ret == -1);
+ return -1;
+ }
+ TEST_VERIFY_EXIT (ret > 12); /* DNS header length. */
+ return res_nsend (&_res, buf, ret, answer, answer_length);
+}
+
+static void
+test_function (const char *fname,
+ int (*func) (int type,
+ unsigned char *answer, int answer_length))
+{
+ unsigned char buf[512];
+ for (int tcp = 0; tcp < 2; ++tcp)
+ {
+ force_tcp = tcp;
+ for (unsigned int type = 1; type <= 65535; ++type)
+ {
+ if (test_verbose)
+ printf ("info: sending QTYPE %d with %s (tcp=%d)\n",
+ type, fname, tcp);
+ int ret = func (type, buf, sizeof (buf));
+ if (ret != 47)
+ FAIL_EXIT1 ("%s tcp=%d qtype=%d return value %d",
+ fname,tcp, type, ret);
+ /* One question, one answer record. */
+ TEST_VERIFY (memcmp (buf + 4, "\0\1\0\1\0\0\0\0", 8) == 0);
+ /* Question section. */
+ static const char qname[] = "\3www\7example\3com";
+ size_t qname_length = sizeof (qname);
+ TEST_VERIFY (memcmp (buf + 12, qname, qname_length) == 0);
+ /* RDATA part of answer. */
+ uint16_t type16 = type;
+ TEST_VERIFY (memcmp (buf + ret - 2, &type16, sizeof (type16)) == 0);
+ }
+ }
+
+ TEST_VERIFY (func (-1, buf, sizeof (buf) == -1));
+ TEST_VERIFY (func (65536, buf, sizeof (buf) == -1));
+}
+
+static int
+do_test (void)
+{
+ struct resolv_redirect_config config =
+ {
+ .response_callback = response,
+ };
+ struct resolv_test *obj = resolv_test_start (config);
+
+ test_function ("res_query", &wrap_res_query);
+ test_function ("res_search", &wrap_res_search);
+ test_function ("res_querydomain", &wrap_res_querydomain);
+ test_function ("res_send", &wrap_res_send);
+
+ test_function ("res_nquery", &wrap_res_nquery);
+ test_function ("res_nsearch", &wrap_res_nsearch);
+ test_function ("res_nquerydomain", &wrap_res_nquerydomain);
+ test_function ("res_nsend", &wrap_res_nsend);
+
+ resolv_test_end (obj);
+ return 0;
+}
+
+#define TIMEOUT 300
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-res_init-multi.c b/resolv/tst-resolv-res_init-multi.c
new file mode 100644
index 0000000000..1aacea49ca
--- /dev/null
+++ b/resolv/tst-resolv-res_init-multi.c
@@ -0,0 +1,89 @@
+/* Multi-threaded test for resolver initialization.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <netdb.h>
+#include <resolv.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include <support/support.h>
+#include <support/xthread.h>
+
+/* Whether name lookups succeed does not really matter. We use this
+ to trigger initialization of the resolver. */
+static const char *test_hostname = "www.gnu.org";
+
+/* The different initialization methods. */
+enum test_type { init, byname, gai };
+enum { type_count = 3 };
+
+/* Thread function. Perform a few resolver options. */
+static void *
+thread_func (void *closure)
+{
+ enum test_type *ptype = closure;
+ /* Perform a few calls to the requested operation. */
+ TEST_VERIFY (*ptype >= 0);
+ TEST_VERIFY (*ptype < (int) type_count);
+ for (int i = 0; i < 3; ++i)
+ switch (*ptype)
+ {
+ case init:
+ res_init ();
+ break;
+ case byname:
+ gethostbyname (test_hostname);
+ break;
+ case gai:
+ {
+ struct addrinfo hints = { 0, };
+ struct addrinfo *ai = NULL;
+ if (getaddrinfo (test_hostname, "80", &hints, &ai) == 0)
+ freeaddrinfo (ai);
+ }
+ break;
+ }
+ free (ptype);
+ return NULL;
+}
+
+static int
+do_test (void)
+{
+ /* Start a small number of threads which perform resolver
+ operations. */
+ enum { thread_count = 30 };
+
+ pthread_t threads[thread_count];
+ for (int i = 0; i < thread_count; ++i)
+ {
+ enum test_type *ptype = xmalloc (sizeof (*ptype));
+ *ptype = i % type_count;
+ threads[i] = xpthread_create (NULL, thread_func, ptype);
+ }
+ for (int i = 0; i < type_count; ++i)
+ {
+ enum test_type *ptype = xmalloc (sizeof (*ptype));
+ *ptype = i;
+ thread_func (ptype);
+ }
+ for (int i = 0; i < thread_count; ++i)
+ xpthread_join (threads[i]);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-res_init-skeleton.c b/resolv/tst-resolv-res_init-skeleton.c
new file mode 100644
index 0000000000..a5061e6d4f
--- /dev/null
+++ b/resolv/tst-resolv-res_init-skeleton.c
@@ -0,0 +1,1096 @@
+/* Test parsing of /etc/resolv.conf. Genric version.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Before including this file, TEST_THREAD has to be defined to 0 or
+ 1, depending on whether the threading tests should be compiled
+ in. */
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <gnu/lib-names.h>
+#include <netdb.h>
+#include <resolv/resolv-internal.h> /* For DEPRECATED_RES_USE_INET6. */
+#include <resolv/resolv_context.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/run_diff.h>
+#include <support/support.h>
+#include <support/temp_file.h>
+#include <support/test-driver.h>
+#include <support/xsocket.h>
+#include <support/xstdio.h>
+#include <support/xunistd.h>
+
+#if TEST_THREAD
+# include <support/xthread.h>
+#endif
+
+/* This is the host name used to ensure predictable behavior of
+ res_init. */
+static const char *const test_hostname = "www.example.com";
+
+struct support_chroot *chroot_env;
+
+static void
+prepare (int argc, char **argv)
+{
+ chroot_env = support_chroot_create
+ ((struct support_chroot_configuration)
+ {
+ .resolv_conf = "",
+ });
+}
+
+/* Verify that the chroot environment has been set up. */
+static void
+check_chroot_working (void *closure)
+{
+ xchroot (chroot_env->path_chroot);
+ FILE *fp = xfopen (_PATH_RESCONF, "r");
+ xfclose (fp);
+
+ TEST_VERIFY_EXIT (res_init () == 0);
+ TEST_VERIFY (_res.options & RES_INIT);
+
+ char buf[100];
+ if (gethostname (buf, sizeof (buf)) < 0)
+ FAIL_EXIT1 ("gethostname: %m");
+ if (strcmp (buf, test_hostname) != 0)
+ FAIL_EXIT1 ("unexpected host name: %s", buf);
+}
+
+/* If FLAG is set in *OPTIONS, write NAME to FP, and clear it in
+ *OPTIONS. */
+static void
+print_option_flag (FILE *fp, int *options, int flag, const char *name)
+{
+ if (*options & flag)
+ {
+ fprintf (fp, " %s", name);
+ *options &= ~flag;
+ }
+}
+
+/* Write a decoded version of the resolver configuration *RESP to the
+ stream FP. */
+static void
+print_resp (FILE *fp, res_state resp)
+{
+ struct resolv_context *ctx = __resolv_context_get_override (resp);
+ TEST_VERIFY_EXIT (ctx != NULL);
+ if (ctx->conf == NULL)
+ fprintf (fp, "; extended resolver state missing\n");
+
+ /* The options directive. */
+ {
+ /* RES_INIT is used internally for tracking initialization. */
+ TEST_VERIFY (resp->options & RES_INIT);
+ /* Also mask out other default flags which cannot be set through
+ the options directive. */
+ int options
+ = resp->options & ~(RES_INIT | RES_RECURSE | RES_DEFNAMES | RES_DNSRCH);
+ if (options != 0
+ || resp->ndots != 1
+ || resp->retrans != RES_TIMEOUT
+ || resp->retry != RES_DFLRETRY)
+ {
+ fputs ("options", fp);
+ if (resp->ndots != 1)
+ fprintf (fp, " ndots:%d", resp->ndots);
+ if (resp->retrans != RES_TIMEOUT)
+ fprintf (fp, " timeout:%d", resp->retrans);
+ if (resp->retry != RES_DFLRETRY)
+ fprintf (fp, " attempts:%d", resp->retry);
+ print_option_flag (fp, &options, RES_USEVC, "use-vc");
+ print_option_flag (fp, &options, DEPRECATED_RES_USE_INET6, "inet6");
+ print_option_flag (fp, &options, RES_ROTATE, "rotate");
+ print_option_flag (fp, &options, RES_USE_EDNS0, "edns0");
+ print_option_flag (fp, &options, RES_SNGLKUP,
+ "single-request");
+ print_option_flag (fp, &options, RES_SNGLKUPREOP,
+ "single-request-reopen");
+ print_option_flag (fp, &options, RES_NOTLDQUERY, "no-tld-query");
+ print_option_flag (fp, &options, RES_NORELOAD, "no-reload");
+ fputc ('\n', fp);
+ if (options != 0)
+ fprintf (fp, "; error: unresolved option bits: 0x%x\n", options);
+ }
+ }
+
+ /* The search and domain directives. */
+ if (resp->dnsrch[0] != NULL)
+ {
+ fputs ("search", fp);
+ for (int i = 0; i < MAXDNSRCH && resp->dnsrch[i] != NULL; ++i)
+ {
+ fputc (' ', fp);
+ fputs (resp->dnsrch[i], fp);
+ }
+ fputc ('\n', fp);
+ }
+ else if (resp->defdname[0] != '\0')
+ fprintf (fp, "domain %s\n", resp->defdname);
+
+ /* The extended search path. */
+ {
+ size_t i = 0;
+ while (true)
+ {
+ const char *name = __resolv_context_search_list (ctx, i);
+ if (name == NULL)
+ break;
+ fprintf (fp, "; search[%zu]: %s\n", i, name);
+ ++i;
+ }
+ }
+
+ /* The sortlist directive. */
+ if (resp->nsort > 0)
+ {
+ fputs ("sortlist", fp);
+ for (int i = 0; i < resp->nsort && i < MAXRESOLVSORT; ++i)
+ {
+ char net[20];
+ if (inet_ntop (AF_INET, &resp->sort_list[i].addr,
+ net, sizeof (net)) == NULL)
+ FAIL_EXIT1 ("inet_ntop: %m\n");
+ char mask[20];
+ if (inet_ntop (AF_INET, &resp->sort_list[i].mask,
+ mask, sizeof (mask)) == NULL)
+ FAIL_EXIT1 ("inet_ntop: %m\n");
+ fprintf (fp, " %s/%s", net, mask);
+ }
+ fputc ('\n', fp);
+ }
+
+ /* The nameserver directives. */
+ for (size_t i = 0; i < resp->nscount; ++i)
+ {
+ char host[NI_MAXHOST];
+ char service[NI_MAXSERV];
+
+ /* See get_nsaddr in res_send.c. */
+ void *addr;
+ size_t addrlen;
+ if (resp->nsaddr_list[i].sin_family == 0
+ && resp->_u._ext.nsaddrs[i] != NULL)
+ {
+ addr = resp->_u._ext.nsaddrs[i];
+ addrlen = sizeof (*resp->_u._ext.nsaddrs[i]);
+ }
+ else
+ {
+ addr = &resp->nsaddr_list[i];
+ addrlen = sizeof (resp->nsaddr_list[i]);
+ }
+
+ int ret = getnameinfo (addr, addrlen,
+ host, sizeof (host), service, sizeof (service),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+ if (ret != 0)
+ {
+ if (ret == EAI_SYSTEM)
+ fprintf (fp, "; error: getnameinfo: %m\n");
+ else
+ fprintf (fp, "; error: getnameinfo: %s\n", gai_strerror (ret));
+ }
+ else
+ {
+ fprintf (fp, "nameserver %s\n", host);
+ if (strcmp (service, "53") != 0)
+ fprintf (fp, "; unrepresentable port number %s\n\n", service);
+ }
+ }
+
+ /* The extended name server list. */
+ {
+ size_t i = 0;
+ while (true)
+ {
+ const struct sockaddr *addr = __resolv_context_nameserver (ctx, i);
+ if (addr == NULL)
+ break;
+ size_t addrlen;
+ switch (addr->sa_family)
+ {
+ case AF_INET:
+ addrlen = sizeof (struct sockaddr_in);
+ break;
+ case AF_INET6:
+ addrlen = sizeof (struct sockaddr_in6);
+ break;
+ default:
+ FAIL_EXIT1 ("invalid address family %d", addr->sa_family);
+ }
+
+ char host[NI_MAXHOST];
+ char service[NI_MAXSERV];
+ int ret = getnameinfo (addr, addrlen,
+ host, sizeof (host), service, sizeof (service),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+
+ if (ret != 0)
+ {
+ if (ret == EAI_SYSTEM)
+ fprintf (fp, "; error: getnameinfo: %m\n");
+ else
+ fprintf (fp, "; error: getnameinfo: %s\n", gai_strerror (ret));
+ }
+ else
+ fprintf (fp, "; nameserver[%zu]: [%s]:%s\n", i, host, service);
+ ++i;
+ }
+ }
+
+ TEST_VERIFY (!ferror (fp));
+
+ __resolv_context_put (ctx);
+}
+
+/* Parameters of one test case. */
+struct test_case
+{
+ /* A short, descriptive name of the test. */
+ const char *name;
+
+ /* The contents of the /etc/resolv.conf file. */
+ const char *conf;
+
+ /* The expected output from print_resp. */
+ const char *expected;
+
+ /* Setting for the LOCALDOMAIN environment variable. NULL if the
+ variable is not to be set. */
+ const char *localdomain;
+
+ /* Setting for the RES_OPTIONS environment variable. NULL if the
+ variable is not to be set. */
+ const char *res_options;
+
+ /* Override the system host name. NULL means that no change is made
+ and the default is used (test_hostname). */
+ const char *hostname;
+};
+
+enum test_init
+{
+ test_init,
+ test_ninit,
+ test_mkquery,
+ test_gethostbyname,
+ test_getaddrinfo,
+ test_init_method_last = test_getaddrinfo
+};
+
+static const char *const test_init_names[] =
+ {
+ [test_init] = "res_init",
+ [test_ninit] = "res_ninit",
+ [test_mkquery] = "res_mkquery",
+ [test_gethostbyname] = "gethostbyname",
+ [test_getaddrinfo] = "getaddrinfo",
+ };
+
+/* Closure argument for run_res_init. */
+struct test_context
+{
+ enum test_init init;
+ const struct test_case *t;
+};
+
+static void
+setup_nss_dns_and_chroot (void)
+{
+ /* Load nss_dns outside of the chroot. */
+ if (dlopen (LIBNSS_DNS_SO, RTLD_LAZY) == NULL)
+ FAIL_EXIT1 ("could not load " LIBNSS_DNS_SO ": %s", dlerror ());
+ xchroot (chroot_env->path_chroot);
+ /* Force the use of nss_dns. */
+ __nss_configure_lookup ("hosts", "dns");
+}
+
+/* Run res_ninit or res_init in a subprocess and dump the parsed
+ resolver state to standard output. */
+static void
+run_res_init (void *closure)
+{
+ struct test_context *ctx = closure;
+ TEST_VERIFY (getenv ("LOCALDOMAIN") == NULL);
+ TEST_VERIFY (getenv ("RES_OPTIONS") == NULL);
+ if (ctx->t->localdomain != NULL)
+ setenv ("LOCALDOMAIN", ctx->t->localdomain, 1);
+ if (ctx->t->res_options != NULL)
+ setenv ("RES_OPTIONS", ctx->t->res_options, 1);
+ if (ctx->t->hostname != NULL)
+ {
+#ifdef CLONE_NEWUTS
+ /* This test needs its own namespace, to avoid changing the host
+ name for the parent, too. */
+ TEST_VERIFY_EXIT (unshare (CLONE_NEWUTS) == 0);
+ if (sethostname (ctx->t->hostname, strlen (ctx->t->hostname)) != 0)
+ FAIL_EXIT1 ("sethostname (\"%s\"): %m", ctx->t->hostname);
+#else
+ FAIL_UNSUPPORTED ("clone (CLONE_NEWUTS) not supported");
+#endif
+ }
+
+ switch (ctx->init)
+ {
+ case test_init:
+ xchroot (chroot_env->path_chroot);
+ TEST_VERIFY (res_init () == 0);
+ print_resp (stdout, &_res);
+ return;
+
+ case test_ninit:
+ xchroot (chroot_env->path_chroot);
+ res_state resp = xmalloc (sizeof (*resp));
+ memset (resp, 0, sizeof (*resp));
+ TEST_VERIFY (res_ninit (resp) == 0);
+ print_resp (stdout, resp);
+ res_nclose (resp);
+ free (resp);
+ return;
+
+ case test_mkquery:
+ xchroot (chroot_env->path_chroot);
+ unsigned char buf[512];
+ TEST_VERIFY (res_mkquery (QUERY, "www.example",
+ C_IN, ns_t_a, NULL, 0,
+ NULL, buf, sizeof (buf)) > 0);
+ print_resp (stdout, &_res);
+ return;
+
+ case test_gethostbyname:
+ setup_nss_dns_and_chroot ();
+ /* Trigger implicit initialization of the _res structure. The
+ actual lookup result is immaterial. */
+ (void )gethostbyname ("www.example");
+ print_resp (stdout, &_res);
+ return;
+
+ case test_getaddrinfo:
+ setup_nss_dns_and_chroot ();
+ /* Trigger implicit initialization of the _res structure. The
+ actual lookup result is immaterial. */
+ struct addrinfo *ai;
+ (void) getaddrinfo ("www.example", NULL, NULL, &ai);
+ print_resp (stdout, &_res);
+ return;
+ }
+
+ FAIL_EXIT1 ("invalid init method %d", ctx->init);
+}
+
+#if TEST_THREAD
+/* Helper function which calls run_res_init from a thread. */
+static void *
+run_res_init_thread_func (void *closure)
+{
+ run_res_init (closure);
+ return NULL;
+}
+
+/* Variant of res_run_init which runs the function on a non-main
+ thread. */
+static void
+run_res_init_on_thread (void *closure)
+{
+ xpthread_join (xpthread_create (NULL, run_res_init_thread_func, closure));
+}
+#endif /* TEST_THREAD */
+
+struct test_case test_cases[] =
+ {
+ {.name = "empty file",
+ .conf = "",
+ .expected = "search example.com\n"
+ "; search[0]: example.com\n"
+ "nameserver 127.0.0.1\n"
+ "; nameserver[0]: [127.0.0.1]:53\n"
+ },
+ {.name = "empty file, no-dot hostname",
+ .conf = "",
+ .expected = "nameserver 127.0.0.1\n"
+ "; nameserver[0]: [127.0.0.1]:53\n",
+ .hostname = "example",
+ },
+ {.name = "empty file with LOCALDOMAIN",
+ .conf = "",
+ .expected = "search example.net\n"
+ "; search[0]: example.net\n"
+ "nameserver 127.0.0.1\n"
+ "; nameserver[0]: [127.0.0.1]:53\n",
+ .localdomain = "example.net",
+ },
+ {.name = "empty file with RES_OPTIONS",
+ .conf = "",
+ .expected = "options attempts:5 edns0\n"
+ "search example.com\n"
+ "; search[0]: example.com\n"
+ "nameserver 127.0.0.1\n"
+ "; nameserver[0]: [127.0.0.1]:53\n",
+ .res_options = "edns0 attempts:5",
+ },
+ {.name = "empty file with RES_OPTIONS and LOCALDOMAIN",
+ .conf = "",
+ .expected = "options attempts:5 edns0\n"
+ "search example.org\n"
+ "; search[0]: example.org\n"
+ "nameserver 127.0.0.1\n"
+ "; nameserver[0]: [127.0.0.1]:53\n",
+ .localdomain = "example.org",
+ .res_options = "edns0 attempts:5",
+ },
+ {.name = "basic",
+ .conf = "search corp.example.com example.com\n"
+ "nameserver 192.0.2.1\n",
+ .expected = "search corp.example.com example.com\n"
+ "; search[0]: corp.example.com\n"
+ "; search[1]: example.com\n"
+ "nameserver 192.0.2.1\n"
+ "; nameserver[0]: [192.0.2.1]:53\n"
+ },
+ {.name = "basic with no-dot hostname",
+ .conf = "search corp.example.com example.com\n"
+ "nameserver 192.0.2.1\n",
+ .expected = "search corp.example.com example.com\n"
+ "; search[0]: corp.example.com\n"
+ "; search[1]: example.com\n"
+ "nameserver 192.0.2.1\n"
+ "; nameserver[0]: [192.0.2.1]:53\n",
+ .hostname = "example",
+ },
+ {.name = "basic no-reload",
+ .conf = "options no-reload\n"
+ "search corp.example.com example.com\n"
+ "nameserver 192.0.2.1\n",
+ .expected = "options no-reload\n"
+ "search corp.example.com example.com\n"
+ "; search[0]: corp.example.com\n"
+ "; search[1]: example.com\n"
+ "nameserver 192.0.2.1\n"
+ "; nameserver[0]: [192.0.2.1]:53\n"
+ },
+ {.name = "basic no-reload via RES_OPTIONS",
+ .conf = "search corp.example.com example.com\n"
+ "nameserver 192.0.2.1\n",
+ .expected = "options no-reload\n"
+ "search corp.example.com example.com\n"
+ "; search[0]: corp.example.com\n"
+ "; search[1]: example.com\n"
+ "nameserver 192.0.2.1\n"
+ "; nameserver[0]: [192.0.2.1]:53\n",
+ .res_options = "no-reload"
+ },
+ {.name = "whitespace",
+ .conf = "# This test covers comment and whitespace processing "
+ " (trailing whitespace,\n"
+ "# missing newline at end of file).\n"
+ "\n"
+ ";search commented out\n"
+ "search corp.example.com\texample.com \n"
+ "#nameserver 192.0.2.3\n"
+ "nameserver 192.0.2.1 \n"
+ "nameserver 192.0.2.2", /* No \n at end of file. */
+ .expected = "search corp.example.com example.com\n"
+ "; search[0]: corp.example.com\n"
+ "; search[1]: example.com\n"
+ "nameserver 192.0.2.1\n"
+ "nameserver 192.0.2.2\n"
+ "; nameserver[0]: [192.0.2.1]:53\n"
+ "; nameserver[1]: [192.0.2.2]:53\n"
+ },
+ {.name = "domain",
+ .conf = "domain example.net\n"
+ "nameserver 192.0.2.1\n",
+ .expected = "search example.net\n"
+ "; search[0]: example.net\n"
+ "nameserver 192.0.2.1\n"
+ "; nameserver[0]: [192.0.2.1]:53\n"
+ },
+ {.name = "domain space",
+ .conf = "domain example.net \n"
+ "nameserver 192.0.2.1\n",
+ .expected = "search example.net\n"
+ "; search[0]: example.net\n"
+ "nameserver 192.0.2.1\n"
+ "; nameserver[0]: [192.0.2.1]:53\n"
+ },
+ {.name = "domain tab",
+ .conf = "domain example.net\t\n"
+ "nameserver 192.0.2.1\n",
+ .expected = "search example.net\n"
+ "; search[0]: example.net\n"
+ "nameserver 192.0.2.1\n"
+ "; nameserver[0]: [192.0.2.1]:53\n"
+ },
+ {.name = "domain override",
+ .conf = "search example.com example.org\n"
+ "nameserver 192.0.2.1\n"
+ "domain example.net", /* No \n at end of file. */
+ .expected = "search example.net\n"
+ "; search[0]: example.net\n"
+ "nameserver 192.0.2.1\n"
+ "; nameserver[0]: [192.0.2.1]:53\n"
+ },
+ {.name = "option values, multiple servers",
+ .conf = "options\tinet6\tndots:3 edns0\tattempts:5\ttimeout:19\n"
+ "domain example.net\n"
+ ";domain comment\n"
+ "search corp.example.com\texample.com\n"
+ "nameserver 192.0.2.1\n"
+ "nameserver ::1\n"
+ "nameserver 192.0.2.2\n",
+ .expected = "options ndots:3 timeout:19 attempts:5 inet6 edns0\n"
+ "search corp.example.com example.com\n"
+ "; search[0]: corp.example.com\n"
+ "; search[1]: example.com\n"
+ "nameserver 192.0.2.1\n"
+ "nameserver ::1\n"
+ "nameserver 192.0.2.2\n"
+ "; nameserver[0]: [192.0.2.1]:53\n"
+ "; nameserver[1]: [::1]:53\n"
+ "; nameserver[2]: [192.0.2.2]:53\n"
+ },
+ {.name = "out-of-range option vales",
+ .conf = "options use-vc timeout:999 attempts:999 ndots:99\n"
+ "search example.com\n",
+ .expected = "options ndots:15 timeout:30 attempts:5 use-vc\n"
+ "search example.com\n"
+ "; search[0]: example.com\n"
+ "nameserver 127.0.0.1\n"
+ "; nameserver[0]: [127.0.0.1]:53\n"
+ },
+ {.name = "repeated directives",
+ .conf = "options ndots:3 use-vc\n"
+ "options edns0 ndots:2\n"
+ "domain corp.example\n"
+ "search example.net corp.example.com example.com\n"
+ "search example.org\n"
+ "search\n",
+ .expected = "options ndots:2 use-vc edns0\n"
+ "search example.org\n"
+ "; search[0]: example.org\n"
+ "nameserver 127.0.0.1\n"
+ "; nameserver[0]: [127.0.0.1]:53\n"
+ },
+ {.name = "many name servers, sortlist",
+ .conf = "options single-request\n"
+ "search example.org example.com example.net corp.example.com\n"
+ "sortlist 192.0.2.0/255.255.255.0\n"
+ "nameserver 192.0.2.1\n"
+ "nameserver 192.0.2.2\n"
+ "nameserver 192.0.2.3\n"
+ "nameserver 192.0.2.4\n"
+ "nameserver 192.0.2.5\n"
+ "nameserver 192.0.2.6\n"
+ "nameserver 192.0.2.7\n"
+ "nameserver 192.0.2.8\n",
+ .expected = "options single-request\n"
+ "search example.org example.com example.net corp.example.com\n"
+ "; search[0]: example.org\n"
+ "; search[1]: example.com\n"
+ "; search[2]: example.net\n"
+ "; search[3]: corp.example.com\n"
+ "sortlist 192.0.2.0/255.255.255.0\n"
+ "nameserver 192.0.2.1\n"
+ "nameserver 192.0.2.2\n"
+ "nameserver 192.0.2.3\n"
+ "; nameserver[0]: [192.0.2.1]:53\n"
+ "; nameserver[1]: [192.0.2.2]:53\n"
+ "; nameserver[2]: [192.0.2.3]:53\n"
+ "; nameserver[3]: [192.0.2.4]:53\n"
+ "; nameserver[4]: [192.0.2.5]:53\n"
+ "; nameserver[5]: [192.0.2.6]:53\n"
+ "; nameserver[6]: [192.0.2.7]:53\n"
+ "; nameserver[7]: [192.0.2.8]:53\n"
+ },
+ {.name = "IPv4 and IPv6 nameservers",
+ .conf = "options single-request\n"
+ "search example.org example.com example.net corp.example.com"
+ " legacy.example.com\n"
+ "sortlist 192.0.2.0\n"
+ "nameserver 192.0.2.1\n"
+ "nameserver 2001:db8::2\n"
+ "nameserver 192.0.2.3\n"
+ "nameserver 2001:db8::4\n"
+ "nameserver 192.0.2.5\n"
+ "nameserver 2001:db8::6\n"
+ "nameserver 192.0.2.7\n"
+ "nameserver 2001:db8::8\n",
+ .expected = "options single-request\n"
+ "search example.org example.com example.net corp.example.com"
+ " legacy.example.com\n"
+ "; search[0]: example.org\n"
+ "; search[1]: example.com\n"
+ "; search[2]: example.net\n"
+ "; search[3]: corp.example.com\n"
+ "; search[4]: legacy.example.com\n"
+ "sortlist 192.0.2.0/255.255.255.0\n"
+ "nameserver 192.0.2.1\n"
+ "nameserver 2001:db8::2\n"
+ "nameserver 192.0.2.3\n"
+ "; nameserver[0]: [192.0.2.1]:53\n"
+ "; nameserver[1]: [2001:db8::2]:53\n"
+ "; nameserver[2]: [192.0.2.3]:53\n"
+ "; nameserver[3]: [2001:db8::4]:53\n"
+ "; nameserver[4]: [192.0.2.5]:53\n"
+ "; nameserver[5]: [2001:db8::6]:53\n"
+ "; nameserver[6]: [192.0.2.7]:53\n"
+ "; nameserver[7]: [2001:db8::8]:53\n",
+ },
+ {.name = "garbage after nameserver",
+ .conf = "nameserver 192.0.2.1 garbage\n"
+ "nameserver 192.0.2.2:5353\n"
+ "nameserver 192.0.2.3 5353\n",
+ .expected = "search example.com\n"
+ "; search[0]: example.com\n"
+ "nameserver 192.0.2.1\n"
+ "nameserver 192.0.2.3\n"
+ "; nameserver[0]: [192.0.2.1]:53\n"
+ "; nameserver[1]: [192.0.2.3]:53\n"
+ },
+ {.name = "RES_OPTIONS is cummulative",
+ .conf = "options timeout:7 ndots:2 use-vc\n"
+ "nameserver 192.0.2.1\n",
+ .expected = "options ndots:3 timeout:7 attempts:5 use-vc edns0\n"
+ "search example.com\n"
+ "; search[0]: example.com\n"
+ "nameserver 192.0.2.1\n"
+ "; nameserver[0]: [192.0.2.1]:53\n",
+ .res_options = "attempts:5 ndots:3 edns0 ",
+ },
+ {.name = "many search list entries (bug 19569)",
+ .conf = "nameserver 192.0.2.1\n"
+ "search corp.example.com support.example.com"
+ " community.example.org wan.example.net vpn.example.net"
+ " example.com example.org example.net\n",
+ .expected = "search corp.example.com support.example.com"
+ " community.example.org wan.example.net vpn.example.net example.com\n"
+ "; search[0]: corp.example.com\n"
+ "; search[1]: support.example.com\n"
+ "; search[2]: community.example.org\n"
+ "; search[3]: wan.example.net\n"
+ "; search[4]: vpn.example.net\n"
+ "; search[5]: example.com\n"
+ "; search[6]: example.org\n"
+ "; search[7]: example.net\n"
+ "nameserver 192.0.2.1\n"
+ "; nameserver[0]: [192.0.2.1]:53\n"
+ },
+ {.name = "very long search list entries (bug 21475)",
+ .conf = "nameserver 192.0.2.1\n"
+ "search example.com "
+#define H63 "this-host-name-is-longer-than-yours-yes-I-really-really-mean-it"
+#define D63 "this-domain-name-is-as-long-as-the-previous-name--63-characters"
+ " " H63 "." D63 ".example.org"
+ " " H63 "." D63 ".example.net\n",
+ .expected = "search example.com " H63 "." D63 ".example.org\n"
+ "; search[0]: example.com\n"
+ "; search[1]: " H63 "." D63 ".example.org\n"
+ "; search[2]: " H63 "." D63 ".example.net\n"
+#undef H63
+#undef D63
+ "nameserver 192.0.2.1\n"
+ "; nameserver[0]: [192.0.2.1]:53\n"
+ },
+ { NULL }
+ };
+
+/* Run the indicated test case. This function assumes that the chroot
+ contents has already been set up. */
+static void
+test_file_contents (const struct test_case *t)
+{
+#if TEST_THREAD
+ for (int do_thread = 0; do_thread < 2; ++do_thread)
+#endif
+ for (int init_method = 0; init_method <= test_init_method_last;
+ ++init_method)
+ {
+ if (test_verbose > 0)
+ printf ("info: testing init method %s\n",
+ test_init_names[init_method]);
+ struct test_context ctx = { .init = init_method, .t = t };
+ void (*func) (void *) = run_res_init;
+#if TEST_THREAD
+ if (do_thread)
+ func = run_res_init_on_thread;
+#endif
+ struct support_capture_subprocess proc
+ = support_capture_subprocess (func, &ctx);
+ if (strcmp (proc.out.buffer, t->expected) != 0)
+ {
+ support_record_failure ();
+ printf ("error: output mismatch for %s (init method %s)\n",
+ t->name, test_init_names[init_method]);
+ support_run_diff ("expected", t->expected,
+ "actual", proc.out.buffer);
+ }
+ support_capture_subprocess_check (&proc, t->name, 0,
+ sc_allow_stdout);
+ support_capture_subprocess_free (&proc);
+ }
+}
+
+/* Special tests which do not follow the general pattern. */
+enum { special_tests_count = 11 };
+
+/* Implementation of special tests. */
+static void
+special_test_callback (void *closure)
+{
+ unsigned int *test_indexp = closure;
+ unsigned test_index = *test_indexp;
+ TEST_VERIFY (test_index < special_tests_count);
+ if (test_verbose > 0)
+ printf ("info: special test %u\n", test_index);
+ xchroot (chroot_env->path_chroot);
+
+ switch (test_index)
+ {
+ case 0:
+ case 1:
+ /* Second res_init with missing or empty file preserves
+ flags. */
+ if (test_index == 1)
+ TEST_VERIFY (unlink (_PATH_RESCONF) == 0);
+ _res.options = RES_USE_EDNS0;
+ TEST_VERIFY (res_init () == 0);
+ /* First res_init clears flag. */
+ TEST_VERIFY (!(_res.options & RES_USE_EDNS0));
+ _res.options |= RES_USE_EDNS0;
+ TEST_VERIFY (res_init () == 0);
+ /* Second res_init preserves flag. */
+ TEST_VERIFY (_res.options & RES_USE_EDNS0);
+ if (test_index == 1)
+ /* Restore empty file. */
+ support_write_file_string (_PATH_RESCONF, "");
+ break;
+
+ case 2:
+ /* Second res_init is cumulative. */
+ support_write_file_string (_PATH_RESCONF,
+ "options rotate\n"
+ "nameserver 192.0.2.1\n");
+ _res.options = RES_USE_EDNS0;
+ TEST_VERIFY (res_init () == 0);
+ /* First res_init clears flag. */
+ TEST_VERIFY (!(_res.options & RES_USE_EDNS0));
+ /* And sets RES_ROTATE. */
+ TEST_VERIFY (_res.options & RES_ROTATE);
+ _res.options |= RES_USE_EDNS0;
+ TEST_VERIFY (res_init () == 0);
+ /* Second res_init preserves flag. */
+ TEST_VERIFY (_res.options & RES_USE_EDNS0);
+ TEST_VERIFY (_res.options & RES_ROTATE);
+ /* Reloading the configuration does not clear the explicitly set
+ flag. */
+ support_write_file_string (_PATH_RESCONF,
+ "nameserver 192.0.2.1\n"
+ "nameserver 192.0.2.2\n");
+ TEST_VERIFY (res_init () == 0);
+ TEST_VERIFY (_res.nscount == 2);
+ TEST_VERIFY (_res.options & RES_USE_EDNS0);
+ /* Whether RES_ROTATE (originally in resolv.conf, now removed)
+ should be preserved is subject to debate. See bug 21701. */
+ /* TEST_VERIFY (!(_res.options & RES_ROTATE)); */
+ break;
+
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ support_write_file_string (_PATH_RESCONF,
+ "options edns0\n"
+ "nameserver 192.0.2.1\n");
+ goto reload_tests;
+ case 7: /* 7 and the following tests are with no-reload. */
+ case 8:
+ case 9:
+ case 10:
+ support_write_file_string (_PATH_RESCONF,
+ "options edns0 no-reload\n"
+ "nameserver 192.0.2.1\n");
+ /* Fall through. */
+ reload_tests:
+ for (int iteration = 0; iteration < 2; ++iteration)
+ {
+ switch (test_index)
+ {
+ case 3:
+ case 7:
+ TEST_VERIFY (res_init () == 0);
+ break;
+ case 4:
+ case 8:
+ {
+ unsigned char buf[512];
+ TEST_VERIFY
+ (res_mkquery (QUERY, test_hostname, C_IN, T_A,
+ NULL, 0, NULL, buf, sizeof (buf)) > 0);
+ }
+ break;
+ case 5:
+ case 9:
+ gethostbyname (test_hostname);
+ break;
+ case 6:
+ case 10:
+ {
+ struct addrinfo *ai;
+ (void) getaddrinfo (test_hostname, NULL, NULL, &ai);
+ }
+ break;
+ }
+ /* test_index == 7 is res_init and performs a reload even
+ with no-reload. */
+ if (iteration == 0 || test_index > 7)
+ {
+ TEST_VERIFY (_res.options & RES_USE_EDNS0);
+ TEST_VERIFY (!(_res.options & RES_ROTATE));
+ if (test_index < 7)
+ TEST_VERIFY (!(_res.options & RES_NORELOAD));
+ else
+ TEST_VERIFY (_res.options & RES_NORELOAD);
+ TEST_VERIFY (_res.nscount == 1);
+ /* File change triggers automatic reloading. */
+ support_write_file_string (_PATH_RESCONF,
+ "options rotate\n"
+ "nameserver 192.0.2.1\n"
+ "nameserver 192.0.2.2\n");
+ }
+ else
+ {
+ if (test_index != 3 && test_index != 7)
+ /* test_index 3, 7 are res_init; this function does
+ not reset flags. See bug 21701. */
+ TEST_VERIFY (!(_res.options & RES_USE_EDNS0));
+ TEST_VERIFY (_res.options & RES_ROTATE);
+ TEST_VERIFY (_res.nscount == 2);
+ }
+ }
+ break;
+ }
+}
+
+#if TEST_THREAD
+/* Helper function which calls special_test_callback from a
+ thread. */
+static void *
+special_test_thread_func (void *closure)
+{
+ special_test_callback (closure);
+ return NULL;
+}
+
+/* Variant of special_test_callback which runs the function on a
+ non-main thread. */
+static void
+run_special_test_on_thread (void *closure)
+{
+ xpthread_join (xpthread_create (NULL, special_test_thread_func, closure));
+}
+#endif /* TEST_THREAD */
+
+/* Perform the requested special test in a subprocess using
+ special_test_callback. */
+static void
+special_test (unsigned int test_index)
+{
+#if TEST_THREAD
+ for (int do_thread = 0; do_thread < 2; ++do_thread)
+#endif
+ {
+ void (*func) (void *) = special_test_callback;
+#if TEST_THREAD
+ if (do_thread)
+ func = run_special_test_on_thread;
+#endif
+ struct support_capture_subprocess proc
+ = support_capture_subprocess (func, &test_index);
+ char *test_name = xasprintf ("special test %u", test_index);
+ if (strcmp (proc.out.buffer, "") != 0)
+ {
+ support_record_failure ();
+ printf ("error: output mismatch for %s\n", test_name);
+ support_run_diff ("expected", "",
+ "actual", proc.out.buffer);
+ }
+ support_capture_subprocess_check (&proc, test_name, 0, sc_allow_stdout);
+ free (test_name);
+ support_capture_subprocess_free (&proc);
+ }
+}
+
+
+/* Dummy DNS server. It ensures that the probe queries sent by
+ gethostbyname and getaddrinfo receive a reply even if the system
+ applies a very strict rate limit to localhost. */
+static pid_t
+start_dummy_server (void)
+{
+ int server_socket = xsocket (AF_INET, SOCK_DGRAM, 0);
+ {
+ struct sockaddr_in sin =
+ {
+ .sin_family = AF_INET,
+ .sin_addr = { .s_addr = htonl (INADDR_LOOPBACK) },
+ .sin_port = htons (53),
+ };
+ int ret = bind (server_socket, (struct sockaddr *) &sin, sizeof (sin));
+ if (ret < 0)
+ {
+ if (errno == EACCES)
+ /* The port is reserved, which means we cannot start the
+ server. */
+ return -1;
+ FAIL_EXIT1 ("cannot bind socket to port 53: %m");
+ }
+ }
+
+ pid_t pid = xfork ();
+ if (pid == 0)
+ {
+ /* Child process. Echo back queries as SERVFAIL responses. */
+ while (true)
+ {
+ union
+ {
+ HEADER header;
+ unsigned char bytes[512];
+ } packet;
+ struct sockaddr_in sin;
+ socklen_t sinlen = sizeof (sin);
+
+ ssize_t ret = recvfrom
+ (server_socket, &packet, sizeof (packet),
+ MSG_NOSIGNAL, (struct sockaddr *) &sin, &sinlen);
+ if (ret < 0)
+ FAIL_EXIT1 ("recvfrom on fake server socket: %m");
+ if (ret > sizeof (HEADER))
+ {
+ /* Turn the query into a SERVFAIL response. */
+ packet.header.qr = 1;
+ packet.header.rcode = ns_r_servfail;
+
+ /* Send the response. */
+ ret = sendto (server_socket, &packet, ret,
+ MSG_NOSIGNAL, (struct sockaddr *) &sin, sinlen);
+ if (ret < 0)
+ /* The peer may have closed socket prematurely, so
+ this is not an error. */
+ printf ("warning: sending DNS server reply: %m\n");
+ }
+ }
+ }
+
+ /* In the parent, close the socket. */
+ xclose (server_socket);
+
+ return pid;
+}
+
+static int
+do_test (void)
+{
+ support_become_root ();
+ support_enter_network_namespace ();
+ if (!support_in_uts_namespace () || !support_can_chroot ())
+ return EXIT_UNSUPPORTED;
+
+ /* We are in an UTS namespace, so we can set the host name without
+ altering the state of the entire system. */
+ if (sethostname (test_hostname, strlen (test_hostname)) != 0)
+ FAIL_EXIT1 ("sethostname: %m");
+
+ /* These environment variables affect resolv.conf parsing. */
+ unsetenv ("LOCALDOMAIN");
+ unsetenv ("RES_OPTIONS");
+
+ /* Ensure that the chroot setup worked. */
+ {
+ struct support_capture_subprocess proc
+ = support_capture_subprocess (check_chroot_working, NULL);
+ support_capture_subprocess_check (&proc, "chroot", 0, sc_allow_none);
+ support_capture_subprocess_free (&proc);
+ }
+
+ pid_t server = start_dummy_server ();
+
+ for (size_t i = 0; test_cases[i].name != NULL; ++i)
+ {
+ if (test_verbose > 0)
+ printf ("info: running test: %s\n", test_cases[i].name);
+ TEST_VERIFY (test_cases[i].conf != NULL);
+ TEST_VERIFY (test_cases[i].expected != NULL);
+
+ support_write_file_string (chroot_env->path_resolv_conf,
+ test_cases[i].conf);
+
+ test_file_contents (&test_cases[i]);
+
+ /* The expected output from the empty file test is used for
+ further tests. */
+ if (test_cases[i].conf[0] == '\0')
+ {
+ if (test_verbose > 0)
+ printf ("info: special test: missing file\n");
+ TEST_VERIFY (unlink (chroot_env->path_resolv_conf) == 0);
+ test_file_contents (&test_cases[i]);
+
+ if (test_verbose > 0)
+ printf ("info: special test: dangling symbolic link\n");
+ TEST_VERIFY (symlink ("does-not-exist", chroot_env->path_resolv_conf) == 0);
+ test_file_contents (&test_cases[i]);
+ TEST_VERIFY (unlink (chroot_env->path_resolv_conf) == 0);
+
+ if (test_verbose > 0)
+ printf ("info: special test: unreadable file\n");
+ support_write_file_string (chroot_env->path_resolv_conf, "");
+ TEST_VERIFY (chmod (chroot_env->path_resolv_conf, 0) == 0);
+ test_file_contents (&test_cases[i]);
+
+ /* Restore the empty file. */
+ TEST_VERIFY (unlink (chroot_env->path_resolv_conf) == 0);
+ support_write_file_string (chroot_env->path_resolv_conf, "");
+ }
+ }
+
+ /* The tests which do not follow a regular pattern. */
+ for (unsigned int test_index = 0;
+ test_index < special_tests_count; ++test_index)
+ special_test (test_index);
+
+ if (server > 0)
+ {
+ if (kill (server, SIGTERM) < 0)
+ FAIL_EXIT1 ("could not terminate server process: %m");
+ xwaitpid (server, NULL, 0);
+ }
+
+ support_chroot_free (chroot_env);
+ return 0;
+}
+
+#define PREPARE prepare
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-res_init-thread.c b/resolv/tst-resolv-res_init-thread.c
new file mode 100644
index 0000000000..8bb935e0f3
--- /dev/null
+++ b/resolv/tst-resolv-res_init-thread.c
@@ -0,0 +1,20 @@
+/* Test parsing of /etc/resolv.conf, threading version.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_THREAD 1
+#include "tst-resolv-res_init-skeleton.c"
diff --git a/resolv/tst-resolv-res_init.c b/resolv/tst-resolv-res_init.c
new file mode 100644
index 0000000000..bb91c9e3ad
--- /dev/null
+++ b/resolv/tst-resolv-res_init.c
@@ -0,0 +1,20 @@
+/* Test parsing of /etc/resolv.conf, non-threading version.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#define TEST_THREAD 0
+#include "tst-resolv-res_init-skeleton.c"
diff --git a/resolv/tst-resolv-res_ninit.c b/resolv/tst-resolv-res_ninit.c
new file mode 100644
index 0000000000..46e72ab7ce
--- /dev/null
+++ b/resolv/tst-resolv-res_ninit.c
@@ -0,0 +1,75 @@
+/* Test the creation of many struct __res_state objects.
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <mcheck.h>
+#include <resolv.h>
+#include <resolv/resolv_context.h>
+#include <stdlib.h>
+#include <support/check.h>
+
+/* Order the resolver states by their extended resolver state
+ index. */
+static int
+sort_res_state (const void *a, const void *b)
+{
+ res_state left = (res_state) a;
+ res_state right = (res_state) b;
+ return memcmp (&left->_u._ext.__glibc_extension_index,
+ &right->_u._ext.__glibc_extension_index,
+ sizeof (left->_u._ext.__glibc_extension_index));
+}
+
+static int
+do_test (void)
+{
+ mtrace ();
+
+ enum { count = 100 * 1000 };
+ res_state array = calloc (count, sizeof (*array));
+ const struct resolv_conf *conf = NULL;
+ for (size_t i = 0; i < count; ++i)
+ {
+ TEST_VERIFY (res_ninit (array + i) == 0);
+ TEST_VERIFY (array[i].nscount > 0);
+ struct resolv_context *ctx = __resolv_context_get_override (array + i);
+ TEST_VERIFY_EXIT (ctx != NULL);
+ TEST_VERIFY (ctx->resp == array + i);
+ if (i == 0)
+ {
+ conf = ctx->conf;
+ TEST_VERIFY (conf != NULL);
+ }
+ else
+ /* The underyling configuration should be identical across all
+ res_state opjects because resolv.conf did not change. */
+ TEST_VERIFY (ctx->conf == conf);
+ }
+ qsort (array, count, sizeof (*array), sort_res_state);
+ for (size_t i = 1; i < count; ++i)
+ /* All extension indices should be different. */
+ TEST_VERIFY (sort_res_state (array + i - 1, array + i) < 0);
+ for (size_t i = 0; i < count; ++i)
+ res_nclose (array + i);
+ free (array);
+
+ TEST_VERIFY (res_init () == 0);
+ return 0;
+}
+
+#define TIMEOUT 50
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-rotate.c b/resolv/tst-resolv-rotate.c
new file mode 100644
index 0000000000..15f52d03e8
--- /dev/null
+++ b/resolv/tst-resolv-rotate.c
@@ -0,0 +1,263 @@
+/* Check that RES_ROTATE works with few nameserver entries (bug 13028).
+ Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <netdb.h>
+#include <resolv.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/check_nss.h>
+#include <support/resolv_test.h>
+#include <support/test-driver.h>
+
+static volatile int drop_server = -1;
+static volatile unsigned int query_counts[resolv_max_test_servers];
+
+static const char address_ipv4[4] = {192, 0, 2, 1};
+static const char address_ipv6[16]
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
+
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ if (ctx->server_index == drop_server)
+ {
+ resolv_response_drop (b);
+ resolv_response_close (b);
+ return;
+ }
+
+ bool force_tcp = strncmp (qname, "2.", 2) == 0;
+ struct resolv_response_flags flags = {.tc = force_tcp && !ctx->tcp};
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+ if (flags.tc)
+ return;
+
+ TEST_VERIFY_EXIT (ctx->server_index < resolv_max_test_servers);
+ ++query_counts[ctx->server_index];
+
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
+ switch (qtype)
+ {
+ case T_A:
+ {
+ char addr[sizeof (address_ipv4)];
+ memcpy (addr, address_ipv4, sizeof (address_ipv4));
+ addr[3] = 1 + ctx->tcp;
+ resolv_response_add_data (b, addr, sizeof (addr));
+ }
+ break;
+ case T_AAAA:
+ {
+ char addr[sizeof (address_ipv6)];
+ memcpy (addr, address_ipv6, sizeof (address_ipv6));
+ addr[15] = 1 + ctx->tcp;
+ resolv_response_add_data (b, addr, sizeof (addr));
+ }
+ break;
+ case T_PTR:
+ if (force_tcp)
+ resolv_response_add_name (b, "2.host.example");
+ else
+ resolv_response_add_name (b, "host.example");
+ break;
+ default:
+ FAIL_EXIT1 ("unexpected QTYPE: %s/%u/%u", qname, qclass, qtype);
+ }
+ resolv_response_close_record (b);
+}
+
+static void
+check_forward_1 (const char *name, int family)
+{
+ unsigned char lsb;
+ if (strncmp (name, "2.", 2) == 0)
+ lsb = 2;
+ else
+ lsb = 1;
+
+ char expected_hostent_v4[200];
+ snprintf (expected_hostent_v4, sizeof (expected_hostent_v4),
+ "name: %s\naddress: 192.0.2.%d\n", name, lsb);
+ char expected_hostent_v6[200];
+ snprintf (expected_hostent_v6, sizeof (expected_hostent_v6),
+ "name: %s\naddress: 2001:db8::%d\n", name, lsb);
+ char expected_ai[200];
+
+ unsigned char address[16];
+ size_t address_length;
+
+ char *expected_hostent;
+ switch (family)
+ {
+ case AF_INET:
+ expected_hostent = expected_hostent_v4;
+ snprintf (expected_ai, sizeof (expected_ai),
+ "address: STREAM/TCP 192.0.2.%d 80\n", lsb);
+ TEST_VERIFY_EXIT (sizeof (address_ipv4) == sizeof (struct in_addr));
+ memcpy (address, address_ipv4, sizeof (address_ipv4));
+ address_length = sizeof (address_ipv4);
+ break;
+ case AF_INET6:
+ expected_hostent = expected_hostent_v6;
+ snprintf (expected_ai, sizeof (expected_ai),
+ "address: STREAM/TCP 2001:db8::%d 80\n", lsb);
+ TEST_VERIFY_EXIT (sizeof (address_ipv6) == sizeof (struct in6_addr));
+ memcpy (address, address_ipv6, sizeof (address_ipv6));
+ address_length = sizeof (address_ipv6);
+ break;
+ case AF_UNSPEC:
+ expected_hostent = NULL;
+ snprintf (expected_ai, sizeof (expected_ai),
+ "address: STREAM/TCP 192.0.2.%d 80\n"
+ "address: STREAM/TCP 2001:db8::%d 80\n",
+ lsb, lsb);
+ address_length = 0;
+ break;
+ default:
+ FAIL_EXIT1 ("unknown address family %d", family);
+ }
+
+
+ if (family == AF_INET)
+ {
+ struct hostent *e = gethostbyname (name);
+ check_hostent (name, e, expected_hostent_v4);
+ }
+
+ if (family != AF_UNSPEC)
+ {
+ struct hostent *e = gethostbyname2 (name, family);
+ check_hostent (name, e, expected_hostent);
+ }
+
+ if (address_length > 0)
+ {
+ address[address_length - 1] = lsb;
+ struct hostent *e = gethostbyaddr (address, address_length, family);
+ check_hostent (name, e, expected_hostent);
+ }
+
+ struct addrinfo hints =
+ {
+ .ai_family = family,
+ .ai_socktype = SOCK_STREAM,
+ .ai_protocol = IPPROTO_TCP,
+ };
+ struct addrinfo *ai;
+ int ret = getaddrinfo (name, "80", &hints, &ai);
+ check_addrinfo (name, ai, ret, expected_ai);
+ if (ret == 0)
+ {
+ for (struct addrinfo *p = ai; p != NULL; p = p->ai_next)
+ {
+ char host[200];
+ ret = getnameinfo (p->ai_addr, p->ai_addrlen,
+ host, sizeof (host),
+ NULL, 0, /* service */
+ 0);
+ if (ret != 0)
+ {
+ support_record_failure ();
+ printf ("error: getnameinfo: %d\n", ret);
+ }
+ else
+ {
+ if (lsb == 1)
+ TEST_VERIFY (strcmp (host, "host.example") == 0);
+ else
+ TEST_VERIFY (strcmp (host, "2.host.example") == 0);
+ }
+ }
+ freeaddrinfo (ai);
+ }
+}
+
+static void
+check_forward (int family)
+{
+ check_forward_1 ("host.example", family);
+ check_forward_1 ("2.host.example", family);
+}
+
+static int
+do_test (void)
+{
+ for (int force_tcp = 0; force_tcp < 2; ++force_tcp)
+ for (int nscount = 1; nscount <= 3; ++nscount)
+ for (int disable_server = -1; disable_server < nscount; ++disable_server)
+ for (drop_server = -1; drop_server < nscount; ++drop_server)
+ {
+ /* A disabled server will never receive queries and
+ therefore cannot drop them. */
+ if (drop_server >= 0 && drop_server == disable_server)
+ continue;
+ /* No servers remaining to query, all queries are expected
+ to fail. */
+ int broken_servers = (disable_server >= 0) + (drop_server >= 0);
+ if (nscount <= broken_servers)
+ continue;
+
+ if (test_verbose > 0)
+ printf ("info: tcp=%d nscount=%d disable=%d drop=%d\n",
+ force_tcp, nscount, disable_server, drop_server);
+ struct resolv_redirect_config config =
+ {
+ .response_callback = response,
+ .nscount = nscount
+ };
+ if (disable_server >= 0)
+ {
+ config.servers[disable_server].disable_udp = true;
+ config.servers[disable_server].disable_tcp = true;
+ }
+
+ struct resolv_test *aux = resolv_test_start (config);
+ _res.options |= RES_ROTATE;
+
+ /* Run a few queries to make sure that all of them
+ succeed. We always perform more than nscount queries,
+ so we cover all active servers due to RES_ROTATE. */
+ for (size_t i = 0; i < resolv_max_test_servers; ++i)
+ query_counts[i] = 0;
+ check_forward (AF_INET);
+ check_forward (AF_INET6);
+ check_forward (AF_UNSPEC);
+
+ for (int i = 0; i < nscount; ++i)
+ {
+ if (i != disable_server && i != drop_server
+ && query_counts[i] == 0)
+ {
+ support_record_failure ();
+ printf ("error: nscount=%d, but no query to server %d\n",
+ nscount, i);
+ }
+ }
+
+ resolv_test_end (aux);
+ }
+ return 0;
+}
+
+#define TIMEOUT 300
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-search.c b/resolv/tst-resolv-search.c
new file mode 100644
index 0000000000..307ecdcbd6
--- /dev/null
+++ b/resolv/tst-resolv-search.c
@@ -0,0 +1,344 @@
+/* Test search/default domain name behavior.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+#include <resolv.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/check_nss.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+#include <support/xmemstream.h>
+
+struct item
+{
+ const char *name;
+ int response;
+};
+
+const struct item items[] =
+ {
+ {"hostname.usersys.example.com", 1},
+ {"hostname.corp.example.com", 1},
+ {"hostname.example.com", 1},
+
+ {"mail.corp.example.com", 1},
+ {"mail.example.com", 1},
+
+ {"file.corp.example.com", 2},
+ {"file.corp", 1},
+ {"file.example.com", 1},
+ {"servfail-usersys.usersys.example.com", -ns_r_servfail},
+ {"servfail-usersys.corp.example.com", 1},
+ {"servfail-usersys.example.com", 1},
+ {"servfail-corp.usersys.example.com", 1},
+ {"servfail-corp.corp.example.com", -ns_r_servfail},
+ {"servfail-corp.example.com", 1},
+ {"www.example.com", 1},
+ {"large.example.com", 200},
+
+ /* Test query amplification with a SERVFAIL response combined with
+ a large RRset. */
+ {"large-servfail.usersys.example.com", -ns_r_servfail},
+ {"large-servfail.example.com", 2000},
+ {}
+ };
+
+enum
+ {
+ name_not_found = -1,
+ name_no_data = -2
+ };
+
+static int
+find_name (const char *name)
+{
+ for (int i = 0; items[i].name != NULL; ++i)
+ {
+ if (strcmp (name, items[i].name) == 0)
+ return i;
+ }
+ if (strcmp (name, "example.com") == 0
+ || strcmp (name, "usersys.example.com") == 0
+ || strcmp (name, "corp.example.com") == 0)
+ return name_no_data;
+ return name_not_found;
+}
+
+static int rcode_override_server_index = -1;
+static int rcode_override;
+
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ if (ctx->server_index == rcode_override_server_index)
+ {
+ struct resolv_response_flags flags = {.rcode = rcode_override};
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+ return;
+ }
+
+ int index = find_name (qname);
+ struct resolv_response_flags flags = {};
+ if (index == name_not_found)
+ flags.rcode = ns_r_nxdomain;
+ else if (index >= 0 && items[index].response < 0)
+ flags.rcode = -items[index].response;
+ else if (index >= 0 && items[index].response > 5 && !ctx->tcp)
+ /* Force TCP if more than 5 addresses where requested. */
+ flags.tc = true;
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+
+ if (flags.tc || index < 0 || items[index].response < 0)
+ return;
+
+ resolv_response_section (b, ns_s_an);
+
+ for (int i = 0; i < items[index].response; ++i)
+ {
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
+
+ switch (qtype)
+ {
+ case T_A:
+ {
+ char addr[4] = {10, index, i >> 8, i};
+ resolv_response_add_data (b, addr, sizeof (addr));
+ }
+ break;
+ case T_AAAA:
+ {
+ char addr[16]
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, index + 1, (i + 1) >> 8, i + 1};
+ resolv_response_add_data (b, addr, sizeof (addr));
+ }
+ break;
+ default:
+ support_record_failure ();
+ printf ("error: unexpected QTYPE: %s/%u/%u\n",
+ qname, qclass, qtype);
+ }
+ resolv_response_close_record (b);
+ }
+}
+
+enum output_format
+ {
+ format_get, format_gai
+ };
+
+static void
+format_expected_1 (FILE *out, int family, enum output_format format, int index)
+{
+ for (int i = 0; i < items[index].response; ++i)
+ {
+ char address[200];
+ switch (family)
+ {
+ case AF_INET:
+ snprintf (address, sizeof (address), "10.%d.%d.%d",
+ index, (i >> 8) & 0xff, i & 0xff);
+ break;
+ case AF_INET6:
+ snprintf (address, sizeof (address), "2001:db8::%x:%x",
+ index + 1, i + 1);
+ break;
+ default:
+ FAIL_EXIT1 ("unreachable");
+ }
+
+ switch (format)
+ {
+ case format_get:
+ fprintf (out, "address: %s\n", address);
+ break;
+ case format_gai:
+ fprintf (out, "address: STREAM/TCP %s 80\n", address);
+ }
+ }
+}
+
+static char *
+format_expected (const char *fqdn, int family, enum output_format format)
+{
+ int index = find_name (fqdn);
+ TEST_VERIFY_EXIT (index >= 0);
+ struct xmemstream stream;
+ xopen_memstream (&stream);
+
+ TEST_VERIFY_EXIT (items[index].response >= 0);
+ if (format == format_get)
+ fprintf (stream.out, "name: %s\n", items[index].name);
+ if (family == AF_INET || family == AF_UNSPEC)
+ format_expected_1 (stream.out, AF_INET, format, index);
+ if (family == AF_INET6 || family == AF_UNSPEC)
+ format_expected_1 (stream.out, AF_INET6, format, index);
+
+ xfclose_memstream (&stream);
+ return stream.buffer;
+}
+
+static void
+do_get (const char *name, const char *fqdn, int family)
+{
+ char *expected = format_expected (fqdn, family, format_get);
+ if (family == AF_INET)
+ {
+ char *query = xasprintf ("gethostbyname (\"%s\")", name);
+ check_hostent (query, gethostbyname (name), expected);
+ free (query);
+ }
+ char *query = xasprintf ("gethostbyname2 (\"%s\", %d)", name, family);
+ check_hostent (query, gethostbyname2 (name, family), expected);
+
+ /* Test res_search. */
+ int qtype;
+ switch (family)
+ {
+ case AF_INET:
+ qtype = T_A;
+ break;
+ case AF_INET6:
+ qtype = T_AAAA;
+ break;
+ default:
+ qtype = -1;
+ }
+ if (qtype >= 0)
+ {
+ int sz = 512;
+ unsigned char *response = xmalloc (sz);
+ int ret = res_search (name, C_IN, qtype, response, sz);
+ TEST_VERIFY_EXIT (ret >= 0);
+ if (ret > sz)
+ {
+ /* Truncation. Retry with a larger buffer. */
+ sz = 65535;
+ unsigned char *newptr = xrealloc (response, sz);
+ response = newptr;
+
+ ret = res_search (name, C_IN, qtype, response, sz);
+ TEST_VERIFY_EXIT (ret >= 0);
+ TEST_VERIFY_EXIT (ret < sz);
+ }
+ check_dns_packet (query, response, ret, expected);
+ free (response);
+ }
+
+ free (query);
+ free (expected);
+}
+
+static void
+do_gai (const char *name, const char *fqdn, int family)
+{
+ struct addrinfo hints =
+ {
+ .ai_family = family,
+ .ai_protocol = IPPROTO_TCP,
+ .ai_socktype = SOCK_STREAM
+ };
+ struct addrinfo *ai;
+ char *query = xasprintf ("%s:80 [%d]", name, family);
+ int ret = getaddrinfo (name, "80", &hints, &ai);
+ char *expected = format_expected (fqdn, family, format_gai);
+ check_addrinfo (query, ai, ret, expected);
+ if (ret == 0)
+ freeaddrinfo (ai);
+ free (expected);
+ free (query);
+}
+
+static void
+do_both (const char *name, const char *fqdn)
+{
+ do_get (name, fqdn, AF_INET);
+ do_get (name, fqdn, AF_INET6);
+ do_gai (name, fqdn, AF_INET);
+ do_gai (name, fqdn, AF_INET6);
+ do_gai (name, fqdn, AF_UNSPEC);
+}
+
+static void
+do_test_all (bool unconnectable_server)
+{
+ struct resolv_redirect_config config =
+ {
+ .response_callback = response,
+ .search = {"usersys.example.com", "corp.example.com", "example.com"},
+ };
+ struct resolv_test *obj = resolv_test_start (config);
+
+ if (unconnectable_server)
+ {
+ /* 255.255.255.255 results in an immediate connect failure. The
+ next server will supply the answer instead. This is a
+ triggering condition for bug 19791. */
+ _res.nsaddr_list[0].sin_addr.s_addr = -1;
+ _res.nsaddr_list[0].sin_port = htons (53);
+ }
+
+ do_both ("file", "file.corp.example.com");
+ do_both ("www", "www.example.com");
+ do_both ("servfail-usersys", "servfail-usersys.corp.example.com");
+ do_both ("servfail-corp", "servfail-corp.usersys.example.com");
+ do_both ("large", "large.example.com");
+ do_both ("large-servfail", "large-servfail.example.com");
+ do_both ("file.corp", "file.corp");
+
+ /* Check that SERVFAIL and REFUSED responses do not alter the search
+ path resolution. */
+ rcode_override_server_index = 0;
+ rcode_override = ns_r_servfail;
+ do_both ("hostname", "hostname.usersys.example.com");
+ do_both ("large", "large.example.com");
+ do_both ("large-servfail", "large-servfail.example.com");
+ rcode_override = ns_r_refused;
+ do_both ("hostname", "hostname.usersys.example.com");
+ do_both ("large", "large.example.com");
+ do_both ("large-servfail", "large-servfail.example.com");
+ /* Likewise, but with an NXDOMAIN for the first search path
+ entry. */
+ rcode_override = ns_r_servfail;
+ do_both ("mail", "mail.corp.example.com");
+ rcode_override = ns_r_refused;
+ do_both ("mail", "mail.corp.example.com");
+ /* Likewise, but with ndots handling. */
+ rcode_override = ns_r_servfail;
+ do_both ("file.corp", "file.corp");
+ rcode_override = ns_r_refused;
+ do_both ("file.corp", "file.corp");
+
+ resolv_test_end (obj);
+}
+
+static int
+do_test (void)
+{
+ for (int unconnectable_server = 0; unconnectable_server < 2;
+ ++unconnectable_server)
+ do_test_all (unconnectable_server);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/resolv/tst-resolv-threads.c b/resolv/tst-resolv-threads.c
new file mode 100644
index 0000000000..4222331d71
--- /dev/null
+++ b/resolv/tst-resolv-threads.c
@@ -0,0 +1,484 @@
+/* Test basic nss_dns functionality with multiple threads.
+ Copyright (C) 2016-2018 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Unlike tst-resolv-basic, this test does not overwrite the _res
+ structure and relies on namespaces to achieve the redirection to
+ the test servers with a custom /etc/resolv.conf file. */
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <gnu/lib-names.h>
+#include <netdb.h>
+#include <resolv/resolv-internal.h>
+#include <resolv/resolv_context.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <support/check.h>
+#include <support/namespace.h>
+#include <support/resolv_test.h>
+#include <support/support.h>
+#include <support/temp_file.h>
+#include <support/test-driver.h>
+#include <support/xthread.h>
+#include <support/xunistd.h>
+
+/* Each client thread sends this many queries. */
+enum { queries_per_thread = 500 };
+
+/* Return a small positive number identifying this thread. */
+static int
+get_thread_number (void)
+{
+ static int __thread local;
+ if (local != 0)
+ return local;
+ static int global = 1;
+ local = __atomic_fetch_add (&global, 1, __ATOMIC_RELAXED);
+ return local;
+}
+
+static void
+response (const struct resolv_response_context *ctx,
+ struct resolv_response_builder *b,
+ const char *qname, uint16_t qclass, uint16_t qtype)
+{
+ TEST_VERIFY_EXIT (qname != NULL);
+
+ int counter = 0;
+ int thread = 0;
+ int dummy = 0;
+ TEST_VERIFY (sscanf (qname, "counter%d.thread%d.example.com%n",
+ &counter, &thread, &dummy) == 2);
+ TEST_VERIFY (dummy > 0);
+
+ struct resolv_response_flags flags = { 0 };
+ resolv_response_init (b, flags);
+ resolv_response_add_question (b, qname, qclass, qtype);
+
+ resolv_response_section (b, ns_s_an);
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
+ switch (qtype)
+ {
+ case T_A:
+ {
+ char ipv4[4] = {10, 0, counter, thread};
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
+ }
+ break;
+ case T_AAAA:
+ {
+ char ipv6[16]
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0,
+ counter, 0, thread, 0, 0};
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
+ }
+ break;
+ default:
+ support_record_failure ();
+ printf ("error: unexpected QTYPE: %s/%u/%u\n",
+ qname, qclass, qtype);
+ }
+ resolv_response_close_record (b);
+}
+
+/* Check that the resolver configuration for this thread has an
+ extended resolver configuration. */
+static void
+check_have_conf (void)
+{
+ struct resolv_context *ctx = __resolv_context_get ();
+ TEST_VERIFY_EXIT (ctx != NULL);
+ TEST_VERIFY (ctx->conf != NULL);
+ __resolv_context_put (ctx);
+}
+
+/* Verify that E matches the expected response for FAMILY and
+ COUNTER. */
+static void
+check_hostent (const char *caller, const char *function, const char *qname,
+ int ret, struct hostent *e, int family, int counter)
+{
+ if (ret != 0)
+ {
+ errno = ret;
+ support_record_failure ();
+ printf ("error: %s: %s for %s failed: %m\n", caller, function, qname);
+ return;
+ }
+
+ TEST_VERIFY_EXIT (e != NULL);
+ TEST_VERIFY (strcmp (qname, e->h_name) == 0);
+ TEST_VERIFY (e->h_addrtype == family);
+ TEST_VERIFY_EXIT (e->h_addr_list[0] != NULL);
+ TEST_VERIFY (e->h_addr_list[1] == NULL);
+ switch (family)
+ {
+ case AF_INET:
+ {
+ char addr[4] = {10, 0, counter, get_thread_number ()};
+ TEST_VERIFY (e->h_length == sizeof (addr));
+ TEST_VERIFY (memcmp (e->h_addr_list[0], addr, sizeof (addr)) == 0);
+ }
+ break;
+ case AF_INET6:
+ {
+ char addr[16]
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0,
+ 0, counter, 0, get_thread_number (), 0, 0};
+ TEST_VERIFY (e->h_length == sizeof (addr));
+ TEST_VERIFY (memcmp (e->h_addr_list[0], addr, sizeof (addr)) == 0);
+ }
+ break;
+ default:
+ FAIL_EXIT1 ("%s: invalid address family %d", caller, family);
+ }
+ check_have_conf ();
+}
+
+/* Check a getaddrinfo result. */
+static void
+check_addrinfo (const char *caller, const char *qname,
+ int ret, struct addrinfo *ai, int family, int counter)
+{
+ if (ret != 0)
+ {
+ support_record_failure ();
+ printf ("error: %s: getaddrinfo for %s failed: %s\n",
+ caller, qname, gai_strerror (ret));
+ return;
+ }
+
+ TEST_VERIFY_EXIT (ai != NULL);
+
+ /* Check that available data matches the requirements. */
+ bool have_ipv4 = false;
+ bool have_ipv6 = false;
+ for (struct addrinfo *p = ai; p != NULL; p = p->ai_next)
+ {
+ TEST_VERIFY (p->ai_socktype == SOCK_STREAM);
+ TEST_VERIFY (p->ai_protocol == IPPROTO_TCP);
+ TEST_VERIFY_EXIT (p->ai_addr != NULL);
+ TEST_VERIFY (p->ai_addr->sa_family == p->ai_family);
+
+ switch (p->ai_family)
+ {
+ case AF_INET:
+ {
+ TEST_VERIFY (!have_ipv4);
+ have_ipv4 = true;
+ struct sockaddr_in *sa = (struct sockaddr_in *) p->ai_addr;
+ TEST_VERIFY (p->ai_addrlen == sizeof (*sa));
+ char addr[4] = {10, 0, counter, get_thread_number ()};
+ TEST_VERIFY (memcmp (&sa->sin_addr, addr, sizeof (addr)) == 0);
+ TEST_VERIFY (ntohs (sa->sin_port) == 80);
+ }
+ break;
+ case AF_INET6:
+ {
+ TEST_VERIFY (!have_ipv6);
+ have_ipv6 = true;
+ struct sockaddr_in6 *sa = (struct sockaddr_in6 *) p->ai_addr;
+ TEST_VERIFY (p->ai_addrlen == sizeof (*sa));
+ char addr[16]
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0,
+ 0, counter, 0, get_thread_number (), 0, 0};
+ TEST_VERIFY (memcmp (&sa->sin6_addr, addr, sizeof (addr)) == 0);
+ TEST_VERIFY (ntohs (sa->sin6_port) == 80);
+ }
+ break;
+ default:
+ FAIL_EXIT1 ("%s: invalid address family %d", caller, family);
+ }
+ }
+
+ switch (family)
+ {
+ case AF_INET:
+ TEST_VERIFY (have_ipv4);
+ TEST_VERIFY (!have_ipv6);
+ break;
+ case AF_INET6:
+ TEST_VERIFY (!have_ipv4);
+ TEST_VERIFY (have_ipv6);
+ break;
+ case AF_UNSPEC:
+ TEST_VERIFY (have_ipv4);
+ TEST_VERIFY (have_ipv6);
+ break;
+ default:
+ FAIL_EXIT1 ("%s: invalid address family %d", caller, family);
+ }
+
+ check_have_conf ();
+}
+
+/* This barrier ensures that all test threads begin their work
+ simultaneously. */
+static pthread_barrier_t barrier;
+
+/* Test gethostbyname2_r (if do_2 is false) or gethostbyname2_r with
+ AF_INET (if do_2 is true). */
+static void *
+byname (bool do_2)
+{
+ int this_thread = get_thread_number ();
+ xpthread_barrier_wait (&barrier);
+ for (int i = 0; i < queries_per_thread; ++i)
+ {
+ char qname[100];
+ snprintf (qname, sizeof (qname), "counter%d.thread%d.example.com",
+ i, this_thread);
+ struct hostent storage;
+ char buf[1000];
+ struct hostent *e = NULL;
+ int herrno;
+ int ret;
+ if (do_2)
+ ret = gethostbyname_r (qname, &storage, buf, sizeof (buf),
+ &e, &herrno);
+ else
+ ret = gethostbyname2_r (qname, AF_INET, &storage, buf, sizeof (buf),
+ &e, &herrno);
+ check_hostent (__func__, do_2 ? "gethostbyname2_r" : "gethostbyname_r",
+ qname, ret, e, AF_INET, i);
+ }
+ check_have_conf ();
+ return NULL;
+}
+
+/* Test gethostbyname_r. */
+static void *
+thread_byname (void *closure)
+{
+ return byname (false);
+}
+
+/* Test gethostbyname2_r with AF_INET. */
+static void *
+thread_byname2 (void *closure)
+{
+ return byname (true);
+}
+
+/* Call gethostbyname_r with RES_USE_INET6 (if do_2 is false), or
+ gethostbyname_r with AF_INET6 (if do_2 is true). */
+static void *
+byname_inet6 (bool do_2)
+{
+ int this_thread = get_thread_number ();
+ xpthread_barrier_wait (&barrier);
+ if (!do_2)
+ {
+ res_init ();
+ _res.options |= DEPRECATED_RES_USE_INET6;
+ TEST_VERIFY (strcmp (_res.defdname, "example.com") == 0);
+ }
+ for (int i = 0; i < queries_per_thread; ++i)
+ {
+ char qname[100];
+ snprintf (qname, sizeof (qname), "counter%d.thread%d.example.com",
+ i, this_thread);
+ struct hostent storage;
+ char buf[1000];
+ struct hostent *e = NULL;
+ int herrno;
+ int ret;
+ if (do_2)
+ ret = gethostbyname2_r (qname, AF_INET6, &storage, buf, sizeof (buf),
+ &e, &herrno);
+ else
+ ret = gethostbyname_r (qname, &storage, buf, sizeof (buf),
+ &e, &herrno);
+ check_hostent (__func__,
+ do_2 ? "gethostbyname2_r" : "gethostbyname_r",
+ qname, ret, e, AF_INET6, i);
+ }
+ return NULL;
+}
+
+/* Test gethostbyname_r with AF_INET6. */
+static void *
+thread_byname_inet6 (void *closure)
+{
+ return byname_inet6 (false);
+}
+
+/* Test gethostbyname2_r with AF_INET6. */
+static void *
+thread_byname2_af_inet6 (void *closure)
+{
+ return byname_inet6 (true);
+}
+
+/* Run getaddrinfo tests for FAMILY. */
+static void *
+gai (int family, bool do_inet6)
+{
+ int this_thread = get_thread_number ();
+ xpthread_barrier_wait (&barrier);
+ if (do_inet6)
+ {
+ res_init ();
+ _res.options |= DEPRECATED_RES_USE_INET6;
+ check_have_conf ();
+ }
+ for (int i = 0; i < queries_per_thread; ++i)
+ {
+ char qname[100];
+ snprintf (qname, sizeof (qname), "counter%d.thread%d.example.com",
+ i, this_thread);
+ struct addrinfo hints =
+ {
+ .ai_family = family,
+ .ai_socktype = SOCK_STREAM,
+ .ai_protocol = IPPROTO_TCP,
+ };
+ struct addrinfo *ai;
+ int ret = getaddrinfo (qname, "80", &hints, &ai);
+ check_addrinfo (__func__, qname, ret, ai, family, i);
+ if (ret == 0)
+ freeaddrinfo (ai);
+ }
+ return NULL;
+}
+
+/* Test getaddrinfo with AF_INET. */
+static void *
+thread_gai_inet (void *closure)
+{
+ return gai (AF_INET, false);
+}
+
+/* Test getaddrinfo with AF_INET6. */
+static void *
+thread_gai_inet6 (void *closure)
+{
+ return gai (AF_INET6, false);
+}
+
+/* Test getaddrinfo with AF_UNSPEC. */
+static void *
+thread_gai_unspec (void *closure)
+{
+ return gai (AF_UNSPEC, false);
+}
+
+/* Test getaddrinfo with AF_INET. */
+static void *
+thread_gai_inet_inet6 (void *closure)
+{
+ return gai (AF_INET, true);
+}
+
+/* Test getaddrinfo with AF_INET6. */
+static void *
+thread_gai_inet6_inet6 (void *closure)
+{
+ return gai (AF_INET6, true);
+}
+
+/* Test getaddrinfo with AF_UNSPEC. */
+static void *
+thread_gai_unspec_inet6 (void *closure)
+{
+ return gai (AF_UNSPEC, true);
+}
+
+/* Description of the chroot environment used to run the tests. */
+static struct support_chroot *chroot_env;
+
+/* Set up the chroot environment. */
+static void
+prepare (int argc, char **argv)
+{
+ chroot_env = support_chroot_create
+ ((struct support_chroot_configuration)
+ {
+ .resolv_conf =
+ "search example.com\n"
+ "nameserver 127.0.0.1\n"
+ "nameserver 127.0.0.2\n"
+ "nameserver 127.0.0.3\n",
+ });
+}
+
+static int
+do_test (void)
+{
+ support_become_root ();
+ if (!support_enter_network_namespace ())
+ return EXIT_UNSUPPORTED;
+ if (!support_can_chroot ())
+ return EXIT_UNSUPPORTED;
+
+ /* Load the shared object outside of the chroot. */
+ TEST_VERIFY (dlopen (LIBNSS_DNS_SO, RTLD_LAZY) != NULL);
+
+ xchroot (chroot_env->path_chroot);
+ TEST_VERIFY_EXIT (chdir ("/") == 0);
+
+ struct sockaddr_in server_address =
+ {
+ .sin_family = AF_INET,
+ .sin_addr = { .s_addr = htonl (INADDR_LOOPBACK) },
+ .sin_port = htons (53)
+ };
+ const struct sockaddr *server_addresses[1] =
+ { (const struct sockaddr *) &server_address };
+
+ struct resolv_test *aux = resolv_test_start
+ ((struct resolv_redirect_config)
+ {
+ .response_callback = response,
+ .nscount = 1,
+ .disable_redirect = true,
+ .server_address_overrides = server_addresses,
+ });
+
+ enum { thread_count = 10 };
+ xpthread_barrier_init (&barrier, NULL, thread_count + 1);
+ pthread_t threads[thread_count];
+ typedef void *(*thread_func) (void *);
+ thread_func thread_funcs[thread_count] =
+ {
+ thread_byname,
+ thread_byname2,
+ thread_byname_inet6,
+ thread_byname2_af_inet6,
+ thread_gai_inet,
+ thread_gai_inet6,
+ thread_gai_unspec,
+ thread_gai_inet_inet6,
+ thread_gai_inet6_inet6,
+ thread_gai_unspec_inet6,
+ };
+ for (int i = 0; i < thread_count; ++i)
+ threads[i] = xpthread_create (NULL, thread_funcs[i], NULL);
+ xpthread_barrier_wait (&barrier); /* Start the test threads. */
+ for (int i = 0; i < thread_count; ++i)
+ xpthread_join (threads[i]);
+
+ resolv_test_end (aux);
+ support_chroot_free (chroot_env);
+
+ return 0;
+}
+
+#define PREPARE prepare
+#include <support/test-driver.c>