19196 lines
789 KiB
Diff
19196 lines
789 KiB
Diff
Rebase the stub resolver and getaddrinfo to the glibc 2.26 version.
|
||
This eliminates the DNS search path limit (#677316), enables automatic
|
||
reloading of /etc/resolv.conf (#1432085), and makes the handling of IPv6
|
||
scope IDs more strict (#1484034).
|
||
|
||
This patch rebases the stub resolver up to and including this upstream
|
||
commit on release/2.26/master upstream branch:
|
||
|
||
commit 27233446a62ca35ce0b54566279a99a6774d4210
|
||
Author: Florian Weimer <fweimer@redhat.com>
|
||
Date: Wed Sep 6 15:47:27 2017 +0200
|
||
|
||
resolv: __resolv_conf_attach must not free passed conf object [BZ #22096]
|
||
|
||
(cherry picked from commit a83047308196e3e54716a39dd85c0a08b198d6bd)
|
||
|
||
The following files are rebased completely:
|
||
|
||
include/arpa/nameser.h
|
||
include/arpa/nameser_compat.h
|
||
include/resolv.h
|
||
inet/gethstbyad_r.c
|
||
inet/gethstbynm2_r.c
|
||
inet/gethstbynm_r.c
|
||
nscd/aicache.c
|
||
nscd/gethstbyad_r.c
|
||
nscd/gethstbynm3_r.c
|
||
nss/digits_dots.c
|
||
nss/getXXbyYY.c
|
||
nss/getXXbyYY_r.c
|
||
nss/getnssent_r.c
|
||
nss/nsswitch.h
|
||
nss/tst-nss-files-hosts-erange.c
|
||
resolv/Depend
|
||
resolv/README
|
||
resolv/Versions
|
||
resolv/arpa/nameser.h
|
||
resolv/arpa/nameser_compat.h
|
||
resolv/base64.c
|
||
resolv/compat-gethnamaddr.c
|
||
resolv/compat-hooks.c
|
||
resolv/herror.c
|
||
resolv/inet_addr.c
|
||
resolv/inet_net_ntop.c
|
||
resolv/inet_net_pton.c
|
||
resolv/inet_neta.c
|
||
resolv/inet_ntop.c
|
||
resolv/ns_date.c
|
||
resolv/ns_name.c
|
||
resolv/ns_netint.c
|
||
resolv/ns_parse.c
|
||
resolv/ns_print.c
|
||
resolv/ns_samedomain.c
|
||
resolv/ns_ttl.c
|
||
resolv/nsap_addr.c
|
||
resolv/nss_dns/dns-canon.c
|
||
resolv/nss_dns/dns-host.c
|
||
resolv/nss_dns/dns-network.c
|
||
resolv/res-close.c
|
||
resolv/res-state.c
|
||
resolv/res_comp.c
|
||
resolv/res_data.c
|
||
resolv/res_debug.c
|
||
resolv/res_hconf.c
|
||
resolv/res_hconf.h
|
||
resolv/res_init.c
|
||
resolv/res_libc.c
|
||
resolv/res_mkquery.c
|
||
resolv/res_query.c
|
||
resolv/res_randomid.c
|
||
resolv/res_send.c
|
||
resolv/res_use_inet6.h
|
||
resolv/resolv-internal.h
|
||
resolv/resolv_conf.c
|
||
resolv/resolv_conf.h
|
||
resolv/resolv_context.c
|
||
resolv/resolv_context.h
|
||
resolv/tst-aton.c
|
||
resolv/tst-bug18665-tcp.c
|
||
resolv/tst-bug18665.c
|
||
resolv/tst-inet_ntop.c
|
||
resolv/tst-leaks.c
|
||
resolv/tst-leaks2.c
|
||
resolv/tst-ns_name.c
|
||
resolv/tst-ns_name.data
|
||
resolv/tst-ns_name_compress.c
|
||
resolv/tst-res_hconf_reorder.c
|
||
resolv/tst-res_use_inet6.c
|
||
resolv/tst-resolv-basic.c
|
||
resolv/tst-resolv-canonname.c
|
||
resolv/tst-resolv-edns.c
|
||
resolv/tst-resolv-network.c
|
||
resolv/tst-resolv-qtypes.c
|
||
resolv/tst-resolv-res_init-multi.c
|
||
resolv/tst-resolv-res_init-skeleton.c
|
||
resolv/tst-resolv-res_init-thread.c
|
||
resolv/tst-resolv-res_init.c
|
||
resolv/tst-resolv-res_ninit.c
|
||
resolv/tst-resolv-rotate.c
|
||
resolv/tst-resolv-search.c
|
||
resolv/tst-resolv-threads.c
|
||
sysdeps/posix/getaddrinfo.c
|
||
|
||
The following files have been deleted because they are no longer needed:
|
||
|
||
resolv/res_debug.h
|
||
resolv/gethnamaddr.c (renamed to resolv/compat-gethnamaddr.c)
|
||
|
||
The following files have remaining differences:
|
||
|
||
resolv/Makefile (build system, <bits/types/res_state.h> not installed)
|
||
resolv/resolv.h (limited changes to public header file)
|
||
|
||
diff --git a/include/arpa/nameser.h b/include/arpa/nameser.h
|
||
index 57f7457848bc1700..7a8290e1f26070e0 100644
|
||
--- a/include/arpa/nameser.h
|
||
+++ b/include/arpa/nameser.h
|
||
@@ -2,6 +2,8 @@
|
||
|
||
#include <resolv/arpa/nameser.h>
|
||
|
||
+# ifndef _ISOMAC
|
||
+
|
||
/* If the machine allows unaligned access we can do better than using
|
||
the NS_GET16, NS_GET32, NS_PUT16, and NS_PUT32 macros from the
|
||
installed header. */
|
||
@@ -47,8 +49,11 @@ extern const struct _ns_flagdata _ns_flagdata[] attribute_hidden;
|
||
|
||
#endif
|
||
|
||
-extern u_int __ns_get16 (const u_char *) __THROW;
|
||
-extern u_long __ns_get32 (const u_char *) __THROW;
|
||
+extern unsigned int __ns_get16 (const unsigned char *) __THROW;
|
||
+extern unsigned long __ns_get32 (const unsigned char *) __THROW;
|
||
+int __ns_name_ntop (const unsigned char *, char *, size_t) __THROW;
|
||
+int __ns_name_unpack (const unsigned char *, const unsigned char *,
|
||
+ const unsigned char *, unsigned char *, size_t) __THROW;
|
||
|
||
#define ns_msg_getflag(handle, flag) \
|
||
(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift)
|
||
@@ -74,4 +79,5 @@ libresolv_hidden_proto (ns_samename)
|
||
libresolv_hidden_proto (ns_makecanon)
|
||
libresolv_hidden_proto (ns_format_ttl)
|
||
|
||
+# endif /* !_ISOMAC */
|
||
#endif
|
||
diff --git a/include/arpa/nameser_compat.h b/include/arpa/nameser_compat.h
|
||
index 2e735ede4c0e922b..f7d0e043c6eedc88 100644
|
||
--- a/include/arpa/nameser_compat.h
|
||
+++ b/include/arpa/nameser_compat.h
|
||
@@ -1,8 +1,11 @@
|
||
#ifndef _ARPA_NAMESER_COMPAT_
|
||
#include <resolv/arpa/nameser_compat.h>
|
||
|
||
-/* Picksome unused number to represent lookups of IPv4 and IPv6 (i.e.,
|
||
- T_A and T_AAAA). */
|
||
-#define T_UNSPEC 62321
|
||
+# ifndef _ISOMAC
|
||
|
||
+/* The number is outside the 16-bit RR type range and is used
|
||
+ internally by the implementation. */
|
||
+#define T_QUERY_A_AND_AAAA 439963904
|
||
+
|
||
+# endif /* !_ISOMAC */
|
||
#endif
|
||
diff --git a/include/resolv.h b/include/resolv.h
|
||
index e1e3caa2a2ecb6ea..634f5525fe9d357a 100644
|
||
--- a/include/resolv.h
|
||
+++ b/include/resolv.h
|
||
@@ -1,68 +1,45 @@
|
||
#ifndef _RESOLV_H_
|
||
|
||
-#define RES_SET_H_ERRNO(r,x) \
|
||
+# ifndef _ISOMAC
|
||
+# include <stdbool.h>
|
||
+# define RES_SET_H_ERRNO(r,x) \
|
||
do \
|
||
{ \
|
||
(r)->res_h_errno = x; \
|
||
__set_h_errno(x); \
|
||
} \
|
||
while (0)
|
||
+# endif
|
||
|
||
-#include <stdbool.h>
|
||
#include <resolv/resolv.h>
|
||
|
||
-#ifdef _RESOLV_H_
|
||
+# if defined _RESOLV_H_ && !defined _ISOMAC
|
||
|
||
-# ifdef _LIBC_REENTRANT
|
||
-# include <tls.h>
|
||
-# undef _res
|
||
-# if IS_IN (libc)
|
||
-# define __resp __libc_resp
|
||
-# endif
|
||
-# define _res (*__resp)
|
||
-extern __thread struct __res_state *__resp attribute_tls_model_ie;
|
||
-# else
|
||
-# ifndef __BIND_NOSTATIC
|
||
-# undef _res
|
||
-extern struct __res_state _res;
|
||
-# endif
|
||
+# if IS_IN (libc)
|
||
+# define __resp __libc_resp
|
||
# endif
|
||
+extern __thread struct __res_state *__resp attribute_tls_model_ie;
|
||
+# undef _res
|
||
+# define _res (*__resp)
|
||
|
||
/* Now define the internal interfaces. */
|
||
-extern int __res_vinit (res_state, int);
|
||
-extern int __res_maybe_init (res_state, int);
|
||
+extern int __res_vinit (res_state, int) attribute_hidden;
|
||
extern void _sethtent (int);
|
||
-extern void _endhtent (void);
|
||
extern struct hostent *_gethtent (void);
|
||
extern struct hostent *_gethtbyname (const char *__name);
|
||
extern struct hostent *_gethtbyname2 (const char *__name, int __af);
|
||
struct hostent *_gethtbyaddr (const char *addr, size_t __len, int __af);
|
||
-extern u_int32_t _getlong (const u_char *__src);
|
||
-extern u_int16_t _getshort (const u_char *__src);
|
||
-extern void res_pquery (const res_state __statp, const u_char *__msg,
|
||
- int __len, FILE *__file);
|
||
-extern void res_send_setqhook (res_send_qhook __hook);
|
||
-extern void res_send_setrhook (res_send_rhook __hook);
|
||
+extern uint32_t _getlong (const unsigned char *__src);
|
||
+extern uint16_t _getshort (const unsigned char *__src);
|
||
extern int res_ourserver_p (const res_state __statp,
|
||
const struct sockaddr_in6 *__inp);
|
||
extern void __res_iclose (res_state statp, bool free_addr);
|
||
-extern int __res_nopt(res_state statp, int n0, u_char *buf, int buflen,
|
||
- int anslen);
|
||
libc_hidden_proto (__res_ninit)
|
||
-libc_hidden_proto (__res_maybe_init)
|
||
libc_hidden_proto (__res_nclose)
|
||
libc_hidden_proto (__res_iclose)
|
||
libc_hidden_proto (__res_randomid)
|
||
libc_hidden_proto (__res_state)
|
||
|
||
-int __libc_res_nquery (res_state, const char *, int, int, u_char *, int,
|
||
- u_char **, u_char **, int *, int *, int *);
|
||
-int __libc_res_nsearch (res_state, const char *, int, int, u_char *, int,
|
||
- u_char **, u_char **, int *, int *, int *);
|
||
-int __libc_res_nsend (res_state, const u_char *, int, const u_char *, int,
|
||
- u_char *, int, u_char **, u_char **, int *, int *, int *)
|
||
- attribute_hidden;
|
||
-
|
||
libresolv_hidden_proto (_sethtent)
|
||
libresolv_hidden_proto (_gethtent)
|
||
libresolv_hidden_proto (_gethtbyaddr)
|
||
@@ -84,25 +61,11 @@ libresolv_hidden_proto (__p_type)
|
||
libresolv_hidden_proto (__loc_ntoa)
|
||
libresolv_hidden_proto (__fp_nquery)
|
||
libresolv_hidden_proto (__fp_query)
|
||
-libresolv_hidden_proto (__hostalias)
|
||
-libresolv_hidden_proto (__res_nmkquery)
|
||
-libresolv_hidden_proto (__libc_res_nquery)
|
||
-libresolv_hidden_proto (__res_nquery)
|
||
-libresolv_hidden_proto (__res_nquerydomain)
|
||
-libresolv_hidden_proto (__res_hostalias)
|
||
-libresolv_hidden_proto (__libc_res_nsearch)
|
||
-libresolv_hidden_proto (__res_nsearch)
|
||
libresolv_hidden_proto (__res_nameinquery)
|
||
libresolv_hidden_proto (__res_queriesmatch)
|
||
-libresolv_hidden_proto (__res_nsend)
|
||
libresolv_hidden_proto (__b64_ntop)
|
||
-libresolv_hidden_proto (__res_nopt)
|
||
libresolv_hidden_proto (__dn_count_labels)
|
||
libresolv_hidden_proto (__p_secstodate)
|
||
|
||
-extern const char *_res_opcodes[];
|
||
-libresolv_hidden_proto (_res_opcodes)
|
||
-
|
||
-#endif
|
||
-
|
||
+# endif /* _RESOLV_H_ && !_ISOMAC */
|
||
#endif
|
||
diff --git a/inet/gethstbyad_r.c b/inet/gethstbyad_r.c
|
||
index 5ae854b4f91e72ad..6b5c13105059dd35 100644
|
||
--- a/inet/gethstbyad_r.c
|
||
+++ b/inet/gethstbyad_r.c
|
||
@@ -1,4 +1,4 @@
|
||
-/* Copyright (C) 1996-2000,2002,2007 Free Software Foundation, Inc.
|
||
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||
|
||
@@ -18,7 +18,7 @@
|
||
|
||
#include <netdb.h>
|
||
#include <string.h>
|
||
-
|
||
+#include <resolv/res_hconf.h>
|
||
|
||
#define LOOKUP_TYPE struct hostent
|
||
#define FUNCTION_NAME gethostbyaddr
|
||
@@ -27,7 +27,6 @@
|
||
#define ADD_VARIABLES addr, len, type
|
||
#define NEED_H_ERRNO 1
|
||
#define NEED__RES 1
|
||
-#define NEED__RES_HCONF 1
|
||
/* If the addr parameter is the IPv6 unspecified address no query must
|
||
be performed. */
|
||
#define PREPROCESS \
|
||
diff --git a/inet/gethstbynm2_r.c b/inet/gethstbynm2_r.c
|
||
index 48e4946f29145bef..580ba6d1cfbd63ec 100644
|
||
--- a/inet/gethstbynm2_r.c
|
||
+++ b/inet/gethstbynm2_r.c
|
||
@@ -1,4 +1,4 @@
|
||
-/* Copyright (C) 1996, 1997, 2002, 2007 Free Software Foundation, Inc.
|
||
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||
|
||
@@ -22,7 +22,7 @@
|
||
#include <string.h>
|
||
#include <arpa/inet.h>
|
||
#include <netinet/in.h>
|
||
-
|
||
+#include <resolv/res_hconf.h>
|
||
|
||
#define LOOKUP_TYPE struct hostent
|
||
#define FUNCTION_NAME gethostbyname2
|
||
@@ -30,7 +30,7 @@
|
||
#define ADD_PARAMS const char *name, int af
|
||
#define ADD_VARIABLES name, af
|
||
#define NEED_H_ERRNO 1
|
||
-#define NEED__RES_HCONF 1
|
||
+#define NEED__RES 1
|
||
#define POSTPROCESS \
|
||
if (status == NSS_STATUS_SUCCESS) \
|
||
_res_hconf_reorder_addrs (resbuf);
|
||
diff --git a/inet/gethstbynm_r.c b/inet/gethstbynm_r.c
|
||
index 49e7028a1fe71a09..8f464b5ff1914b86 100644
|
||
--- a/inet/gethstbynm_r.c
|
||
+++ b/inet/gethstbynm_r.c
|
||
@@ -1,4 +1,4 @@
|
||
-/* Copyright (C) 1996, 1997, 1998, 2002, 2007 Free Software Foundation, Inc.
|
||
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||
|
||
@@ -22,7 +22,7 @@
|
||
#include <string.h>
|
||
#include <arpa/inet.h>
|
||
#include <netinet/in.h>
|
||
-
|
||
+#include <resolv/res_hconf.h>
|
||
|
||
#define LOOKUP_TYPE struct hostent
|
||
#define FUNCTION_NAME gethostbyname
|
||
@@ -30,7 +30,7 @@
|
||
#define ADD_PARAMS const char *name
|
||
#define ADD_VARIABLES name
|
||
#define NEED_H_ERRNO 1
|
||
-#define NEED__RES_HCONF 1
|
||
+#define NEED__RES 1
|
||
#define POSTPROCESS \
|
||
if (status == NSS_STATUS_SUCCESS) \
|
||
_res_hconf_reorder_addrs (resbuf);
|
||
diff --git a/nscd/aicache.c b/nscd/aicache.c
|
||
index 0ee25247cd464940..a3de792cc429b546 100644
|
||
--- a/nscd/aicache.c
|
||
+++ b/nscd/aicache.c
|
||
@@ -1,5 +1,5 @@
|
||
/* Cache handling for host lookup.
|
||
- Copyright (C) 2004-2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
|
||
+ Copyright (C) 2004-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
|
||
|
||
@@ -26,7 +26,8 @@
|
||
#include <unistd.h>
|
||
#include <sys/mman.h>
|
||
#include <resolv/resolv-internal.h>
|
||
-#include <resolv/res_hconf.h>
|
||
+#include <resolv/resolv_context.h>
|
||
+#include <resolv/res_use_inet6.h>
|
||
|
||
#include "dbg_log.h"
|
||
#include "nscd.h"
|
||
@@ -78,7 +79,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
|
||
char strdata[0];
|
||
} *dataset = NULL;
|
||
|
||
- if (__builtin_expect (debug_level > 0, 0))
|
||
+ if (__glibc_unlikely (debug_level > 0))
|
||
{
|
||
if (he == NULL)
|
||
dbg_log (_("Haven't found \"%s\" in hosts cache!"), (char *) key);
|
||
@@ -87,34 +88,29 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
|
||
}
|
||
|
||
static service_user *hosts_database;
|
||
- service_user *nip = NULL;
|
||
+ service_user *nip;
|
||
int no_more;
|
||
int rc6 = 0;
|
||
int rc4 = 0;
|
||
int herrno = 0;
|
||
|
||
- if (hosts_database != NULL)
|
||
- {
|
||
- nip = hosts_database;
|
||
- no_more = 0;
|
||
- }
|
||
- else
|
||
+ if (hosts_database == NULL)
|
||
no_more = __nss_database_lookup ("hosts", NULL,
|
||
- "dns [!UNAVAIL=return] files", &nip);
|
||
-
|
||
- /* Initialize configurations. */
|
||
- if (__builtin_expect (!_res_hconf.initialized, 0))
|
||
- _res_hconf_init ();
|
||
- if (__res_maybe_init (&_res, 0) == -1)
|
||
+ "dns [!UNAVAIL=return] files",
|
||
+ &hosts_database);
|
||
+ else
|
||
+ no_more = 0;
|
||
+ nip = hosts_database;
|
||
+
|
||
+ /* Initialize configurations. If we are looking for both IPv4 and
|
||
+ IPv6 address we don't want the lookup functions to automatically
|
||
+ promote IPv4 addresses to IPv6 addresses. Therefore, use the
|
||
+ _no_inet6 variant. */
|
||
+ struct resolv_context *ctx = __resolv_context_get ();
|
||
+ bool enable_inet6 = __resolv_context_disable_inet6 (ctx);
|
||
+ if (ctx == NULL)
|
||
no_more = 1;
|
||
|
||
- /* If we are looking for both IPv4 and IPv6 address we don't want
|
||
- the lookup functions to automatically promote IPv4 addresses to
|
||
- IPv6 addresses. Currently this is decided by setting the
|
||
- RES_USE_INET6 bit in _res.options. */
|
||
- int old_res_options = _res.options;
|
||
- _res.options &= ~DEPRECATED_RES_USE_INET6;
|
||
-
|
||
size_t tmpbuf6len = 1024;
|
||
char *tmpbuf6 = alloca (tmpbuf6len);
|
||
size_t tmpbuf4len = 0;
|
||
@@ -431,7 +427,7 @@ addhstaiX (struct database_dyn *db, int fd, request_header *req,
|
||
struct dataset *newp
|
||
= (struct dataset *) mempool_alloc (db, total + req->key_len,
|
||
1);
|
||
- if (__builtin_expect (newp != NULL, 1))
|
||
+ if (__glibc_likely (newp != NULL))
|
||
{
|
||
/* Adjust pointer into the memory block. */
|
||
key_copy = (char *) newp + (key_copy - (char *) dataset);
|
||
@@ -538,7 +534,8 @@ next_nip:
|
||
}
|
||
|
||
out:
|
||
- _res.options |= old_res_options & DEPRECATED_RES_USE_INET6;
|
||
+ __resolv_context_enable_inet6 (ctx, enable_inet6);
|
||
+ __resolv_context_put (ctx);
|
||
|
||
if (dataset != NULL && !alloca_used)
|
||
{
|
||
diff --git a/nscd/gethstbyad_r.c b/nscd/gethstbyad_r.c
|
||
index c0988b862da3ef03..842ced2ec64048ea 100644
|
||
--- a/nscd/gethstbyad_r.c
|
||
+++ b/nscd/gethstbyad_r.c
|
||
@@ -1,4 +1,4 @@
|
||
-/* Copyright (C) 1996-2012 Free Software Foundation, Inc.
|
||
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||
|
||
@@ -28,7 +28,6 @@
|
||
#define EXTRA_VARIABLES , ttlp
|
||
#define NEED_H_ERRNO 1
|
||
#define NEED__RES 1
|
||
-#define NEED__RES_HCONF 1
|
||
|
||
/* We are nscd, so we don't want to be talking to ourselves. */
|
||
#undef USE_NSCD
|
||
diff --git a/nscd/gethstbynm3_r.c b/nscd/gethstbynm3_r.c
|
||
index a7d25548a8ef3f36..2ab75e469eca1589 100644
|
||
--- a/nscd/gethstbynm3_r.c
|
||
+++ b/nscd/gethstbynm3_r.c
|
||
@@ -1,4 +1,4 @@
|
||
-/* Copyright (C) 1996-2012 Free Software Foundation, Inc.
|
||
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||
|
||
@@ -32,7 +32,7 @@
|
||
#define ADD_VARIABLES name, af
|
||
#define EXTRA_VARIABLES , ttlp, canonp
|
||
#define NEED_H_ERRNO 1
|
||
-#define NEED__RES_HCONF 1
|
||
+#define NEED__RES 1
|
||
|
||
#define HANDLE_DIGITS_DOTS 1
|
||
#define HAVE_LOOKUP_BUFFER 1
|
||
diff --git a/nss/Makefile b/nss/Makefile
|
||
index 4d6a9ef83b885d7c..dda1e5e51b7a3ea3 100644
|
||
--- a/nss/Makefile
|
||
+++ b/nss/Makefile
|
||
@@ -39,7 +39,7 @@ makedb-modules = xmalloc hash-string
|
||
extra-objs += $(makedb-modules:=.o)
|
||
|
||
tests = test-netdb tst-nss-test1 bug17079 tst-nss-getpwent \
|
||
- test-digits-dots
|
||
+ test-digits-dots tst-nss-files-hosts-erange
|
||
xtests = bug-erange
|
||
|
||
include ../Makeconfig
|
||
@@ -115,3 +115,5 @@ $(objpfx)/libnss_test1.so$(libnss_test1.so-version): $(objpfx)/libnss_test1.so
|
||
$(make-link)
|
||
endif
|
||
$(objpfx)tst-nss-test1.out: $(objpfx)/libnss_test1.so$(libnss_test1.so-version)
|
||
+
|
||
+$(objpfx)tst-nss-files-hosts-erange: $(libdl)
|
||
diff --git a/nss/digits_dots.c b/nss/digits_dots.c
|
||
index 7a2b57bdebe03408..0c1fa97e3977a81e 100644
|
||
--- a/nss/digits_dots.c
|
||
+++ b/nss/digits_dots.c
|
||
@@ -1,4 +1,4 @@
|
||
-/* Copyright (C) 1997, 1999, 2000, 2001, 2004 Free Software Foundation, Inc.
|
||
+/* Copyright (C) 1997-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
Contributed by H.J. Lu <hjl@gnu.ai.mit.edu>, 1997.
|
||
|
||
@@ -23,6 +23,7 @@
|
||
#include <ctype.h>
|
||
#include <wctype.h>
|
||
#include <resolv/resolv-internal.h>
|
||
+#include <resolv/resolv_context.h>
|
||
#include <netdb.h>
|
||
#include <arpa/inet.h>
|
||
#include "nsswitch.h"
|
||
@@ -38,11 +39,10 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
|
||
size_t buflen, struct hostent **result,
|
||
enum nss_status *status, int af, int *h_errnop)
|
||
{
|
||
- int save;
|
||
-
|
||
/* We have to test for the use of IPv6 which can only be done by
|
||
examining `_res'. */
|
||
- if (__res_maybe_init (&_res, 0) == -1)
|
||
+ struct resolv_context *ctx = __resolv_context_get ();
|
||
+ if (ctx == NULL)
|
||
{
|
||
if (h_errnop)
|
||
*h_errnop = NETDB_INTERNAL;
|
||
@@ -52,6 +52,21 @@ __nss_hostname_digits_dots (const char *name, struct hostent *resbuf,
|
||
*result = NULL;
|
||
return -1;
|
||
}
|
||
+ int ret = __nss_hostname_digits_dots_context
|
||
+ (ctx, name, resbuf, buffer, buffer_size, buflen,
|
||
+ result, status, af, h_errnop);
|
||
+ __resolv_context_put (ctx);
|
||
+ return ret;
|
||
+}
|
||
+
|
||
+int
|
||
+__nss_hostname_digits_dots_context (struct resolv_context *ctx,
|
||
+ const char *name, struct hostent *resbuf,
|
||
+ char **buffer, size_t *buffer_size,
|
||
+ size_t buflen, struct hostent **result,
|
||
+ enum nss_status *status, int af, int *h_errnop)
|
||
+{
|
||
+ int save;
|
||
|
||
/*
|
||
* disallow names consisting only of digits/dots, unless
|
||
diff --git a/nss/getXXbyYY.c b/nss/getXXbyYY.c
|
||
index c308a70b93ba8a77..a439b816f70aa2e7 100644
|
||
--- a/nss/getXXbyYY.c
|
||
+++ b/nss/getXXbyYY.c
|
||
@@ -1,4 +1,4 @@
|
||
-/* Copyright (C) 1996-2001,2003, 2004 Free Software Foundation, Inc.
|
||
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
@@ -17,7 +17,7 @@
|
||
|
||
#include <assert.h>
|
||
#include <errno.h>
|
||
-#include <bits/libc-lock.h>
|
||
+#include <libc-lock.h>
|
||
#include <stdlib.h>
|
||
#include <resolv.h>
|
||
|
||
@@ -47,6 +47,11 @@
|
||
|* *|
|
||
\*******************************************************************/
|
||
|
||
+
|
||
+#ifdef HANDLE_DIGITS_DOTS
|
||
+# include <resolv/resolv_context.h>
|
||
+#endif
|
||
+
|
||
/* To make the real sources a bit prettier. */
|
||
#define REENTRANT_NAME APPEND_R (FUNCTION_NAME)
|
||
#define APPEND_R(name) APPEND_R1 (name)
|
||
@@ -93,6 +98,19 @@ FUNCTION_NAME (ADD_PARAMS)
|
||
int h_errno_tmp = 0;
|
||
#endif
|
||
|
||
+#ifdef HANDLE_DIGITS_DOTS
|
||
+ /* Wrap both __nss_hostname_digits_dots and the actual lookup
|
||
+ function call in the same context. */
|
||
+ struct resolv_context *res_ctx = __resolv_context_get ();
|
||
+ if (res_ctx == NULL)
|
||
+ {
|
||
+# if NEED_H_ERRNO
|
||
+ __set_h_errno (NETDB_INTERNAL);
|
||
+# endif
|
||
+ return NULL;
|
||
+ }
|
||
+#endif
|
||
+
|
||
/* Get lock. */
|
||
__libc_lock_lock (lock);
|
||
|
||
@@ -105,9 +123,9 @@ FUNCTION_NAME (ADD_PARAMS)
|
||
#ifdef HANDLE_DIGITS_DOTS
|
||
if (buffer != NULL)
|
||
{
|
||
- if (__nss_hostname_digits_dots (name, &resbuf, &buffer,
|
||
- &buffer_size, 0, &result, NULL, AF_VAL,
|
||
- H_ERRNO_VAR_P))
|
||
+ if (__nss_hostname_digits_dots_context
|
||
+ (res_ctx, name, &resbuf, &buffer, &buffer_size, 0, &result, NULL,
|
||
+ AF_VAL, H_ERRNO_VAR_P))
|
||
goto done;
|
||
}
|
||
#endif
|
||
@@ -143,6 +161,10 @@ done:
|
||
/* Release lock. */
|
||
__libc_lock_unlock (lock);
|
||
|
||
+#ifdef HANDLE_DIGITS_DOTS
|
||
+ __resolv_context_put (res_ctx);
|
||
+#endif
|
||
+
|
||
#ifdef NEED_H_ERRNO
|
||
if (h_errno_tmp != 0)
|
||
__set_h_errno (h_errno_tmp);
|
||
diff --git a/nss/getXXbyYY_r.c b/nss/getXXbyYY_r.c
|
||
index 1b457897517fdfb8..bce80e05dd2d1764 100644
|
||
--- a/nss/getXXbyYY_r.c
|
||
+++ b/nss/getXXbyYY_r.c
|
||
@@ -1,4 +1,4 @@
|
||
-/* Copyright (C) 1996-2012 Free Software Foundation, Inc.
|
||
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||
|
||
@@ -25,11 +25,8 @@
|
||
#ifdef USE_NSCD
|
||
# include <nscd/nscd_proto.h>
|
||
#endif
|
||
-#ifdef NEED__RES_HCONF
|
||
-# include <resolv/res_hconf.h>
|
||
-#endif
|
||
#ifdef NEED__RES
|
||
-# include <resolv.h>
|
||
+# include <resolv/resolv_context.h>
|
||
#endif
|
||
/*******************************************************************\
|
||
|* Here we assume several symbols to be defined: *|
|
||
@@ -56,8 +53,7 @@
|
||
|* NEED_H_ERRNO - an extra parameter will be passed to point to *|
|
||
|* the global `h_errno' variable. *|
|
||
|* *|
|
||
-|* NEED__RES - the global _res variable might be used so we *|
|
||
-|* will have to initialize it if necessary *|
|
||
+|* NEED__RES - obtain a struct resolv_context resolver context *|
|
||
|* *|
|
||
|* PREPROCESS - code run before anything else *|
|
||
|* *|
|
||
@@ -216,6 +212,18 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
|
||
bool any_service = false;
|
||
#endif
|
||
|
||
+#ifdef NEED__RES
|
||
+ /* The HANDLE_DIGITS_DOTS case below already needs the resolver
|
||
+ configuration, so this has to happen early. */
|
||
+ struct resolv_context *res_ctx = __resolv_context_get ();
|
||
+ if (res_ctx == NULL)
|
||
+ {
|
||
+ *h_errnop = NETDB_INTERNAL;
|
||
+ *result = NULL;
|
||
+ return errno;
|
||
+ }
|
||
+#endif /* NEED__RES */
|
||
+
|
||
#ifdef PREPROCESS
|
||
PREPROCESS;
|
||
#endif
|
||
@@ -226,6 +234,9 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
|
||
H_ERRNO_VAR_P))
|
||
{
|
||
case -1:
|
||
+# ifdef NEED__RES
|
||
+ __resolv_context_put (res_ctx);
|
||
+# endif
|
||
return errno;
|
||
case 1:
|
||
#ifdef NEED_H_ERRNO
|
||
@@ -245,7 +256,12 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
|
||
nscd_status = NSCD_NAME (ADD_VARIABLES, resbuf, buffer, buflen, result
|
||
H_ERRNO_VAR);
|
||
if (nscd_status >= 0)
|
||
- return nscd_status;
|
||
+ {
|
||
+# ifdef NEED__RES
|
||
+ __resolv_context_put (res_ctx);
|
||
+# endif
|
||
+ return nscd_status;
|
||
+ }
|
||
}
|
||
#endif
|
||
|
||
@@ -263,21 +279,6 @@ INTERNAL (REENTRANT_NAME) (ADD_PARAMS, LOOKUP_TYPE *resbuf, char *buffer,
|
||
}
|
||
else
|
||
{
|
||
-#ifdef NEED__RES
|
||
- /* The resolver code will really be used so we have to
|
||
- initialize it. */
|
||
- if (__res_maybe_init (&_res, 0) == -1)
|
||
- {
|
||
- *h_errnop = NETDB_INTERNAL;
|
||
- *result = NULL;
|
||
- return errno;
|
||
- }
|
||
-#endif /* need _res */
|
||
-#ifdef NEED__RES_HCONF
|
||
- if (!_res_hconf.initialized)
|
||
- _res_hconf_init ();
|
||
-#endif /* need _res_hconf */
|
||
-
|
||
void *tmp_ptr = fct.l;
|
||
#ifdef PTR_MANGLE
|
||
PTR_MANGLE (tmp_ptr);
|
||
@@ -406,6 +407,12 @@ done:
|
||
POSTPROCESS;
|
||
#endif
|
||
|
||
+#ifdef NEED__RES
|
||
+ /* This has to happen late because the POSTPROCESS stage above might
|
||
+ need the resolver context. */
|
||
+ __resolv_context_put (res_ctx);
|
||
+#endif /* NEED__RES */
|
||
+
|
||
int res;
|
||
if (status == NSS_STATUS_SUCCESS || status == NSS_STATUS_NOTFOUND)
|
||
res = 0;
|
||
diff --git a/nss/getnssent_r.c b/nss/getnssent_r.c
|
||
index 25e952f5317e6999..d85065b6cc05dbcb 100644
|
||
--- a/nss/getnssent_r.c
|
||
+++ b/nss/getnssent_r.c
|
||
@@ -1,4 +1,4 @@
|
||
-/* Copyright (C) 2000, 2002, 2004, 2007, 2011 Free Software Foundation, Inc.
|
||
+/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
@@ -18,6 +18,7 @@
|
||
#include <errno.h>
|
||
#include <netdb.h>
|
||
#include "nsswitch.h"
|
||
+#include <resolv/resolv_context.h>
|
||
|
||
/* Set up NIP to run through the services. If ALL is zero, use NIP's
|
||
current location if it's not nil. Return nonzero if there are no
|
||
@@ -59,10 +60,15 @@ __nss_setent (const char *func_name, db_lookup_function lookup_fct,
|
||
} fct;
|
||
int no_more;
|
||
|
||
- if (res && __res_maybe_init (&_res, 0) == -1)
|
||
+ struct resolv_context *res_ctx = NULL;
|
||
+ if (res)
|
||
{
|
||
- __set_h_errno (NETDB_INTERNAL);
|
||
- return;
|
||
+ res_ctx = __resolv_context_get ();
|
||
+ if (res_ctx == NULL)
|
||
+ {
|
||
+ __set_h_errno (NETDB_INTERNAL);
|
||
+ return;
|
||
+ }
|
||
}
|
||
|
||
/* Cycle through the services and run their `setXXent' functions until
|
||
@@ -95,6 +101,8 @@ __nss_setent (const char *func_name, db_lookup_function lookup_fct,
|
||
*last_nip = *nip;
|
||
}
|
||
|
||
+ __resolv_context_put (res_ctx);
|
||
+
|
||
if (stayopen_tmp)
|
||
*stayopen_tmp = stayopen;
|
||
}
|
||
@@ -112,10 +120,15 @@ __nss_endent (const char *func_name, db_lookup_function lookup_fct,
|
||
} fct;
|
||
int no_more;
|
||
|
||
- if (res && __res_maybe_init (&_res, 0) == -1)
|
||
+ struct resolv_context *res_ctx = NULL;
|
||
+ if (res)
|
||
{
|
||
- __set_h_errno (NETDB_INTERNAL);
|
||
- return;
|
||
+ res_ctx = __resolv_context_get ();
|
||
+ if (res_ctx == NULL)
|
||
+ {
|
||
+ __set_h_errno (NETDB_INTERNAL);
|
||
+ return;
|
||
+ }
|
||
}
|
||
|
||
/* Cycle through all the services and run their endXXent functions. */
|
||
@@ -132,6 +145,8 @@ __nss_endent (const char *func_name, db_lookup_function lookup_fct,
|
||
no_more = __nss_next2 (nip, func_name, NULL, &fct.ptr, 0, 1);
|
||
}
|
||
*last_nip = *nip = NULL;
|
||
+
|
||
+ __resolv_context_put (res_ctx);
|
||
}
|
||
|
||
|
||
@@ -152,11 +167,16 @@ __nss_getent_r (const char *getent_func_name,
|
||
int no_more;
|
||
enum nss_status status;
|
||
|
||
- if (res && __res_maybe_init (&_res, 0) == -1)
|
||
+ struct resolv_context *res_ctx = NULL;
|
||
+ if (res)
|
||
{
|
||
- *h_errnop = NETDB_INTERNAL;
|
||
- *result = NULL;
|
||
- return errno;
|
||
+ res_ctx = __resolv_context_get ();
|
||
+ if (res_ctx == NULL)
|
||
+ {
|
||
+ *h_errnop = NETDB_INTERNAL;
|
||
+ *result = NULL;
|
||
+ return errno;
|
||
+ }
|
||
}
|
||
|
||
/* Initialize status to return if no more functions are found. */
|
||
@@ -227,6 +247,8 @@ __nss_getent_r (const char *getent_func_name,
|
||
while (! no_more && status != NSS_STATUS_SUCCESS);
|
||
}
|
||
|
||
+ __resolv_context_put (res_ctx);
|
||
+
|
||
*result = status == NSS_STATUS_SUCCESS ? resbuf : NULL;
|
||
return (status == NSS_STATUS_SUCCESS ? 0
|
||
: status != NSS_STATUS_TRYAGAIN ? ENOENT
|
||
diff --git a/nss/nsswitch.h b/nss/nsswitch.h
|
||
index 23a77747555fab53..bd3fbcb08250c61c 100644
|
||
--- a/nss/nsswitch.h
|
||
+++ b/nss/nsswitch.h
|
||
@@ -1,4 +1,4 @@
|
||
-/* Copyright (C) 1996-2012 Free Software Foundation, Inc.
|
||
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
@@ -197,7 +197,17 @@ extern int __nss_getent_r (const char *getent_func_name,
|
||
extern void *__nss_getent (getent_r_function func,
|
||
void **resbuf, char **buffer, size_t buflen,
|
||
size_t *buffer_size, int *h_errnop);
|
||
+struct resolv_context;
|
||
struct hostent;
|
||
+extern int __nss_hostname_digits_dots_context (struct resolv_context *,
|
||
+ const char *name,
|
||
+ struct hostent *resbuf,
|
||
+ char **buffer,
|
||
+ size_t *buffer_size,
|
||
+ size_t buflen,
|
||
+ struct hostent **result,
|
||
+ enum nss_status *status, int af,
|
||
+ int *h_errnop) attribute_hidden;
|
||
extern int __nss_hostname_digits_dots (const char *name,
|
||
struct hostent *resbuf, char **buffer,
|
||
size_t *buffer_size, size_t buflen,
|
||
diff --git a/nss/tst-nss-files-hosts-erange.c b/nss/tst-nss-files-hosts-erange.c
|
||
new file mode 100644
|
||
index 0000000000000000..beb7aa9fa0b5926f
|
||
--- /dev/null
|
||
+++ b/nss/tst-nss-files-hosts-erange.c
|
||
@@ -0,0 +1,109 @@
|
||
+/* Parse /etc/hosts in multi mode with a trailing long line (bug 21915).
|
||
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+
|
||
+#include <dlfcn.h>
|
||
+#include <errno.h>
|
||
+#include <gnu/lib-names.h>
|
||
+#include <netdb.h>
|
||
+#include <nss.h>
|
||
+#include <support/check.h>
|
||
+#include <support/check_nss.h>
|
||
+#include <support/namespace.h>
|
||
+#include <support/test-driver.h>
|
||
+#include <support/xunistd.h>
|
||
+
|
||
+struct support_chroot *chroot_env;
|
||
+
|
||
+#define X10 "XXXXXXXXXX"
|
||
+#define X100 X10 X10 X10 X10 X10 X10 X10 X10 X10 X10
|
||
+#define X1000 X100 X100 X100 X100 X100 X100 X100 X100 X100 X100
|
||
+
|
||
+static void
|
||
+prepare (int argc, char **argv)
|
||
+{
|
||
+ chroot_env = support_chroot_create
|
||
+ ((struct support_chroot_configuration)
|
||
+ {
|
||
+ .resolv_conf = "",
|
||
+ .hosts =
|
||
+ "127.0.0.1 localhost localhost.localdomain\n"
|
||
+ "::1 localhost localhost.localdomain\n"
|
||
+ "192.0.2.1 example.com\n"
|
||
+ "#" X1000 X100 "\n",
|
||
+ .host_conf = "multi on\n",
|
||
+ });
|
||
+}
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ support_become_root ();
|
||
+ if (!support_can_chroot ())
|
||
+ return EXIT_UNSUPPORTED;
|
||
+
|
||
+ __nss_configure_lookup ("hosts", "files");
|
||
+ if (dlopen (LIBNSS_FILES_SO, RTLD_LAZY) == NULL)
|
||
+ FAIL_EXIT1 ("could not load " LIBNSS_DNS_SO ": %s", dlerror ());
|
||
+
|
||
+ xchroot (chroot_env->path_chroot);
|
||
+
|
||
+ errno = ERANGE;
|
||
+ h_errno = NETDB_INTERNAL;
|
||
+ check_hostent ("gethostbyname example.com",
|
||
+ gethostbyname ("example.com"),
|
||
+ "name: example.com\n"
|
||
+ "address: 192.0.2.1\n");
|
||
+ errno = ERANGE;
|
||
+ h_errno = NETDB_INTERNAL;
|
||
+ check_hostent ("gethostbyname2 AF_INET example.com",
|
||
+ gethostbyname2 ("example.com", AF_INET),
|
||
+ "name: example.com\n"
|
||
+ "address: 192.0.2.1\n");
|
||
+ {
|
||
+ struct addrinfo hints =
|
||
+ {
|
||
+ .ai_family = AF_UNSPEC,
|
||
+ .ai_socktype = SOCK_STREAM,
|
||
+ .ai_protocol = IPPROTO_TCP,
|
||
+ };
|
||
+ errno = ERANGE;
|
||
+ h_errno = NETDB_INTERNAL;
|
||
+ struct addrinfo *ai;
|
||
+ int ret = getaddrinfo ("example.com", "80", &hints, &ai);
|
||
+ check_addrinfo ("example.com AF_UNSPEC", ai, ret,
|
||
+ "address: STREAM/TCP 192.0.2.1 80\n");
|
||
+ if (ret == 0)
|
||
+ freeaddrinfo (ai);
|
||
+
|
||
+ hints.ai_family = AF_INET;
|
||
+ errno = ERANGE;
|
||
+ h_errno = NETDB_INTERNAL;
|
||
+ ret = getaddrinfo ("example.com", "80", &hints, &ai);
|
||
+ check_addrinfo ("example.com AF_INET", ai, ret,
|
||
+ "address: STREAM/TCP 192.0.2.1 80\n");
|
||
+ if (ret == 0)
|
||
+ freeaddrinfo (ai);
|
||
+ }
|
||
+
|
||
+ support_chroot_free (chroot_env);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#define PREPARE prepare
|
||
+#include <support/test-driver.c>
|
||
diff --git a/resolv/Depend b/resolv/Depend
|
||
index 8d2587bbc1fd0b89..6c1aa44e6eb7b9a3 100644
|
||
--- a/resolv/Depend
|
||
+++ b/resolv/Depend
|
||
@@ -1,2 +1 @@
|
||
-linuxthreads
|
||
nptl
|
||
diff --git a/resolv/Makefile b/resolv/Makefile
|
||
index 3f525bcc75ee83ae..1124897ce5f9610b 100644
|
||
--- a/resolv/Makefile
|
||
+++ b/resolv/Makefile
|
||
@@ -1,5 +1,4 @@
|
||
-# Copyright (C) 1994-2001,2003,2004,2007,2008,2011,2012
|
||
-# Free Software Foundation, Inc.
|
||
+# Copyright (C) 1994-2017 Free Software Foundation, Inc.
|
||
# This file is part of the GNU C Library.
|
||
|
||
# The GNU C Library is free software; you can redistribute it and/or
|
||
@@ -21,33 +20,73 @@
|
||
#
|
||
subdir := resolv
|
||
|
||
+include ../Makeconfig
|
||
+
|
||
headers := resolv.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 tst-inet_pton
|
||
+tests = tst-aton tst-leaks tst-inet_ntop
|
||
xtests = tst-leaks2
|
||
|
||
-generate := mtrace-tst-leaks tst-leaks.mtrace tst-leaks2.mtrace
|
||
-
|
||
-include ../Makeconfig
|
||
+generate := mtrace-tst-leaks.out tst-leaks.mtrace tst-leaks2.mtrace
|
||
|
||
extra-libs := libresolv libnss_dns
|
||
ifeq ($(have-thread-library),yes)
|
||
extra-libs += libanl
|
||
routines += gai_sigqueue
|
||
-tests += tst-res_hconf_reorder
|
||
+
|
||
+tests += \
|
||
+ tst-bug18665 \
|
||
+ tst-bug18665-tcp \
|
||
+ tst-ns_name \
|
||
+ tst-ns_name_compress \
|
||
+ tst-res_hconf_reorder \
|
||
+ tst-res_use_inet6 \
|
||
+ tst-resolv-basic \
|
||
+ tst-resolv-edns \
|
||
+ tst-resolv-network \
|
||
+ tst-resolv-res_init-multi \
|
||
+ tst-resolv-search \
|
||
+
|
||
+# These tests need libdl.
|
||
+ifeq (yes,$(build-shared))
|
||
+tests += \
|
||
+ tst-resolv-canonname \
|
||
+
|
||
+# uses DEPRECATED_RES_USE_INET6 from <resolv-internal.h>.
|
||
+tests += \
|
||
+ tst-resolv-res_init \
|
||
+ tst-resolv-res_init-thread \
|
||
+
|
||
+# Needs resolv_context.
|
||
+tests += \
|
||
+ tst-resolv-res_ninit \
|
||
+ tst-resolv-threads \
|
||
+
|
||
+endif
|
||
+
|
||
+# This test accesses __inet_ntop_range, an internal libc function.
|
||
+tests += tst-inet_pton
|
||
+
|
||
+# 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
|
||
@@ -66,29 +105,23 @@ ifeq (yesyes,$(build-shared)$(have-thread-library))
|
||
tests: $(objpfx)ga_test
|
||
endif
|
||
|
||
-generated := mtrace-tst-leaks tst-leaks.mtrace \
|
||
- mtrace-tst-leaks2 tst-leaks2.mtrace
|
||
+ifeq (,$(filter sunrpc,$(subdirs)))
|
||
+# The netdb.h we install does '#include <rpc/netdb.h>', so one must exist.
|
||
+# If sunrpc/ is built in this configuration, it installs a real <rpc/netdb.h>.
|
||
+# If that's not going to happen, install our dummy file.
|
||
+headers += rpc/netdb.h
|
||
+endif
|
||
|
||
-include ../Rules
|
||
+generated += mtrace-tst-leaks.out tst-leaks.mtrace \
|
||
+ mtrace-tst-leaks2.out tst-leaks2.mtrace \
|
||
+ mtrace-tst-resolv-res_ninit.out tst-resolv-res_ninit.mtrace \
|
||
|
||
-CPPFLAGS += -Dgethostbyname=res_gethostbyname \
|
||
- -Dgethostbyname2=res_gethostbyname2 \
|
||
- -Dgethostbyaddr=res_gethostbyaddr \
|
||
- -Dgetnetbyname=res_getnetbyname \
|
||
- -Dgetnetbyaddr=res_getnetbyaddr
|
||
+include ../Rules
|
||
|
||
-ifeq (yes,$(have-ssp))
|
||
-CFLAGS-libresolv += -fstack-protector
|
||
-endif
|
||
-ifeq (yes,$(have-ssp-strong))
|
||
CFLAGS-libresolv += -fstack-protector-strong
|
||
-endif
|
||
-
|
||
+CFLAGS-libnss_dns += -fstack-protector-strong
|
||
CFLAGS-res_hconf.c = -fexceptions
|
||
|
||
-# The BIND code elicits some harmless warnings.
|
||
-+cflags += -Wno-strict-prototypes -Wno-write-strings
|
||
-
|
||
# The DNS NSS modules needs the resolver.
|
||
$(objpfx)libnss_dns.so: $(objpfx)libresolv.so
|
||
|
||
@@ -104,17 +137,45 @@ $(objpfx)tst-leaks: $(objpfx)libresolv.so
|
||
tst-leaks-ENV = MALLOC_TRACE=$(objpfx)tst-leaks.mtrace
|
||
$(objpfx)mtrace-tst-leaks: $(objpfx)tst-leaks.out
|
||
$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks.mtrace > $@
|
||
-ifeq ($(run-built-tests),yes)
|
||
-ifneq (no,$(PERL))
|
||
-tests: $(objpfx)mtrace-tst-leaks
|
||
-endif
|
||
-endif
|
||
|
||
tst-leaks2-ENV = MALLOC_TRACE=$(objpfx)tst-leaks2.mtrace
|
||
$(objpfx)mtrace-tst-leaks2: $(objpfx)tst-leaks2.out
|
||
$(common-objpfx)malloc/mtrace $(objpfx)tst-leaks2.mtrace > $@
|
||
-ifeq ($(run-built-tests),yes)
|
||
+
|
||
+tst-resolv-res_ninit-ENV = MALLOC_TRACE=$(objpfx)tst-resolv-res_ninit.mtrace
|
||
+$(objpfx)mtrace-tst-resolv-res_ninit: $(objpfx)tst-resolv-res_ninit.out
|
||
+ $(common-objpfx)malloc/mtrace \
|
||
+ $(objpfx)tst-resolv-res_ninit.mtrace > $@
|
||
+
|
||
ifneq (no,$(PERL))
|
||
+tests: $(objpfx)mtrace-tst-leaks $(objpfx)mtrace-tst-resolv-res_ninit
|
||
xtests: $(objpfx)mtrace-tst-leaks2
|
||
endif
|
||
-endif
|
||
+
|
||
+
|
||
+$(objpfx)tst-bug18665-tcp: $(objpfx)libresolv.so $(shared-thread-library)
|
||
+$(objpfx)tst-bug18665: $(objpfx)libresolv.so $(shared-thread-library)
|
||
+$(objpfx)tst-res_use_inet6: $(objpfx)libresolv.so $(shared-thread-library)
|
||
+$(objpfx)tst-resolv-basic: $(objpfx)libresolv.so $(shared-thread-library)
|
||
+$(objpfx)tst-resolv-edns: $(objpfx)libresolv.so $(shared-thread-library)
|
||
+$(objpfx)tst-resolv-network: $(objpfx)libresolv.so $(shared-thread-library)
|
||
+$(objpfx)tst-resolv-res_init: $(libdl) $(objpfx)libresolv.so
|
||
+$(objpfx)tst-resolv-res_init-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
|
||
+
|
||
+
|
||
+# 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 1a70bbb1dc615ac9..514e9bb617e710f1 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.
|
||
|
||
@@ -62,7 +58,7 @@ the `gethostby*' family of functions, which means that for example
|
||
traditional resolver interfaces however, continue to use a single
|
||
resolver state and are therefore still thread-unsafe. The resolver
|
||
state is the same resolver state that is used for the initial ("main")
|
||
-thread.
|
||
+thread.
|
||
|
||
This has the following consequences for existing binaries and source
|
||
code:
|
||
@@ -118,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
|
||
@@ -145,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 24b07ef770ed3915..b05778d9654aa0f2 100644
|
||
--- a/resolv/Versions
|
||
+++ b/resolv/Versions
|
||
@@ -1,5 +1,3 @@
|
||
-%include <tls.h>
|
||
-
|
||
libc {
|
||
GLIBC_2.0 {
|
||
_res;
|
||
@@ -28,8 +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;
|
||
}
|
||
}
|
||
|
||
@@ -81,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;
|
||
}
|
||
}
|
||
|
||
@@ -98,6 +102,6 @@ libnss_dns {
|
||
|
||
libanl {
|
||
GLIBC_2.2.3 {
|
||
- getaddrinfo_a; gai_cancel; gai_error; gai_suspend;
|
||
+ gai_cancel; gai_error; gai_suspend; getaddrinfo_a;
|
||
}
|
||
}
|
||
diff --git a/resolv/arpa/nameser.h b/resolv/arpa/nameser.h
|
||
index 6a2c8376bd6565cb..a99d5ec508592486 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 { \
|
||
- register 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 { \
|
||
- register 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 { \
|
||
- register u_int16_t t_s = (u_int16_t)(s); \
|
||
- register 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 { \
|
||
- register u_int32_t t_l = (u_int32_t)(l); \
|
||
- register 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 d59c9e41b3a5c45c..f1c390f3b918b547 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/base64.c b/resolv/base64.c
|
||
index ea584ed357f02a66..fedc086b0c1b28a0 100644
|
||
--- a/resolv/base64.c
|
||
+++ b/resolv/base64.c
|
||
@@ -40,10 +40,6 @@
|
||
* IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||
*/
|
||
|
||
-#if !defined(LINT) && !defined(CODECENTER)
|
||
-static const char rcsid[] = "$BINDId: base64.c,v 8.7 1999/10/13 16:39:33 vixie Exp $";
|
||
-#endif /* not lint */
|
||
-
|
||
#include <sys/types.h>
|
||
#include <sys/param.h>
|
||
#include <sys/socket.h>
|
||
@@ -195,10 +191,7 @@ libresolv_hidden_def (b64_ntop)
|
||
*/
|
||
|
||
int
|
||
-b64_pton(src, target, targsize)
|
||
- char const *src;
|
||
- u_char *target;
|
||
- size_t targsize;
|
||
+b64_pton (char const *src, u_char *target, size_t targsize)
|
||
{
|
||
int tarindex, state, ch;
|
||
char *pos;
|
||
diff --git a/resolv/gethnamaddr.c b/resolv/compat-gethnamaddr.c
|
||
similarity index 74%
|
||
rename from resolv/gethnamaddr.c
|
||
rename to resolv/compat-gethnamaddr.c
|
||
index bea3ec588cf60991..259378b2be2d5f63 100644
|
||
--- a/resolv/gethnamaddr.c
|
||
+++ b/resolv/compat-gethnamaddr.c
|
||
@@ -49,54 +49,32 @@
|
||
* --Copyright--
|
||
*/
|
||
|
||
-#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)
|
||
+/* XXX This file is not used by any of the resolver functions implemented by
|
||
+ glibc (i.e. get*info and gethostby*). It cannot be removed however because
|
||
+ it exports symbols in the libresolv ABI. The file is not maintained any
|
||
+ more, nor are these functions. */
|
||
+
|
||
+#include <shlib-compat.h>
|
||
+#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_25)
|
||
+
|
||
+# include <sys/types.h>
|
||
+# include <sys/param.h>
|
||
+# include <sys/socket.h>
|
||
+# include <netinet/in.h>
|
||
+# include <arpa/inet.h>
|
||
+# include <arpa/nameser.h>
|
||
+
|
||
+# include <stdio.h>
|
||
+# include <netdb.h>
|
||
+# include <resolv/resolv-internal.h>
|
||
+# include <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];
|
||
|
||
@@ -107,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;
|
||
@@ -136,15 +115,13 @@ typedef union {
|
||
char ac;
|
||
} align;
|
||
|
||
-#ifndef h_errno
|
||
+# ifndef h_errno
|
||
extern int h_errno;
|
||
-#endif
|
||
+# endif
|
||
|
||
-#ifdef DEBUG
|
||
+# ifdef DEBUG
|
||
static void
|
||
-Dprintf(msg, num)
|
||
- char *msg;
|
||
- int num;
|
||
+Dprintf (char *msg, int num)
|
||
{
|
||
if (_res.options & RES_DEBUG) {
|
||
int save = errno;
|
||
@@ -153,11 +130,11 @@ Dprintf(msg, 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) { \
|
||
@@ -166,7 +143,7 @@ Dprintf(msg, num)
|
||
} \
|
||
} while (0)
|
||
|
||
-#define BOUNDS_CHECK(ptr, count) \
|
||
+# define BOUNDS_CHECK(ptr, count) \
|
||
do { \
|
||
if ((ptr) + (count) > eom) { \
|
||
__set_h_errno (NO_RECOVERY); \
|
||
@@ -178,9 +155,9 @@ Dprintf(msg, num)
|
||
static struct hostent *
|
||
getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
|
||
{
|
||
- register const HEADER *hp;
|
||
- register const u_char *cp;
|
||
- register int n;
|
||
+ const HEADER *hp;
|
||
+ const u_char *cp;
|
||
+ int n;
|
||
const u_char *eom, *erdata;
|
||
char *bp, **ap, **hap;
|
||
int type, class, buflen, ancount, qdcount;
|
||
@@ -332,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++ ? */
|
||
}
|
||
@@ -354,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);
|
||
@@ -376,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++ ? */
|
||
}
|
||
@@ -404,7 +355,7 @@ getanswer (const querybuf *answer, int anslen, const char *qname, int qtype)
|
||
continue;
|
||
}
|
||
if (!haveanswer) {
|
||
- register int nn;
|
||
+ int nn;
|
||
|
||
host.h_name = bp;
|
||
nn = strlen(bp) + 1; /* for the \0 */
|
||
@@ -449,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"
|
||
@@ -457,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)
|
||
@@ -467,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);
|
||
@@ -477,31 +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(name)
|
||
- 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(name, af)
|
||
- const char *name;
|
||
- int af;
|
||
+static struct hostent *
|
||
+res_gethostbyname2_context (struct resolv_context *ctx,
|
||
+ const char *name, int af)
|
||
{
|
||
union
|
||
{
|
||
@@ -509,16 +464,11 @@ gethostbyname2(name, af)
|
||
u_char *ptr;
|
||
} buf;
|
||
querybuf *origbuf;
|
||
- register const char *cp;
|
||
+ const char *cp;
|
||
char *bp;
|
||
int n, size, type, len;
|
||
struct hostent *ret;
|
||
|
||
- if (__res_maybe_init (&_res, 0) == -1) {
|
||
- __set_h_errno (NETDB_INTERNAL);
|
||
- return (NULL);
|
||
- }
|
||
-
|
||
switch (af) {
|
||
case AF_INET:
|
||
size = INADDRSZ;
|
||
@@ -542,8 +492,10 @@ gethostbyname2(name, 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(name, 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(name, 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,13 +582,26 @@ gethostbyname2(name, af)
|
||
free (buf.buf);
|
||
return ret;
|
||
}
|
||
-libresolv_hidden_def (gethostbyname2)
|
||
|
||
struct hostent *
|
||
-gethostbyaddr(addr, len, af)
|
||
- 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 };
|
||
@@ -648,22 +614,12 @@ gethostbyaddr(addr, len, af)
|
||
u_char *ptr;
|
||
} buf;
|
||
querybuf *orig_buf;
|
||
- register struct hostent *hp;
|
||
+ struct hostent *hp;
|
||
char qbuf[MAXDNAME+1], *qp = NULL;
|
||
-#ifdef SUNSECURITY
|
||
- register 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 &&
|
||
- (!bcmp(uaddr, mapped, sizeof mapped) ||
|
||
- !bcmp(uaddr, tunnelled, sizeof tunnelled))) {
|
||
+ (!memcmp(uaddr, mapped, sizeof mapped) ||
|
||
+ !memcmp(uaddr, tunnelled, sizeof tunnelled))) {
|
||
/* Unmap. */
|
||
addr += sizeof mapped;
|
||
uaddr += sizeof mapped;
|
||
@@ -698,9 +654,9 @@ gethostbyaddr(addr, len, 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;
|
||
@@ -710,14 +666,8 @@ gethostbyaddr(addr, len, 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);
|
||
@@ -731,44 +681,12 @@ gethostbyaddr(addr, len, 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;
|
||
@@ -777,9 +695,23 @@ gethostbyaddr(addr, len, 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(f)
|
||
- int f;
|
||
+_sethtent (int f)
|
||
{
|
||
if (!hostf)
|
||
hostf = fopen(_PATH_HOSTS, "rce" );
|
||
@@ -788,9 +720,10 @@ _sethtent(f)
|
||
stayopen = f;
|
||
}
|
||
libresolv_hidden_def (_sethtent)
|
||
+compat_symbol (libresolv, _sethtent, _sethtent, GLIBC_2_0);
|
||
|
||
-void
|
||
-_endhtent()
|
||
+static void
|
||
+_endhtent (void)
|
||
{
|
||
if (hostf && !stayopen) {
|
||
(void) fclose(hostf);
|
||
@@ -799,10 +732,10 @@ _endhtent()
|
||
}
|
||
|
||
struct hostent *
|
||
-_gethtent()
|
||
+_gethtent (void)
|
||
{
|
||
char *p;
|
||
- register char *cp, **q;
|
||
+ char *cp, **q;
|
||
int af, len;
|
||
|
||
if (!hostf && !(hostf = fopen(_PATH_HOSTS, "rce" ))) {
|
||
@@ -826,7 +759,7 @@ _gethtent()
|
||
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;
|
||
@@ -863,28 +796,27 @@ _gethtent()
|
||
return (&host);
|
||
}
|
||
libresolv_hidden_def (_gethtent)
|
||
+compat_symbol (libresolv, _gethtent, _gethtent, GLIBC_2_0);
|
||
|
||
struct hostent *
|
||
-_gethtbyname(name)
|
||
- const char *name;
|
||
+_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(name, af)
|
||
- const char *name;
|
||
- int af;
|
||
+_gethtbyname2 (const char *name, int af)
|
||
{
|
||
- register struct hostent *p;
|
||
- register char **cp;
|
||
+ struct hostent *p;
|
||
+ char **cp;
|
||
|
||
_sethtent(0);
|
||
while ((p = _gethtent())) {
|
||
@@ -901,28 +833,25 @@ _gethtbyname2(name, af)
|
||
return (p);
|
||
}
|
||
libresolv_hidden_def (_gethtbyname2)
|
||
+compat_symbol (libresolv, _gethtbyname2, _gethtbyname2, GLIBC_2_0);
|
||
|
||
struct hostent *
|
||
-_gethtbyaddr(addr, len, af)
|
||
- const char *addr;
|
||
- size_t len;
|
||
- int af;
|
||
+_gethtbyaddr (const char *addr, size_t len, int af)
|
||
{
|
||
- register struct hostent *p;
|
||
+ struct hostent *p;
|
||
|
||
_sethtent(0);
|
||
while ((p = _gethtent()))
|
||
- if (p->h_addrtype == af && !bcmp(p->h_addr, addr, len))
|
||
+ if (p->h_addrtype == af && !memcmp(p->h_addr, addr, len))
|
||
break;
|
||
_endhtent();
|
||
return (p);
|
||
}
|
||
libresolv_hidden_def (_gethtbyaddr)
|
||
+compat_symbol (libresolv, _gethtbyaddr, _gethtbyaddr, GLIBC_2_0);
|
||
|
||
static void
|
||
-map_v4v6_address(src, dst)
|
||
- const char *src;
|
||
- char *dst;
|
||
+map_v4v6_address (const char *src, char *dst)
|
||
{
|
||
u_char *p = (u_char *)dst;
|
||
char tmp[INADDRSZ];
|
||
@@ -940,10 +869,7 @@ map_v4v6_address(src, dst)
|
||
}
|
||
|
||
static void
|
||
-map_v4v6_hostent(hp, bpp, lenp)
|
||
- struct hostent *hp;
|
||
- char **bpp;
|
||
- int *lenp;
|
||
+map_v4v6_hostent (struct hostent *hp, char **bpp, int *lenp)
|
||
{
|
||
char **ap;
|
||
|
||
@@ -968,11 +894,8 @@ map_v4v6_hostent(hp, bpp, lenp)
|
||
}
|
||
}
|
||
|
||
-#ifdef RESOLVSORT
|
||
extern void
|
||
-addrsort(ap, num)
|
||
- char **ap;
|
||
- int num;
|
||
+addrsort (char **ap, int num)
|
||
{
|
||
int i, j;
|
||
char **p;
|
||
@@ -1011,55 +934,5 @@ addrsort(ap, 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(stayopen)
|
||
- int stayopen;
|
||
-{
|
||
- _sethtent(stayopen);
|
||
-}
|
||
-
|
||
-void
|
||
-ht_endhostent()
|
||
-{
|
||
- _endhtent();
|
||
-}
|
||
-
|
||
-struct hostent *
|
||
-ht_gethostbyname(name)
|
||
- char *name;
|
||
-{
|
||
- return (_gethtbyname(name));
|
||
-}
|
||
-
|
||
-struct hostent *
|
||
-ht_gethostbyaddr(addr, len, af)
|
||
- const char *addr;
|
||
- size_t len;
|
||
- int af;
|
||
-{
|
||
- return (_gethtbyaddr(addr, len, af));
|
||
-}
|
||
-
|
||
-struct hostent *
|
||
-gethostent()
|
||
-{
|
||
- return (_gethtent());
|
||
-}
|
||
|
||
-void
|
||
-dns_service()
|
||
-{
|
||
- 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 0000000000000000..e36a370f04837340
|
||
--- /dev/null
|
||
+++ b/resolv/compat-hooks.c
|
||
@@ -0,0 +1,56 @@
|
||
+/* Compatibility functions for obsolete libresolv hooks.
|
||
+ Copyright (C) 1999-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+/*
|
||
+ * Copyright (c) 1995-1999 by Internet Software Consortium.
|
||
+ *
|
||
+ * Permission to use, copy, modify, and distribute this software for any
|
||
+ * purpose with or without fee is hereby granted, provided that the above
|
||
+ * copyright notice and this permission notice appear in all copies.
|
||
+ *
|
||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||
+ * SOFTWARE.
|
||
+ */
|
||
+
|
||
+#include <resolv.h>
|
||
+
|
||
+#include <shlib-compat.h>
|
||
+
|
||
+#if SHLIB_COMPAT (libresolv, GLIBC_2_0, GLIBC_2_25)
|
||
+
|
||
+void
|
||
+attribute_compat_text_section
|
||
+res_send_setqhook(void *hook) {
|
||
+ _res.__glibc_unused_qhook = hook;
|
||
+}
|
||
+compat_symbol (libresolv, res_send_setqhook, res_send_setqhook, GLIBC_2_0);
|
||
+
|
||
+void
|
||
+attribute_compat_text_section
|
||
+res_send_setrhook(void *hook) {
|
||
+ _res.__glibc_unused_rhook = hook;
|
||
+}
|
||
+compat_symbol (libresolv, res_send_setrhook, res_send_setrhook, GLIBC_2_0);
|
||
+
|
||
+#endif
|
||
diff --git a/resolv/herror.c b/resolv/herror.c
|
||
index 0aaf29f9db724bb3..b3df236bc95d67df 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,14 +80,14 @@ 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);
|
||
}
|
||
diff --git a/resolv/inet_addr.c b/resolv/inet_addr.c
|
||
index 144b87a74c1aef62..022f7ea0841b6bae 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,26 +72,25 @@ 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.
|
||
* The value returned is in network order.
|
||
*/
|
||
in_addr_t
|
||
-inet_addr(const char *cp) {
|
||
+__inet_addr(const char *cp) {
|
||
struct in_addr val;
|
||
|
||
if (__inet_aton(cp, &val))
|
||
return (val.s_addr);
|
||
return (INADDR_NONE);
|
||
}
|
||
+weak_alias (__inet_addr, inet_addr)
|
||
|
||
/*
|
||
* Check whether "cp" is a valid ascii representation
|
||
@@ -110,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];
|
||
@@ -121,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;
|
||
|
||
@@ -137,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);
|
||
@@ -150,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:
|
||
@@ -210,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 e50c6a049b875555..aaa78f664b5bc261 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>
|
||
@@ -49,12 +45,7 @@ static char * inet_net_ntop_ipv4 (const u_char *src, int bits,
|
||
* Paul Vixie (ISC), July 1996
|
||
*/
|
||
char *
|
||
-inet_net_ntop(af, src, bits, dst, size)
|
||
- int af;
|
||
- const void *src;
|
||
- int bits;
|
||
- char *dst;
|
||
- size_t size;
|
||
+inet_net_ntop (int af, const void *src, int bits, char *dst, size_t size)
|
||
{
|
||
switch (af) {
|
||
case AF_INET:
|
||
@@ -79,11 +70,7 @@ inet_net_ntop(af, src, bits, dst, size)
|
||
* Paul Vixie (ISC), July 1996
|
||
*/
|
||
static char *
|
||
-inet_net_ntop_ipv4(src, bits, dst, size)
|
||
- const u_char *src;
|
||
- int bits;
|
||
- char *dst;
|
||
- size_t size;
|
||
+inet_net_ntop_ipv4 (const u_char *src, int bits, char *dst, size_t size)
|
||
{
|
||
char *odst = dst;
|
||
char *t;
|
||
diff --git a/resolv/inet_net_pton.c b/resolv/inet_net_pton.c
|
||
index 14916f83f840bcef..aab9b7b58228bb2d 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>
|
||
@@ -54,11 +50,7 @@ static int inet_net_pton_ipv4 (const char *src, u_char *dst,
|
||
* Paul Vixie (ISC), June 1996
|
||
*/
|
||
int
|
||
-inet_net_pton(af, src, dst, size)
|
||
- int af;
|
||
- const char *src;
|
||
- void *dst;
|
||
- size_t size;
|
||
+inet_net_pton (int af, const char *src, void *dst, size_t size)
|
||
{
|
||
switch (af) {
|
||
case AF_INET:
|
||
@@ -86,10 +78,7 @@ inet_net_pton(af, src, dst, size)
|
||
* Paul Vixie (ISC), June 1996
|
||
*/
|
||
static int
|
||
-inet_net_pton_ipv4(src, dst, size)
|
||
- const char *src;
|
||
- u_char *dst;
|
||
- size_t size;
|
||
+inet_net_pton_ipv4 (const char *src, u_char *dst, size_t size)
|
||
{
|
||
static const char xdigits[] = "0123456789abcdef";
|
||
int n, ch, tmp, dirty, bits;
|
||
diff --git a/resolv/inet_neta.c b/resolv/inet_neta.c
|
||
index 349e6bd8802b21fb..348ff4784f412bc0 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,10 +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(src, dst, size)
|
||
- u_int32_t src;
|
||
- char *dst;
|
||
- size_t size;
|
||
+inet_neta (u_int32_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 6e89f2d0589ad013..01c45ce8b79bec56 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>
|
||
@@ -56,11 +52,7 @@ static const char *inet_ntop6 (const u_char *src, char *dst, socklen_t size)
|
||
* Paul Vixie, 1996.
|
||
*/
|
||
const char *
|
||
-inet_ntop(af, src, dst, size)
|
||
- int af;
|
||
- const void *src;
|
||
- char *dst;
|
||
- socklen_t size;
|
||
+inet_ntop (int af, const void *src, char *dst, socklen_t size)
|
||
{
|
||
switch (af) {
|
||
case AF_INET:
|
||
@@ -88,10 +80,7 @@ libc_hidden_def (inet_ntop)
|
||
*/
|
||
static const char *
|
||
internal_function
|
||
-inet_ntop4(src, dst, size)
|
||
- const u_char *src;
|
||
- char *dst;
|
||
- socklen_t size;
|
||
+inet_ntop4 (const u_char *src, char *dst, socklen_t size)
|
||
{
|
||
static const char fmt[] = "%u.%u.%u.%u";
|
||
char tmp[sizeof "255.255.255.255"];
|
||
@@ -111,10 +100,7 @@ inet_ntop4(src, dst, size)
|
||
*/
|
||
static const char *
|
||
internal_function
|
||
-inet_ntop6(src, dst, size)
|
||
- const u_char *src;
|
||
- char *dst;
|
||
- socklen_t size;
|
||
+inet_ntop6 (const u_char *src, char *dst, socklen_t size)
|
||
{
|
||
/*
|
||
* Note that int32_t and int16_t need only be "at least" large enough
|
||
diff --git a/resolv/ns_date.c b/resolv/ns_date.c
|
||
index 9801ac46d40b501c..31cef74c928013e8 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>
|
||
diff --git a/resolv/ns_name.c b/resolv/ns_name.c
|
||
index adf64bbd9ac8e503..08a75e2fe0b4edd6 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)) {
|
||
@@ -180,7 +133,7 @@ libresolv_hidden_def (ns_name_ntop)
|
||
strong_alias (ns_name_ntop, __ns_name_ntop)
|
||
|
||
/*%
|
||
- * Convert a ascii string into an encoded domain name as per RFC1035.
|
||
+ * Convert an ascii string into an encoded domain name as per RFC1035.
|
||
*
|
||
* return:
|
||
*
|
||
@@ -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) {
|
||
@@ -295,7 +227,6 @@ ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
|
||
__set_errno (EMSGSIZE);
|
||
return (-1);
|
||
}
|
||
- done:
|
||
if (label >= eom) {
|
||
__set_errno (EMSGSIZE);
|
||
return (-1);
|
||
@@ -398,7 +329,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 +475,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 +573,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 +581,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;
|
||
@@ -681,7 +603,7 @@ libresolv_hidden_def (ns_name_skip)
|
||
|
||
/*%
|
||
* Thinking in noninternationalized USASCII (per the DNS spec),
|
||
- * is this characted special ("in need of quoting") ?
|
||
+ * is this character special ("in need of quoting") ?
|
||
*
|
||
* return:
|
||
*\li boolean.
|
||
@@ -795,180 +717,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)
|
||
-{
|
||
- 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)
|
||
+labellen (const unsigned 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 4318f18879d774dd..6a365a3b8c37e21a 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 712469be1d88c58a..863b20a9f7fd902b 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 36d39784a5bfce1b..f55680c311bd015b 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;
|
||
@@ -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)
|
||
-{
|
||
- register 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 44b843a74b342d61..5d1bf39fc7280d3b 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>
|
||
@@ -29,7 +25,7 @@ static const char rcsid[] = "$BINDId: ns_samedomain.c,v 8.9 1999/10/15 21:06:51
|
||
* Check whether a name belongs to a domain.
|
||
*
|
||
* Inputs:
|
||
- *\li a - the domain whose ancestory is being verified
|
||
+ *\li a - the domain whose ancestry is being verified
|
||
*\li b - the potential ancestor we're checking against
|
||
*
|
||
* Return:
|
||
diff --git a/resolv/ns_ttl.c b/resolv/ns_ttl.c
|
||
index d4c98bcf3ae2757d..079948790b94b05e 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 7041e5282ebae4ed..9a1d3f7fdc960e54 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 7f735f51ffb69f19..7a5c39dc20f6ebb8 100644
|
||
--- a/resolv/nss_dns/dns-canon.c
|
||
+++ b/resolv/nss_dns/dns-canon.c
|
||
@@ -1,4 +1,4 @@
|
||
-/* Copyright (C) 2004, 2006, 2008 Free Software Foundation, Inc.
|
||
+/* Copyright (C) 2004-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
Contributed by Ulrich Drepper <drepper@redhat.com>, 2004.
|
||
|
||
@@ -20,9 +20,11 @@
|
||
#include <netdb.h>
|
||
#include <resolv.h>
|
||
#include <stdlib.h>
|
||
+#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
|
||
@@ -57,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.
|
||
@@ -102,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);
|
||
@@ -136,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:
|
||
@@ -150,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 7fc154db5d3130a3..1e85e4f08ffc8600 100644
|
||
--- a/resolv/nss_dns/dns-host.c
|
||
+++ b/resolv/nss_dns/dns-host.c
|
||
@@ -1,4 +1,4 @@
|
||
-/* Copyright (C) 1996-2012 Free Software Foundation, Inc.
|
||
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||
|
||
@@ -78,12 +78,13 @@
|
||
#include <stdlib.h>
|
||
#include <stddef.h>
|
||
#include <string.h>
|
||
-#include <sys/syslog.h>
|
||
|
||
#include "nsswitch.h"
|
||
+#include <arpa/nameser.h>
|
||
|
||
/* Get implementeation for some internal functions. */
|
||
#include <resolv/resolv-internal.h>
|
||
+#include <resolv/resolv_context.h>
|
||
#include <resolv/mapv4v6addr.h>
|
||
#include <resolv/mapv4v6hostent.h>
|
||
|
||
@@ -100,10 +101,6 @@
|
||
#endif
|
||
#define MAXHOSTNAMELEN 256
|
||
|
||
-static const char AskedForGot[] = "\
|
||
-gethostby*.getanswer: asked for \"%s\", got \"%s\"";
|
||
-
|
||
-
|
||
/* We need this time later. */
|
||
typedef union querybuf
|
||
{
|
||
@@ -111,14 +108,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,
|
||
@@ -132,19 +123,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;
|
||
@@ -158,9 +185,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;
|
||
@@ -185,13 +209,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)
|
||
@@ -223,10 +247,10 @@ _nss_dns_gethostbyname3_r (const char *name, int af, struct hostent *result,
|
||
by having the RES_USE_INET6 bit in _res.options set, we try
|
||
another lookup. */
|
||
if (af == AF_INET6 && res_use_inet6 ())
|
||
- n = __libc_res_nsearch (&_res, name, C_IN, T_A, host_buffer.buf->buf,
|
||
- host_buffer.buf != orig_host_buffer
|
||
- ? MAXPACKET : 1024, &host_buffer.ptr,
|
||
- NULL, NULL, NULL, NULL);
|
||
+ 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)
|
||
{
|
||
@@ -241,14 +265,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,
|
||
@@ -265,15 +288,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_use_inet6 ())
|
||
- status = _nss_dns_gethostbyname3_r (name, AF_INET6, result, buffer,
|
||
- buflen, errnop, h_errnop, NULL, NULL);
|
||
+ 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;
|
||
}
|
||
|
||
@@ -283,8 +312,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.
|
||
@@ -294,7 +328,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;
|
||
}
|
||
@@ -313,9 +347,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,
|
||
@@ -358,6 +392,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;
|
||
}
|
||
|
||
@@ -401,7 +436,7 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
|
||
buffer += pad;
|
||
buflen = buflen > pad ? buflen - pad : 0;
|
||
|
||
- if (__builtin_expect (buflen < sizeof (struct host_data), 0))
|
||
+ if (__glibc_unlikely (buflen < sizeof (struct host_data)))
|
||
{
|
||
*errnop = ERANGE;
|
||
*h_errnop = NETDB_INTERNAL;
|
||
@@ -410,8 +445,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
|
||
@@ -436,12 +476,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;
|
||
}
|
||
|
||
@@ -454,19 +496,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 (__builtin_expect (_res.options & RES_USEBSTRING, 0))
|
||
- {
|
||
- 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--)
|
||
{
|
||
@@ -483,37 +512,28 @@ _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;
|
||
@@ -521,6 +541,7 @@ _nss_dns_gethostbyaddr2_r (const void *addr, socklen_t len, int af,
|
||
host_data->h_addr_ptrs[0] = (char *) host_data->host_addr;
|
||
host_data->h_addr_ptrs[1] = NULL;
|
||
*h_errnop = NETDB_SUCCESS;
|
||
+ __resolv_context_put (ctx);
|
||
return NSS_STATUS_SUCCESS;
|
||
}
|
||
hidden_def (_nss_dns_gethostbyaddr2_r)
|
||
@@ -535,26 +556,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;
|
||
@@ -579,10 +601,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)
|
||
{
|
||
@@ -593,7 +615,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||
char *h_addr_ptrs[0];
|
||
} *host_data;
|
||
int linebuflen;
|
||
- register const HEADER *hp;
|
||
+ const HEADER *hp;
|
||
const u_char *end_of_message, *cp;
|
||
int n, ancount, qdcount;
|
||
int haveanswer, had_error;
|
||
@@ -606,7 +628,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||
uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct host_data);
|
||
buffer += pad;
|
||
buflen = buflen > pad ? buflen - pad : 0;
|
||
- if (__builtin_expect (buflen < sizeof (struct host_data), 0))
|
||
+ if (__glibc_unlikely (buflen < sizeof (struct host_data)))
|
||
{
|
||
/* The buffer is too small. */
|
||
too_small:
|
||
@@ -643,7 +665,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;
|
||
@@ -657,7 +679,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;
|
||
@@ -666,13 +688,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)
|
||
@@ -714,20 +742,20 @@ 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;
|
||
}
|
||
|
||
- if (__builtin_expect (n < 0 || (*name_ok) (bp) == 0, 0))
|
||
+ if (__glibc_unlikely (n < 0 || (*name_ok) (bp) == 0))
|
||
{
|
||
++had_error;
|
||
continue;
|
||
}
|
||
cp += n; /* name */
|
||
|
||
- if (__builtin_expect (cp + 10 > end_of_message, 0))
|
||
+ if (__glibc_unlikely (cp + 10 > end_of_message))
|
||
{
|
||
++had_error;
|
||
continue;
|
||
@@ -741,7 +769,15 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||
cp += INT32SZ; /* TTL */
|
||
n = __ns_get16 (cp);
|
||
cp += INT16SZ; /* len */
|
||
- if (__builtin_expect (class != C_IN, 0))
|
||
+
|
||
+ if (end_of_message - cp < n)
|
||
+ {
|
||
+ /* RDATA extends beyond the end of the packet. */
|
||
+ ++had_error;
|
||
+ continue;
|
||
+ }
|
||
+
|
||
+ if (__glibc_unlikely (class != C_IN))
|
||
{
|
||
/* XXX - debug? syslog? */
|
||
cp += n;
|
||
@@ -757,7 +793,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||
if (ap >= &host_data->aliases[MAX_NR_ALIASES - 1])
|
||
continue;
|
||
n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
|
||
- if (__builtin_expect (n < 0 || (*name_ok) (tbuf) == 0, 0))
|
||
+ if (__glibc_unlikely (n < 0 || (*name_ok) (tbuf) == 0))
|
||
{
|
||
++had_error;
|
||
continue;
|
||
@@ -766,7 +802,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;
|
||
@@ -775,9 +811,9 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||
linebuflen -= n;
|
||
/* Get canonical name. */
|
||
n = strlen (tbuf) + 1; /* For the \0. */
|
||
- if (__builtin_expect (n > linebuflen, 0))
|
||
+ if (__glibc_unlikely (n > linebuflen))
|
||
goto too_small;
|
||
- if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
|
||
+ if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
|
||
{
|
||
++had_error;
|
||
continue;
|
||
@@ -795,7 +831,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||
*ttlp = ttl;
|
||
|
||
n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
|
||
- if (__builtin_expect (n < 0 || res_dnok (tbuf) == 0, 0))
|
||
+ if (__glibc_unlikely (n < 0 || res_dnok (tbuf) == 0))
|
||
{
|
||
++had_error;
|
||
continue;
|
||
@@ -803,9 +839,9 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||
cp += n;
|
||
/* Get canonical name. */
|
||
n = strlen (tbuf) + 1; /* For the \0. */
|
||
- if (__builtin_expect (n > linebuflen, 0))
|
||
+ if (__glibc_unlikely (n > linebuflen))
|
||
goto too_small;
|
||
- if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
|
||
+ if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
|
||
{
|
||
++had_error;
|
||
continue;
|
||
@@ -818,16 +854,8 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||
|
||
if (type == T_A && qtype == T_AAAA && map)
|
||
have_to_map = 1;
|
||
- else if (__builtin_expect (type != qtype, 0))
|
||
+ 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++ ? */
|
||
}
|
||
@@ -835,9 +863,8 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||
switch (type)
|
||
{
|
||
case T_PTR:
|
||
- if (__builtin_expect (strcasecmp (tname, bp) != 0, 0))
|
||
+ if (__glibc_unlikely (strcasecmp (tname, bp) != 0))
|
||
{
|
||
- syslog (LOG_NOTICE | LOG_AUTH, AskedForGot, qname, bp);
|
||
cp += n;
|
||
continue; /* XXX - had_error++ ? */
|
||
}
|
||
@@ -846,65 +873,40 @@ 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;
|
||
}
|
||
|
||
- if (__builtin_expect (n < 0 || res_hnok (bp) == 0, 0))
|
||
+ if (__glibc_unlikely (n < 0 || res_hnok (bp) == 0))
|
||
{
|
||
++had_error;
|
||
break;
|
||
}
|
||
if (ttlp != NULL && ttl < *ttlp)
|
||
*ttlp = ttl;
|
||
-#if MULTI_PTRS_ARE_ALIASES
|
||
- cp += n;
|
||
- if (haveanswer == 0)
|
||
- result->h_name = bp;
|
||
- else if (ap < &host_data->aliases[MAXALIASES-1])
|
||
- *ap++ = bp;
|
||
- else
|
||
- n = -1;
|
||
- if (n != -1)
|
||
- {
|
||
- n = strlen (bp) + 1; /* for the \0 */
|
||
- if (__builtin_expect (n, 0) >= MAXHOSTNAMELEN)
|
||
- {
|
||
- ++had_error;
|
||
- break;
|
||
- }
|
||
- bp += n;
|
||
- linebuflen -= n;
|
||
- }
|
||
- break;
|
||
-#else
|
||
+ /* 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 (__builtin_expect (n >= MAXHOSTNAMELEN, 0))
|
||
- {
|
||
- ++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;
|
||
-#endif
|
||
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;
|
||
@@ -912,7 +914,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||
}
|
||
if (!haveanswer)
|
||
{
|
||
- register int nn;
|
||
+ int nn;
|
||
|
||
/* We compose a single hostent out of the entire chain of
|
||
entries, so the TTL of the hostent is essentially the lowest
|
||
@@ -930,7 +932,7 @@ getanswer_r (const querybuf *answer, int anslen, const char *qname, int qtype,
|
||
linebuflen -= sizeof (align) - ((u_long) bp % sizeof (align));
|
||
bp += sizeof (align) - ((u_long) bp % sizeof (align));
|
||
|
||
- if (__builtin_expect (n > linebuflen, 0))
|
||
+ if (__glibc_unlikely (n > linebuflen))
|
||
goto too_small;
|
||
bp = __mempcpy (*hap++ = bp, cp, n);
|
||
cp += n;
|
||
@@ -947,15 +949,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)
|
||
{
|
||
@@ -1001,7 +1002,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||
int qdcount = ntohs (hp->qdcount);
|
||
const u_char *cp = answer->buf + HFIXEDSZ;
|
||
const u_char *end_of_message = answer->buf + anslen;
|
||
- if (__builtin_expect (qdcount != 1, 0))
|
||
+ if (__glibc_unlikely (qdcount != 1))
|
||
{
|
||
*h_errnop = NO_RECOVERY;
|
||
return NSS_STATUS_UNAVAIL;
|
||
@@ -1014,7 +1015,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;
|
||
@@ -1025,13 +1026,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;
|
||
@@ -1053,12 +1060,12 @@ 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;
|
||
}
|
||
- if (__builtin_expect (n < 0 || res_hnok (buffer) == 0, 0))
|
||
+ if (__glibc_unlikely (n < 0 || res_hnok (buffer) == 0))
|
||
{
|
||
++had_error;
|
||
continue;
|
||
@@ -1072,7 +1079,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||
|
||
cp += n; /* name */
|
||
|
||
- if (__builtin_expect (cp + 10 > end_of_message, 0))
|
||
+ if (__glibc_unlikely (cp + 10 > end_of_message))
|
||
{
|
||
++had_error;
|
||
continue;
|
||
@@ -1087,6 +1094,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;
|
||
@@ -1102,7 +1116,7 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||
*ttlp = ttl;
|
||
|
||
n = dn_expand (answer->buf, end_of_message, cp, tbuf, sizeof tbuf);
|
||
- if (__builtin_expect (n < 0 || res_hnok (tbuf) == 0, 0))
|
||
+ if (__glibc_unlikely (n < 0 || res_hnok (tbuf) == 0))
|
||
{
|
||
++had_error;
|
||
continue;
|
||
@@ -1119,9 +1133,9 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
|
||
}
|
||
|
||
n = strlen (tbuf) + 1;
|
||
- if (__builtin_expect (n > buflen, 0))
|
||
+ if (__glibc_unlikely (n > buflen))
|
||
goto too_small;
|
||
- if (__builtin_expect (n >= MAXHOSTNAMELEN, 0))
|
||
+ if (__glibc_unlikely (n >= MAXHOSTNAMELEN))
|
||
{
|
||
++had_error;
|
||
continue;
|
||
@@ -1134,32 +1148,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 (__builtin_expect (type != T_A && type != T_AAAA, 0))
|
||
-#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
|
||
@@ -1167,8 +1174,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;
|
||
@@ -1193,12 +1199,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;
|
||
@@ -1259,8 +1259,8 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
|
||
expected application behaviour. Some of the synthesized responses
|
||
aren't very well thought out and sometimes appear to imply that
|
||
IPv4 responses are always answer 1, and IPv6 responses are always
|
||
- answer 2, but that's not true (see the implemetnation of send_dg
|
||
- and send_vc to see response can arrive in any order, particlarly
|
||
+ answer 2, but that's not true (see the implementation of send_dg
|
||
+ and send_vc to see response can arrive in any order, particularly
|
||
for UDP). However, we expect it holds roughly enough of the time
|
||
that this code works, but certainly needs to be fixed to make this
|
||
a more robust implementation.
|
||
@@ -1297,12 +1297,12 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
|
||
----------------------------------------------
|
||
|
||
[1] If the first response is a success we return success.
|
||
- This ignores the state of the second answer and in fact
|
||
- incorrectly sets errno and h_errno to that of the second
|
||
+ This ignores the state of the second answer and in fact
|
||
+ incorrectly sets errno and h_errno to that of the second
|
||
answer. However because the response is a success we ignore
|
||
*errnop and *h_errnop (though that means you touched errno on
|
||
- success). We are being conservative here and returning the
|
||
- likely IPv4 response in the first answer as a success.
|
||
+ success). We are being conservative here and returning the
|
||
+ likely IPv4 response in the first answer as a success.
|
||
|
||
[2] If the first response is a recoverable TRYAGAIN we return
|
||
that instead of looking at the second response. The
|
||
@@ -1356,7 +1356,7 @@ gaih_getanswer (const querybuf *answer1, int anslen1, const querybuf *answer2,
|
||
if (status != NSS_STATUS_SUCCESS && status2 != NSS_STATUS_NOTFOUND)
|
||
status = status2;
|
||
/* Do not return a truncated second response (unless it was
|
||
- unavoidable e.g. unrecoverable TRYAGAIN). */
|
||
+ unavoidable e.g. unrecoverable TRYAGAIN). */
|
||
if (status == NSS_STATUS_SUCCESS
|
||
&& (status2 == NSS_STATUS_TRYAGAIN
|
||
&& *errnop == ERANGE && *h_errnop != NO_RECOVERY))
|
||
diff --git a/resolv/nss_dns/dns-network.c b/resolv/nss_dns/dns-network.c
|
||
index ccf871c8e4cb25e0..f190eb2225d39d16 100644
|
||
--- a/resolv/nss_dns/dns-network.c
|
||
+++ b/resolv/nss_dns/dns-network.c
|
||
@@ -1,5 +1,4 @@
|
||
-/* Copyright (C) 1996,1997,1998,1999,2002,2004,2007,2008,2011
|
||
- Free Software Foundation, Inc.
|
||
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
Extended from original form by Ulrich Drepper <drepper@cygnus.com>, 1996.
|
||
|
||
@@ -62,9 +61,14 @@
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
+#include <stdint.h>
|
||
+#include <stddef.h>
|
||
|
||
#include "nsswitch.h"
|
||
#include <arpa/inet.h>
|
||
+#include <arpa/nameser.h>
|
||
+#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,
|
||
@@ -120,19 +117,26 @@ _nss_dns_getnetbyname_r (const char *name, struct netent *result,
|
||
int anslen;
|
||
enum nss_status status;
|
||
|
||
- 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;
|
||
+ }
|
||
|
||
net_buffer.buf = orig_net_buffer = (querybuf *) alloca (1024);
|
||
|
||
- anslen = __libc_res_nsearch (&_res, name, C_IN, T_PTR, net_buffer.buf->buf,
|
||
- 1024, &net_buffer.ptr, NULL, NULL, NULL, NULL);
|
||
+ 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)
|
||
@@ -143,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;
|
||
}
|
||
|
||
@@ -170,8 +175,13 @@ _nss_dns_getnetbyaddr_r (uint32_t net, int type, struct netent *result,
|
||
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;
|
||
for (cnt = 4; net2 != 0; net2 >>= 8)
|
||
@@ -201,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. */
|
||
@@ -210,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)
|
||
@@ -230,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,
|
||
@@ -265,7 +274,7 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
|
||
uintptr_t pad = -(uintptr_t) buffer % __alignof__ (struct net_data);
|
||
buffer += pad;
|
||
|
||
- if (__builtin_expect (buflen < sizeof (*net_data) + pad, 0))
|
||
+ if (__glibc_unlikely (buflen < sizeof (*net_data) + pad))
|
||
{
|
||
/* The buffer is too small. */
|
||
too_small:
|
||
@@ -326,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)
|
||
@@ -345,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)
|
||
{
|
||
@@ -370,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;
|
||
@@ -381,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)
|
||
@@ -395,8 +418,8 @@ getanswer_r (const querybuf *answer, int anslen, struct netent *result,
|
||
|
||
case BYNAME:
|
||
{
|
||
- char **ap = result->n_aliases++;
|
||
- while (*ap != NULL)
|
||
+ char **ap;
|
||
+ for (ap = result->n_aliases; *ap != NULL; ++ap)
|
||
{
|
||
/* Check each alias name for being of the forms:
|
||
4.3.2.1.in-addr.arpa = net 1.2.3.4
|
||
diff --git a/resolv/res-close.c b/resolv/res-close.c
|
||
new file mode 100644
|
||
index 0000000000000000..21f038c2c77f7375
|
||
--- /dev/null
|
||
+++ b/resolv/res-close.c
|
||
@@ -0,0 +1,143 @@
|
||
+/* Deallocation functions for the resolver state.
|
||
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+/*
|
||
+ * Copyright (c) 1985, 1989, 1993
|
||
+ * The Regents of the University of California. All rights reserved.
|
||
+ *
|
||
+ * Redistribution and use in source and binary forms, with or without
|
||
+ * modification, are permitted provided that the following conditions
|
||
+ * are met:
|
||
+ * 1. Redistributions of source code must retain the above copyright
|
||
+ * notice, this list of conditions and the following disclaimer.
|
||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||
+ * notice, this list of conditions and the following disclaimer in the
|
||
+ * documentation and/or other materials provided with the distribution.
|
||
+ * 4. Neither the name of the University nor the names of its contributors
|
||
+ * may be used to endorse or promote products derived from this software
|
||
+ * without specific prior written permission.
|
||
+ *
|
||
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||
+ * SUCH DAMAGE.
|
||
+ */
|
||
+
|
||
+/*
|
||
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||
+ *
|
||
+ * Permission to use, copy, modify, and distribute this software for any
|
||
+ * purpose with or without fee is hereby granted, provided that the above
|
||
+ * copyright notice and this permission notice appear in all copies, and that
|
||
+ * the name of Digital Equipment Corporation not be used in advertising or
|
||
+ * publicity pertaining to distribution of the document or software without
|
||
+ * specific, written prior permission.
|
||
+ *
|
||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||
+ * SOFTWARE.
|
||
+ */
|
||
+
|
||
+/*
|
||
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
|
||
+ *
|
||
+ * Permission to use, copy, modify, and distribute this software for any
|
||
+ * purpose with or without fee is hereby granted, provided that the above
|
||
+ * copyright notice and this permission notice appear in all copies.
|
||
+ *
|
||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||
+ * SOFTWARE.
|
||
+ */
|
||
+
|
||
+#include <resolv-internal.h>
|
||
+#include <resolv_context.h>
|
||
+#include <resolv_conf.h>
|
||
+#include <not-cancel.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_not_cancel_no_status (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_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;
|
||
+ }
|
||
+ }
|
||
+ 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. */
|
||
+static void __attribute__ ((section ("__libc_thread_freeres_fn")))
|
||
+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;
|
||
+}
|
||
+text_set_element (__libc_thread_subfreeres, res_thread_freeres);
|
||
+text_set_element (__libc_subfreeres, res_thread_freeres);
|
||
diff --git a/resolv/res-state.c b/resolv/res-state.c
|
||
index 3a2a4d5649c9af3f..4d4245459bfc68ca 100644
|
||
--- a/resolv/res-state.c
|
||
+++ b/resolv/res-state.c
|
||
@@ -1,4 +1,4 @@
|
||
-/* Copyright (C) 1996, 97, 98, 2002, 2003, 2011 Free Software Foundation, Inc.
|
||
+/* Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
diff --git a/resolv/res_comp.c b/resolv/res_comp.c
|
||
index c7212fab11deda78..ffb2ed59147d3680 100644
|
||
--- a/resolv/res_comp.c
|
||
+++ b/resolv/res_comp.c
|
||
@@ -64,11 +64,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>
|
||
@@ -81,7 +76,7 @@ static const char rcsid[] = "$BINDId: res_comp.c,v 8.15 1999/10/13 16:39:39 vixi
|
||
|
||
/*
|
||
* Expand compressed domain name 'comp_dn' to full domain name.
|
||
- * 'msg' is a pointer to the begining of the message,
|
||
+ * 'msg' is a pointer to the beginning of the message,
|
||
* 'eomorig' points to the first location after the message,
|
||
* 'exp_dn' is a pointer to a buffer of size 'length' for the result.
|
||
* Return size of compressed name or -1 if there was an error.
|
||
@@ -233,7 +228,6 @@ res_dnok(const char *dn) {
|
||
}
|
||
libresolv_hidden_def (res_dnok)
|
||
|
||
-#ifdef BIND_4_COMPAT
|
||
/*
|
||
* This module must export the following externally-visible symbols:
|
||
* ___putlong
|
||
@@ -246,11 +240,8 @@ void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); }
|
||
libresolv_hidden_def (__putlong)
|
||
void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); }
|
||
libresolv_hidden_def (__putshort)
|
||
-#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*/
|
||
|
||
|
||
#include <shlib-compat.h>
|
||
diff --git a/resolv/res_data.c b/resolv/res_data.c
|
||
index 1beea1dc4fb8c2c4..2cafd3805548d8e4 100644
|
||
--- a/resolv/res_data.c
|
||
+++ b/resolv/res_data.c
|
||
@@ -1,3 +1,21 @@
|
||
+/* Miscellaneous definitions for libresolv.
|
||
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
/*
|
||
* Copyright (c) 1995-1999 by Internet Software Consortium.
|
||
*
|
||
@@ -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 6549e4ba5ee77f93..919b86e2b37dc150 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>
|
||
@@ -111,6 +106,7 @@ static const char rcsid[] = "$BINDId: res_debug.c,v 8.34 2000/02/29 05:30:55 vix
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <time.h>
|
||
+#include <shlib-compat.h>
|
||
|
||
#ifdef SPRINTF_CHAR
|
||
# define SPRINTF(x) strlen(sprintf/**/x)
|
||
@@ -120,6 +116,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 +161,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 +172,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 +190,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 +236,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 +264,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 +289,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 +299,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) {
|
||
@@ -307,11 +353,8 @@ p_cdname(const u_char *cp, const u_char *msg, FILE *file) {
|
||
length supplied). */
|
||
|
||
const u_char *
|
||
-p_fqnname(cp, msg, msglen, name, namelen)
|
||
- const u_char *cp, *msg;
|
||
- int msglen;
|
||
- char *name;
|
||
- int namelen;
|
||
+p_fqnname (const u_char *cp, const u_char *msg, int msglen, char *name,
|
||
+ int namelen)
|
||
{
|
||
int n, newlen;
|
||
|
||
@@ -350,13 +393,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)
|
||
|
||
@@ -364,93 +407,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)
|
||
|
||
@@ -458,22 +483,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
|
||
@@ -538,7 +563,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;
|
||
|
||
@@ -572,9 +597,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 "usevc";
|
||
- case RES_PRIMARY: return "primry(unimpl)";
|
||
+ case RES_USEVC: return "use-vc";
|
||
case RES_IGNTC: return "igntc";
|
||
case RES_RECURSE: return "recurs";
|
||
case RES_DEFNAMES: return "defnam";
|
||
@@ -582,13 +605,15 @@ p_option(u_long option) {
|
||
case RES_DNSRCH: return "dnsrch";
|
||
case RES_INSECURE1: return "insecure1";
|
||
case RES_INSECURE2: return "insecure2";
|
||
+ case RES_NOALIASES: return "noaliases";
|
||
case DEPRECATED_RES_USE_INET6: return "inet6";
|
||
case RES_ROTATE: return "rotate";
|
||
- case RES_NOCHECKNAME: return "no-check-names";
|
||
- case RES_USEBSTRING: return "ip6-bytstring";
|
||
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);
|
||
@@ -784,9 +809,7 @@ latlon2ul (const char **latlonstrptr, int *which)
|
||
/* converts a zone file representation in a string to an RDATA on-the-wire
|
||
* representation. */
|
||
int
|
||
-loc_aton(ascii, binary)
|
||
- const char *ascii;
|
||
- u_char *binary;
|
||
+loc_aton (const char *ascii, u_char *binary)
|
||
{
|
||
const char *cp, *maxcp;
|
||
u_char *bcp;
|
||
@@ -895,9 +918,7 @@ loc_aton(ascii, binary)
|
||
|
||
/* takes an on-the-wire LOC RR and formats it in a human readable format. */
|
||
const char *
|
||
-loc_ntoa(binary, ascii)
|
||
- const u_char *binary;
|
||
- char *ascii;
|
||
+loc_ntoa (const u_char *binary, char *ascii)
|
||
{
|
||
static const char error[] = "?";
|
||
static char tmpbuf[sizeof
|
||
@@ -1041,13 +1062,8 @@ p_secstodate (u_long secs) {
|
||
time_t clock = secs;
|
||
struct tm *time;
|
||
|
||
-#ifdef HAVE_TIME_R
|
||
struct tm timebuf;
|
||
-
|
||
- time = gmtime_r(&clock, &timebuf);
|
||
-#else
|
||
- time = gmtime(&clock);
|
||
-#endif
|
||
+ time = __gmtime_r(&clock, &timebuf);
|
||
time->tm_year += 1900;
|
||
time->tm_mon += 1;
|
||
sprintf(output, "%04d%02d%02d%02d%02d%02d",
|
||
diff --git a/resolv/res_debug.h b/resolv/res_debug.h
|
||
deleted file mode 100644
|
||
index 4a0aa99ab48f362c..0000000000000000
|
||
--- 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 66383deea81cf3eb..8fc06e9abdc084f6 100644
|
||
--- a/resolv/res_hconf.c
|
||
+++ b/resolv/res_hconf.c
|
||
@@ -1,5 +1,4 @@
|
||
-/* Copyright (C) 1993,1995-2006,2007,2009,2011
|
||
- Free Software Foundation, Inc.
|
||
+/* Copyright (C) 1993-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
Contributed by David Mosberger (davidm@azstarnet.com).
|
||
|
||
@@ -22,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)
|
||
*/
|
||
@@ -42,16 +38,20 @@
|
||
#include <sys/ioctl.h>
|
||
#include <unistd.h>
|
||
#include <netinet/in.h>
|
||
-#include <bits/libc-lock.h>
|
||
+#include <libc-lock.h>
|
||
#include "ifreq.h"
|
||
#include "res_hconf.h"
|
||
#include <wchar.h>
|
||
+#include <atomic.h>
|
||
+
|
||
+#if IS_IN (libc)
|
||
+# define fgets_unlocked __fgets_unlocked
|
||
+#endif
|
||
|
||
#define _PATH_HOSTCONF "/etc/host.conf"
|
||
|
||
/* Environment vars that all user to override default behavior: */
|
||
#define ENV_HOSTCONF "RESOLV_HOST_CONF"
|
||
-#define ENV_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"
|
||
@@ -61,7 +61,6 @@ enum parse_cbs
|
||
{
|
||
CB_none,
|
||
CB_arg_trimdomain_list,
|
||
- CB_arg_spoof,
|
||
CB_arg_bool
|
||
};
|
||
|
||
@@ -74,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}
|
||
};
|
||
|
||
@@ -160,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)
|
||
@@ -257,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
|
||
@@ -321,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);
|
||
@@ -344,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);
|
||
}
|
||
|
||
|
||
@@ -360,6 +329,7 @@ _res_hconf_init (void)
|
||
|
||
|
||
#if IS_IN (libc)
|
||
+# if defined SIOCGIFCONF && defined SIOCGIFNETMASK
|
||
/* List of known interfaces. */
|
||
libc_freeres_ptr (
|
||
static struct netaddr
|
||
@@ -374,6 +344,7 @@ static struct netaddr
|
||
} ipv4;
|
||
} u;
|
||
} *ifaddrs);
|
||
+# endif
|
||
|
||
/* Reorder addresses returned in a hostent such that the first address
|
||
is an address on the local subnet, if there is such an address.
|
||
@@ -386,9 +357,14 @@ _res_hconf_reorder_addrs (struct hostent *hp)
|
||
{
|
||
#if defined SIOCGIFCONF && defined SIOCGIFNETMASK
|
||
int i, j;
|
||
- /* Number of interfaces. */
|
||
+ /* Number of interfaces. Also serves as a flag for the
|
||
+ double-checked locking idiom. */
|
||
static int num_ifs = -1;
|
||
- /* We need to protect the dynamic buffer handling. */
|
||
+ /* Local copy of num_ifs, for non-atomic access. */
|
||
+ int num_ifs_local;
|
||
+ /* We need to protect the dynamic buffer handling. The lock is only
|
||
+ acquired during initialization. Afterwards, a positive num_ifs
|
||
+ value indicates completed initialization. */
|
||
__libc_lock_define_initialized (static, lock);
|
||
|
||
/* Only reorder if we're supposed to. */
|
||
@@ -399,7 +375,10 @@ _res_hconf_reorder_addrs (struct hostent *hp)
|
||
if (hp->h_addrtype != AF_INET)
|
||
return;
|
||
|
||
- if (num_ifs <= 0)
|
||
+ /* This load synchronizes with the release MO store in the
|
||
+ initialization block below. */
|
||
+ num_ifs_local = atomic_load_acquire (&num_ifs);
|
||
+ if (num_ifs_local <= 0)
|
||
{
|
||
struct ifreq *ifr, *cur_ifr;
|
||
int sd, num, i;
|
||
@@ -409,16 +388,26 @@ _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;
|
||
|
||
/* Get lock. */
|
||
__libc_lock_lock (lock);
|
||
|
||
- /* Recheck, somebody else might have done the work by done. */
|
||
- if (num_ifs <= 0)
|
||
+ /* Recheck, somebody else might have done the work by now. No
|
||
+ ordering is required for the load because we have the lock,
|
||
+ and num_ifs is only updated under the lock. Also see (3) in
|
||
+ the analysis below. */
|
||
+ num_ifs_local = atomic_load_relaxed (&num_ifs);
|
||
+ if (num_ifs_local <= 0)
|
||
{
|
||
+ /* This is the only block which writes to num_ifs. It can
|
||
+ be executed several times (sequentially) if
|
||
+ initialization does not yield any interfaces, and num_ifs
|
||
+ remains zero. However, once we stored a positive value
|
||
+ in num_ifs below, this block cannot be entered again due
|
||
+ to the condition above. */
|
||
int new_num_ifs = 0;
|
||
|
||
/* Get a list of interfaces. */
|
||
@@ -434,18 +423,24 @@ _res_hconf_reorder_addrs (struct hostent *hp)
|
||
for (cur_ifr = ifr, i = 0; i < num;
|
||
cur_ifr = __if_nextreq (cur_ifr), ++i)
|
||
{
|
||
+ union
|
||
+ {
|
||
+ struct sockaddr sa;
|
||
+ struct sockaddr_in sin;
|
||
+ } ss;
|
||
+
|
||
if (cur_ifr->ifr_addr.sa_family != AF_INET)
|
||
continue;
|
||
|
||
ifaddrs[new_num_ifs].addrtype = AF_INET;
|
||
- ifaddrs[new_num_ifs].u.ipv4.addr =
|
||
- ((struct sockaddr_in *) &cur_ifr->ifr_addr)->sin_addr.s_addr;
|
||
+ ss.sa = cur_ifr->ifr_addr;
|
||
+ ifaddrs[new_num_ifs].u.ipv4.addr = ss.sin.sin_addr.s_addr;
|
||
|
||
if (__ioctl (sd, SIOCGIFNETMASK, cur_ifr) < 0)
|
||
continue;
|
||
|
||
- ifaddrs[new_num_ifs].u.ipv4.mask =
|
||
- ((struct sockaddr_in *) &cur_ifr->ifr_netmask)->sin_addr.s_addr;
|
||
+ ss.sa = cur_ifr->ifr_netmask;
|
||
+ ifaddrs[new_num_ifs].u.ipv4.mask = ss.sin.sin_addr.s_addr;
|
||
|
||
/* Now we're committed to this entry. */
|
||
++new_num_ifs;
|
||
@@ -461,7 +456,14 @@ _res_hconf_reorder_addrs (struct hostent *hp)
|
||
/* Release lock, preserve error value, and close socket. */
|
||
errno = save;
|
||
|
||
- num_ifs = new_num_ifs;
|
||
+ /* Advertise successful initialization if new_num_ifs is
|
||
+ positive (and no updates to ifaddrs are permitted after
|
||
+ that). Otherwise, num_ifs remains unchanged, at zero.
|
||
+ This store synchronizes with the initial acquire MO
|
||
+ load. */
|
||
+ atomic_store_release (&num_ifs, new_num_ifs);
|
||
+ /* Keep the local copy current, to save another load. */
|
||
+ num_ifs_local = new_num_ifs;
|
||
}
|
||
|
||
__libc_lock_unlock (lock);
|
||
@@ -469,15 +471,43 @@ _res_hconf_reorder_addrs (struct hostent *hp)
|
||
__close (sd);
|
||
}
|
||
|
||
- if (num_ifs == 0)
|
||
+ /* num_ifs_local cannot be negative because the if statement above
|
||
+ covered this case. It can still be zero if we just performed
|
||
+ initialization, but could not find any interfaces. */
|
||
+ if (num_ifs_local == 0)
|
||
return;
|
||
|
||
+ /* The code below accesses ifaddrs, so we need to ensure that the
|
||
+ initialization happens-before this point.
|
||
+
|
||
+ The actual initialization is sequenced-before the release store
|
||
+ to num_ifs, and sequenced-before the end of the critical section.
|
||
+
|
||
+ This means there are three possible executions:
|
||
+
|
||
+ (1) The thread that initialized the data also uses it, so
|
||
+ sequenced-before is sufficient to ensure happens-before.
|
||
+
|
||
+ (2) The release MO store of num_ifs synchronizes-with the acquire
|
||
+ MO load, and the acquire MO load is sequenced before the use
|
||
+ of the initialized data below.
|
||
+
|
||
+ (3) We enter the critical section, and the relaxed MO load of
|
||
+ num_ifs yields a positive value. The write to ifaddrs is
|
||
+ sequenced-before leaving the critical section. Leaving the
|
||
+ critical section happens-before we entered the critical
|
||
+ section ourselves, which means that the write to ifaddrs
|
||
+ happens-before this point.
|
||
+
|
||
+ Consequently, all potential writes to ifaddrs (and the data it
|
||
+ points to) happens-before this point. */
|
||
+
|
||
/* Find an address for which we have a direct connection. */
|
||
for (i = 0; hp->h_addr_list[i]; ++i)
|
||
{
|
||
struct in_addr *haddr = (struct in_addr *) hp->h_addr_list[i];
|
||
|
||
- for (j = 0; j < num_ifs; ++j)
|
||
+ 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;
|
||
diff --git a/resolv/res_hconf.h b/resolv/res_hconf.h
|
||
index 90c56eb61a87ba26..209f76a0d6ef8193 100644
|
||
--- a/resolv/res_hconf.h
|
||
+++ b/resolv/res_hconf.h
|
||
@@ -1,4 +1,4 @@
|
||
-/* Copyright (C) 1993, 1995-1998, 2006 Free Software Foundation, Inc.
|
||
+/* Copyright (C) 1993-2017 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 0ed74e0520131418..4e1f9fe8dea93e8a 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-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
/*
|
||
* Copyright (c) 1985, 1989, 1993
|
||
* The Regents of the University of California. All rights reserved.
|
||
@@ -64,19 +82,16 @@
|
||
* 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/resolv-internal.h>
|
||
+#include <res_hconf.h>
|
||
#include <stdio.h>
|
||
#include <stdio_ext.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
#include <unistd.h>
|
||
+#include <stdint.h>
|
||
#include <arpa/inet.h>
|
||
#include <arpa/nameser.h>
|
||
#include <net/if.h>
|
||
@@ -85,570 +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) {
|
||
- register FILE *fp;
|
||
- register char *cp, **pp;
|
||
- register int n;
|
||
- char buf[BUFSIZ];
|
||
- int nserv = 0; /* number of nameserver records read from file */
|
||
-#ifdef _LIBC
|
||
- int nservall = 0; /* number of NS records read, nserv IPv4 only */
|
||
-#endif
|
||
- 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->ndots = 1;
|
||
- statp->pfcode = 0;
|
||
- statp->_vcsock = -1;
|
||
- statp->_flags = 0;
|
||
- statp->qhook = NULL;
|
||
- statp->rhook = NULL;
|
||
- statp->_u._ext.nsinit = 0;
|
||
- statp->_u._ext.nscount = 0;
|
||
-#ifdef _LIBC
|
||
- statp->_u._ext.nscount6 = 0;
|
||
- for (n = 0; n < MAXNS; n++) {
|
||
- statp->_u._ext.nsaddrs[n] = NULL;
|
||
- statp->_u._ext.nsmap[n] = MAXNS;
|
||
- }
|
||
-#endif
|
||
-
|
||
- /* 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 */
|
||
-#ifdef _LIBC
|
||
- if (MATCH(buf, "nameserver") && nservall < MAXNS) {
|
||
-#else
|
||
- if (MATCH(buf, "nameserver") && nserv < MAXNS) {
|
||
-#endif
|
||
- 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
|
||
- nservall++;
|
||
- } 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 (__builtin_expect (el == NULL, 1))
|
||
- 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->_u._ext.nsaddrs[nservall] = sa6;
|
||
- statp->_u._ext.nssocks[nservall] = -1;
|
||
- statp->_u._ext.nsmap[nservall] = MAXNS + 1;
|
||
- nservall++;
|
||
- }
|
||
- }
|
||
-#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 = nservall;
|
||
-#ifdef _LIBC
|
||
- if (nservall - nserv > 0) {
|
||
- statp->_u._ext.nscount6 = nservall - nserv;
|
||
- /* 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, DEPRECATED_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. */
|
||
-static u_int32_t
|
||
-net_mask(in) /* XXX - should really use system's version of this */
|
||
- 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)
|
||
{
|
||
- register 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);
|
||
- }
|
||
-#ifdef _LIBC
|
||
- for (ns = 0; ns < MAXNS; ns++)
|
||
-#else
|
||
- for (ns = 0; ns < statp->_u._ext.nscount; ns++)
|
||
-#endif
|
||
- 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;
|
||
- }
|
||
- }
|
||
- statp->_u._ext.nsinit = 0;
|
||
+/* 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 48d3200b7e2cd913..9f2d3c3bd442bb38 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-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
/*
|
||
* Copyright (c) 1995-1999 by Internet Software Consortium.
|
||
*
|
||
@@ -21,99 +39,47 @@
|
||
#include <netinet/in.h>
|
||
#include <arpa/nameser.h>
|
||
#include <resolv.h>
|
||
-#include <bits/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
|
||
-
|
||
-int
|
||
-res_init(void) {
|
||
- extern int __res_vinit(res_state, int);
|
||
+#include <libc-lock.h>
|
||
+#include <resolv-internal.h>
|
||
|
||
- /*
|
||
- * 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();
|
||
-
|
||
- atomicinclock (lock);
|
||
- /* Request all threads to re-initialize their resolver states,
|
||
- resolv.conf might have changed. */
|
||
- atomicinc (__res_initstamp);
|
||
- atomicincunlock (lock);
|
||
-
|
||
- return (__res_vinit(&_res, 1));
|
||
-}
|
||
-
|
||
-/* Initialize resp if RES_INIT is not yet set or if res_init in some other
|
||
- thread requested re-initializing. */
|
||
int
|
||
-__res_maybe_init (res_state resp, int preinit)
|
||
+res_init (void)
|
||
{
|
||
- 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);
|
||
+ /* These three fields used to be statically initialized. This made
|
||
+ it hard to use this code in a shared library. It is necessary,
|
||
+ now that we're doing dynamic initialization here, that we
|
||
+ preserve the old semantics: if an application modifies one of
|
||
+ these three fields of _res before res_init is called,
|
||
+ res_init will not alter them. Of course, if an application is
|
||
+ setting them to _zero_ before calling res_init, hoping to
|
||
+ override what used to be the static default, we can't detect it
|
||
+ and unexpected results will follow. Zero for any of these fields
|
||
+ would make no sense, so one can safely assume that the
|
||
+ applications were already getting unexpected results.
|
||
+
|
||
+ _res.options is tricky since some apps were known to diddle the
|
||
+ bits before res_init was first called. We can't replicate that
|
||
+ semantic with dynamic initialization (they may have turned bits
|
||
+ off that are set in RES_DEFAULT). Our solution is to declare
|
||
+ such applications "broken". They could fool us by setting
|
||
+ RES_INIT but none do (yet). */
|
||
+ if (!_res.retrans)
|
||
+ _res.retrans = RES_TIMEOUT;
|
||
+ if (!_res.retry)
|
||
+ _res.retry = RES_DFLRETRY;
|
||
+ if (!(_res.options & RES_INIT))
|
||
+ _res.options = RES_DEFAULT;
|
||
+ else if (_res.nscount > 0)
|
||
+ __res_iclose (&_res, true); /* Close any VC sockets. */
|
||
+
|
||
+ /* This one used to initialize implicitly to zero, so unless the app
|
||
+ has set it to something in particular, we can randomize it *
|
||
+ now. */
|
||
+ if (!_res.id)
|
||
+ _res.id = res_randomid ();
|
||
+
|
||
+ 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
|
||
@@ -122,25 +88,22 @@ libc_hidden_def (__res_maybe_init)
|
||
This differs from plain `struct __res_state _res;' in that it doesn't
|
||
create a common definition, but a plain symbol that resides in .bss,
|
||
which can have an alias. */
|
||
-struct __res_state _res __attribute__((section (".bss")));
|
||
-
|
||
-#include <tls.h>
|
||
+struct __res_state _res __attribute__ ((nocommon));
|
||
|
||
#undef __resp
|
||
__thread struct __res_state *__resp = &_res;
|
||
extern __thread struct __res_state *__libc_resp
|
||
__attribute__ ((alias ("__resp"))) attribute_hidden;
|
||
|
||
+#include <shlib-compat.h>
|
||
+
|
||
/* We declare this with compat_symbol so that it's not
|
||
visible at link time. Programs must use the accessor functions. */
|
||
-#if defined SHARED && defined DO_VERSIONING
|
||
-# include <shlib-compat.h>
|
||
+#ifdef SHARED
|
||
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 2bc2d2497fdf5dfa..59fc5ab28c0faa66 100644
|
||
--- a/resolv/res_mkquery.c
|
||
+++ b/resolv/res_mkquery.c
|
||
@@ -1,3 +1,21 @@
|
||
+/* Creation of DNS query packets.
|
||
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
/*
|
||
* Copyright (c) 1985, 1993
|
||
* The Regents of the University of California. All rights reserved.
|
||
@@ -64,202 +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>
|
||
-# 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)
|
||
{
|
||
- register HEADER *hp;
|
||
- register u_char *cp;
|
||
- register 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 (__builtin_expect (n < 0, 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 (__builtin_expect (buflen < 1 + RRFIXEDSZ + datalen, 0))
|
||
- 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 57c679d6fca5d9dc..ebbe5a6a4ed86abe 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;
|
||
@@ -203,43 +198,25 @@ __libc_res_nquery(res_state statp,
|
||
goto again;
|
||
}
|
||
}
|
||
- if (__builtin_expect (n <= 0, 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
|
||
+ if (__glibc_unlikely (n <= 0)) {
|
||
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,20 +392,31 @@ __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++) {
|
||
+ 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;
|
||
|
||
- if (domain[0][0] == '\0' ||
|
||
- (domain[0][0] == '.' && domain[0][1] == '\0'))
|
||
+ /* __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
|
||
+ up with "name..", which won't resolve.
|
||
+ OTOH, passing it "" will result in "name.",
|
||
+ which has the intended effect for both
|
||
+ possible representations of the root
|
||
+ domain. */
|
||
+ if (dname[0] == '.')
|
||
+ dname++;
|
||
+ if (dname[0] == '\0')
|
||
root_on_list++;
|
||
|
||
- ret = __libc_res_nquerydomain(statp, name, *domain,
|
||
- 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);
|
||
@@ -487,15 +479,15 @@ __libc_res_nsearch(res_state statp,
|
||
}
|
||
|
||
/*
|
||
- * f the query has not already been tried as is then try it
|
||
+ * If the query has not already been tried as is then try it
|
||
* unless RES_NOTLDQUERY is set and there were no dots.
|
||
*/
|
||
if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0)
|
||
&& !(tried_as_is || root_on_list)) {
|
||
- ret = __libc_res_nquerydomain(statp, name, NULL, class, type,
|
||
- answer, anslen, answerp,
|
||
- answerp2, nanswerp2, resplen2,
|
||
- answerp2_malloced);
|
||
+ 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);
|
||
@@ -523,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,
|
||
@@ -532,42 +541,35 @@ 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,
|
||
- * removing a trailing dot from name if domain is NULL.
|
||
- */
|
||
+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) {
|
||
- /*
|
||
- * Check for trailing '.';
|
||
- * copy without '.' if present.
|
||
- */
|
||
n = strlen(name);
|
||
|
||
/* Decrement N prior to checking it against MAXDNAME
|
||
@@ -578,11 +580,7 @@ __libc_res_nquerydomain(res_state statp,
|
||
RES_SET_H_ERRNO(statp, NO_RECOVERY);
|
||
return (-1);
|
||
}
|
||
- if (name[n] == '.') {
|
||
- strncpy(nbuf, name, n);
|
||
- nbuf[n] = '\0';
|
||
- } else
|
||
- longname = name;
|
||
+ longname = name;
|
||
} else {
|
||
n = strlen(name);
|
||
d = strlen(domain);
|
||
@@ -592,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
|
||
@@ -605,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)
|
||
@@ -647,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 0000000000000000..e0dbe4c8ff259527
|
||
--- /dev/null
|
||
+++ b/resolv/res_randomid.c
|
||
@@ -0,0 +1,92 @@
|
||
+/* Legacy libresolv random number generator.
|
||
+ Copyright (C) 1995-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+/*
|
||
+ * Copyright (c) 1985, 1989, 1993
|
||
+ * The Regents of the University of California. All rights reserved.
|
||
+ *
|
||
+ * Redistribution and use in source and binary forms, with or without
|
||
+ * modification, are permitted provided that the following conditions
|
||
+ * are met:
|
||
+ * 1. Redistributions of source code must retain the above copyright
|
||
+ * notice, this list of conditions and the following disclaimer.
|
||
+ * 2. Redistributions in binary form must reproduce the above copyright
|
||
+ * notice, this list of conditions and the following disclaimer in the
|
||
+ * documentation and/or other materials provided with the distribution.
|
||
+ * 4. Neither the name of the University nor the names of its contributors
|
||
+ * may be used to endorse or promote products derived from this software
|
||
+ * without specific prior written permission.
|
||
+ *
|
||
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||
+ * SUCH DAMAGE.
|
||
+ */
|
||
+
|
||
+/*
|
||
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
|
||
+ *
|
||
+ * Permission to use, copy, modify, and distribute this software for any
|
||
+ * purpose with or without fee is hereby granted, provided that the above
|
||
+ * copyright notice and this permission notice appear in all copies, and that
|
||
+ * the name of Digital Equipment Corporation not be used in advertising or
|
||
+ * publicity pertaining to distribution of the document or software without
|
||
+ * specific, written prior permission.
|
||
+ *
|
||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
|
||
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
|
||
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
|
||
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||
+ * SOFTWARE.
|
||
+ */
|
||
+
|
||
+/*
|
||
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
|
||
+ *
|
||
+ * Permission to use, copy, modify, and distribute this software for any
|
||
+ * purpose with or without fee is hereby granted, provided that the above
|
||
+ * copyright notice and this permission notice appear in all copies.
|
||
+ *
|
||
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
|
||
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
|
||
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
|
||
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
|
||
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
|
||
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
|
||
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
||
+ * SOFTWARE.
|
||
+ */
|
||
+
|
||
+#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 0cb573857583dd93..b396aae03c9eeb6e 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-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
@@ -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,13 +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-diag.h>
|
||
+#include <hp-timing.h>
|
||
|
||
#if PACKETSZ > 65536
|
||
#define MAXPACKET PACKETSZ
|
||
@@ -120,14 +117,6 @@ static const char rcsid[] = "$BINDId: res_send.c,v 8.38 2000/03/30 20:16:51 vixi
|
||
#define MAXPACKET 65536
|
||
#endif
|
||
|
||
-
|
||
-#ifndef __ASSUME_SOCK_CLOEXEC
|
||
-static int __have_o_nonblock;
|
||
-#else
|
||
-# define __have_o_nonblock 0
|
||
-#endif
|
||
-
|
||
-
|
||
/* From ev_streams.c. */
|
||
|
||
static inline void
|
||
@@ -172,7 +161,7 @@ evSubTime(struct timespec *res, const struct timespec *minuend,
|
||
}
|
||
}
|
||
|
||
-static inline int
|
||
+static int
|
||
evCmpTime(struct timespec a, struct timespec b) {
|
||
long x = a.tv_sec - b.tv_sec;
|
||
|
||
@@ -181,7 +170,7 @@ evCmpTime(struct timespec a, struct timespec b) {
|
||
return (x < 0L ? (-1) : x > 0L ? (1) : (0));
|
||
}
|
||
|
||
-static inline void
|
||
+static void
|
||
evNowTime(struct timespec *res) {
|
||
struct timeval now;
|
||
|
||
@@ -192,14 +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, unsigned int);
|
||
static int send_vc(res_state, const u_char *, int,
|
||
const u_char *, int,
|
||
u_char **, int *, int *, int, u_char **,
|
||
@@ -209,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. */
|
||
@@ -237,20 +218,21 @@ res_ourserver_p(const res_state statp, const struct sockaddr_in6 *inp)
|
||
in_port_t port = in4p->sin_port;
|
||
in_addr_t addr = in4p->sin_addr.s_addr;
|
||
|
||
- for (ns = 0; ns < MAXNS; ns++) {
|
||
+ for (ns = 0; ns < statp->nscount; ns++) {
|
||
const struct sockaddr_in *srv =
|
||
- (struct sockaddr_in *)EXT(statp).nsaddrs[ns];
|
||
+ (struct sockaddr_in *) get_nsaddr (statp, ns);
|
||
|
||
- if ((srv != NULL) && (srv->sin_family == AF_INET) &&
|
||
+ if ((srv->sin_family == AF_INET) &&
|
||
(srv->sin_port == port) &&
|
||
(srv->sin_addr.s_addr == INADDR_ANY ||
|
||
srv->sin_addr.s_addr == addr))
|
||
return (1);
|
||
}
|
||
} else if (inp->sin6_family == AF_INET6) {
|
||
- for (ns = 0; ns < MAXNS; ns++) {
|
||
- const struct sockaddr_in6 *srv = EXT(statp).nsaddrs[ns];
|
||
- if ((srv != NULL) && (srv->sin6_family == AF_INET6) &&
|
||
+ for (ns = 0; ns < statp->nscount; ns++) {
|
||
+ const struct sockaddr_in6 *srv
|
||
+ = (struct sockaddr_in6 *) get_nsaddr (statp, ns);
|
||
+ if ((srv->sin6_family == AF_INET6) &&
|
||
(srv->sin6_port == inp->sin6_port) &&
|
||
!(memcmp(&srv->sin6_addr, &in6addr_any,
|
||
sizeof (struct in6_addr)) &&
|
||
@@ -262,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)
|
||
@@ -301,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)
|
||
@@ -357,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);
|
||
@@ -374,24 +421,6 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
|
||
return (-1);
|
||
}
|
||
|
||
-#ifdef USE_HOOKS
|
||
- if (__builtin_expect (statp->qhook || statp->rhook, 0)) {
|
||
- 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);
|
||
@@ -402,165 +431,68 @@ __libc_res_nsend(res_state statp, const u_char *buf, int buflen,
|
||
* If the ns_addr_list in the resolver context has changed, then
|
||
* invalidate our cached copy and the associated timing data.
|
||
*/
|
||
- if (EXT(statp).nsinit) {
|
||
+ if (EXT(statp).nscount != 0) {
|
||
int needclose = 0;
|
||
|
||
if (EXT(statp).nscount != statp->nscount)
|
||
needclose++;
|
||
else
|
||
- for (ns = 0; ns < MAXNS; ns++) {
|
||
- unsigned int map = EXT(statp).nsmap[ns];
|
||
- if (map < MAXNS
|
||
+ 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[map],
|
||
+ &statp->nsaddr_list[ns],
|
||
EXT(statp).nsaddrs[ns]))
|
||
{
|
||
needclose++;
|
||
break;
|
||
}
|
||
}
|
||
- if (needclose)
|
||
+ if (needclose) {
|
||
__res_iclose(statp, false);
|
||
+ EXT(statp).nscount = 0;
|
||
+ }
|
||
}
|
||
|
||
/*
|
||
* Maybe initialize our private copy of the ns_addr_list.
|
||
*/
|
||
- if (EXT(statp).nsinit == 0) {
|
||
- unsigned char map[MAXNS];
|
||
-
|
||
- memset (map, MAXNS, sizeof (map));
|
||
- for (n = 0; n < MAXNS; n++) {
|
||
- ns = EXT(statp).nsmap[n];
|
||
- if (ns < statp->nscount)
|
||
- map[ns] = n;
|
||
- else if (ns < MAXNS) {
|
||
- free(EXT(statp).nsaddrs[n]);
|
||
- EXT(statp).nsaddrs[n] = NULL;
|
||
- EXT(statp).nsmap[n] = MAXNS;
|
||
- }
|
||
- }
|
||
- n = statp->nscount - EXT(statp).nscount6;
|
||
- if (n > EXT(statp).nscount)
|
||
- for (n = EXT(statp).nscount, ns = 0;
|
||
- n < statp->nscount - EXT(statp).nscount6; n++) {
|
||
- while (ns < MAXNS
|
||
- && EXT(statp).nsmap[ns] != MAXNS)
|
||
- ns++;
|
||
- if (ns == MAXNS)
|
||
- break;
|
||
- EXT(statp).nsmap[ns] = n;
|
||
- map[n] = ns++;
|
||
- }
|
||
- EXT(statp).nscount = n;
|
||
- for (ns = 0; ns < EXT(statp).nscount; ns++) {
|
||
- n = map[ns];
|
||
- if (EXT(statp).nsaddrs[n] == NULL)
|
||
- EXT(statp).nsaddrs[n] =
|
||
+ if (EXT(statp).nscount == 0) {
|
||
+ for (unsigned int ns = 0; ns < statp->nscount; ns++) {
|
||
+ EXT(statp).nssocks[ns] = -1;
|
||
+ if (statp->nsaddr_list[ns].sin_family == 0)
|
||
+ continue;
|
||
+ if (EXT(statp).nsaddrs[ns] == NULL)
|
||
+ EXT(statp).nsaddrs[ns] =
|
||
malloc(sizeof (struct sockaddr_in6));
|
||
- if (EXT(statp).nsaddrs[n] != NULL) {
|
||
- memset (mempcpy(EXT(statp).nsaddrs[n],
|
||
+ if (EXT(statp).nsaddrs[ns] != NULL)
|
||
+ memset (mempcpy(EXT(statp).nsaddrs[ns],
|
||
&statp->nsaddr_list[ns],
|
||
sizeof (struct sockaddr_in)),
|
||
'\0',
|
||
sizeof (struct sockaddr_in6)
|
||
- sizeof (struct sockaddr_in));
|
||
- EXT(statp).nssocks[n] = -1;
|
||
- n++;
|
||
- }
|
||
}
|
||
- EXT(statp).nsinit = 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_in6 *ina;
|
||
- unsigned int map;
|
||
-
|
||
- n = 0;
|
||
- while (n < MAXNS && EXT(statp).nsmap[n] == MAXNS)
|
||
- n++;
|
||
- if (n < MAXNS) {
|
||
- ina = EXT(statp).nsaddrs[n];
|
||
- map = EXT(statp).nsmap[n];
|
||
- for (;;) {
|
||
- ns = n + 1;
|
||
- while (ns < MAXNS
|
||
- && EXT(statp).nsmap[ns] == MAXNS)
|
||
- ns++;
|
||
- if (ns == MAXNS)
|
||
- break;
|
||
- EXT(statp).nsaddrs[n] = EXT(statp).nsaddrs[ns];
|
||
- EXT(statp).nsmap[n] = EXT(statp).nsmap[ns];
|
||
- n = ns;
|
||
- }
|
||
- EXT(statp).nsaddrs[n] = ina;
|
||
- EXT(statp).nsmap[n] = map;
|
||
- }
|
||
- }
|
||
+ /* 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 < MAXNS; ns++)
|
||
+ for (unsigned ns_shift = 0; ns_shift < statp->nscount; ns_shift++)
|
||
{
|
||
-#ifdef DEBUG
|
||
- char tmpbuf[40];
|
||
-#endif
|
||
- struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
|
||
+ /* The actual name server index. This implements
|
||
+ RES_ROTATE. */
|
||
+ unsigned int ns = ns_shift + ns_offset;
|
||
+ if (ns >= statp->nscount)
|
||
+ ns -= statp->nscount;
|
||
|
||
- if (nsap == NULL)
|
||
- goto next_ns;
|
||
same_ns:
|
||
-#ifdef USE_HOOKS
|
||
- if (__builtin_expect (statp->qhook != NULL, 0)) {
|
||
- 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->sin6_family,
|
||
- (nsap->sin6_family == AF_INET6
|
||
- ? &nsap->sin6_addr
|
||
- : &((struct sockaddr_in *) nsap)->sin_addr),
|
||
- tmpbuf, sizeof (tmpbuf))));
|
||
-
|
||
- if (__builtin_expect (v_circuit, 0)) {
|
||
+ if (__glibc_unlikely (v_circuit)) {
|
||
/* Use VC; at most one attempt per server. */
|
||
try = statp->retry;
|
||
n = send_vc(statp, buf, buflen, buf2, buflen2,
|
||
@@ -589,22 +521,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,
|
||
@@ -614,38 +530,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 (__builtin_expect (statp->rhook, 0)) {
|
||
- 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*/
|
||
@@ -661,17 +545,56 @@ __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 unsigned char *buf, int buflen,
|
||
+ unsigned char *ans, int anssiz)
|
||
+{
|
||
+ return context_send_common
|
||
+ (__resolv_context_get_override (statp), buf, buflen, ans, anssiz);
|
||
+}
|
||
+
|
||
int
|
||
-res_nsend(res_state statp,
|
||
- const u_char *buf, int buflen, u_char *ans, int anssiz)
|
||
+res_send (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 (), buf, buflen, ans, anssiz);
|
||
}
|
||
-libresolv_hidden_def (res_nsend)
|
||
|
||
/* Private */
|
||
|
||
+static struct sockaddr *
|
||
+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
|
||
+ struct sockaddr, and user code did not update
|
||
+ statp->nsaddr_list[n]. */
|
||
+ return (struct sockaddr *) EXT(statp).nsaddrs[n];
|
||
+ else
|
||
+ /* User code updated statp->nsaddr_list[n], or statp->nsaddr_list[n]
|
||
+ has the same content as EXT(statp).nsaddrs[n]. */
|
||
+ return (struct sockaddr *) (void *) &statp->nsaddr_list[n];
|
||
+}
|
||
+
|
||
/* Close the resolver structure, assign zero to *RESPLEN2 if RESPLEN2
|
||
is not NULL, and return zero. */
|
||
static int
|
||
@@ -692,7 +615,7 @@ close_and_return_error (res_state statp, int *resplen2)
|
||
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
|
||
@@ -722,7 +645,7 @@ close_and_return_error (res_state statp, int *resplen2)
|
||
are needed but ANSCP is NULL, then as much of the response as
|
||
possible is read into the buffer, but the results will be truncated.
|
||
When truncation happens because of a small answer buffer the DNS
|
||
- packets header feild TC will bet set to 1, indicating a truncated
|
||
+ packets header field TC will bet set to 1, indicating a truncated
|
||
message and the rest of the socket data will be read and discarded.
|
||
|
||
Answers to the query are stored secondly in *ANSP2 up to a max of
|
||
@@ -765,15 +688,26 @@ send_vc(res_state statp,
|
||
const HEADER *hp = (HEADER *) buf;
|
||
const HEADER *hp2 = (HEADER *) buf2;
|
||
HEADER *anhp = (HEADER *) *ansp;
|
||
- struct sockaddr_in6 *nsap = EXT(statp).nsaddrs[ns];
|
||
- int truncating, connreset, resplen, n;
|
||
+ struct sockaddr *nsap = get_nsaddr (statp, ns);
|
||
+ int truncating, connreset, n;
|
||
+ /* On some architectures compiler might emit a warning indicating
|
||
+ 'resplen' may be used uninitialized. However if buf2 == NULL
|
||
+ then this code won't be executed; if buf2 != NULL, then first
|
||
+ time round the loop recvresp1 and recvresp2 will be 0 so this
|
||
+ code won't be executed but "thisresplenp = &resplen;" followed
|
||
+ by "*thisresplenp = rlen;" will be executed so that subsequent
|
||
+ times round the loop resplen has been initialized. So this is
|
||
+ a false-positive.
|
||
+ */
|
||
+ DIAG_PUSH_NEEDS_COMMENT;
|
||
+ DIAG_IGNORE_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
|
||
+ int resplen;
|
||
+ DIAG_POP_NEEDS_COMMENT;
|
||
struct iovec iov[4];
|
||
u_short len;
|
||
u_short len2;
|
||
u_char *cp;
|
||
|
||
- if (resplen2 != NULL)
|
||
- *resplen2 = 0;
|
||
connreset = 0;
|
||
same_ns:
|
||
truncating = 0;
|
||
@@ -785,8 +719,8 @@ send_vc(res_state statp,
|
||
|
||
if (getpeername(statp->_vcsock,
|
||
(struct sockaddr *)&peer, &size) < 0 ||
|
||
- !sock_eq(&peer, nsap)) {
|
||
- __res_iclose(statp, false);
|
||
+ !sock_eq(&peer, (struct sockaddr_in6 *) nsap)) {
|
||
+ __res_iclose(statp, false);
|
||
statp->_flags &= ~RES_F_VC;
|
||
}
|
||
}
|
||
@@ -795,22 +729,21 @@ send_vc(res_state statp,
|
||
if (statp->_vcsock >= 0)
|
||
__res_iclose(statp, false);
|
||
|
||
- statp->_vcsock = socket(nsap->sin6_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);
|
||
- if (connect(statp->_vcsock, (struct sockaddr *)nsap,
|
||
- nsap->sin6_family == AF_INET
|
||
+ if (connect(statp->_vcsock, nsap,
|
||
+ nsap->sa_family == AF_INET
|
||
? sizeof (struct sockaddr_in)
|
||
: sizeof (struct sockaddr_in6)) < 0) {
|
||
*terrno = errno;
|
||
- Aerror(statp, stderr, "connect/vc", errno,
|
||
- (struct sockaddr *) nsap);
|
||
- __res_iclose(statp, false);
|
||
- return (0);
|
||
+ return close_and_return_error (statp, resplen2);
|
||
}
|
||
statp->_flags |= RES_F_VC;
|
||
}
|
||
@@ -832,16 +765,14 @@ 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
|
||
*/
|
||
int recvresp1 = 0;
|
||
/* Skip the second response if there is no second query.
|
||
- To do that we mark the second response as received. */
|
||
+ To do that we mark the second response as received. */
|
||
int recvresp2 = buf2 == NULL;
|
||
uint16_t rlen16;
|
||
read_len:
|
||
@@ -855,8 +786,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
|
||
@@ -866,11 +795,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);
|
||
|
||
@@ -895,18 +826,18 @@ send_vc(res_state statp,
|
||
*thisresplenp = rlen;
|
||
/* Is the answer buffer too small? */
|
||
if (*thisanssizp < rlen) {
|
||
- /* If the current buffer is non-NULL and it's not
|
||
- pointing at the static user-supplied buffer then
|
||
- we can reallocate it. */
|
||
+ /* If the current buffer is not the the static
|
||
+ user-supplied buffer then we can reallocate
|
||
+ it. */
|
||
if (thisansp != NULL && thisansp != ansp) {
|
||
/* Always allocate MAXPACKET, callers expect
|
||
this specific size. */
|
||
u_char *newp = malloc (MAXPACKET);
|
||
- if (newp == NULL) {
|
||
- *terrno = ENOMEM;
|
||
- __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)
|
||
@@ -917,24 +848,18 @@ 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;
|
||
}
|
||
} else
|
||
len = rlen;
|
||
|
||
- if (__builtin_expect (len < HFIXEDSZ, 0)) {
|
||
+ if (__glibc_unlikely (len < HFIXEDSZ)) {
|
||
/*
|
||
* 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;
|
||
@@ -942,13 +867,11 @@ send_vc(res_state statp,
|
||
cp += n;
|
||
len -= n;
|
||
}
|
||
- if (__builtin_expect (n <= 0, 0)) {
|
||
+ 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 (__builtin_expect (truncating, 0)) {
|
||
+ if (__glibc_unlikely (truncating)) {
|
||
/*
|
||
* Flush rest of answer so connection stays in synch.
|
||
*/
|
||
@@ -966,21 +889,15 @@ send_vc(res_state statp,
|
||
}
|
||
}
|
||
/*
|
||
- * If the calling applicating has bailed out of
|
||
+ * If the calling application has bailed out of
|
||
* a previous call and failed to arrange to have
|
||
* the circuit closed or the server has got
|
||
* itself confused, then drop the packet and
|
||
* wait for the correct one.
|
||
*/
|
||
if ((recvresp1 || hp->id != anhp->id)
|
||
- && (recvresp2 || hp2->id != anhp->id)) {
|
||
- DprintQ((statp->options & RES_DEBUG) ||
|
||
- (statp->pfcode & RES_PRF_REPLY),
|
||
- (stdout, ";; old answer (unexpected):\n"),
|
||
- *thisansp,
|
||
- (rlen > *thisanssizp) ? *thisanssizp: rlen);
|
||
+ && (recvresp2 || hp2->id != anhp->id))
|
||
goto read_len;
|
||
- }
|
||
|
||
/* Mark which reply we received. */
|
||
if (recvresp1 == 0 && hp->id == anhp->id)
|
||
@@ -1002,49 +919,25 @@ static int
|
||
reopen (res_state statp, int *terrno, int ns)
|
||
{
|
||
if (EXT(statp).nssocks[ns] == -1) {
|
||
- struct sockaddr *nsap
|
||
- = (struct sockaddr *) EXT(statp).nsaddrs[ns];
|
||
+ struct sockaddr *nsap = get_nsaddr (statp, ns);
|
||
socklen_t slen;
|
||
|
||
/* only try IPv6 if IPv6 NS and if not failed before */
|
||
if (nsap->sa_family == AF_INET6 && !statp->ipv6_unavail) {
|
||
- if (__builtin_expect (__have_o_nonblock >= 0, 1)) {
|
||
- EXT(statp).nssocks[ns] =
|
||
- socket(PF_INET6, SOCK_DGRAM|SOCK_NONBLOCK,
|
||
- 0);
|
||
-#ifndef __ASSUME_SOCK_CLOEXEC
|
||
- if (__have_o_nonblock == 0)
|
||
- __have_o_nonblock
|
||
- = (EXT(statp).nssocks[ns] == -1
|
||
- && errno == EINVAL ? -1 : 1);
|
||
-#endif
|
||
- }
|
||
- if (__builtin_expect (__have_o_nonblock < 0, 0))
|
||
- EXT(statp).nssocks[ns] =
|
||
- socket(PF_INET6, SOCK_DGRAM, 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) {
|
||
- if (__builtin_expect (__have_o_nonblock >= 0, 1)) {
|
||
- EXT(statp).nssocks[ns]
|
||
- = socket(PF_INET, SOCK_DGRAM|SOCK_NONBLOCK,
|
||
- 0);
|
||
-#ifndef __ASSUME_SOCK_CLOEXEC
|
||
- if (__have_o_nonblock == 0)
|
||
- __have_o_nonblock
|
||
- = (EXT(statp).nssocks[ns] == -1
|
||
- && errno == EINVAL ? -1 : 1);
|
||
-#endif
|
||
- }
|
||
- if (__builtin_expect (__have_o_nonblock < 0, 0))
|
||
- EXT(statp).nssocks[ns]
|
||
- = socket(PF_INET, SOCK_DGRAM, 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);
|
||
}
|
||
|
||
@@ -1059,20 +952,19 @@ 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);
|
||
}
|
||
- if (__builtin_expect (__have_o_nonblock < 0, 0)) {
|
||
- /* Make socket non-blocking. */
|
||
- int fl = __fcntl (EXT(statp).nssocks[ns], F_GETFL);
|
||
- if (fl != -1)
|
||
- __fcntl (EXT(statp).nssocks[ns], F_SETFL,
|
||
- fl | O_NONBLOCK);
|
||
- Dprint(statp->options & RES_DEBUG,
|
||
- (stdout, ";; new DG socket\n"))
|
||
- }
|
||
}
|
||
|
||
return 1;
|
||
@@ -1098,7 +990,7 @@ reopen (res_state statp, int *terrno, int ns)
|
||
are needed but ANSCP is NULL, then as much of the response as
|
||
possible is read into the buffer, but the results will be truncated.
|
||
When truncation happens because of a small answer buffer the DNS
|
||
- packets header feild TC will bet set to 1, indicating a truncated
|
||
+ packets header field TC will bet set to 1, indicating a truncated
|
||
message, while the rest of the UDP packet is discarded.
|
||
|
||
Answers to the query are stored secondly in *ANSP2 up to a max of
|
||
@@ -1184,7 +1076,7 @@ send_dg(res_state statp,
|
||
int nwritten = 0;
|
||
int recvresp1 = 0;
|
||
/* Skip the second response if there is no second query.
|
||
- To do that we mark the second response as received. */
|
||
+ To do that we mark the second response as received. */
|
||
int recvresp2 = buf2 == NULL;
|
||
pfd[0].fd = EXT(statp).nssocks[ns];
|
||
pfd[0].events = POLLOUT;
|
||
@@ -1194,7 +1086,6 @@ send_dg(res_state statp,
|
||
evNowTime(&now);
|
||
if (evCmpTime(finish, now) <= 0) {
|
||
poll_err_out:
|
||
- Perror(statp, stderr, "poll", errno);
|
||
return close_and_return_error (statp, resplen2);
|
||
}
|
||
evSubTime(&timeout, &finish, &now);
|
||
@@ -1206,12 +1097,11 @@ send_dg(res_state statp,
|
||
n = 0;
|
||
if (nwritten == 0)
|
||
n = __poll (pfd, 1, 0);
|
||
- if (__builtin_expect (n == 0, 0)) {
|
||
+ if (__glibc_unlikely (n == 0)) {
|
||
n = __poll (pfd, 1, ptimeout);
|
||
need_recompute = 1;
|
||
}
|
||
if (n == 0) {
|
||
- Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
|
||
if (resplen > 1 && (recvresp1 || (buf2 != NULL && recvresp2)))
|
||
{
|
||
/* There are quite a few broken name servers out
|
||
@@ -1283,7 +1173,7 @@ send_dg(res_state statp,
|
||
reqs[1].msg_hdr.msg_controllen = 0;
|
||
|
||
int ndg = __sendmmsg (pfd[0].fd, reqs, 2, MSG_NOSIGNAL);
|
||
- if (__builtin_expect (ndg == 2, 1))
|
||
+ if (__glibc_likely (ndg == 2))
|
||
{
|
||
if (reqs[0].msg_len != buflen
|
||
|| reqs[1].msg_len != buflen2)
|
||
@@ -1299,7 +1189,7 @@ send_dg(res_state statp,
|
||
else
|
||
{
|
||
#ifndef __ASSUME_SENDMMSG
|
||
- if (__builtin_expect (have_sendmmsg == 0, 0))
|
||
+ if (__glibc_unlikely (have_sendmmsg == 0))
|
||
{
|
||
if (ndg < 0 && errno == ENOSYS)
|
||
{
|
||
@@ -1311,7 +1201,6 @@ send_dg(res_state statp,
|
||
#endif
|
||
|
||
fail_sendmmsg:
|
||
- Perror(statp, stderr, "sendmmsg", errno);
|
||
return close_and_return_error (statp, resplen2);
|
||
}
|
||
}
|
||
@@ -1329,7 +1218,6 @@ send_dg(res_state statp,
|
||
if (sr != (nwritten != 0 ? buflen2 : buflen)) {
|
||
if (errno == EINTR || errno == EAGAIN)
|
||
goto recompute_resend;
|
||
- Perror(statp, stderr, "send", errno);
|
||
return close_and_return_error (statp, resplen2);
|
||
}
|
||
just_one:
|
||
@@ -1360,14 +1248,16 @@ send_dg(res_state statp,
|
||
}
|
||
|
||
if (*thisanssizp < MAXPACKET
|
||
- /* If the current buffer is non-NULL and it's not
|
||
- pointing at the static user-supplied buffer then
|
||
- we can reallocate it. */
|
||
+ /* If the current buffer is not the the static
|
||
+ user-supplied buffer then we can reallocate
|
||
+ it. */
|
||
&& (thisansp != NULL && thisansp != ansp)
|
||
+#ifdef FIONREAD
|
||
/* Is the size too small? */
|
||
&& (ioctl (pfd[0].fd, FIONREAD, thisresplenp) < 0
|
||
|| *thisanssizp < *thisresplenp)
|
||
- ) {
|
||
+#endif
|
||
+ ) {
|
||
/* Always allocate MAXPACKET, callers expect
|
||
this specific size. */
|
||
u_char *newp = malloc (MAXPACKET);
|
||
@@ -1388,34 +1278,24 @@ 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);
|
||
*thisresplenp = recvfrom(pfd[0].fd, (char*)*thisansp,
|
||
*thisanssizp, 0,
|
||
(struct sockaddr *)&from, &fromlen);
|
||
- if (__builtin_expect (*thisresplenp <= 0, 0)) {
|
||
+ if (__glibc_unlikely (*thisresplenp <= 0)) {
|
||
if (errno == EINTR || errno == EAGAIN) {
|
||
need_recompute = 1;
|
||
goto wait;
|
||
}
|
||
- Perror(statp, stderr, "recvfrom", errno);
|
||
return close_and_return_error (statp, resplen2);
|
||
}
|
||
*gotsomewhere = 1;
|
||
- if (__builtin_expect (*thisresplenp < HFIXEDSZ, 0)) {
|
||
+ if (__glibc_unlikely (*thisresplenp < HFIXEDSZ)) {
|
||
/*
|
||
* Undersized message.
|
||
*/
|
||
- Dprint(statp->options & RES_DEBUG,
|
||
- (stdout, ";; undersized: %d\n",
|
||
- *thisresplenp));
|
||
*terrno = EMSGSIZE;
|
||
return close_and_return_error (statp, resplen2);
|
||
}
|
||
@@ -1426,12 +1306,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) &&
|
||
@@ -1441,34 +1315,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;
|
||
- return close_and_return_error (statp, resplen2);
|
||
- }
|
||
-#endif
|
||
if (!(statp->options & RES_INSECURE2)
|
||
&& (recvresp1 || !res_queriesmatch(buf, buf + buflen,
|
||
*thisansp,
|
||
@@ -1483,23 +1331,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;
|
||
@@ -1525,11 +1361,6 @@ send_dg(res_state statp,
|
||
}
|
||
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) {
|
||
@@ -1537,8 +1368,6 @@ 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
|
||
@@ -1582,46 +1411,6 @@ send_dg(res_state statp,
|
||
}
|
||
}
|
||
|
||
-#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 0000000000000000..8649833072ade9cf
|
||
--- /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 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
|
||
index a9f5659dbbacb477..32dc44777e311849 100644
|
||
--- a/resolv/resolv-internal.h
|
||
+++ b/resolv/resolv-internal.h
|
||
@@ -1,5 +1,5 @@
|
||
/* libresolv interfaces for internal use across glibc.
|
||
- Copyright (C) 2016 Free Software Foundation, Inc.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
@@ -22,6 +22,12 @@
|
||
#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
|
||
@@ -32,6 +38,56 @@ 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
|
||
diff --git a/resolv/resolv.h b/resolv/resolv.h
|
||
index ed15a702bf3bb9e8..7d85cbd011acf669 100644
|
||
--- a/resolv/resolv.h
|
||
+++ b/resolv/resolv.h
|
||
@@ -123,8 +123,8 @@ struct __res_state {
|
||
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 */
|
||
+ res_send_qhook __glibc_unused_qhook;
|
||
+ res_send_rhook __glibc_unused_rhook;
|
||
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 */
|
||
@@ -139,10 +139,10 @@ struct __res_state {
|
||
u_int16_t nsinit;
|
||
struct sockaddr_in6 *nsaddrs[MAXNS];
|
||
#ifdef _LIBC
|
||
- unsigned long long int initstamp
|
||
+ unsigned long long int __glibc_extension_index
|
||
__attribute__((packed));
|
||
#else
|
||
- unsigned int _initstamp[2];
|
||
+ unsigned int __glibc_reserved[2];
|
||
#endif
|
||
} _ext;
|
||
} _u;
|
||
@@ -221,6 +221,7 @@ 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)
|
||
|
||
@@ -250,7 +251,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 +265,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
|
||
@@ -298,7 +301,6 @@ __END_DECLS
|
||
#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 +314,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,57 +332,62 @@ 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;
|
||
+char * p_secstodate (unsigned long) __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
|
||
|
||
diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
|
||
new file mode 100644
|
||
index 0000000000000000..e0f296d02e061a89
|
||
--- /dev/null
|
||
+++ b/resolv/resolv_conf.c
|
||
@@ -0,0 +1,701 @@
|
||
+/* Extended resolver state separate from struct __res_state.
|
||
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <resolv_conf.h>
|
||
+
|
||
+#include <alloc_buffer.h>
|
||
+#include <assert.h>
|
||
+#include <libc-lock.h>
|
||
+#include <resolv-internal.h>
|
||
+#include <sys/stat.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. */
|
||
+static void __attribute__ ((section ("__libc_thread_freeres_fn")))
|
||
+freeres (void)
|
||
+{
|
||
+ /* 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;
|
||
+}
|
||
+text_set_element (__libc_subfreeres, freeres);
|
||
diff --git a/resolv/resolv_conf.h b/resolv/resolv_conf.h
|
||
new file mode 100644
|
||
index 0000000000000000..0ff8bd7e928708fc
|
||
--- /dev/null
|
||
+++ b/resolv/resolv_conf.h
|
||
@@ -0,0 +1,103 @@
|
||
+/* Extended resolver state separate from struct __res_state.
|
||
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#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 0000000000000000..35d4b3d41d59fc98
|
||
--- /dev/null
|
||
+++ b/resolv/resolv_context.c
|
||
@@ -0,0 +1,252 @@
|
||
+/* Temporary, thread-local resolver state.
|
||
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <resolv_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 0000000000000000..e2f7ad66458f94bc
|
||
--- /dev/null
|
||
+++ b/resolv/resolv_context.h
|
||
@@ -0,0 +1,182 @@
|
||
+/* Temporary, thread-local resolver state.
|
||
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+/* 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-aton.c b/resolv/tst-aton.c
|
||
index 6cb59604961ebd93..08110a007af909ff 100644
|
||
--- a/resolv/tst-aton.c
|
||
+++ b/resolv/tst-aton.c
|
||
@@ -1,4 +1,5 @@
|
||
#include <stdio.h>
|
||
+#include <stdint.h>
|
||
#include <sys/socket.h>
|
||
#include <netinet/in.h>
|
||
#include <arpa/inet.h>
|
||
@@ -43,8 +44,8 @@ static struct tests
|
||
};
|
||
|
||
|
||
-int
|
||
-main (int argc, char *argv[])
|
||
+static int
|
||
+do_test (void)
|
||
{
|
||
int result = 0;
|
||
size_t cnt;
|
||
@@ -71,3 +72,6 @@ main (int argc, char *argv[])
|
||
|
||
return result;
|
||
}
|
||
+
|
||
+#define TEST_FUNCTION do_test ()
|
||
+#include "../test-skeleton.c"
|
||
diff --git a/resolv/tst-bug18665-tcp.c b/resolv/tst-bug18665-tcp.c
|
||
new file mode 100644
|
||
index 0000000000000000..4bc0c262b1cd7aab
|
||
--- /dev/null
|
||
+++ b/resolv/tst-bug18665-tcp.c
|
||
@@ -0,0 +1,230 @@
|
||
+/* Test __libc_res_nsend buffer mismanagement, basic TCP coverage.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <errno.h>
|
||
+#include <netdb.h>
|
||
+#include <resolv.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <support/check.h>
|
||
+#include <support/check_nss.h>
|
||
+#include <support/resolv_test.h>
|
||
+#include <support/xthread.h>
|
||
+#include <support/xmemstream.h>
|
||
+
|
||
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
||
+
|
||
+static int initial_address_count = 1;
|
||
+static int subsequent_address_count = 2000;
|
||
+static int response_number = 0;
|
||
+
|
||
+static void
|
||
+response (const struct resolv_response_context *ctx,
|
||
+ struct resolv_response_builder *b,
|
||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||
+{
|
||
+ TEST_VERIFY_EXIT (qname != NULL);
|
||
+
|
||
+ /* If not using TCP, just force its use. */
|
||
+ if (!ctx->tcp)
|
||
+ {
|
||
+ struct resolv_response_flags flags = {.tc = true};
|
||
+ resolv_response_init (b, flags);
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ struct resolv_response_flags flags = {};
|
||
+ resolv_response_init (b, flags);
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+
|
||
+ /* The number of addresses (in the additional section) for the name
|
||
+ server record (in the authoritative section). */
|
||
+ int address_count;
|
||
+ xpthread_mutex_lock (&lock);
|
||
+ ++response_number;
|
||
+ if (response_number == 1)
|
||
+ address_count = initial_address_count;
|
||
+ else if (response_number == 2)
|
||
+ {
|
||
+ address_count = 0;
|
||
+ resolv_response_drop (b);
|
||
+ resolv_response_close (b);
|
||
+ }
|
||
+ else
|
||
+ address_count = subsequent_address_count;
|
||
+ xpthread_mutex_unlock (&lock);
|
||
+
|
||
+ /* Only add the address record to the answer section if we requested
|
||
+ any name server addresses. */
|
||
+ if (address_count > 0)
|
||
+ {
|
||
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
|
||
+ switch (qtype)
|
||
+ {
|
||
+ case T_A:
|
||
+ {
|
||
+ char ipv4[4] = {10, response_number >> 8, response_number, 0};
|
||
+ ipv4[3] = 2 * ctx->tcp + 4 * ctx->server_index;
|
||
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
|
||
+ }
|
||
+ break;
|
||
+ case T_AAAA:
|
||
+ {
|
||
+ char ipv6[16]
|
||
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
+ response_number >> 8, response_number, 0, 0};
|
||
+ ipv6[15] = 2 * ctx->tcp + 4 * ctx->server_index;
|
||
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
|
||
+ }
|
||
+ break;
|
||
+ default:
|
||
+ support_record_failure ();
|
||
+ printf ("error: unexpected QTYPE: %s/%u/%u\n",
|
||
+ qname, qclass, qtype);
|
||
+ }
|
||
+ resolv_response_close_record (b);
|
||
+
|
||
+ /* Add the name server record. */
|
||
+ resolv_response_section (b, ns_s_ns);
|
||
+ resolv_response_open_record (b, "example", C_IN, T_NS, 0);
|
||
+ resolv_response_add_name (b, "ns.example");
|
||
+ resolv_response_close_record (b);
|
||
+
|
||
+ /* Increase the response size with name server addresses. These
|
||
+ addresses are not copied out of nss_dns, and thus do not
|
||
+ trigger getaddrinfo retries with a larger buffer, making
|
||
+ testing more predictable. */
|
||
+ resolv_response_section (b, ns_s_ar);
|
||
+ for (int i = 1; i <= address_count; ++i)
|
||
+ {
|
||
+ resolv_response_open_record (b, "ns.example", qclass, qtype, 0);
|
||
+ switch (qtype)
|
||
+ {
|
||
+ case T_A:
|
||
+ {
|
||
+ char ipv4[4] = {response_number, i >> 8, i, 0};
|
||
+ ipv4[3] = 2 * ctx->tcp + 4 * ctx->server_index;
|
||
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
|
||
+ }
|
||
+ break;
|
||
+ case T_AAAA:
|
||
+ {
|
||
+ char ipv6[16]
|
||
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0,
|
||
+ response_number >> 8, response_number,
|
||
+ i >> 8, i, 0, 0};
|
||
+ ipv6[15] = 2 * ctx->tcp + 4 * ctx->server_index;
|
||
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
|
||
+ }
|
||
+ break;
|
||
+ default:
|
||
+ support_record_failure ();
|
||
+ printf ("error: unexpected QTYPE: %s/%u/%u\n",
|
||
+ qname, qclass, qtype);
|
||
+ }
|
||
+ resolv_response_close_record (b);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+static char *
|
||
+expected_result (unsigned port, unsigned response_number)
|
||
+{
|
||
+ struct xmemstream mem;
|
||
+ xopen_memstream (&mem);
|
||
+ /* We fail the second TCP query to the first server by closing the
|
||
+ connection immediately, without returning any data. This should
|
||
+ cause failover to the second server. */
|
||
+ int server_index = 1;
|
||
+ fprintf (mem.out, "address: STREAM/TCP 10.%u.%u.%u %u\n",
|
||
+ (response_number >> 8) & 0xff, response_number & 0xff,
|
||
+ 2 + 4 * server_index, port);
|
||
+ fprintf (mem.out, "address: STREAM/TCP 2001:db8::%x:%x %u\n",
|
||
+ (response_number + 1) & 0xffff,
|
||
+ 2 + 4 * server_index, port);
|
||
+ xfclose_memstream (&mem);
|
||
+ return mem.buffer;
|
||
+}
|
||
+
|
||
+static void
|
||
+test_different_sizes (void)
|
||
+{
|
||
+ struct addrinfo hints =
|
||
+ {
|
||
+ .ai_family = AF_UNSPEC,
|
||
+ .ai_socktype = SOCK_STREAM,
|
||
+ .ai_protocol = IPPROTO_TCP,
|
||
+ };
|
||
+ struct addrinfo *ai;
|
||
+ char *expected;
|
||
+ int ret;
|
||
+
|
||
+ /* This magic number produces a response size close to 2048
|
||
+ bytes. */
|
||
+ initial_address_count = 124;
|
||
+ response_number = 0;
|
||
+
|
||
+ ret = getaddrinfo ("www.example", "80", &hints, &ai);
|
||
+ expected = expected_result (80, 3);
|
||
+ check_addrinfo ("www.example:80", ai, ret, expected);
|
||
+ if (ret == 0)
|
||
+ freeaddrinfo (ai);
|
||
+ free (expected);
|
||
+
|
||
+ response_number = 0;
|
||
+ ret = getaddrinfo ("www123.example", "80", &hints, &ai);
|
||
+ if (ret == 0)
|
||
+ freeaddrinfo (ai);
|
||
+
|
||
+ response_number = 0;
|
||
+ ret = getaddrinfo ("www1234.example", "80", &hints, &ai);
|
||
+ if (ret == 0)
|
||
+ freeaddrinfo (ai);
|
||
+
|
||
+ response_number = 0;
|
||
+ ret = getaddrinfo ("www12345.example", "80", &hints, &ai);
|
||
+ if (ret == 0)
|
||
+ freeaddrinfo (ai);
|
||
+}
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ struct resolv_test *obj = resolv_test_start
|
||
+ ((struct resolv_redirect_config)
|
||
+ {
|
||
+ .response_callback = response
|
||
+ });
|
||
+
|
||
+ test_different_sizes ();
|
||
+
|
||
+ _res.options |= RES_SNGLKUP;
|
||
+ test_different_sizes ();
|
||
+
|
||
+ _res.options |= RES_SNGLKUPREOP;
|
||
+ test_different_sizes ();
|
||
+
|
||
+ resolv_test_end (obj);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#include <support/test-driver.c>
|
||
diff --git a/resolv/tst-bug18665.c b/resolv/tst-bug18665.c
|
||
new file mode 100644
|
||
index 0000000000000000..3c699919fcfe4231
|
||
--- /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-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <errno.h>
|
||
+#include <netdb.h>
|
||
+#include <resolv.h>
|
||
+#include <stdio.h>
|
||
+#include <string.h>
|
||
+#include <support/check.h>
|
||
+#include <support/resolv_test.h>
|
||
+#include <support/xthread.h>
|
||
+
|
||
+static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
|
||
+
|
||
+static int initial_address_count;
|
||
+static int response_count;
|
||
+
|
||
+static void
|
||
+response (const struct resolv_response_context *ctx,
|
||
+ struct resolv_response_builder *b,
|
||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||
+{
|
||
+ TEST_VERIFY_EXIT (qname != NULL);
|
||
+ struct resolv_response_flags flags = {};
|
||
+ resolv_response_init (b, flags);
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+
|
||
+ /* Add many A/AAAA records to the second response. */
|
||
+ int address_count;
|
||
+ xpthread_mutex_lock (&lock);
|
||
+ if (response_count == 0)
|
||
+ address_count = initial_address_count;
|
||
+ else
|
||
+ address_count = 2000;
|
||
+ ++response_count;
|
||
+ xpthread_mutex_unlock (&lock);
|
||
+
|
||
+ for (int i = 0; i < address_count; ++i)
|
||
+ {
|
||
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
|
||
+ switch (qtype)
|
||
+ {
|
||
+ case T_A:
|
||
+ {
|
||
+ char ipv4[4] = {10, i >> 8, i, 0};
|
||
+ ipv4[3] = 2 * ctx->tcp + 4 * ctx->server_index;
|
||
+ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
|
||
+ }
|
||
+ break;
|
||
+ case T_AAAA:
|
||
+ {
|
||
+ char ipv6[16]
|
||
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
+ i >> 8, i, 0};
|
||
+ ipv6[15] = 2 * ctx->tcp + 4 * ctx->server_index;
|
||
+ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
|
||
+ }
|
||
+ break;
|
||
+ default:
|
||
+ support_record_failure ();
|
||
+ printf ("error: unexpected QTYPE: %s/%u/%u\n",
|
||
+ qname, qclass, qtype);
|
||
+ }
|
||
+ resolv_response_close_record (b);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+test_different_sizes (void)
|
||
+{
|
||
+ struct addrinfo hints = { .ai_family = AF_UNSPEC, };
|
||
+ struct addrinfo *ai;
|
||
+ int ret;
|
||
+
|
||
+ /* This magic number produces a response size close to 2048
|
||
+ bytes. */
|
||
+ initial_address_count = 126;
|
||
+ response_count = 0;
|
||
+
|
||
+ ret = getaddrinfo ("www.example", "80", &hints, &ai);
|
||
+ if (ret == 0)
|
||
+ freeaddrinfo (ai);
|
||
+
|
||
+ response_count = 0;
|
||
+ ret = getaddrinfo ("www123.example", "80", &hints, &ai);
|
||
+ if (ret == 0)
|
||
+ freeaddrinfo (ai);
|
||
+
|
||
+ response_count = 0;
|
||
+ ret = getaddrinfo ("www1234.example", "80", &hints, &ai);
|
||
+ if (ret == 0)
|
||
+ freeaddrinfo (ai);
|
||
+
|
||
+ response_count = 0;
|
||
+ ret = getaddrinfo ("www12345.example", "80", &hints, &ai);
|
||
+ if (ret == 0)
|
||
+ freeaddrinfo (ai);
|
||
+}
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ struct resolv_test *obj = resolv_test_start
|
||
+ ((struct resolv_redirect_config)
|
||
+ {
|
||
+ .response_callback = response
|
||
+ });
|
||
+
|
||
+ test_different_sizes ();
|
||
+
|
||
+ _res.options |= RES_SNGLKUP;
|
||
+ test_different_sizes ();
|
||
+
|
||
+ _res.options |= RES_SNGLKUPREOP;
|
||
+ test_different_sizes ();
|
||
+
|
||
+ resolv_test_end (obj);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#include <support/test-driver.c>
|
||
diff --git a/resolv/tst-inet_ntop.c b/resolv/tst-inet_ntop.c
|
||
index 7267c5b4f2f48b8c..f0de06306c20b1c5 100644
|
||
--- a/resolv/tst-inet_ntop.c
|
||
+++ b/resolv/tst-inet_ntop.c
|
||
@@ -106,7 +106,7 @@ do_test (void)
|
||
result++;
|
||
}
|
||
|
||
-
|
||
+
|
||
return result;
|
||
}
|
||
|
||
diff --git a/resolv/tst-leaks.c b/resolv/tst-leaks.c
|
||
index 4e47a6a12152adb4..4f6453517fe66a88 100644
|
||
--- a/resolv/tst-leaks.c
|
||
+++ b/resolv/tst-leaks.c
|
||
@@ -1,5 +1,5 @@
|
||
/* Tests for res_query in libresolv
|
||
- Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||
+ Copyright (C) 2003-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
diff --git a/resolv/tst-leaks2.c b/resolv/tst-leaks2.c
|
||
index b098e8af5d858d18..5a68a4c6574b66c0 100644
|
||
--- a/resolv/tst-leaks2.c
|
||
+++ b/resolv/tst-leaks2.c
|
||
@@ -1,5 +1,5 @@
|
||
/* Tests for res_init in libresolv
|
||
- Copyright (C) 2004 Free Software Foundation, Inc.
|
||
+ Copyright (C) 2004-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
diff --git a/resolv/tst-ns_name.c b/resolv/tst-ns_name.c
|
||
new file mode 100644
|
||
index 0000000000000000..65eea4c827780826
|
||
--- /dev/null
|
||
+++ b/resolv/tst-ns_name.c
|
||
@@ -0,0 +1,438 @@
|
||
+/* Test ns_name-related functions.
|
||
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+/* This test program processes the tst-ns_name.data file. */
|
||
+
|
||
+#include <ctype.h>
|
||
+#include <resolv.h>
|
||
+#include <stdbool.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <support/check.h>
|
||
+#include <support/support.h>
|
||
+#include <support/xstdio.h>
|
||
+
|
||
+/* A byte buffer and its length. */
|
||
+struct buffer
|
||
+{
|
||
+ unsigned char *data;
|
||
+ size_t length;
|
||
+};
|
||
+
|
||
+/* Convert a base64-encoded string to its binary representation. */
|
||
+static bool
|
||
+base64_to_buffer (const char *base64, struct buffer *result)
|
||
+{
|
||
+ /* "-" denotes an empty input. */
|
||
+ if (strcmp (base64, "-") == 0)
|
||
+ {
|
||
+ result->data = xmalloc (1);
|
||
+ result->length = 0;
|
||
+ return true;
|
||
+ }
|
||
+
|
||
+ size_t size = strlen (base64);
|
||
+ unsigned char *data = xmalloc (size);
|
||
+ int ret = b64_pton (base64, data, size);
|
||
+ if (ret < 0 || ret > size)
|
||
+ return false;
|
||
+ result->data = xrealloc (data, ret);
|
||
+ result->length = ret;
|
||
+ return true;
|
||
+}
|
||
+
|
||
+/* A test case for ns_name_unpack and ns_name_ntop. */
|
||
+struct test_case
|
||
+{
|
||
+ char *path;
|
||
+ size_t lineno;
|
||
+ struct buffer input;
|
||
+ size_t input_offset;
|
||
+ int unpack_result;
|
||
+ struct buffer unpack_output;
|
||
+ int ntop_result;
|
||
+ char *ntop_text;
|
||
+};
|
||
+
|
||
+/* Deallocate the buffers associated with the test case. */
|
||
+static void
|
||
+free_test_case (struct test_case *t)
|
||
+{
|
||
+ free (t->path);
|
||
+ free (t->input.data);
|
||
+ free (t->unpack_output.data);
|
||
+ free (t->ntop_text);
|
||
+}
|
||
+
|
||
+/* Extract the test case information from a test file line. */
|
||
+static bool
|
||
+parse_test_case (const char *path, size_t lineno, const char *line,
|
||
+ struct test_case *result)
|
||
+{
|
||
+ memset (result, 0, sizeof (*result));
|
||
+ result->path = xstrdup (path);
|
||
+ result->lineno = lineno;
|
||
+ result->ntop_result = -1;
|
||
+ char *input = NULL;
|
||
+ char *unpack_output = NULL;
|
||
+ int ret = sscanf (line, "%ms %zu %d %ms %d %ms",
|
||
+ &input, &result->input_offset,
|
||
+ &result->unpack_result, &unpack_output,
|
||
+ &result->ntop_result, &result->ntop_text);
|
||
+ if (ret < 3)
|
||
+ {
|
||
+ printf ("%s:%zu: error: missing input fields\n", path, lineno);
|
||
+ free (input);
|
||
+ return false;
|
||
+ }
|
||
+ if (!base64_to_buffer (input, &result->input))
|
||
+ {
|
||
+ printf ("%s:%zu: error: malformed base64 input data\n", path, lineno);
|
||
+ free (input);
|
||
+ free (unpack_output);
|
||
+ free (result->ntop_text);
|
||
+ return false;
|
||
+ }
|
||
+ free (input);
|
||
+
|
||
+ if (unpack_output == NULL)
|
||
+ result->unpack_output = (struct buffer) { NULL, 0 };
|
||
+ else if (!base64_to_buffer (unpack_output, &result->unpack_output))
|
||
+ {
|
||
+ printf ("%s:%zu: error: malformed base64 unpack data\n", path, lineno);
|
||
+ free (result->input.data);
|
||
+ free (unpack_output);
|
||
+ free (result->ntop_text);
|
||
+ return false;
|
||
+ }
|
||
+ free (unpack_output);
|
||
+
|
||
+ /* At this point, all allocated buffers have been transferred to
|
||
+ *result. */
|
||
+
|
||
+ if (result->input_offset > result->input.length)
|
||
+ {
|
||
+ printf ("%s:%zu: error: input offset %zu exceeds buffer size %zu\n",
|
||
+ path, lineno, result->input_offset, result->input.length);
|
||
+ free_test_case (result);
|
||
+ return false;
|
||
+ }
|
||
+ if (result->unpack_result < -1)
|
||
+ {
|
||
+ printf ("%s:%zu: error: invalid unpack result %d\n",
|
||
+ path, lineno, result->unpack_result);
|
||
+ free_test_case (result);
|
||
+ return false;
|
||
+ }
|
||
+ if (result->ntop_result < -1)
|
||
+ {
|
||
+ printf ("%s:%zu: error: invalid ntop result %d\n",
|
||
+ path, lineno, result->ntop_result);
|
||
+ free_test_case (result);
|
||
+ return false;
|
||
+ }
|
||
+
|
||
+ bool fields_consistent;
|
||
+ switch (ret)
|
||
+ {
|
||
+ case 3:
|
||
+ fields_consistent = result->unpack_result == -1;
|
||
+ break;
|
||
+ case 5:
|
||
+ fields_consistent = result->unpack_result != -1
|
||
+ && result->ntop_result == -1;
|
||
+ break;
|
||
+ case 6:
|
||
+ fields_consistent = result->unpack_result != -1
|
||
+ && result->ntop_result != -1;
|
||
+ break;
|
||
+ default:
|
||
+ fields_consistent = false;
|
||
+ }
|
||
+ if (!fields_consistent)
|
||
+ {
|
||
+ printf ("%s:%zu: error: wrong number of fields: %d\n",
|
||
+ path, lineno, ret);
|
||
+ free_test_case (result);
|
||
+ return false;
|
||
+ }
|
||
+ return true;
|
||
+}
|
||
+
|
||
+/* Format the buffer as a hexadecimal string and write it to standard
|
||
+ output. */
|
||
+static void
|
||
+print_hex (const char *label, struct buffer buffer)
|
||
+{
|
||
+ printf (" %s ", label);
|
||
+ unsigned char *p = buffer.data;
|
||
+ unsigned char *end = p + buffer.length;
|
||
+ while (p < end)
|
||
+ {
|
||
+ printf ("%02X", *p & 0xFF);
|
||
+ ++p;
|
||
+ }
|
||
+ putchar ('\n');
|
||
+}
|
||
+
|
||
+/* Run the test case specified in *T. */
|
||
+static void
|
||
+run_test_case (struct test_case *t)
|
||
+{
|
||
+ /* Test ns_name_unpack. */
|
||
+ unsigned char *unpacked = xmalloc (NS_MAXCDNAME);
|
||
+ int consumed = ns_name_unpack
|
||
+ (t->input.data, t->input.data + t->input.length,
|
||
+ t->input.data + t->input_offset,
|
||
+ unpacked, NS_MAXCDNAME);
|
||
+ if (consumed != t->unpack_result)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("%s:%zu: error: wrong result from ns_name_unpack\n"
|
||
+ " expected: %d\n"
|
||
+ " actual: %d\n",
|
||
+ t->path, t->lineno, t->unpack_result, consumed);
|
||
+ return;
|
||
+ }
|
||
+ if (consumed != -1)
|
||
+ {
|
||
+ if (memcmp (unpacked, t->unpack_output.data,
|
||
+ t->unpack_output.length) != 0)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("%s:%zu: error: wrong data from ns_name_unpack\n",
|
||
+ t->path, t->lineno);
|
||
+ print_hex ("expected:", t->unpack_output);
|
||
+ print_hex ("actual: ",
|
||
+ (struct buffer) { unpacked, t->unpack_output.length });
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ /* Test ns_name_ntop. */
|
||
+ char *text = xmalloc (NS_MAXDNAME);
|
||
+ int ret = ns_name_ntop (unpacked, text, NS_MAXDNAME);
|
||
+ if (ret != t->ntop_result)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("%s:%zu: error: wrong result from ns_name_top\n"
|
||
+ " expected: %d\n"
|
||
+ " actual: %d\n",
|
||
+ t->path, t->lineno, t->ntop_result, ret);
|
||
+ return;
|
||
+ }
|
||
+ if (ret != -1)
|
||
+ {
|
||
+ if (strcmp (text, t->ntop_text) != 0)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("%s:%zu: error: wrong data from ns_name_ntop\n",
|
||
+ t->path, t->lineno);
|
||
+ printf (" expected: \"%s\"\n", t->ntop_text);
|
||
+ printf (" actual: \"%s\"\n", text);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ /* Test ns_name_pton. Unpacking does not check the
|
||
+ NS_MAXCDNAME limit, but packing does, so we need to
|
||
+ adjust the expected result. */
|
||
+ int expected;
|
||
+ if (t->unpack_output.length > NS_MAXCDNAME)
|
||
+ expected = -1;
|
||
+ else if (strcmp (text, ".") == 0)
|
||
+ /* The root domain is fully qualified. */
|
||
+ expected = 1;
|
||
+ else
|
||
+ /* The domain name is never fully qualified. */
|
||
+ expected = 0;
|
||
+ unsigned char *repacked = xmalloc (NS_MAXCDNAME);
|
||
+ ret = ns_name_pton (text, repacked, NS_MAXCDNAME);
|
||
+ if (ret != expected)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("%s:%zu: error: wrong result from ns_name_pton\n"
|
||
+ " expected: %d\n"
|
||
+ " actual: %d\n",
|
||
+ t->path, t->lineno, expected, ret);
|
||
+ return;
|
||
+ }
|
||
+ if (ret >= 0
|
||
+ && memcmp (repacked, unpacked, t->unpack_output.length) != 0)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("%s:%zu: error: wrong data from ns_name_pton\n",
|
||
+ t->path, t->lineno);
|
||
+ print_hex ("expected:", t->unpack_output);
|
||
+ print_hex ("actual: ",
|
||
+ (struct buffer) { repacked, t->unpack_output.length });
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ /* Test ns_name_compress, no compression case. */
|
||
+ if (t->unpack_output.length > NS_MAXCDNAME)
|
||
+ expected = -1;
|
||
+ else
|
||
+ expected = t->unpack_output.length;
|
||
+ memset (repacked, '$', NS_MAXCDNAME);
|
||
+ {
|
||
+ enum { ptr_count = 5 };
|
||
+ const unsigned char *dnptrs[ptr_count] = { repacked, };
|
||
+ ret = ns_name_compress (text, repacked, NS_MAXCDNAME,
|
||
+ dnptrs, dnptrs + ptr_count);
|
||
+ if (ret != expected)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("%s:%zu: error: wrong result from ns_name_compress\n"
|
||
+ " expected: %d\n"
|
||
+ " actual: %d\n",
|
||
+ t->path, t->lineno, expected, ret);
|
||
+ return;
|
||
+ }
|
||
+ if (ret < 0)
|
||
+ {
|
||
+ TEST_VERIFY (dnptrs[0] == repacked);
|
||
+ TEST_VERIFY (dnptrs[1] == NULL);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ if (memcmp (repacked, unpacked, t->unpack_output.length) != 0)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("%s:%zu: error: wrong data from ns_name_compress\n",
|
||
+ t->path, t->lineno);
|
||
+ print_hex ("expected:", t->unpack_output);
|
||
+ print_hex ("actual: ", (struct buffer) { repacked, ret });
|
||
+ return;
|
||
+ }
|
||
+ TEST_VERIFY (dnptrs[0] == repacked);
|
||
+ if (unpacked[0] == '\0')
|
||
+ /* The root domain is not a compression target. */
|
||
+ TEST_VERIFY (dnptrs[1] == NULL);
|
||
+ else
|
||
+ {
|
||
+ TEST_VERIFY (dnptrs[1] == repacked);
|
||
+ TEST_VERIFY (dnptrs[2] == NULL);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+
|
||
+ /* Test ns_name_compress, full compression case. Skip this
|
||
+ test for invalid names and the root domain. */
|
||
+ if (expected >= 0 && unpacked[0] != '\0')
|
||
+ {
|
||
+ /* The destination buffer needs additional room for the
|
||
+ offset, the initial name, and the compression
|
||
+ reference. */
|
||
+ enum { name_offset = 259 };
|
||
+ size_t target_offset = name_offset + t->unpack_output.length;
|
||
+ size_t repacked_size = target_offset + 2;
|
||
+ repacked = xrealloc (repacked, repacked_size);
|
||
+ memset (repacked, '@', repacked_size);
|
||
+ memcpy (repacked + name_offset,
|
||
+ t->unpack_output.data, t->unpack_output.length);
|
||
+ enum { ptr_count = 5 };
|
||
+ const unsigned char *dnptrs[ptr_count]
|
||
+ = { repacked, repacked + name_offset, };
|
||
+ ret = ns_name_compress
|
||
+ (text, repacked + target_offset, NS_MAXCDNAME,
|
||
+ dnptrs, dnptrs + ptr_count);
|
||
+ if (ret != 2)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("%s:%zu: error: wrong result from ns_name_compress"
|
||
+ " (2)\n"
|
||
+ " expected: 2\n"
|
||
+ " actual: %d\n",
|
||
+ t->path, t->lineno, ret);
|
||
+ return;
|
||
+ }
|
||
+ if (memcmp (repacked + target_offset, "\xc1\x03", 2) != 0)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("%s:%zu: error: wrong data from ns_name_compress"
|
||
+ " (2)\n"
|
||
+ " expected: C103\n",
|
||
+ t->path, t->lineno);
|
||
+ print_hex ("actual: ",
|
||
+ (struct buffer) { repacked + target_offset, ret });
|
||
+ return;
|
||
+ }
|
||
+ TEST_VERIFY (dnptrs[0] == repacked);
|
||
+ TEST_VERIFY (dnptrs[1] == repacked + name_offset);
|
||
+ TEST_VERIFY (dnptrs[2] == NULL);
|
||
+ }
|
||
+
|
||
+ free (repacked);
|
||
+ }
|
||
+ free (text);
|
||
+ }
|
||
+ free (unpacked);
|
||
+}
|
||
+
|
||
+/* Open the file at PATH, parse the test cases contained in it, and
|
||
+ run them. */
|
||
+static void
|
||
+run_test_file (const char *path)
|
||
+{
|
||
+ FILE *fp = xfopen (path, "re");
|
||
+ char *line = NULL;
|
||
+ size_t line_allocated = 0;
|
||
+ size_t lineno = 0;
|
||
+
|
||
+ while (true)
|
||
+ {
|
||
+ ssize_t ret = getline (&line, &line_allocated, fp);
|
||
+ if (ret < 0)
|
||
+ {
|
||
+ if (ferror (fp))
|
||
+ {
|
||
+ printf ("%s: error reading file: %m\n", path);
|
||
+ exit (1);
|
||
+ }
|
||
+ TEST_VERIFY (feof (fp));
|
||
+ break;
|
||
+ }
|
||
+
|
||
+ ++lineno;
|
||
+ char *p = line;
|
||
+ while (isspace (*p))
|
||
+ ++p;
|
||
+ if (*p == '\0' || *p == '#')
|
||
+ continue;
|
||
+
|
||
+ struct test_case test_case;
|
||
+ if (!parse_test_case (path, lineno, line, &test_case))
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ continue;
|
||
+ }
|
||
+ run_test_case (&test_case);
|
||
+ free_test_case (&test_case);
|
||
+ }
|
||
+ free (line);
|
||
+ xfclose (fp);
|
||
+}
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ run_test_file ("tst-ns_name.data");
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#include <support/test-driver.c>
|
||
diff --git a/resolv/tst-ns_name.data b/resolv/tst-ns_name.data
|
||
new file mode 100644
|
||
index 0000000000000000..0ff0dc3de7a722ae
|
||
--- /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 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 0000000000000000..0c01b753e7764763
|
||
--- /dev/null
|
||
+++ b/resolv/tst-ns_name_compress.c
|
||
@@ -0,0 +1,76 @@
|
||
+/* Test ns_name_compress corner cases.
|
||
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <resolv.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <support/check.h>
|
||
+#include <support/support.h>
|
||
+
|
||
+/* Check that we can process names which fit into the destination
|
||
+ buffer exactly. See bug 21359. */
|
||
+static void
|
||
+test_exact_fit (const char *name, size_t length)
|
||
+{
|
||
+ unsigned char *buf = xmalloc (length + 1);
|
||
+ memset (buf, '$', length + 1);
|
||
+ enum { ptr_count = 5 };
|
||
+ const unsigned char *dnptrs[ptr_count] = { buf, };
|
||
+ int ret = ns_name_compress (name, buf, length,
|
||
+ dnptrs, dnptrs + ptr_count);
|
||
+ if (ret < 0)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: ns_name_compress for %s/%zu failed\n", name, length);
|
||
+ return;
|
||
+ }
|
||
+ if ((size_t) ret != length)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: ns_name_compress for %s/%zu result mismatch: %d\n",
|
||
+ name, length, ret);
|
||
+ }
|
||
+ if (buf[length] != '$')
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: ns_name_compress for %s/%zu padding write\n",
|
||
+ name, length);
|
||
+ }
|
||
+ free (buf);
|
||
+}
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ test_exact_fit ("abc", 5);
|
||
+ test_exact_fit ("abc.", 5);
|
||
+ {
|
||
+ char long_name[]
|
||
+ = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
|
||
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
|
||
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa."
|
||
+ "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.";
|
||
+ TEST_VERIFY (strlen (long_name) == NS_MAXCDNAME - 1);
|
||
+ test_exact_fit (long_name, NS_MAXCDNAME);
|
||
+ long_name[sizeof (long_name) - 1] = '\0';
|
||
+ test_exact_fit (long_name, NS_MAXCDNAME);
|
||
+ }
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#include <support/test-driver.c>
|
||
diff --git a/resolv/tst-res_hconf_reorder.c b/resolv/tst-res_hconf_reorder.c
|
||
index 1e7e0e2fa5aa8735..20e5a5a448437840 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 Free Software Foundation, Inc.
|
||
+ Copyright (C) 2015-2017 Free Software Foundation, Inc.
|
||
This file is part of the GNU C Library.
|
||
|
||
The GNU C Library is free software; you can redistribute it and/or
|
||
@@ -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_use_inet6.c b/resolv/tst-res_use_inet6.c
|
||
new file mode 100644
|
||
index 0000000000000000..d819f921d6e6746d
|
||
--- /dev/null
|
||
+++ b/resolv/tst-res_use_inet6.c
|
||
@@ -0,0 +1,509 @@
|
||
+/* Basic functionality tests for inet6 option processing.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <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-basic.c b/resolv/tst-resolv-basic.c
|
||
new file mode 100644
|
||
index 0000000000000000..66a0e8a1659219b4
|
||
--- /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-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <errno.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <support/check.h>
|
||
+#include <support/check_nss.h>
|
||
+#include <support/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-canonname.c b/resolv/tst-resolv-canonname.c
|
||
new file mode 100644
|
||
index 0000000000000000..5daac33882957791
|
||
--- /dev/null
|
||
+++ b/resolv/tst-resolv-canonname.c
|
||
@@ -0,0 +1,313 @@
|
||
+/* Test _nss_dns_getcanonname_r corner cases.
|
||
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <dlfcn.h>
|
||
+#include <errno.h>
|
||
+#include <gnu/lib-names.h>
|
||
+#include <netdb.h>
|
||
+#include <nss.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <support/check.h>
|
||
+#include <support/resolv_test.h>
|
||
+#include <support/support.h>
|
||
+
|
||
+/* _nss_dns_getcanonname_r is not called during regular operation
|
||
+ because nss_dns directly provides a canonical name, so we have to
|
||
+ test it directly. The function pointer is initialized by do_test
|
||
+ below. */
|
||
+static enum nss_status
|
||
+(*getcanonname) (const char *name, char *buffer, size_t buflen,
|
||
+ char **result, int *errnop, int *h_errnop);
|
||
+
|
||
+static void
|
||
+response (const struct resolv_response_context *ctx,
|
||
+ struct resolv_response_builder *b,
|
||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||
+{
|
||
+ int code;
|
||
+ {
|
||
+ char *tail;
|
||
+ if (sscanf (qname, "code%d.%ms", &code, &tail) != 2
|
||
+ || strcmp (tail, "example") != 0)
|
||
+ FAIL_EXIT1 ("error: invalid QNAME: %s\n", qname);
|
||
+ free (tail);
|
||
+ }
|
||
+
|
||
+ switch (code)
|
||
+ {
|
||
+ case 1:
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+ resolv_response_open_record (b, "www.example", qclass, qtype, 0);
|
||
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
|
||
+ resolv_response_close_record (b);
|
||
+ break;
|
||
+ case 2:
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+ if (qtype == T_AAAA)
|
||
+ {
|
||
+ resolv_response_open_record (b, "www.example", qclass, qtype, 0);
|
||
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
|
||
+ resolv_response_close_record (b);
|
||
+ for (int i = 0; i < 30000; ++i)
|
||
+ resolv_response_add_data (b, "", 1);
|
||
+ }
|
||
+ break;
|
||
+ case 3:
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+ if (qtype == T_AAAA)
|
||
+ {
|
||
+ resolv_response_open_record (b, "www.example", qclass, qtype, 0);
|
||
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
|
||
+ resolv_response_close_record (b);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ for (int i = 0; i < 30000; ++i)
|
||
+ resolv_response_add_data (b, "", 1);
|
||
+ }
|
||
+ break;
|
||
+ case 4:
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+ resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
|
||
+ resolv_response_add_name (b, "www.example");
|
||
+ resolv_response_close_record (b);
|
||
+ resolv_response_open_record (b, "www.example", qclass, qtype, 0);
|
||
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
|
||
+ resolv_response_close_record (b);
|
||
+ break;
|
||
+ case 5:
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+ resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
|
||
+ resolv_response_add_name (b, "www.example");
|
||
+ resolv_response_close_record (b);
|
||
+ resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
|
||
+ resolv_response_add_name (b, "www1.example");
|
||
+ resolv_response_close_record (b);
|
||
+ resolv_response_open_record (b, "www1.example", qclass, qtype, 0);
|
||
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
|
||
+ resolv_response_close_record (b);
|
||
+ break;
|
||
+ case 6:
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+ resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
|
||
+ resolv_response_add_name (b, "www.example");
|
||
+ resolv_response_close_record (b);
|
||
+ resolv_response_open_record (b, qname, qclass, 46 /* RRSIG */, 0);
|
||
+ resolv_response_add_name (b, ".");
|
||
+ resolv_response_close_record (b);
|
||
+ resolv_response_open_record (b, "www.example", qclass, qtype, 0);
|
||
+ resolv_response_add_data (b, "\xC0\x00\x02\x01", 4);
|
||
+ resolv_response_close_record (b);
|
||
+ break;
|
||
+ case 102:
|
||
+ if (!ctx->tcp)
|
||
+ {
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {.tc = true});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ resolv_response_init
|
||
+ (b, (struct resolv_response_flags) {.ancount = 1});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+ resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
|
||
+ size_t to_fill = 65535 - resolv_response_length (b)
|
||
+ - 2 /* length, "n" */ - 2 /* compression reference */
|
||
+ - 2 /* RR type */;
|
||
+ for (size_t i = 0; i < to_fill; ++i)
|
||
+ resolv_response_add_data (b, "", 1);
|
||
+ resolv_response_close_record (b);
|
||
+ resolv_response_add_name (b, "n.example");
|
||
+ uint16_t rrtype = htons (T_CNAME);
|
||
+ resolv_response_add_data (b, &rrtype, sizeof (rrtype));
|
||
+ }
|
||
+ break;
|
||
+ case 103:
|
||
+ /* NODATA repsonse. */
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ break;
|
||
+ case 104:
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {.ancount = 1});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ /* No RR metadata. */
|
||
+ resolv_response_add_name (b, "www.example");
|
||
+ break;
|
||
+ case 105:
|
||
+ if (qtype == T_A)
|
||
+ {
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ /* No data, trigger AAAA query. */
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ resolv_response_init
|
||
+ (b, (struct resolv_response_flags) {.ancount = 1});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ /* No RR metadata. */
|
||
+ resolv_response_add_name
|
||
+ (b, "long-name-exceed-previously-initialized-buffer.example");
|
||
+ }
|
||
+ break;
|
||
+ case 106:
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {.ancount = 1});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ /* No RR metadata. */
|
||
+ resolv_response_add_name (b, "www.example");
|
||
+ resolv_response_add_data (b, "\xff\xff", 2);
|
||
+ break;
|
||
+ case 107:
|
||
+ if (qtype == T_A)
|
||
+ {
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ /* No data, trigger AAAA query. */
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ resolv_response_init
|
||
+ (b, (struct resolv_response_flags) {.ancount = 1});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ /* No RR metadata. */
|
||
+ resolv_response_add_name (b, "www.example");
|
||
+ resolv_response_add_data (b, "\xff\xff", 2);
|
||
+ }
|
||
+ break;
|
||
+ default:
|
||
+ FAIL_EXIT1 ("error: invalid QNAME: %s (code %d)\n", qname, code);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+check (int code, const char *expected)
|
||
+{
|
||
+ char qname[200];
|
||
+ snprintf (qname, sizeof (qname), "code%d.example", code);
|
||
+ char *result;
|
||
+ enum nss_status status;
|
||
+ {
|
||
+ enum { buffer_size = 4096 };
|
||
+ char *buffer = xmalloc (buffer_size);
|
||
+ char *temp_result;
|
||
+ int temp_errno;
|
||
+ int temp_herrno;
|
||
+ status = getcanonname
|
||
+ (qname, buffer, buffer_size, &temp_result, &temp_errno, &temp_herrno);
|
||
+ if (status == NSS_STATUS_SUCCESS)
|
||
+ result = xstrdup (temp_result);
|
||
+ else
|
||
+ {
|
||
+ errno = temp_errno;
|
||
+ h_errno = temp_herrno;
|
||
+ }
|
||
+ free (buffer);
|
||
+ }
|
||
+
|
||
+ if (status == NSS_STATUS_SUCCESS)
|
||
+ {
|
||
+ if (expected != NULL)
|
||
+ {
|
||
+ if (strcmp (result, expected) != 0)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: getcanonname (%s) failed\n", qname);
|
||
+ printf ("error: expected: %s\n", expected);
|
||
+ printf ("error: actual: %s\n", result);
|
||
+ free (result);
|
||
+ return;
|
||
+ }
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: getcanonname (%s) unexpected success\n", qname);
|
||
+ printf ("error: actual: %s\n", result);
|
||
+ free (result);
|
||
+ return;
|
||
+ }
|
||
+ free (result);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ if (expected != NULL)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: getcanonname (%s) failed\n", qname);
|
||
+ printf ("error: expected: %s\n", expected);
|
||
+ return;
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ void *nss_dns_handle = dlopen (LIBNSS_DNS_SO, RTLD_LAZY);
|
||
+ if (nss_dns_handle == NULL)
|
||
+ FAIL_EXIT1 ("could not dlopen %s: %s", LIBNSS_DNS_SO, dlerror ());
|
||
+ {
|
||
+ const char *func = "_nss_dns_getcanonname_r";
|
||
+ void *ptr = dlsym (nss_dns_handle, func);
|
||
+ if (ptr == NULL)
|
||
+ FAIL_EXIT1 ("could not look up %s: %s", func, dlerror ());
|
||
+ getcanonname = ptr;
|
||
+ }
|
||
+
|
||
+ struct resolv_test *aux = resolv_test_start
|
||
+ ((struct resolv_redirect_config)
|
||
+ {
|
||
+ .response_callback = response,
|
||
+ });
|
||
+
|
||
+ check (1, "www.example");
|
||
+ check (2, "www.example");
|
||
+ check (3, "www.example");
|
||
+ check (4, "www.example");
|
||
+ check (5, "www1.example");
|
||
+
|
||
+ /* This should really result in "www.example", but the fake RRSIG
|
||
+ record causes the current implementation to stop parsing. */
|
||
+ check (6, NULL);
|
||
+
|
||
+ for (int i = 102; i <= 107; ++i)
|
||
+ check (i, NULL);
|
||
+
|
||
+ resolv_test_end (aux);
|
||
+
|
||
+ TEST_VERIFY (dlclose (nss_dns_handle) == 0);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#include <support/test-driver.c>
|
||
diff --git a/resolv/tst-resolv-edns.c b/resolv/tst-resolv-edns.c
|
||
new file mode 100644
|
||
index 0000000000000000..8945d79d092ff5d3
|
||
--- /dev/null
|
||
+++ b/resolv/tst-resolv-edns.c
|
||
@@ -0,0 +1,532 @@
|
||
+/* Test EDNS handling in the stub resolver.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <errno.h>
|
||
+#include <netdb.h>
|
||
+#include <resolv.h>
|
||
+#include <stdio.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <support/check.h>
|
||
+#include <support/resolv_test.h>
|
||
+#include <support/support.h>
|
||
+#include <support/test-driver.h>
|
||
+#include <support/xthread.h>
|
||
+
|
||
+/* Data produced by a test query. */
|
||
+struct response_data
|
||
+{
|
||
+ char *qname;
|
||
+ uint16_t qtype;
|
||
+ struct resolv_edns_info edns;
|
||
+};
|
||
+
|
||
+/* Global array used by put_response and get_response to record
|
||
+ response data. The test DNS server returns the index of the array
|
||
+ element which contains the actual response data. This enables the
|
||
+ test case to return arbitrary amounts of data with the limited
|
||
+ number of bits which fit into an IP addres.
|
||
+
|
||
+ The volatile specifier is needed because the test case accesses
|
||
+ these variables from a callback function called from a function
|
||
+ which is marked as __THROW (i.e., a leaf function which actually is
|
||
+ not). */
|
||
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||
+static struct response_data ** volatile response_data_array;
|
||
+volatile static size_t response_data_count;
|
||
+
|
||
+/* Extract information from the query, store it in a struct
|
||
+ response_data object, and return its index in the
|
||
+ response_data_array. */
|
||
+static unsigned int
|
||
+put_response (const struct resolv_response_context *ctx,
|
||
+ const char *qname, uint16_t qtype)
|
||
+{
|
||
+ xpthread_mutex_lock (&mutex);
|
||
+ ++response_data_count;
|
||
+ /* We only can represent 2**24 indexes in 10.0.0.0/8. */
|
||
+ TEST_VERIFY (response_data_count < (1 << 24));
|
||
+ response_data_array = xrealloc
|
||
+ (response_data_array, sizeof (*response_data_array) * response_data_count);
|
||
+ unsigned int index = response_data_count - 1;
|
||
+ struct response_data *data = xmalloc (sizeof (*data));
|
||
+ *data = (struct response_data)
|
||
+ {
|
||
+ .qname = xstrdup (qname),
|
||
+ .qtype = qtype,
|
||
+ .edns = ctx->edns,
|
||
+ };
|
||
+ response_data_array[index] = data;
|
||
+ xpthread_mutex_unlock (&mutex);
|
||
+ return index;
|
||
+}
|
||
+
|
||
+/* Verify the index into the response_data array and return the data
|
||
+ at it. */
|
||
+static struct response_data *
|
||
+get_response (unsigned int index)
|
||
+{
|
||
+ xpthread_mutex_lock (&mutex);
|
||
+ TEST_VERIFY_EXIT (index < response_data_count);
|
||
+ struct response_data *result = response_data_array[index];
|
||
+ xpthread_mutex_unlock (&mutex);
|
||
+ return result;
|
||
+}
|
||
+
|
||
+/* Deallocate all response data. */
|
||
+static void
|
||
+free_response_data (void)
|
||
+{
|
||
+ xpthread_mutex_lock (&mutex);
|
||
+ size_t count = response_data_count;
|
||
+ struct response_data **array = response_data_array;
|
||
+ for (unsigned int i = 0; i < count; ++i)
|
||
+ {
|
||
+ struct response_data *data = array[i];
|
||
+ free (data->qname);
|
||
+ free (data);
|
||
+ }
|
||
+ free (array);
|
||
+ response_data_array = NULL;
|
||
+ response_data_count = 0;
|
||
+ xpthread_mutex_unlock (&mutex);
|
||
+}
|
||
+
|
||
+#define EDNS_PROBE_EXAMPLE "edns-probe.example"
|
||
+
|
||
+static void
|
||
+response (const struct resolv_response_context *ctx,
|
||
+ struct resolv_response_builder *b,
|
||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||
+{
|
||
+ TEST_VERIFY_EXIT (qname != NULL);
|
||
+
|
||
+ const char *qname_compare = qname;
|
||
+
|
||
+ /* The "formerr." prefix can be used to request a FORMERR response on the
|
||
+ first server. */
|
||
+ bool send_formerr;
|
||
+ if (strncmp ("formerr.", qname, strlen ("formerr.")) == 0)
|
||
+ {
|
||
+ send_formerr = true;
|
||
+ qname_compare = qname + strlen ("formerr.");
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ send_formerr = false;
|
||
+ qname_compare = qname;
|
||
+ }
|
||
+
|
||
+ /* The "tcp." prefix can be used to request TCP fallback. */
|
||
+ bool force_tcp;
|
||
+ if (strncmp ("tcp.", qname_compare, strlen ("tcp.")) == 0)
|
||
+ {
|
||
+ force_tcp = true;
|
||
+ qname_compare += strlen ("tcp.");
|
||
+ }
|
||
+ else
|
||
+ force_tcp = false;
|
||
+
|
||
+ enum {edns_probe} requested_qname;
|
||
+ if (strcmp (qname_compare, EDNS_PROBE_EXAMPLE) == 0)
|
||
+ requested_qname = edns_probe;
|
||
+ else
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: unexpected QNAME: %s (reduced: %s)\n",
|
||
+ qname, qname_compare);
|
||
+ return;
|
||
+ }
|
||
+ TEST_VERIFY_EXIT (qclass == C_IN);
|
||
+ struct resolv_response_flags flags = { };
|
||
+ flags.tc = force_tcp && !ctx->tcp;
|
||
+ if (!flags.tc && send_formerr && ctx->server_index == 0)
|
||
+ /* Send a FORMERR for the first full response from the first
|
||
+ server. */
|
||
+ flags.rcode = 1; /* FORMERR */
|
||
+ resolv_response_init (b, flags);
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ if (flags.tc || flags.rcode != 0)
|
||
+ return;
|
||
+
|
||
+ if (test_verbose)
|
||
+ printf ("info: edns=%d payload_size=%d\n",
|
||
+ ctx->edns.active, ctx->edns.payload_size);
|
||
+
|
||
+ /* Encode the response_data object in multiple address records.
|
||
+ Each record carries two bytes of payload data, and an index. */
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+ switch (requested_qname)
|
||
+ {
|
||
+ case edns_probe:
|
||
+ {
|
||
+ unsigned int index = put_response (ctx, qname, qtype);
|
||
+ switch (qtype)
|
||
+ {
|
||
+ case T_A:
|
||
+ {
|
||
+ uint32_t addr = htonl (0x0a000000 | index);
|
||
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
|
||
+ resolv_response_add_data (b, &addr, sizeof (addr));
|
||
+ resolv_response_close_record (b);
|
||
+ }
|
||
+ break;
|
||
+ case T_AAAA:
|
||
+ {
|
||
+ char addr[16]
|
||
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
+ index >> 16, index >> 8, index};
|
||
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
|
||
+ resolv_response_add_data (b, &addr, sizeof (addr));
|
||
+ resolv_response_close_record (b);
|
||
+ }
|
||
+ }
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Update *DATA with data from ADDRESS of SIZE. Set the corresponding
|
||
+ flag in SHADOW for each byte written. */
|
||
+static struct response_data *
|
||
+decode_address (const void *address, size_t size)
|
||
+{
|
||
+ switch (size)
|
||
+ {
|
||
+ case 4:
|
||
+ TEST_VERIFY (memcmp (address, "\x0a", 1) == 0);
|
||
+ break;
|
||
+ case 16:
|
||
+ TEST_VERIFY (memcmp (address, "\x20\x01\x0d\xb8", 4) == 0);
|
||
+ break;
|
||
+ default:
|
||
+ FAIL_EXIT1 ("unexpected address size %zu", size);
|
||
+ }
|
||
+ const unsigned char *addr = address;
|
||
+ unsigned int index = addr[size - 3] * 256 * 256
|
||
+ + addr[size - 2] * 256
|
||
+ + addr[size - 1];
|
||
+ return get_response (index);
|
||
+}
|
||
+
|
||
+static struct response_data *
|
||
+decode_hostent (struct hostent *e)
|
||
+{
|
||
+ TEST_VERIFY_EXIT (e != NULL);
|
||
+ TEST_VERIFY_EXIT (e->h_addr_list[0] != NULL);
|
||
+ TEST_VERIFY (e->h_addr_list[1] == NULL);
|
||
+ return decode_address (e->h_addr_list[0], e->h_length);
|
||
+}
|
||
+
|
||
+static struct response_data *
|
||
+decode_addrinfo (struct addrinfo *ai, int family)
|
||
+{
|
||
+ struct response_data *data = NULL;
|
||
+ while (ai != NULL)
|
||
+ {
|
||
+ if (ai->ai_family == family)
|
||
+ {
|
||
+ struct response_data *new_data;
|
||
+ switch (family)
|
||
+ {
|
||
+ case AF_INET:
|
||
+ {
|
||
+ struct sockaddr_in *pin = (struct sockaddr_in *) ai->ai_addr;
|
||
+ new_data = decode_address (&pin->sin_addr.s_addr, 4);
|
||
+ }
|
||
+ break;
|
||
+ case AF_INET6:
|
||
+ {
|
||
+ struct sockaddr_in6 *pin = (struct sockaddr_in6 *) ai->ai_addr;
|
||
+ new_data = decode_address (&pin->sin6_addr.s6_addr, 16);
|
||
+ }
|
||
+ break;
|
||
+ default:
|
||
+ FAIL_EXIT1 ("invalid address family %d", ai->ai_family);
|
||
+ }
|
||
+ if (data == NULL)
|
||
+ data = new_data;
|
||
+ else
|
||
+ /* Check pointer equality because this should be the same
|
||
+ response (same index). */
|
||
+ TEST_VERIFY (data == new_data);
|
||
+ }
|
||
+ ai = ai->ai_next;
|
||
+ }
|
||
+ TEST_VERIFY_EXIT (data != NULL);
|
||
+ return data;
|
||
+}
|
||
+
|
||
+/* Updated by the main test loop in accordance with what is set in
|
||
+ _res.options. */
|
||
+static bool use_edns;
|
||
+static bool use_dnssec;
|
||
+
|
||
+/* Verify the decoded response data against the flags above. */
|
||
+static void
|
||
+verify_response_data_payload (struct response_data *data,
|
||
+ size_t expected_payload)
|
||
+{
|
||
+ bool edns = use_edns || use_dnssec;
|
||
+ TEST_VERIFY (data->edns.active == edns);
|
||
+ if (!edns)
|
||
+ expected_payload = 0;
|
||
+ if (data->edns.payload_size != expected_payload)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: unexpected payload size %d (edns=%d)\n",
|
||
+ (int) data->edns.payload_size, edns);
|
||
+ }
|
||
+ uint16_t expected_flags = 0;
|
||
+ if (use_dnssec)
|
||
+ expected_flags |= 0x8000; /* DO flag. */
|
||
+ if (data->edns.flags != expected_flags)
|
||
+ {
|
||
+ support_record_failure ();
|
||
+ printf ("error: unexpected EDNS flags 0x%04x (edns=%d)\n",
|
||
+ (int) data->edns.flags, edns);
|
||
+ }
|
||
+}
|
||
+
|
||
+/* Same as verify_response_data_payload, but use the default
|
||
+ payload. */
|
||
+static void
|
||
+verify_response_data (struct response_data *data)
|
||
+{
|
||
+ verify_response_data_payload (data, 1200);
|
||
+}
|
||
+
|
||
+static void
|
||
+check_hostent (struct hostent *e)
|
||
+{
|
||
+ TEST_VERIFY_EXIT (e != NULL);
|
||
+ verify_response_data (decode_hostent (e));
|
||
+}
|
||
+
|
||
+static void
|
||
+do_ai (int family)
|
||
+{
|
||
+ struct addrinfo hints = { .ai_family = family };
|
||
+ struct addrinfo *ai;
|
||
+ int ret = getaddrinfo (EDNS_PROBE_EXAMPLE, "80", &hints, &ai);
|
||
+ TEST_VERIFY_EXIT (ret == 0);
|
||
+ switch (family)
|
||
+ {
|
||
+ case AF_INET:
|
||
+ case AF_INET6:
|
||
+ verify_response_data (decode_addrinfo (ai, family));
|
||
+ break;
|
||
+ case AF_UNSPEC:
|
||
+ verify_response_data (decode_addrinfo (ai, AF_INET));
|
||
+ verify_response_data (decode_addrinfo (ai, AF_INET6));
|
||
+ break;
|
||
+ default:
|
||
+ FAIL_EXIT1 ("invalid address family %d", family);
|
||
+ }
|
||
+ freeaddrinfo (ai);
|
||
+}
|
||
+
|
||
+enum res_op
|
||
+{
|
||
+ res_op_search,
|
||
+ res_op_query,
|
||
+ res_op_querydomain,
|
||
+ res_op_nsearch,
|
||
+ res_op_nquery,
|
||
+ res_op_nquerydomain,
|
||
+
|
||
+ res_op_last = res_op_nquerydomain,
|
||
+};
|
||
+
|
||
+static const char *
|
||
+res_op_string (enum res_op op)
|
||
+{
|
||
+ switch (op)
|
||
+ {
|
||
+ case res_op_search:
|
||
+ return "res_search";
|
||
+ case res_op_query:
|
||
+ return "res_query";
|
||
+ case res_op_querydomain:
|
||
+ return "res_querydomain";
|
||
+ case res_op_nsearch:
|
||
+ return "res_nsearch";
|
||
+ case res_op_nquery:
|
||
+ return "res_nquery";
|
||
+ case res_op_nquerydomain:
|
||
+ return "res_nquerydomain";
|
||
+ }
|
||
+ FAIL_EXIT1 ("invalid res_op value %d", (int) op);
|
||
+}
|
||
+
|
||
+/* Call libresolv function OP to look up PROBE_NAME, with an answer
|
||
+ buffer of SIZE bytes. Check that the advertised UDP buffer size is
|
||
+ in fact EXPECTED_BUFFER_SIZE. */
|
||
+static void
|
||
+do_res_search (const char *probe_name, enum res_op op, size_t size,
|
||
+ size_t expected_buffer_size)
|
||
+{
|
||
+ if (test_verbose)
|
||
+ printf ("info: testing %s with buffer size %zu\n",
|
||
+ res_op_string (op), size);
|
||
+ unsigned char *buffer = xmalloc (size);
|
||
+ int ret = -1;
|
||
+ switch (op)
|
||
+ {
|
||
+ case res_op_search:
|
||
+ ret = res_search (probe_name, C_IN, T_A, buffer, size);
|
||
+ break;
|
||
+ case res_op_query:
|
||
+ ret = res_query (probe_name, C_IN, T_A, buffer, size);
|
||
+ break;
|
||
+ case res_op_nsearch:
|
||
+ ret = res_nsearch (&_res, probe_name, C_IN, T_A, buffer, size);
|
||
+ break;
|
||
+ case res_op_nquery:
|
||
+ ret = res_nquery (&_res, probe_name, C_IN, T_A, buffer, size);
|
||
+ break;
|
||
+ case res_op_querydomain:
|
||
+ case res_op_nquerydomain:
|
||
+ {
|
||
+ char *example_stripped = xstrdup (probe_name);
|
||
+ char *dot_example = strstr (example_stripped, ".example");
|
||
+ if (dot_example != NULL && strcmp (dot_example, ".example") == 0)
|
||
+ {
|
||
+ /* Truncate the domain name. */
|
||
+ *dot_example = '\0';
|
||
+ if (op == res_op_querydomain)
|
||
+ ret = res_querydomain
|
||
+ (example_stripped, "example", C_IN, T_A, buffer, size);
|
||
+ else
|
||
+ ret = res_nquerydomain
|
||
+ (&_res, example_stripped, "example", C_IN, T_A, buffer, size);
|
||
+ }
|
||
+ else
|
||
+ FAIL_EXIT1 ("invalid probe name: %s", probe_name);
|
||
+ free (example_stripped);
|
||
+ }
|
||
+ break;
|
||
+ }
|
||
+ TEST_VERIFY_EXIT (ret > 12);
|
||
+ unsigned char *end = buffer + ret;
|
||
+
|
||
+ HEADER *hd = (HEADER *) buffer;
|
||
+ TEST_VERIFY (ntohs (hd->qdcount) == 1);
|
||
+ TEST_VERIFY (ntohs (hd->ancount) == 1);
|
||
+ /* Skip over the header. */
|
||
+ unsigned char *p = buffer + sizeof (*hd);
|
||
+ /* Skip over the question. */
|
||
+ ret = dn_skipname (p, end);
|
||
+ TEST_VERIFY_EXIT (ret > 0);
|
||
+ p += ret;
|
||
+ TEST_VERIFY_EXIT (end - p >= 4);
|
||
+ p += 4;
|
||
+ /* Skip over the RNAME and the RR header, but stop at the RDATA
|
||
+ length. */
|
||
+ ret = dn_skipname (p, end);
|
||
+ TEST_VERIFY_EXIT (ret > 0);
|
||
+ p += ret;
|
||
+ TEST_VERIFY_EXIT (end - p >= 2 + 2 + 4 + 2 + 4);
|
||
+ p += 2 + 2 + 4;
|
||
+ /* The IP address should be 4 bytes long. */
|
||
+ TEST_VERIFY_EXIT (p[0] == 0);
|
||
+ TEST_VERIFY_EXIT (p[1] == 4);
|
||
+ /* Extract the address information. */
|
||
+ p += 2;
|
||
+ struct response_data *data = decode_address (p, 4);
|
||
+
|
||
+ verify_response_data_payload (data, expected_buffer_size);
|
||
+
|
||
+ free (buffer);
|
||
+}
|
||
+
|
||
+static void
|
||
+run_test (const char *probe_name)
|
||
+{
|
||
+ if (test_verbose)
|
||
+ printf ("\ninfo: * use_edns=%d use_dnssec=%d\n",
|
||
+ use_edns, use_dnssec);
|
||
+ check_hostent (gethostbyname (probe_name));
|
||
+ check_hostent (gethostbyname2 (probe_name, AF_INET));
|
||
+ check_hostent (gethostbyname2 (probe_name, AF_INET6));
|
||
+ do_ai (AF_UNSPEC);
|
||
+ do_ai (AF_INET);
|
||
+ do_ai (AF_INET6);
|
||
+
|
||
+ for (int op = 0; op <= res_op_last; ++op)
|
||
+ {
|
||
+ do_res_search (probe_name, op, 301, 512);
|
||
+ do_res_search (probe_name, op, 511, 512);
|
||
+ do_res_search (probe_name, op, 512, 512);
|
||
+ do_res_search (probe_name, op, 513, 513);
|
||
+ do_res_search (probe_name, op, 657, 657);
|
||
+ do_res_search (probe_name, op, 1199, 1199);
|
||
+ do_res_search (probe_name, op, 1200, 1200);
|
||
+ do_res_search (probe_name, op, 1201, 1200);
|
||
+ do_res_search (probe_name, op, 65535, 1200);
|
||
+ }
|
||
+}
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ for (int do_edns = 0; do_edns < 2; ++do_edns)
|
||
+ for (int do_dnssec = 0; do_dnssec < 2; ++do_dnssec)
|
||
+ for (int do_tcp = 0; do_tcp < 2; ++do_tcp)
|
||
+ for (int do_formerr = 0; do_formerr < 2; ++do_formerr)
|
||
+ {
|
||
+ struct resolv_test *aux = resolv_test_start
|
||
+ ((struct resolv_redirect_config)
|
||
+ {
|
||
+ .response_callback = response,
|
||
+ });
|
||
+
|
||
+ use_edns = do_edns;
|
||
+ if (do_edns)
|
||
+ _res.options |= RES_USE_EDNS0;
|
||
+ use_dnssec = do_dnssec;
|
||
+ if (do_dnssec)
|
||
+ _res.options |= RES_USE_DNSSEC;
|
||
+
|
||
+ char *probe_name = xstrdup (EDNS_PROBE_EXAMPLE);
|
||
+ if (do_tcp)
|
||
+ {
|
||
+ char *n = xasprintf ("tcp.%s", probe_name);
|
||
+ free (probe_name);
|
||
+ probe_name = n;
|
||
+ }
|
||
+ if (do_formerr)
|
||
+ {
|
||
+ /* Send a garbage query in an attempt to trigger EDNS
|
||
+ fallback. */
|
||
+ char *n = xasprintf ("formerr.%s", probe_name);
|
||
+ gethostbyname (n);
|
||
+ free (n);
|
||
+ }
|
||
+
|
||
+ run_test (probe_name);
|
||
+
|
||
+ free (probe_name);
|
||
+ resolv_test_end (aux);
|
||
+ }
|
||
+
|
||
+ free_response_data ();
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#include <support/test-driver.c>
|
||
diff --git a/resolv/tst-resolv-network.c b/resolv/tst-resolv-network.c
|
||
new file mode 100644
|
||
index 0000000000000000..df9daf8d5825cf01
|
||
--- /dev/null
|
||
+++ b/resolv/tst-resolv-network.c
|
||
@@ -0,0 +1,299 @@
|
||
+/* Test getnetbyname and getnetbyaddr.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <netdb.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <support/check.h>
|
||
+#include <support/check_nss.h>
|
||
+#include <support/resolv_test.h>
|
||
+#include <support/support.h>
|
||
+#include <support/xmemstream.h>
|
||
+
|
||
+static void
|
||
+send_ptr (struct resolv_response_builder *b,
|
||
+ const char *qname, uint16_t qclass, uint16_t qtype,
|
||
+ const char *alias)
|
||
+{
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
|
||
+ resolv_response_add_name (b, alias);
|
||
+ resolv_response_close_record (b);
|
||
+}
|
||
+
|
||
+static void
|
||
+handle_code (const struct resolv_response_context *ctx,
|
||
+ struct resolv_response_builder *b,
|
||
+ const char *qname, uint16_t qclass, uint16_t qtype,
|
||
+ int code)
|
||
+{
|
||
+ switch (code)
|
||
+ {
|
||
+ case 1:
|
||
+ send_ptr (b, qname, qclass, qtype, "1.in-addr.arpa");
|
||
+ break;
|
||
+ case 2:
|
||
+ send_ptr (b, qname, qclass, qtype, "2.1.in-addr.arpa");
|
||
+ break;
|
||
+ case 3:
|
||
+ send_ptr (b, qname, qclass, qtype, "3.2.1.in-addr.arpa");
|
||
+ break;
|
||
+ case 4:
|
||
+ send_ptr (b, qname, qclass, qtype, "4.3.2.1.in-addr.arpa");
|
||
+ break;
|
||
+ case 5:
|
||
+ /* Test multiple PTR records. */
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
|
||
+ resolv_response_add_name (b, "127.in-addr.arpa");
|
||
+ resolv_response_close_record (b);
|
||
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
|
||
+ resolv_response_add_name (b, "0.in-addr.arpa");
|
||
+ resolv_response_close_record (b);
|
||
+ break;
|
||
+ case 6:
|
||
+ /* Test skipping of RRSIG record. */
|
||
+ resolv_response_init (b, (struct resolv_response_flags) { });
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+
|
||
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
|
||
+ resolv_response_add_name (b, "127.in-addr.arpa");
|
||
+ resolv_response_close_record (b);
|
||
+
|
||
+ resolv_response_open_record (b, qname, qclass, 46 /* RRSIG */, 0);
|
||
+ {
|
||
+ char buf[500];
|
||
+ memset (buf, 0x3f, sizeof (buf));
|
||
+ resolv_response_add_data (b, buf, sizeof (buf));
|
||
+ }
|
||
+ resolv_response_close_record (b);
|
||
+
|
||
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
|
||
+ resolv_response_add_name (b, "0.in-addr.arpa");
|
||
+ resolv_response_close_record (b);
|
||
+ break;
|
||
+ case 7:
|
||
+ /* Test CNAME handling. */
|
||
+ resolv_response_init (b, (struct resolv_response_flags) { });
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+ resolv_response_open_record (b, qname, qclass, T_CNAME, 0);
|
||
+ resolv_response_add_name (b, "cname.example");
|
||
+ resolv_response_close_record (b);
|
||
+ resolv_response_open_record (b, "cname.example", qclass, T_PTR, 0);
|
||
+ resolv_response_add_name (b, "4.3.2.1.in-addr.arpa");
|
||
+ resolv_response_close_record (b);
|
||
+ break;
|
||
+
|
||
+ case 100:
|
||
+ resolv_response_init (b, (struct resolv_response_flags) { .rcode = 0, });
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ break;
|
||
+ case 101:
|
||
+ resolv_response_init (b, (struct resolv_response_flags)
|
||
+ { .rcode = NXDOMAIN, });
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ break;
|
||
+ case 102:
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {.rcode = SERVFAIL});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ break;
|
||
+ case 103:
|
||
+ /* Check response length matching. */
|
||
+ if (!ctx->tcp)
|
||
+ {
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {.tc = true});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ resolv_response_init (b, (struct resolv_response_flags) {.ancount = 1});
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
|
||
+ resolv_response_add_name (b, "127.in-addr.arpa");
|
||
+ resolv_response_close_record (b);
|
||
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
|
||
+ resolv_response_add_name (b, "example");
|
||
+ resolv_response_close_record (b);
|
||
+
|
||
+ resolv_response_open_record (b, qname, qclass, T_PTR, 0);
|
||
+ size_t to_fill = 65535 - resolv_response_length (b)
|
||
+ - 2 /* length, "n" */ - 2 /* compression reference */
|
||
+ - 2 /* RR type */;
|
||
+ for (size_t i = 0; i < to_fill; ++i)
|
||
+ resolv_response_add_data (b, "", 1);
|
||
+ resolv_response_close_record (b);
|
||
+ resolv_response_add_name (b, "n.example");
|
||
+ uint16_t rrtype = htons (T_PTR);
|
||
+ resolv_response_add_data (b, &rrtype, sizeof (rrtype));
|
||
+ }
|
||
+ break;
|
||
+ default:
|
||
+ FAIL_EXIT1 ("invalid QNAME: %s (code %d)", qname, code);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+response (const struct resolv_response_context *ctx,
|
||
+ struct resolv_response_builder *b,
|
||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||
+{
|
||
+ int code;
|
||
+ if (strstr (qname, "in-addr.arpa") == NULL)
|
||
+ {
|
||
+ char *tail;
|
||
+ if (sscanf (qname, "code%d.%ms", &code, &tail) != 2
|
||
+ || strcmp (tail, "example") != 0)
|
||
+ FAIL_EXIT1 ("invalid QNAME: %s", qname);
|
||
+ free (tail);
|
||
+ handle_code (ctx, b, qname, qclass, qtype, code);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ /* Reverse lookup. */
|
||
+ int components[4];
|
||
+ char *tail;
|
||
+ if (sscanf (qname, "%d.%d.%d.%d.%ms",
|
||
+ components, components + 1, components + 2, components + 3,
|
||
+ &tail) != 5
|
||
+ || strcmp (tail, "in-addr.arpa") != 0)
|
||
+ FAIL_EXIT1 ("invalid QNAME: %s", qname);
|
||
+ free (tail);
|
||
+ handle_code (ctx, b, qname, qclass, qtype, components[3]);
|
||
+ }
|
||
+}
|
||
+
|
||
+static void
|
||
+check_reverse (int code, const char *expected)
|
||
+{
|
||
+ char *query = xasprintf ("code=%d", code);
|
||
+ check_netent (query, getnetbyaddr (code, AF_INET), expected);
|
||
+ free (query);
|
||
+}
|
||
+
|
||
+/* Test for CVE-2016-3075. */
|
||
+static void
|
||
+check_long_name (void)
|
||
+{
|
||
+ struct xmemstream mem;
|
||
+ xopen_memstream (&mem);
|
||
+
|
||
+ char label[65];
|
||
+ memset (label, 'x', 63);
|
||
+ label[63] = '.';
|
||
+ label[64] = '\0';
|
||
+ for (unsigned i = 0; i < 64 * 1024 * 1024 / strlen (label); ++i)
|
||
+ fprintf (mem.out, "%s", label);
|
||
+
|
||
+ xfclose_memstream (&mem);
|
||
+
|
||
+ check_netent ("long name", getnetbyname (mem.buffer),
|
||
+ "error: NO_RECOVERY\n");
|
||
+
|
||
+ free (mem.buffer);
|
||
+}
|
||
+
|
||
+int
|
||
+main (void)
|
||
+{
|
||
+ struct resolv_test *obj = resolv_test_start
|
||
+ ((struct resolv_redirect_config)
|
||
+ {
|
||
+ .response_callback = response
|
||
+ });
|
||
+
|
||
+ /* Lookup by name, success cases. */
|
||
+ check_netent ("code1.example", getnetbyname ("code1.example"),
|
||
+ "alias: 1.in-addr.arpa\n"
|
||
+ "net: 0x00000001\n");
|
||
+ check_netent ("code2.example", getnetbyname ("code2.example"),
|
||
+ "alias: 2.1.in-addr.arpa\n"
|
||
+ "net: 0x00000102\n");
|
||
+ check_netent ("code3.example", getnetbyname ("code3.example"),
|
||
+ "alias: 3.2.1.in-addr.arpa\n"
|
||
+ "net: 0x00010203\n");
|
||
+ check_netent ("code4.example", getnetbyname ("code4.example"),
|
||
+ "alias: 4.3.2.1.in-addr.arpa\n"
|
||
+ "net: 0x01020304\n");
|
||
+ check_netent ("code5.example", getnetbyname ("code5.example"),
|
||
+ "alias: 127.in-addr.arpa\n"
|
||
+ "alias: 0.in-addr.arpa\n"
|
||
+ "net: 0x0000007f\n");
|
||
+ check_netent ("code6.example", getnetbyname ("code6.example"),
|
||
+ "alias: 127.in-addr.arpa\n"
|
||
+ "alias: 0.in-addr.arpa\n"
|
||
+ "net: 0x0000007f\n");
|
||
+ check_netent ("code7.example", getnetbyname ("code7.example"),
|
||
+ "alias: 4.3.2.1.in-addr.arpa\n"
|
||
+ "net: 0x01020304\n");
|
||
+
|
||
+ /* Lookup by name, failure cases. */
|
||
+ check_netent ("code100.example", getnetbyname ("code100.example"),
|
||
+ "error: NO_ADDRESS\n");
|
||
+ check_netent ("code101.example", getnetbyname ("code101.example"),
|
||
+ "error: HOST_NOT_FOUND\n");
|
||
+ check_netent ("code102.example", getnetbyname ("code102.example"),
|
||
+ "error: TRY_AGAIN\n");
|
||
+ check_netent ("code103.example", getnetbyname ("code103.example"),
|
||
+ "error: NO_RECOVERY\n");
|
||
+
|
||
+ /* Lookup by address, success cases. */
|
||
+ check_reverse (1,
|
||
+ "name: 1.in-addr.arpa\n"
|
||
+ "net: 0x00000001\n");
|
||
+ check_reverse (2,
|
||
+ "name: 2.1.in-addr.arpa\n"
|
||
+ "net: 0x00000002\n");
|
||
+ check_reverse (3,
|
||
+ "name: 3.2.1.in-addr.arpa\n"
|
||
+ "net: 0x00000003\n");
|
||
+ check_reverse (4,
|
||
+ "name: 4.3.2.1.in-addr.arpa\n"
|
||
+ "net: 0x00000004\n");
|
||
+ check_reverse (5,
|
||
+ "name: 127.in-addr.arpa\n"
|
||
+ "alias: 0.in-addr.arpa\n"
|
||
+ "net: 0x00000005\n");
|
||
+ check_reverse (6,
|
||
+ "name: 127.in-addr.arpa\n"
|
||
+ "alias: 0.in-addr.arpa\n"
|
||
+ "net: 0x00000006\n");
|
||
+ check_reverse (7,
|
||
+ "name: 4.3.2.1.in-addr.arpa\n"
|
||
+ "net: 0x00000007\n");
|
||
+
|
||
+ /* Lookup by address, failure cases. */
|
||
+ check_reverse (100,
|
||
+ "error: NO_ADDRESS\n");
|
||
+ check_reverse (101,
|
||
+ "error: HOST_NOT_FOUND\n");
|
||
+ check_reverse (102,
|
||
+ "error: TRY_AGAIN\n");
|
||
+ check_reverse (103,
|
||
+ "error: NO_RECOVERY\n");
|
||
+
|
||
+ check_long_name ();
|
||
+
|
||
+ resolv_test_end (obj);
|
||
+}
|
||
diff --git a/resolv/tst-resolv-qtypes.c b/resolv/tst-resolv-qtypes.c
|
||
new file mode 100644
|
||
index 0000000000000000..06ea3dbd1463ef60
|
||
--- /dev/null
|
||
+++ b/resolv/tst-resolv-qtypes.c
|
||
@@ -0,0 +1,185 @@
|
||
+/* Exercise low-level query functions with different QTYPEs.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <resolv.h>
|
||
+#include <string.h>
|
||
+#include <support/check.h>
|
||
+#include <support/check_nss.h>
|
||
+#include <support/resolv_test.h>
|
||
+#include <support/support.h>
|
||
+#include <support/test-driver.h>
|
||
+#include <support/xmemstream.h>
|
||
+
|
||
+/* If ture, the response function will send the actual response packet
|
||
+ over TCP instead of UDP. */
|
||
+static volatile bool force_tcp;
|
||
+
|
||
+/* Send back a fake resource record matching the QTYPE. */
|
||
+static void
|
||
+response (const struct resolv_response_context *ctx,
|
||
+ struct resolv_response_builder *b,
|
||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||
+{
|
||
+ if (force_tcp && ctx->tcp)
|
||
+ {
|
||
+ resolv_response_init (b, (struct resolv_response_flags) { .tc = 1 });
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ resolv_response_init (b, (struct resolv_response_flags) { });
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
|
||
+ resolv_response_add_data (b, &qtype, sizeof (qtype));
|
||
+ resolv_response_close_record (b);
|
||
+}
|
||
+
|
||
+static const char * const domain = "www.example.com";
|
||
+
|
||
+static int
|
||
+wrap_res_query (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ return res_query (domain, C_IN, type, answer, answer_length);
|
||
+}
|
||
+
|
||
+static int
|
||
+wrap_res_search (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ return res_query (domain, C_IN, type, answer, answer_length);
|
||
+}
|
||
+
|
||
+static int
|
||
+wrap_res_querydomain (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ return res_querydomain ("www", "example.com", C_IN, type,
|
||
+ answer, answer_length);
|
||
+}
|
||
+
|
||
+static int
|
||
+wrap_res_send (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ unsigned char buf[512];
|
||
+ int ret = res_mkquery (QUERY, domain, C_IN, type,
|
||
+ (const unsigned char *) "", 0, NULL,
|
||
+ buf, sizeof (buf));
|
||
+ if (type < 0 || type >= 65536)
|
||
+ {
|
||
+ /* res_mkquery fails for out-of-range record types. */
|
||
+ TEST_VERIFY_EXIT (ret == -1);
|
||
+ return -1;
|
||
+ }
|
||
+ TEST_VERIFY_EXIT (ret > 12); /* DNS header length. */
|
||
+ return res_send (buf, ret, answer, answer_length);
|
||
+}
|
||
+
|
||
+static int
|
||
+wrap_res_nquery (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ return res_nquery (&_res, domain, C_IN, type, answer, answer_length);
|
||
+}
|
||
+
|
||
+static int
|
||
+wrap_res_nsearch (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ return res_nquery (&_res, domain, C_IN, type, answer, answer_length);
|
||
+}
|
||
+
|
||
+static int
|
||
+wrap_res_nquerydomain (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ return res_nquerydomain (&_res, "www", "example.com", C_IN, type,
|
||
+ answer, answer_length);
|
||
+}
|
||
+
|
||
+static int
|
||
+wrap_res_nsend (int type, unsigned char *answer, int answer_length)
|
||
+{
|
||
+ unsigned char buf[512];
|
||
+ int ret = res_nmkquery (&_res, QUERY, domain, C_IN, type,
|
||
+ (const unsigned char *) "", 0, NULL,
|
||
+ buf, sizeof (buf));
|
||
+ if (type < 0 || type >= 65536)
|
||
+ {
|
||
+ /* res_mkquery fails for out-of-range record types. */
|
||
+ TEST_VERIFY_EXIT (ret == -1);
|
||
+ return -1;
|
||
+ }
|
||
+ TEST_VERIFY_EXIT (ret > 12); /* DNS header length. */
|
||
+ return res_nsend (&_res, buf, ret, answer, answer_length);
|
||
+}
|
||
+
|
||
+static void
|
||
+test_function (const char *fname,
|
||
+ int (*func) (int type,
|
||
+ unsigned char *answer, int answer_length))
|
||
+{
|
||
+ unsigned char buf[512];
|
||
+ for (int tcp = 0; tcp < 2; ++tcp)
|
||
+ {
|
||
+ force_tcp = tcp;
|
||
+ for (unsigned int type = 1; type <= 65535; ++type)
|
||
+ {
|
||
+ if (test_verbose)
|
||
+ printf ("info: sending QTYPE %d with %s (tcp=%d)\n",
|
||
+ type, fname, tcp);
|
||
+ int ret = func (type, buf, sizeof (buf));
|
||
+ if (ret != 47)
|
||
+ FAIL_EXIT1 ("%s tcp=%d qtype=%d return value %d",
|
||
+ fname,tcp, type, ret);
|
||
+ /* One question, one answer record. */
|
||
+ TEST_VERIFY (memcmp (buf + 4, "\0\1\0\1\0\0\0\0", 8) == 0);
|
||
+ /* Question section. */
|
||
+ static const char qname[] = "\3www\7example\3com";
|
||
+ size_t qname_length = sizeof (qname);
|
||
+ TEST_VERIFY (memcmp (buf + 12, qname, qname_length) == 0);
|
||
+ /* RDATA part of answer. */
|
||
+ uint16_t type16 = type;
|
||
+ TEST_VERIFY (memcmp (buf + ret - 2, &type16, sizeof (type16)) == 0);
|
||
+ }
|
||
+ }
|
||
+
|
||
+ TEST_VERIFY (func (-1, buf, sizeof (buf) == -1));
|
||
+ TEST_VERIFY (func (65536, buf, sizeof (buf) == -1));
|
||
+}
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ struct resolv_redirect_config config =
|
||
+ {
|
||
+ .response_callback = response,
|
||
+ };
|
||
+ struct resolv_test *obj = resolv_test_start (config);
|
||
+
|
||
+ test_function ("res_query", &wrap_res_query);
|
||
+ test_function ("res_search", &wrap_res_search);
|
||
+ test_function ("res_querydomain", &wrap_res_querydomain);
|
||
+ test_function ("res_send", &wrap_res_send);
|
||
+
|
||
+ test_function ("res_nquery", &wrap_res_nquery);
|
||
+ test_function ("res_nsearch", &wrap_res_nsearch);
|
||
+ test_function ("res_nquerydomain", &wrap_res_nquerydomain);
|
||
+ test_function ("res_nsend", &wrap_res_nsend);
|
||
+
|
||
+ resolv_test_end (obj);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#define TIMEOUT 300
|
||
+#include <support/test-driver.c>
|
||
diff --git a/resolv/tst-resolv-res_init-multi.c b/resolv/tst-resolv-res_init-multi.c
|
||
new file mode 100644
|
||
index 0000000000000000..bdc68a5a33f7f017
|
||
--- /dev/null
|
||
+++ b/resolv/tst-resolv-res_init-multi.c
|
||
@@ -0,0 +1,89 @@
|
||
+/* Multi-threaded test for resolver initialization.
|
||
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <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 0000000000000000..3b7b4129e31eaa22
|
||
--- /dev/null
|
||
+++ b/resolv/tst-resolv-res_init-skeleton.c
|
||
@@ -0,0 +1,1092 @@
|
||
+/* Test parsing of /etc/resolv.conf. Genric version.
|
||
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+/* Before including this file, TEST_THREAD has to be defined to 0 or
|
||
+ 1, depending on whether the threading tests should be compiled
|
||
+ in. */
|
||
+
|
||
+#include <arpa/inet.h>
|
||
+#include <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)
|
||
+ {
|
||
+ /* 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);
|
||
+ }
|
||
+
|
||
+ 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 0000000000000000..f47ac34f7fc7a6c8
|
||
--- /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 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 0000000000000000..40c0154eca7363cb
|
||
--- /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 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 0000000000000000..d08153fed78b5f03
|
||
--- /dev/null
|
||
+++ b/resolv/tst-resolv-res_ninit.c
|
||
@@ -0,0 +1,74 @@
|
||
+/* Test the creation of many struct __res_state objects.
|
||
+ Copyright (C) 2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <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;
|
||
+}
|
||
+
|
||
+#include <support/test-driver.c>
|
||
diff --git a/resolv/tst-resolv-rotate.c b/resolv/tst-resolv-rotate.c
|
||
new file mode 100644
|
||
index 0000000000000000..d01b85b2fe82930b
|
||
--- /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 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 0000000000000000..a5406b3b0ecb28c4
|
||
--- /dev/null
|
||
+++ b/resolv/tst-resolv-search.c
|
||
@@ -0,0 +1,344 @@
|
||
+/* Test search/default domain name behavior.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+#include <resolv.h>
|
||
+#include <stdlib.h>
|
||
+#include <string.h>
|
||
+#include <support/check.h>
|
||
+#include <support/check_nss.h>
|
||
+#include <support/resolv_test.h>
|
||
+#include <support/support.h>
|
||
+#include <support/xmemstream.h>
|
||
+
|
||
+struct item
|
||
+{
|
||
+ const char *name;
|
||
+ int response;
|
||
+};
|
||
+
|
||
+const struct item items[] =
|
||
+ {
|
||
+ {"hostname.usersys.example.com", 1},
|
||
+ {"hostname.corp.example.com", 1},
|
||
+ {"hostname.example.com", 1},
|
||
+
|
||
+ {"mail.corp.example.com", 1},
|
||
+ {"mail.example.com", 1},
|
||
+
|
||
+ {"file.corp.example.com", 2},
|
||
+ {"file.corp", 1},
|
||
+ {"file.example.com", 1},
|
||
+ {"servfail-usersys.usersys.example.com", -ns_r_servfail},
|
||
+ {"servfail-usersys.corp.example.com", 1},
|
||
+ {"servfail-usersys.example.com", 1},
|
||
+ {"servfail-corp.usersys.example.com", 1},
|
||
+ {"servfail-corp.corp.example.com", -ns_r_servfail},
|
||
+ {"servfail-corp.example.com", 1},
|
||
+ {"www.example.com", 1},
|
||
+ {"large.example.com", 200},
|
||
+
|
||
+ /* Test query amplification with a SERVFAIL response combined with
|
||
+ a large RRset. */
|
||
+ {"large-servfail.usersys.example.com", -ns_r_servfail},
|
||
+ {"large-servfail.example.com", 2000},
|
||
+ {}
|
||
+ };
|
||
+
|
||
+enum
|
||
+ {
|
||
+ name_not_found = -1,
|
||
+ name_no_data = -2
|
||
+ };
|
||
+
|
||
+static int
|
||
+find_name (const char *name)
|
||
+{
|
||
+ for (int i = 0; items[i].name != NULL; ++i)
|
||
+ {
|
||
+ if (strcmp (name, items[i].name) == 0)
|
||
+ return i;
|
||
+ }
|
||
+ if (strcmp (name, "example.com") == 0
|
||
+ || strcmp (name, "usersys.example.com") == 0
|
||
+ || strcmp (name, "corp.example.com") == 0)
|
||
+ return name_no_data;
|
||
+ return name_not_found;
|
||
+}
|
||
+
|
||
+static int rcode_override_server_index = -1;
|
||
+static int rcode_override;
|
||
+
|
||
+static void
|
||
+response (const struct resolv_response_context *ctx,
|
||
+ struct resolv_response_builder *b,
|
||
+ const char *qname, uint16_t qclass, uint16_t qtype)
|
||
+{
|
||
+ if (ctx->server_index == rcode_override_server_index)
|
||
+ {
|
||
+ struct resolv_response_flags flags = {.rcode = rcode_override};
|
||
+ resolv_response_init (b, flags);
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+ return;
|
||
+ }
|
||
+
|
||
+ int index = find_name (qname);
|
||
+ struct resolv_response_flags flags = {};
|
||
+ if (index == name_not_found)
|
||
+ flags.rcode = ns_r_nxdomain;
|
||
+ else if (index >= 0 && items[index].response < 0)
|
||
+ flags.rcode = -items[index].response;
|
||
+ else if (index >= 0 && items[index].response > 5 && !ctx->tcp)
|
||
+ /* Force TCP if more than 5 addresses where requested. */
|
||
+ flags.tc = true;
|
||
+ resolv_response_init (b, flags);
|
||
+ resolv_response_add_question (b, qname, qclass, qtype);
|
||
+
|
||
+ if (flags.tc || index < 0 || items[index].response < 0)
|
||
+ return;
|
||
+
|
||
+ resolv_response_section (b, ns_s_an);
|
||
+
|
||
+ for (int i = 0; i < items[index].response; ++i)
|
||
+ {
|
||
+ resolv_response_open_record (b, qname, qclass, qtype, 0);
|
||
+
|
||
+ switch (qtype)
|
||
+ {
|
||
+ case T_A:
|
||
+ {
|
||
+ char addr[4] = {10, index, i >> 8, i};
|
||
+ resolv_response_add_data (b, addr, sizeof (addr));
|
||
+ }
|
||
+ break;
|
||
+ case T_AAAA:
|
||
+ {
|
||
+ char addr[16]
|
||
+ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0,
|
||
+ 0, index + 1, (i + 1) >> 8, i + 1};
|
||
+ resolv_response_add_data (b, addr, sizeof (addr));
|
||
+ }
|
||
+ break;
|
||
+ default:
|
||
+ support_record_failure ();
|
||
+ printf ("error: unexpected QTYPE: %s/%u/%u\n",
|
||
+ qname, qclass, qtype);
|
||
+ }
|
||
+ resolv_response_close_record (b);
|
||
+ }
|
||
+}
|
||
+
|
||
+enum output_format
|
||
+ {
|
||
+ format_get, format_gai
|
||
+ };
|
||
+
|
||
+static void
|
||
+format_expected_1 (FILE *out, int family, enum output_format format, int index)
|
||
+{
|
||
+ for (int i = 0; i < items[index].response; ++i)
|
||
+ {
|
||
+ char address[200];
|
||
+ switch (family)
|
||
+ {
|
||
+ case AF_INET:
|
||
+ snprintf (address, sizeof (address), "10.%d.%d.%d",
|
||
+ index, (i >> 8) & 0xff, i & 0xff);
|
||
+ break;
|
||
+ case AF_INET6:
|
||
+ snprintf (address, sizeof (address), "2001:db8::%x:%x",
|
||
+ index + 1, i + 1);
|
||
+ break;
|
||
+ default:
|
||
+ FAIL_EXIT1 ("unreachable");
|
||
+ }
|
||
+
|
||
+ switch (format)
|
||
+ {
|
||
+ case format_get:
|
||
+ fprintf (out, "address: %s\n", address);
|
||
+ break;
|
||
+ case format_gai:
|
||
+ fprintf (out, "address: STREAM/TCP %s 80\n", address);
|
||
+ }
|
||
+ }
|
||
+}
|
||
+
|
||
+static char *
|
||
+format_expected (const char *fqdn, int family, enum output_format format)
|
||
+{
|
||
+ int index = find_name (fqdn);
|
||
+ TEST_VERIFY_EXIT (index >= 0);
|
||
+ struct xmemstream stream;
|
||
+ xopen_memstream (&stream);
|
||
+
|
||
+ TEST_VERIFY_EXIT (items[index].response >= 0);
|
||
+ if (format == format_get)
|
||
+ fprintf (stream.out, "name: %s\n", items[index].name);
|
||
+ if (family == AF_INET || family == AF_UNSPEC)
|
||
+ format_expected_1 (stream.out, AF_INET, format, index);
|
||
+ if (family == AF_INET6 || family == AF_UNSPEC)
|
||
+ format_expected_1 (stream.out, AF_INET6, format, index);
|
||
+
|
||
+ xfclose_memstream (&stream);
|
||
+ return stream.buffer;
|
||
+}
|
||
+
|
||
+static void
|
||
+do_get (const char *name, const char *fqdn, int family)
|
||
+{
|
||
+ char *expected = format_expected (fqdn, family, format_get);
|
||
+ if (family == AF_INET)
|
||
+ {
|
||
+ char *query = xasprintf ("gethostbyname (\"%s\")", name);
|
||
+ check_hostent (query, gethostbyname (name), expected);
|
||
+ free (query);
|
||
+ }
|
||
+ char *query = xasprintf ("gethostbyname2 (\"%s\", %d)", name, family);
|
||
+ check_hostent (query, gethostbyname2 (name, family), expected);
|
||
+
|
||
+ /* Test res_search. */
|
||
+ int qtype;
|
||
+ switch (family)
|
||
+ {
|
||
+ case AF_INET:
|
||
+ qtype = T_A;
|
||
+ break;
|
||
+ case AF_INET6:
|
||
+ qtype = T_AAAA;
|
||
+ break;
|
||
+ default:
|
||
+ qtype = -1;
|
||
+ }
|
||
+ if (qtype >= 0)
|
||
+ {
|
||
+ int sz = 512;
|
||
+ unsigned char *response = xmalloc (sz);
|
||
+ int ret = res_search (name, C_IN, qtype, response, sz);
|
||
+ TEST_VERIFY_EXIT (ret >= 0);
|
||
+ if (ret > sz)
|
||
+ {
|
||
+ /* Truncation. Retry with a larger buffer. */
|
||
+ sz = 65535;
|
||
+ unsigned char *newptr = xrealloc (response, sz);
|
||
+ response = newptr;
|
||
+
|
||
+ ret = res_search (name, C_IN, qtype, response, sz);
|
||
+ TEST_VERIFY_EXIT (ret >= 0);
|
||
+ TEST_VERIFY_EXIT (ret < sz);
|
||
+ }
|
||
+ check_dns_packet (query, response, ret, expected);
|
||
+ free (response);
|
||
+ }
|
||
+
|
||
+ free (query);
|
||
+ free (expected);
|
||
+}
|
||
+
|
||
+static void
|
||
+do_gai (const char *name, const char *fqdn, int family)
|
||
+{
|
||
+ struct addrinfo hints =
|
||
+ {
|
||
+ .ai_family = family,
|
||
+ .ai_protocol = IPPROTO_TCP,
|
||
+ .ai_socktype = SOCK_STREAM
|
||
+ };
|
||
+ struct addrinfo *ai;
|
||
+ char *query = xasprintf ("%s:80 [%d]", name, family);
|
||
+ int ret = getaddrinfo (name, "80", &hints, &ai);
|
||
+ char *expected = format_expected (fqdn, family, format_gai);
|
||
+ check_addrinfo (query, ai, ret, expected);
|
||
+ if (ret == 0)
|
||
+ freeaddrinfo (ai);
|
||
+ free (expected);
|
||
+ free (query);
|
||
+}
|
||
+
|
||
+static void
|
||
+do_both (const char *name, const char *fqdn)
|
||
+{
|
||
+ do_get (name, fqdn, AF_INET);
|
||
+ do_get (name, fqdn, AF_INET6);
|
||
+ do_gai (name, fqdn, AF_INET);
|
||
+ do_gai (name, fqdn, AF_INET6);
|
||
+ do_gai (name, fqdn, AF_UNSPEC);
|
||
+}
|
||
+
|
||
+static void
|
||
+do_test_all (bool unconnectable_server)
|
||
+{
|
||
+ struct resolv_redirect_config config =
|
||
+ {
|
||
+ .response_callback = response,
|
||
+ .search = {"usersys.example.com", "corp.example.com", "example.com"},
|
||
+ };
|
||
+ struct resolv_test *obj = resolv_test_start (config);
|
||
+
|
||
+ if (unconnectable_server)
|
||
+ {
|
||
+ /* 255.255.255.255 results in an immediate connect failure. The
|
||
+ next server will supply the answer instead. This is a
|
||
+ triggering condition for bug 19791. */
|
||
+ _res.nsaddr_list[0].sin_addr.s_addr = -1;
|
||
+ _res.nsaddr_list[0].sin_port = htons (53);
|
||
+ }
|
||
+
|
||
+ do_both ("file", "file.corp.example.com");
|
||
+ do_both ("www", "www.example.com");
|
||
+ do_both ("servfail-usersys", "servfail-usersys.corp.example.com");
|
||
+ do_both ("servfail-corp", "servfail-corp.usersys.example.com");
|
||
+ do_both ("large", "large.example.com");
|
||
+ do_both ("large-servfail", "large-servfail.example.com");
|
||
+ do_both ("file.corp", "file.corp");
|
||
+
|
||
+ /* Check that SERVFAIL and REFUSED responses do not alter the search
|
||
+ path resolution. */
|
||
+ rcode_override_server_index = 0;
|
||
+ rcode_override = ns_r_servfail;
|
||
+ do_both ("hostname", "hostname.usersys.example.com");
|
||
+ do_both ("large", "large.example.com");
|
||
+ do_both ("large-servfail", "large-servfail.example.com");
|
||
+ rcode_override = ns_r_refused;
|
||
+ do_both ("hostname", "hostname.usersys.example.com");
|
||
+ do_both ("large", "large.example.com");
|
||
+ do_both ("large-servfail", "large-servfail.example.com");
|
||
+ /* Likewise, but with an NXDOMAIN for the first search path
|
||
+ entry. */
|
||
+ rcode_override = ns_r_servfail;
|
||
+ do_both ("mail", "mail.corp.example.com");
|
||
+ rcode_override = ns_r_refused;
|
||
+ do_both ("mail", "mail.corp.example.com");
|
||
+ /* Likewise, but with ndots handling. */
|
||
+ rcode_override = ns_r_servfail;
|
||
+ do_both ("file.corp", "file.corp");
|
||
+ rcode_override = ns_r_refused;
|
||
+ do_both ("file.corp", "file.corp");
|
||
+
|
||
+ resolv_test_end (obj);
|
||
+}
|
||
+
|
||
+static int
|
||
+do_test (void)
|
||
+{
|
||
+ for (int unconnectable_server = 0; unconnectable_server < 2;
|
||
+ ++unconnectable_server)
|
||
+ do_test_all (unconnectable_server);
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+#include <support/test-driver.c>
|
||
diff --git a/resolv/tst-resolv-threads.c b/resolv/tst-resolv-threads.c
|
||
new file mode 100644
|
||
index 0000000000000000..7be417b056f720d8
|
||
--- /dev/null
|
||
+++ b/resolv/tst-resolv-threads.c
|
||
@@ -0,0 +1,484 @@
|
||
+/* Test basic nss_dns functionality with multiple threads.
|
||
+ Copyright (C) 2016-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
+/* 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>
|
||
diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
|
||
index 7a6cf71c170ec42f..2c4b6d6793a4c3a9 100644
|
||
--- a/sysdeps/posix/getaddrinfo.c
|
||
+++ b/sysdeps/posix/getaddrinfo.c
|
||
@@ -1,3 +1,21 @@
|
||
+/* Host and service name lookups using Name Service Switch modules.
|
||
+ Copyright (C) 1996-2017 Free Software Foundation, Inc.
|
||
+ This file is part of the GNU C Library.
|
||
+
|
||
+ The GNU C Library is free software; you can redistribute it and/or
|
||
+ modify it under the terms of the GNU Lesser General Public
|
||
+ License as published by the Free Software Foundation; either
|
||
+ version 2.1 of the License, or (at your option) any later version.
|
||
+
|
||
+ The GNU C Library is distributed in the hope that it will be useful,
|
||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
+ Lesser General Public License for more details.
|
||
+
|
||
+ You should have received a copy of the GNU Lesser General Public
|
||
+ License along with the GNU C Library; if not, see
|
||
+ <http://www.gnu.org/licenses/>. */
|
||
+
|
||
/* The Inner Net License, Version 2.00
|
||
|
||
The author(s) grant permission for redistribution and use in source and
|
||
@@ -42,11 +60,14 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
#include <netdb.h>
|
||
#include <nss.h>
|
||
#include <resolv/resolv-internal.h>
|
||
+#include <resolv/resolv_context.h>
|
||
+#include <resolv/res_use_inet6.h>
|
||
#include <stdbool.h>
|
||
#include <stdio.h>
|
||
#include <stdio_ext.h>
|
||
#include <stdlib.h>
|
||
#include <string.h>
|
||
+#include <stdint.h>
|
||
#include <arpa/inet.h>
|
||
#include <net/if.h>
|
||
#include <netinet/in.h>
|
||
@@ -57,11 +78,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||
#include <sys/utsname.h>
|
||
#include <unistd.h>
|
||
#include <nsswitch.h>
|
||
-#include <bits/libc-lock.h>
|
||
+#include <libc-lock.h>
|
||
#include <not-cancel.h>
|
||
#include <nscd/nscd-client.h>
|
||
#include <nscd/nscd_proto.h>
|
||
-#include <resolv/res_hconf.h>
|
||
+#include <scratch_buffer.h>
|
||
+#include <inet/net-internal.h>
|
||
|
||
#ifdef HAVE_LIBIDN
|
||
extern int __idna_to_ascii_lz (const char *input, char **output, int flags);
|
||
@@ -70,13 +92,6 @@ extern int __idna_to_unicode_lzlz (const char *input, char **output,
|
||
# include <libidn/idna.h>
|
||
#endif
|
||
|
||
-#define GAIH_OKIFUNSPEC 0x0100
|
||
-#define GAIH_EAI ~(GAIH_OKIFUNSPEC)
|
||
-
|
||
-#ifndef UNIX_PATH_MAX
|
||
-# define UNIX_PATH_MAX 108
|
||
-#endif
|
||
-
|
||
struct gaih_service
|
||
{
|
||
const char *name;
|
||
@@ -126,14 +141,6 @@ static const struct gaih_typeproto gaih_inet_typeproto[] =
|
||
{ 0, 0, 0, false, "" }
|
||
};
|
||
|
||
-struct gaih
|
||
- {
|
||
- int family;
|
||
- int (*gaih)(const char *name, const struct gaih_service *service,
|
||
- const struct addrinfo *req, struct addrinfo **pai,
|
||
- unsigned int *naddrs);
|
||
- };
|
||
-
|
||
static const struct addrinfo default_hints =
|
||
{
|
||
.ai_flags = AI_DEFAULT,
|
||
@@ -149,26 +156,26 @@ static const struct addrinfo default_hints =
|
||
|
||
static int
|
||
gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
|
||
- const struct addrinfo *req, struct gaih_servtuple *st)
|
||
+ const struct addrinfo *req, struct gaih_servtuple *st,
|
||
+ struct scratch_buffer *tmpbuf)
|
||
{
|
||
struct servent *s;
|
||
- size_t tmpbuflen = 1024;
|
||
struct servent ts;
|
||
- char *tmpbuf;
|
||
int r;
|
||
|
||
do
|
||
{
|
||
- tmpbuf = __alloca (tmpbuflen);
|
||
-
|
||
- r = __getservbyname_r (servicename, tp->name, &ts, tmpbuf, tmpbuflen,
|
||
- &s);
|
||
+ r = __getservbyname_r (servicename, tp->name, &ts,
|
||
+ tmpbuf->data, tmpbuf->length, &s);
|
||
if (r != 0 || s == NULL)
|
||
{
|
||
if (r == ERANGE)
|
||
- tmpbuflen *= 2;
|
||
+ {
|
||
+ if (!scratch_buffer_grow (tmpbuf))
|
||
+ return -EAI_MEMORY;
|
||
+ }
|
||
else
|
||
- return GAIH_OKIFUNSPEC | -EAI_SERVICE;
|
||
+ return -EAI_SERVICE;
|
||
}
|
||
}
|
||
while (r);
|
||
@@ -182,87 +189,114 @@ gaih_inet_serv (const char *servicename, const struct gaih_typeproto *tp,
|
||
return 0;
|
||
}
|
||
|
||
+/* Convert struct hostent to a list of struct gaih_addrtuple objects.
|
||
+ h_name is not copied, and the struct hostent object must not be
|
||
+ deallocated prematurely. *RESULT must be NULL or a pointer to a
|
||
+ linked-list. The new addresses are appended at the end. */
|
||
+static bool
|
||
+convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
|
||
+ int family,
|
||
+ struct hostent *h,
|
||
+ struct gaih_addrtuple **result)
|
||
+{
|
||
+ while (*result)
|
||
+ result = &(*result)->next;
|
||
+
|
||
+ /* Count the number of addresses in h->h_addr_list. */
|
||
+ size_t count = 0;
|
||
+ for (char **p = h->h_addr_list; *p != NULL; ++p)
|
||
+ ++count;
|
||
+
|
||
+ /* Report no data if no addresses are available, or if the incoming
|
||
+ address size is larger than what we can store. */
|
||
+ if (count == 0 || h->h_length > sizeof (((struct gaih_addrtuple) {}).addr))
|
||
+ return true;
|
||
+
|
||
+ struct gaih_addrtuple *array = calloc (count, sizeof (*array));
|
||
+ if (array == NULL)
|
||
+ return false;
|
||
+
|
||
+ for (size_t i = 0; i < count; ++i)
|
||
+ {
|
||
+ if (family == AF_INET && req->ai_family == AF_INET6)
|
||
+ {
|
||
+ /* Perform address mapping. */
|
||
+ array[i].family = AF_INET6;
|
||
+ memcpy(array[i].addr + 3, h->h_addr_list[i], sizeof (uint32_t));
|
||
+ array[i].addr[2] = htonl (0xffff);
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ array[i].family = family;
|
||
+ memcpy (array[i].addr, h->h_addr_list[i], h->h_length);
|
||
+ }
|
||
+ array[i].next = array + i + 1;
|
||
+ }
|
||
+ array[0].name = h->h_name;
|
||
+ array[count - 1].next = NULL;
|
||
+
|
||
+ *result = array;
|
||
+ return true;
|
||
+}
|
||
+
|
||
#define gethosts(_family, _type) \
|
||
{ \
|
||
- int i; \
|
||
- int herrno; \
|
||
struct hostent th; \
|
||
- struct hostent *h; \
|
||
char *localcanon = NULL; \
|
||
no_data = 0; \
|
||
- while (1) { \
|
||
- rc = 0; \
|
||
- status = DL_CALL_FCT (fct, (name, _family, &th, tmpbuf, tmpbuflen, \
|
||
- &rc, &herrno, NULL, &localcanon)); \
|
||
- if (rc != ERANGE || herrno != NETDB_INTERNAL) \
|
||
- break; \
|
||
- if (!malloc_tmpbuf && __libc_use_alloca (alloca_used + 2 * tmpbuflen)) \
|
||
- tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen, 2 * tmpbuflen, \
|
||
- alloca_used); \
|
||
- else \
|
||
- { \
|
||
- char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL, \
|
||
- 2 * tmpbuflen); \
|
||
- if (newp == NULL) \
|
||
- { \
|
||
- result = -EAI_MEMORY; \
|
||
- goto free_and_return; \
|
||
- } \
|
||
- tmpbuf = newp; \
|
||
- malloc_tmpbuf = true; \
|
||
- tmpbuflen = 2 * tmpbuflen; \
|
||
- } \
|
||
- } \
|
||
- if (status == NSS_STATUS_SUCCESS && rc == 0) \
|
||
- h = &th; \
|
||
- else \
|
||
- h = NULL; \
|
||
- if (rc != 0) \
|
||
+ while (1) \
|
||
{ \
|
||
- if (herrno == NETDB_INTERNAL) \
|
||
+ status = DL_CALL_FCT (fct, (name, _family, &th, \
|
||
+ tmpbuf->data, tmpbuf->length, \
|
||
+ &errno, &h_errno, NULL, &localcanon)); \
|
||
+ if (status != NSS_STATUS_TRYAGAIN || h_errno != NETDB_INTERNAL \
|
||
+ || errno != ERANGE) \
|
||
+ break; \
|
||
+ if (!scratch_buffer_grow (tmpbuf)) \
|
||
{ \
|
||
- __set_h_errno (herrno); \
|
||
- _res.options |= old_res_options & DEPRECATED_RES_USE_INET6; \
|
||
+ __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \
|
||
+ __resolv_context_put (res_ctx); \
|
||
+ result = -EAI_MEMORY; \
|
||
+ goto free_and_return; \
|
||
+ } \
|
||
+ } \
|
||
+ if (status == NSS_STATUS_NOTFOUND \
|
||
+ || status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL) \
|
||
+ { \
|
||
+ if (h_errno == NETDB_INTERNAL) \
|
||
+ { \
|
||
+ __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \
|
||
+ __resolv_context_put (res_ctx); \
|
||
result = -EAI_SYSTEM; \
|
||
goto free_and_return; \
|
||
} \
|
||
- if (herrno == TRY_AGAIN) \
|
||
+ if (h_errno == TRY_AGAIN) \
|
||
no_data = EAI_AGAIN; \
|
||
else \
|
||
- no_data = herrno == NO_DATA; \
|
||
+ no_data = h_errno == NO_DATA; \
|
||
} \
|
||
- else if (h != NULL) \
|
||
+ else if (status == NSS_STATUS_SUCCESS) \
|
||
{ \
|
||
- for (i = 0; h->h_addr_list[i]; i++) \
|
||
+ if (!convert_hostent_to_gaih_addrtuple (req, _family, &th, &addrmem)) \
|
||
{ \
|
||
- if (*pat == NULL) \
|
||
- { \
|
||
- *pat = __alloca (sizeof (struct gaih_addrtuple)); \
|
||
- (*pat)->scopeid = 0; \
|
||
- } \
|
||
- uint32_t *addr = (*pat)->addr; \
|
||
- (*pat)->next = NULL; \
|
||
- (*pat)->name = i == 0 ? strdupa (h->h_name) : NULL; \
|
||
- if (_family == AF_INET && req->ai_family == AF_INET6) \
|
||
- { \
|
||
- (*pat)->family = AF_INET6; \
|
||
- addr[3] = *(uint32_t *) h->h_addr_list[i]; \
|
||
- addr[2] = htonl (0xffff); \
|
||
- addr[1] = 0; \
|
||
- addr[0] = 0; \
|
||
- } \
|
||
- else \
|
||
+ __resolv_context_enable_inet6 (res_ctx, res_enable_inet6); \
|
||
+ __resolv_context_put (res_ctx); \
|
||
+ result = -EAI_SYSTEM; \
|
||
+ goto free_and_return; \
|
||
+ } \
|
||
+ *pat = addrmem; \
|
||
+ \
|
||
+ if (localcanon != NULL && canon == NULL) \
|
||
+ { \
|
||
+ canonbuf = __strdup (localcanon); \
|
||
+ if (canonbuf == NULL) \
|
||
{ \
|
||
- (*pat)->family = _family; \
|
||
- memcpy (addr, h->h_addr_list[i], sizeof(_type)); \
|
||
+ result = -EAI_SYSTEM; \
|
||
+ goto free_and_return; \
|
||
} \
|
||
- pat = &((*pat)->next); \
|
||
+ canon = canonbuf; \
|
||
} \
|
||
- \
|
||
- if (localcanon != NULL && canon == NULL) \
|
||
- canon = strdupa (localcanon); \
|
||
- \
|
||
- if (_family == AF_INET6 && i > 0) \
|
||
+ if (_family == AF_INET6 && *pat != NULL) \
|
||
got_ipv6 = true; \
|
||
} \
|
||
}
|
||
@@ -281,20 +315,44 @@ typedef enum nss_status (*nss_getcanonname_r)
|
||
int *errnop, int *h_errnop);
|
||
extern service_user *__nss_hosts_database attribute_hidden;
|
||
|
||
+/* This function is called if a canonical name is requested, but if
|
||
+ the service function did not provide it. It tries to obtain the
|
||
+ name using getcanonname_r from the same service NIP. If the name
|
||
+ cannot be canonicalized, return a copy of NAME. Return NULL on
|
||
+ memory allocation failure. The returned string is allocated on the
|
||
+ heap; the caller has to free it. */
|
||
+static char *
|
||
+getcanonname (service_user *nip, struct gaih_addrtuple *at, const char *name)
|
||
+{
|
||
+ nss_getcanonname_r cfct = __nss_lookup_function (nip, "getcanonname_r");
|
||
+ char *s = (char *) name;
|
||
+ if (cfct != NULL)
|
||
+ {
|
||
+ char buf[256];
|
||
+ if (DL_CALL_FCT (cfct, (at->name ?: name, buf, sizeof (buf),
|
||
+ &s, &errno, &h_errno)) != NSS_STATUS_SUCCESS)
|
||
+ /* If the canonical name cannot be determined, use the passed
|
||
+ string. */
|
||
+ s = (char *) name;
|
||
+ }
|
||
+ return __strdup (name);
|
||
+}
|
||
|
||
static int
|
||
gaih_inet (const char *name, const struct gaih_service *service,
|
||
const struct addrinfo *req, struct addrinfo **pai,
|
||
- unsigned int *naddrs)
|
||
+ unsigned int *naddrs, struct scratch_buffer *tmpbuf)
|
||
{
|
||
const struct gaih_typeproto *tp = gaih_inet_typeproto;
|
||
struct gaih_servtuple *st = (struct gaih_servtuple *) &nullserv;
|
||
struct gaih_addrtuple *at = NULL;
|
||
- int rc;
|
||
bool got_ipv6 = false;
|
||
const char *canon = NULL;
|
||
const char *orig_name = name;
|
||
- size_t alloca_used = 0;
|
||
+
|
||
+ /* Reserve stack memory for the scratch buffer in the getaddrinfo
|
||
+ function. */
|
||
+ size_t alloca_used = sizeof (struct scratch_buffer);
|
||
|
||
if (req->ai_protocol || req->ai_socktype)
|
||
{
|
||
@@ -310,9 +368,9 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
if (! tp->name[0])
|
||
{
|
||
if (req->ai_socktype)
|
||
- return GAIH_OKIFUNSPEC | -EAI_SOCKTYPE;
|
||
+ return -EAI_SOCKTYPE;
|
||
else
|
||
- return GAIH_OKIFUNSPEC | -EAI_SERVICE;
|
||
+ return -EAI_SERVICE;
|
||
}
|
||
}
|
||
|
||
@@ -320,7 +378,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
if (service != NULL)
|
||
{
|
||
if ((tp->protoflag & GAI_PROTO_NOSERVICE) != 0)
|
||
- return GAIH_OKIFUNSPEC | -EAI_SERVICE;
|
||
+ return -EAI_SERVICE;
|
||
|
||
if (service->num < 0)
|
||
{
|
||
@@ -329,7 +387,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
st = (struct gaih_servtuple *)
|
||
alloca_account (sizeof (struct gaih_servtuple), alloca_used);
|
||
|
||
- if ((rc = gaih_inet_serv (service->name, tp, req, st)))
|
||
+ int rc = gaih_inet_serv (service->name, tp, req, st, tmpbuf);
|
||
+ if (__glibc_unlikely (rc != 0))
|
||
return rc;
|
||
}
|
||
else
|
||
@@ -354,18 +413,15 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
alloca_account (sizeof (struct gaih_servtuple),
|
||
alloca_used);
|
||
|
||
- if ((rc = gaih_inet_serv (service->name, tp, req, newp)))
|
||
- {
|
||
- if (rc & GAIH_OKIFUNSPEC)
|
||
- continue;
|
||
- return rc;
|
||
- }
|
||
+ if (gaih_inet_serv (service->name,
|
||
+ tp, req, newp, tmpbuf) != 0)
|
||
+ continue;
|
||
|
||
*pst = newp;
|
||
pst = &(newp->next);
|
||
}
|
||
if (st == (struct gaih_servtuple *) &nullserv)
|
||
- return GAIH_OKIFUNSPEC | -EAI_SERVICE;
|
||
+ return -EAI_SERVICE;
|
||
}
|
||
}
|
||
else
|
||
@@ -411,13 +467,10 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
}
|
||
|
||
bool malloc_name = false;
|
||
- bool malloc_addrmem = false;
|
||
struct gaih_addrtuple *addrmem = NULL;
|
||
- bool malloc_canonbuf = false;
|
||
char *canonbuf = NULL;
|
||
- bool malloc_tmpbuf = false;
|
||
- char *tmpbuf = NULL;
|
||
int result = 0;
|
||
+
|
||
if (name != NULL)
|
||
{
|
||
at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
|
||
@@ -435,7 +488,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
idn_flags |= IDNA_USE_STD3_ASCII_RULES;
|
||
|
||
char *p = NULL;
|
||
- rc = __idna_to_ascii_lz (name, &p, idn_flags);
|
||
+ int rc = __idna_to_ascii_lz (name, &p, idn_flags);
|
||
if (rc != IDNA_SUCCESS)
|
||
{
|
||
/* No need to jump to free_and_return here. */
|
||
@@ -480,46 +533,11 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
{
|
||
char *scope_delim = strchr (name, SCOPE_DELIMITER);
|
||
int e;
|
||
-
|
||
- {
|
||
- bool malloc_namebuf = false;
|
||
- char *namebuf = (char *) name;
|
||
-
|
||
- if (__builtin_expect (scope_delim != NULL, 0))
|
||
- {
|
||
- if (malloc_name)
|
||
- *scope_delim = '\0';
|
||
- else
|
||
- {
|
||
- if (__libc_use_alloca (alloca_used
|
||
- + scope_delim - name + 1))
|
||
- {
|
||
- namebuf = alloca_account (scope_delim - name + 1,
|
||
- alloca_used);
|
||
- *((char *) __mempcpy (namebuf, name,
|
||
- scope_delim - name)) = '\0';
|
||
- }
|
||
- else
|
||
- {
|
||
- namebuf = strndup (name, scope_delim - name);
|
||
- if (namebuf == NULL)
|
||
- {
|
||
- assert (!malloc_name);
|
||
- return -EAI_MEMORY;
|
||
- }
|
||
- malloc_namebuf = true;
|
||
- }
|
||
- }
|
||
- }
|
||
-
|
||
- e = inet_pton (AF_INET6, namebuf, at->addr);
|
||
-
|
||
- if (malloc_namebuf)
|
||
- free (namebuf);
|
||
- else if (scope_delim != NULL && malloc_name)
|
||
- /* Undo what we did above. */
|
||
- *scope_delim = SCOPE_DELIMITER;
|
||
- }
|
||
+ if (scope_delim == NULL)
|
||
+ e = inet_pton (AF_INET6, name, at->addr);
|
||
+ else
|
||
+ e = __inet_pton_length (AF_INET6, name, scope_delim - name,
|
||
+ at->addr);
|
||
if (e > 0)
|
||
{
|
||
if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
|
||
@@ -536,31 +554,13 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
goto free_and_return;
|
||
}
|
||
|
||
- if (scope_delim != NULL)
|
||
+ if (scope_delim != NULL
|
||
+ && __inet6_scopeid_pton ((struct in6_addr *) at->addr,
|
||
+ scope_delim + 1,
|
||
+ &at->scopeid) != 0)
|
||
{
|
||
- int try_numericscope = 0;
|
||
- if (IN6_IS_ADDR_LINKLOCAL (at->addr)
|
||
- || IN6_IS_ADDR_MC_LINKLOCAL (at->addr))
|
||
- {
|
||
- at->scopeid = if_nametoindex (scope_delim + 1);
|
||
- if (at->scopeid == 0)
|
||
- try_numericscope = 1;
|
||
- }
|
||
- else
|
||
- try_numericscope = 1;
|
||
-
|
||
- if (try_numericscope != 0)
|
||
- {
|
||
- char *end;
|
||
- assert (sizeof (uint32_t) <= sizeof (unsigned long));
|
||
- at->scopeid = (uint32_t) strtoul (scope_delim + 1, &end,
|
||
- 10);
|
||
- if (*end != '\0')
|
||
- {
|
||
- result = GAIH_OKIFUNSPEC | -EAI_NONAME;
|
||
- goto free_and_return;
|
||
- }
|
||
- }
|
||
+ result = -EAI_NONAME;
|
||
+ goto free_and_return;
|
||
}
|
||
|
||
if (req->ai_flags & AI_CANONNAME)
|
||
@@ -573,51 +573,34 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
struct gaih_addrtuple **pat = &at;
|
||
int no_data = 0;
|
||
int no_inet6_data = 0;
|
||
- service_user *nip = NULL;
|
||
+ service_user *nip;
|
||
enum nss_status inet6_status = NSS_STATUS_UNAVAIL;
|
||
enum nss_status status = NSS_STATUS_UNAVAIL;
|
||
int no_more;
|
||
- int old_res_options;
|
||
+ struct resolv_context *res_ctx = NULL;
|
||
+ bool res_enable_inet6 = false;
|
||
|
||
- /* If we do not have to look for IPv6 addresses, use
|
||
- the simple, old functions, which do not support
|
||
+ /* If we do not have to look for IPv6 addresses or the canonical
|
||
+ name, use the simple, old functions, which do not support
|
||
IPv6 scope ids, nor retrieving the canonical name. */
|
||
- if (req->ai_family == AF_INET && (req->ai_flags & AI_CANONNAME) == 0)
|
||
+ if (req->ai_family == AF_INET
|
||
+ && (req->ai_flags & AI_CANONNAME) == 0)
|
||
{
|
||
- /* Allocate additional room for struct host_data. */
|
||
- size_t tmpbuflen = (512 + MAX_NR_ALIASES * sizeof(char*)
|
||
- + 16 * sizeof(char));
|
||
- assert (tmpbuf == NULL);
|
||
- tmpbuf = alloca_account (tmpbuflen, alloca_used);
|
||
int rc;
|
||
struct hostent th;
|
||
struct hostent *h;
|
||
- int herrno;
|
||
|
||
while (1)
|
||
{
|
||
- rc = __gethostbyname2_r (name, AF_INET, &th, tmpbuf,
|
||
- tmpbuflen, &h, &herrno);
|
||
- if (rc != ERANGE || herrno != NETDB_INTERNAL)
|
||
+ rc = __gethostbyname2_r (name, AF_INET, &th,
|
||
+ tmpbuf->data, tmpbuf->length,
|
||
+ &h, &h_errno);
|
||
+ if (rc != ERANGE || h_errno != NETDB_INTERNAL)
|
||
break;
|
||
-
|
||
- if (!malloc_tmpbuf
|
||
- && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
|
||
- tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
|
||
- 2 * tmpbuflen,
|
||
- alloca_used);
|
||
- else
|
||
+ if (!scratch_buffer_grow (tmpbuf))
|
||
{
|
||
- char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
|
||
- 2 * tmpbuflen);
|
||
- if (newp == NULL)
|
||
- {
|
||
- result = -EAI_MEMORY;
|
||
- goto free_and_return;
|
||
- }
|
||
- tmpbuf = newp;
|
||
- malloc_tmpbuf = true;
|
||
- tmpbuflen = 2 * tmpbuflen;
|
||
+ result = -EAI_MEMORY;
|
||
+ goto free_and_return;
|
||
}
|
||
}
|
||
|
||
@@ -625,59 +608,34 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
{
|
||
if (h != NULL)
|
||
{
|
||
- int i;
|
||
- /* We found data, count the number of addresses. */
|
||
- for (i = 0; h->h_addr_list[i]; ++i)
|
||
- ;
|
||
- if (i > 0 && *pat != NULL)
|
||
- --i;
|
||
-
|
||
- if (__libc_use_alloca (alloca_used
|
||
- + i * sizeof (struct gaih_addrtuple)))
|
||
- addrmem = alloca_account (i * sizeof (struct gaih_addrtuple),
|
||
- alloca_used);
|
||
- else
|
||
- {
|
||
- addrmem = malloc (i
|
||
- * sizeof (struct gaih_addrtuple));
|
||
- if (addrmem == NULL)
|
||
- {
|
||
- result = -EAI_MEMORY;
|
||
- goto free_and_return;
|
||
- }
|
||
- malloc_addrmem = true;
|
||
- }
|
||
-
|
||
- /* Now convert it into the list. */
|
||
- struct gaih_addrtuple *addrfree = addrmem;
|
||
- for (i = 0; h->h_addr_list[i]; ++i)
|
||
+ /* We found data, convert it. */
|
||
+ if (!convert_hostent_to_gaih_addrtuple
|
||
+ (req, AF_INET, h, &addrmem))
|
||
{
|
||
- if (*pat == NULL)
|
||
- {
|
||
- *pat = addrfree++;
|
||
- (*pat)->scopeid = 0;
|
||
- }
|
||
- (*pat)->next = NULL;
|
||
- (*pat)->family = AF_INET;
|
||
- memcpy ((*pat)->addr, h->h_addr_list[i],
|
||
- h->h_length);
|
||
- pat = &((*pat)->next);
|
||
+ result = -EAI_MEMORY;
|
||
+ goto free_and_return;
|
||
}
|
||
+ *pat = addrmem;
|
||
+ }
|
||
+ else
|
||
+ {
|
||
+ if (h_errno == NO_DATA)
|
||
+ result = -EAI_NODATA;
|
||
+ else
|
||
+ result = -EAI_NONAME;
|
||
+ goto free_and_return;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
- if (herrno == NETDB_INTERNAL)
|
||
- {
|
||
- __set_h_errno (herrno);
|
||
- result = -EAI_SYSTEM;
|
||
- }
|
||
- else if (herrno == TRY_AGAIN)
|
||
+ if (h_errno == NETDB_INTERNAL)
|
||
+ result = -EAI_SYSTEM;
|
||
+ else if (h_errno == TRY_AGAIN)
|
||
result = -EAI_AGAIN;
|
||
else
|
||
/* We made requests but they turned out no data.
|
||
The name is known, though. */
|
||
- result = GAIH_OKIFUNSPEC | -EAI_NODATA;
|
||
+ result = -EAI_NODATA;
|
||
|
||
goto free_and_return;
|
||
}
|
||
@@ -695,29 +653,18 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
{
|
||
/* Try to use nscd. */
|
||
struct nscd_ai_result *air = NULL;
|
||
- int herrno;
|
||
- int err = __nscd_getai (name, &air, &herrno);
|
||
+ int err = __nscd_getai (name, &air, &h_errno);
|
||
if (air != NULL)
|
||
{
|
||
/* Transform into gaih_addrtuple list. */
|
||
bool added_canon = (req->ai_flags & AI_CANONNAME) == 0;
|
||
char *addrs = air->addrs;
|
||
|
||
- if (__libc_use_alloca (alloca_used
|
||
- + air->naddrs * sizeof (struct gaih_addrtuple)))
|
||
- addrmem = alloca_account (air->naddrs
|
||
- * sizeof (struct gaih_addrtuple),
|
||
- alloca_used);
|
||
- else
|
||
+ addrmem = calloc (air->naddrs, sizeof (*addrmem));
|
||
+ if (addrmem == NULL)
|
||
{
|
||
- addrmem = malloc (air->naddrs
|
||
- * sizeof (struct gaih_addrtuple));
|
||
- if (addrmem == NULL)
|
||
- {
|
||
- result = -EAI_MEMORY;
|
||
- goto free_and_return;
|
||
- }
|
||
- malloc_addrmem = true;
|
||
+ result = -EAI_MEMORY;
|
||
+ goto free_and_return;
|
||
}
|
||
|
||
struct gaih_addrtuple *addrfree = addrmem;
|
||
@@ -748,22 +695,13 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
(*pat)->name = NULL;
|
||
else if (canonbuf == NULL)
|
||
{
|
||
- size_t canonlen = strlen (air->canon) + 1;
|
||
- if ((req->ai_flags & AI_CANONIDN) != 0
|
||
- && __libc_use_alloca (alloca_used + canonlen))
|
||
- canonbuf = alloca_account (canonlen, alloca_used);
|
||
- else
|
||
+ canonbuf = __strdup (air->canon);
|
||
+ if (canonbuf == NULL)
|
||
{
|
||
- canonbuf = malloc (canonlen);
|
||
- if (canonbuf == NULL)
|
||
- {
|
||
- result = -EAI_MEMORY;
|
||
- goto free_and_return;
|
||
- }
|
||
- malloc_canonbuf = true;
|
||
+ result = -EAI_MEMORY;
|
||
+ goto free_and_return;
|
||
}
|
||
- canon = (*pat)->name = memcpy (canonbuf, air->canon,
|
||
- canonlen);
|
||
+ canon = (*pat)->name = canonbuf;
|
||
}
|
||
|
||
if (air->family[i] == AF_INET
|
||
@@ -795,7 +733,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
|
||
if (at->family == AF_UNSPEC)
|
||
{
|
||
- result = GAIH_OKIFUNSPEC | -EAI_NONAME;
|
||
+ result = -EAI_NONAME;
|
||
goto free_and_return;
|
||
}
|
||
|
||
@@ -806,9 +744,9 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
goto free_and_return;
|
||
else if (__nss_not_use_nscd_hosts == 0)
|
||
{
|
||
- if (herrno == NETDB_INTERNAL && errno == ENOMEM)
|
||
+ if (h_errno == NETDB_INTERNAL && errno == ENOMEM)
|
||
result = -EAI_MEMORY;
|
||
- else if (herrno == TRY_AGAIN)
|
||
+ else if (h_errno == TRY_AGAIN)
|
||
result = -EAI_AGAIN;
|
||
else
|
||
result = -EAI_SYSTEM;
|
||
@@ -818,44 +756,22 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
}
|
||
#endif
|
||
|
||
- if (__nss_hosts_database != NULL)
|
||
- {
|
||
- no_more = 0;
|
||
- nip = __nss_hosts_database;
|
||
- }
|
||
- else
|
||
+ if (__nss_hosts_database == NULL)
|
||
no_more = __nss_database_lookup ("hosts", NULL,
|
||
"dns [!UNAVAIL=return] files",
|
||
- &nip);
|
||
-
|
||
- /* Initialize configurations. */
|
||
- if (__builtin_expect (!_res_hconf.initialized, 0))
|
||
- _res_hconf_init ();
|
||
- if (__res_maybe_init (&_res, 0) == -1)
|
||
- no_more = 1;
|
||
+ &__nss_hosts_database);
|
||
+ else
|
||
+ no_more = 0;
|
||
+ nip = __nss_hosts_database;
|
||
|
||
/* If we are looking for both IPv4 and IPv6 address we don't
|
||
want the lookup functions to automatically promote IPv4
|
||
- addresses to IPv6 addresses. Currently this is decided
|
||
- by setting the RES_USE_INET6 bit in _res.options. */
|
||
- old_res_options = _res.options;
|
||
- _res.options &= ~DEPRECATED_RES_USE_INET6;
|
||
-
|
||
- size_t tmpbuflen = 1024 + sizeof(struct gaih_addrtuple);
|
||
- malloc_tmpbuf = !__libc_use_alloca (alloca_used + tmpbuflen);
|
||
- assert (tmpbuf == NULL);
|
||
- if (!malloc_tmpbuf)
|
||
- tmpbuf = alloca_account (tmpbuflen, alloca_used);
|
||
- else
|
||
- {
|
||
- tmpbuf = malloc (tmpbuflen);
|
||
- if (tmpbuf == NULL)
|
||
- {
|
||
- _res.options |= old_res_options & RES_USE_INET6;
|
||
- result = -EAI_MEMORY;
|
||
- goto free_and_return;
|
||
- }
|
||
- }
|
||
+ addresses to IPv6 addresses, so we use the no_inet6
|
||
+ function variant. */
|
||
+ res_ctx = __resolv_context_get ();
|
||
+ res_enable_inet6 = __resolv_context_disable_inet6 (res_ctx);
|
||
+ if (res_ctx == NULL)
|
||
+ no_more = 1;
|
||
|
||
while (!no_more)
|
||
{
|
||
@@ -869,44 +785,31 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
|
||
if (fct4 != NULL)
|
||
{
|
||
- int herrno;
|
||
-
|
||
while (1)
|
||
{
|
||
- rc = 0;
|
||
- status = DL_CALL_FCT (fct4, (name, pat, tmpbuf,
|
||
- tmpbuflen, &rc, &herrno,
|
||
+ status = DL_CALL_FCT (fct4, (name, pat,
|
||
+ tmpbuf->data, tmpbuf->length,
|
||
+ &errno, &h_errno,
|
||
NULL));
|
||
if (status == NSS_STATUS_SUCCESS)
|
||
break;
|
||
if (status != NSS_STATUS_TRYAGAIN
|
||
- || rc != ERANGE || herrno != NETDB_INTERNAL)
|
||
+ || errno != ERANGE || h_errno != NETDB_INTERNAL)
|
||
{
|
||
- if (herrno == TRY_AGAIN)
|
||
+ if (h_errno == TRY_AGAIN)
|
||
no_data = EAI_AGAIN;
|
||
else
|
||
- no_data = herrno == NO_DATA;
|
||
+ no_data = h_errno == NO_DATA;
|
||
break;
|
||
}
|
||
|
||
- if (!malloc_tmpbuf
|
||
- && __libc_use_alloca (alloca_used + 2 * tmpbuflen))
|
||
- tmpbuf = extend_alloca_account (tmpbuf, tmpbuflen,
|
||
- 2 * tmpbuflen,
|
||
- alloca_used);
|
||
- else
|
||
+ if (!scratch_buffer_grow (tmpbuf))
|
||
{
|
||
- char *newp = realloc (malloc_tmpbuf ? tmpbuf : NULL,
|
||
- 2 * tmpbuflen);
|
||
- if (newp == NULL)
|
||
- {
|
||
- _res.options |= old_res_options & DEPRECATED_RES_USE_INET6;
|
||
- result = -EAI_MEMORY;
|
||
- goto free_and_return;
|
||
- }
|
||
- tmpbuf = newp;
|
||
- malloc_tmpbuf = true;
|
||
- tmpbuflen = 2 * tmpbuflen;
|
||
+ __resolv_context_enable_inet6
|
||
+ (res_ctx, res_enable_inet6);
|
||
+ __resolv_context_put (res_ctx);
|
||
+ result = -EAI_MEMORY;
|
||
+ goto free_and_return;
|
||
}
|
||
}
|
||
|
||
@@ -1000,54 +903,16 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
if ((req->ai_flags & AI_CANONNAME) != 0
|
||
&& canon == NULL)
|
||
{
|
||
- /* If we need the canonical name, get it
|
||
- from the same service as the result. */
|
||
- nss_getcanonname_r cfct;
|
||
- int herrno;
|
||
-
|
||
- cfct = __nss_lookup_function (nip,
|
||
- "getcanonname_r");
|
||
- if (cfct != NULL)
|
||
+ canonbuf = getcanonname (nip, at, name);
|
||
+ if (canonbuf == NULL)
|
||
{
|
||
- const size_t max_fqdn_len = 256;
|
||
- if ((req->ai_flags & AI_CANONIDN) != 0
|
||
- && __libc_use_alloca (alloca_used
|
||
- + max_fqdn_len))
|
||
- canonbuf = alloca_account (max_fqdn_len,
|
||
- alloca_used);
|
||
- else
|
||
- {
|
||
- canonbuf = malloc (max_fqdn_len);
|
||
- if (canonbuf == NULL)
|
||
- {
|
||
- _res.options
|
||
- |= old_res_options
|
||
- & DEPRECATED_RES_USE_INET6;
|
||
- result = -EAI_MEMORY;
|
||
- goto free_and_return;
|
||
- }
|
||
- malloc_canonbuf = true;
|
||
- }
|
||
- char *s;
|
||
-
|
||
- if (DL_CALL_FCT (cfct, (at->name ?: name,
|
||
- canonbuf,
|
||
- max_fqdn_len,
|
||
- &s, &rc, &herrno))
|
||
- == NSS_STATUS_SUCCESS)
|
||
- canon = s;
|
||
- else
|
||
- {
|
||
- /* Set to name now to avoid using
|
||
- gethostbyaddr. */
|
||
- if (malloc_canonbuf)
|
||
- {
|
||
- free (canonbuf);
|
||
- malloc_canonbuf = false;
|
||
- }
|
||
- canon = name;
|
||
- }
|
||
+ __resolv_context_enable_inet6
|
||
+ (res_ctx, res_enable_inet6);
|
||
+ __resolv_context_put (res_ctx);
|
||
+ result = -EAI_MEMORY;
|
||
+ goto free_and_return;
|
||
}
|
||
+ canon = canonbuf;
|
||
}
|
||
status = NSS_STATUS_SUCCESS;
|
||
}
|
||
@@ -1064,13 +929,17 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
}
|
||
else
|
||
{
|
||
+ /* Could not locate any of the lookup functions.
|
||
+ The NSS lookup code does not consistently set
|
||
+ errno, so we need to supply our own error
|
||
+ code here. The root cause could either be a
|
||
+ resource allocation failure, or a missing
|
||
+ service function in the DSO (so it should not
|
||
+ be listed in /etc/nsswitch.conf). Assume the
|
||
+ former, and return EBUSY. */
|
||
status = NSS_STATUS_UNAVAIL;
|
||
- /* Could not load any of the lookup functions. Indicate
|
||
- an internal error if the failure was due to a system
|
||
- error other than the file not being found. We use the
|
||
- errno from the last failed callback. */
|
||
- if (errno != 0 && errno != ENOENT)
|
||
- __set_h_errno (NETDB_INTERNAL);
|
||
+ __set_h_errno (NETDB_INTERNAL);
|
||
+ __set_errno (EBUSY);
|
||
}
|
||
}
|
||
|
||
@@ -1083,11 +952,15 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
nip = nip->next;
|
||
}
|
||
|
||
- _res.options |= old_res_options & DEPRECATED_RES_USE_INET6;
|
||
+ __resolv_context_enable_inet6 (res_ctx, res_enable_inet6);
|
||
+ __resolv_context_put (res_ctx);
|
||
|
||
- if (h_errno == NETDB_INTERNAL)
|
||
+ /* If we have a failure which sets errno, report it using
|
||
+ EAI_SYSTEM. */
|
||
+ if ((status == NSS_STATUS_TRYAGAIN || status == NSS_STATUS_UNAVAIL)
|
||
+ && h_errno == NETDB_INTERNAL)
|
||
{
|
||
- result = GAIH_OKIFUNSPEC | -EAI_SYSTEM;
|
||
+ result = -EAI_SYSTEM;
|
||
goto free_and_return;
|
||
}
|
||
|
||
@@ -1099,7 +972,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
else
|
||
/* We made requests but they turned out no data. The name
|
||
is known, though. */
|
||
- result = GAIH_OKIFUNSPEC | -EAI_NODATA;
|
||
+ result = -EAI_NODATA;
|
||
|
||
goto free_and_return;
|
||
}
|
||
@@ -1108,7 +981,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
process_list:
|
||
if (at->family == AF_UNSPEC)
|
||
{
|
||
- result = GAIH_OKIFUNSPEC | -EAI_NONAME;
|
||
+ result = -EAI_NONAME;
|
||
goto free_and_return;
|
||
}
|
||
}
|
||
@@ -1193,12 +1066,13 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
#ifdef HAVE_LIBIDN
|
||
make_copy:
|
||
#endif
|
||
- if (malloc_canonbuf)
|
||
- /* We already allocated the string using malloc. */
|
||
- malloc_canonbuf = false;
|
||
+ if (canonbuf != NULL)
|
||
+ /* We already allocated the string using malloc, but
|
||
+ the buffer is now owned by canon. */
|
||
+ canonbuf = NULL;
|
||
else
|
||
{
|
||
- canon = strdup (canon);
|
||
+ canon = __strdup (canon);
|
||
if (canon == NULL)
|
||
{
|
||
result = -EAI_MEMORY;
|
||
@@ -1289,12 +1163,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
|
||
free_and_return:
|
||
if (malloc_name)
|
||
free ((char *) name);
|
||
- if (malloc_addrmem)
|
||
- free (addrmem);
|
||
- if (malloc_canonbuf)
|
||
- free (canonbuf);
|
||
- if (malloc_tmpbuf)
|
||
- free (tmpbuf);
|
||
+ free (addrmem);
|
||
+ free (canonbuf);
|
||
|
||
return result;
|
||
}
|
||
@@ -2429,13 +2299,17 @@ getaddrinfo (const char *name, const char *service,
|
||
if (hints->ai_family == AF_UNSPEC || hints->ai_family == AF_INET
|
||
|| hints->ai_family == AF_INET6)
|
||
{
|
||
- last_i = gaih_inet (name, pservice, hints, end, &naddrs);
|
||
+ struct scratch_buffer tmpbuf;
|
||
+ scratch_buffer_init (&tmpbuf);
|
||
+ last_i = gaih_inet (name, pservice, hints, end, &naddrs, &tmpbuf);
|
||
+ scratch_buffer_free (&tmpbuf);
|
||
+
|
||
if (last_i != 0)
|
||
{
|
||
freeaddrinfo (p);
|
||
__free_in6ai (in6ai);
|
||
|
||
- return -(last_i & GAIH_EAI);
|
||
+ return -last_i;
|
||
}
|
||
while (*end)
|
||
{
|
||
@@ -2462,12 +2336,13 @@ getaddrinfo (const char *name, const char *service,
|
||
struct addrinfo *last = NULL;
|
||
char *canonname = NULL;
|
||
bool malloc_results;
|
||
+ size_t alloc_size = nresults * (sizeof (*results) + sizeof (size_t));
|
||
|
||
malloc_results
|
||
- = !__libc_use_alloca (nresults * (sizeof (*results) + sizeof (size_t)));
|
||
+ = !__libc_use_alloca (alloc_size);
|
||
if (malloc_results)
|
||
{
|
||
- results = malloc (nresults * (sizeof (*results) + sizeof (size_t)));
|
||
+ results = malloc (alloc_size);
|
||
if (results == NULL)
|
||
{
|
||
__free_in6ai (in6ai);
|
||
@@ -2475,7 +2350,7 @@ getaddrinfo (const char *name, const char *service,
|
||
}
|
||
}
|
||
else
|
||
- results = alloca (nresults * (sizeof (*results) + sizeof (size_t)));
|
||
+ results = alloca (alloc_size);
|
||
order = (size_t *) (results + nresults);
|
||
|
||
/* Now we definitely need the interface information. */
|
||
@@ -2526,7 +2401,7 @@ getaddrinfo (const char *name, const char *service,
|
||
close_retry:
|
||
close_not_cancel_no_status (fd);
|
||
af = q->ai_family;
|
||
- fd = __socket (af, SOCK_DGRAM, IPPROTO_IP);
|
||
+ fd = __socket (af, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_IP);
|
||
}
|
||
else
|
||
{
|
||
@@ -2559,7 +2434,7 @@ getaddrinfo (const char *name, const char *service,
|
||
tmp.addr[1] = 0;
|
||
tmp.addr[2] = htonl (0xffff);
|
||
/* Special case for lo interface, the source address
|
||
- being possibly different than the interface
|
||
+ being possibly different than the interface
|
||
address. */
|
||
if ((ntohl(sinp->sin_addr.s_addr) & 0xff000000)
|
||
== 0x7f000000)
|
||
@@ -2633,7 +2508,7 @@ getaddrinfo (const char *name, const char *service,
|
||
the information. */
|
||
struct sort_result_combo src
|
||
= { .results = results, .nresults = nresults };
|
||
- if (__builtin_expect (gaiconf_reload_flag_ever_set, 0))
|
||
+ if (__glibc_unlikely (gaiconf_reload_flag_ever_set))
|
||
{
|
||
__libc_lock_define_initialized (static, lock);
|
||
|
||
@@ -2667,7 +2542,7 @@ getaddrinfo (const char *name, const char *service,
|
||
return 0;
|
||
}
|
||
|
||
- return last_i ? -(last_i & GAIH_EAI) : EAI_NONAME;
|
||
+ return last_i ? -last_i : EAI_NONAME;
|
||
}
|
||
libc_hidden_def (getaddrinfo)
|
||
|