diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index babeec345..64ff7f428 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,21 @@ +2006-12-11 Corinna Vinschen + + * Makefile.in (DLL_OFILES): Add minires-os-if.o and minires.o. + (SUBLIBS): Add libresolv.a. + Add rule for libresolv.a. + * autoload.cc: Fix return code handling for IP Helper API in case + of being unable to load iphlpapi.dll. + (DnsQuery_A): Define. + (DnsRecordListFree): Define. + * cygwin.din: Export resolver functions. + * include/resolv.h: New header. + * include/arpa/nameser.h: New header. + * include/arpa/nameser_compat.h: New header. + * include/cygwin/version.h: Bump API minor number. + * libc/minires-os-if.c: New file. + * libc/minires.c: New file. + * libc/minires.h: New file. + 2006-12-11 Christopher Faylor * sigproc.cc (child_info::child_info): Move old comment about msv_count diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in index bf7ea3de0..c8ef03e63 100644 --- a/winsup/cygwin/Makefile.in +++ b/winsup/cygwin/Makefile.in @@ -134,15 +134,15 @@ DLL_OFILES:=assert.o autoload.o bsdlib.o ctype.o cxx.o cygheap.o cygthread.o \ fhandler_tty.o fhandler_virtual.o fhandler_windows.o fhandler_zero.o \ flock.o fnmatch.o fork.o fts.o ftw.o getopt.o glob.o grp.o heap.o \ hookapi.o inet_addr.o inet_network.o init.o ioctl.o ipc.o localtime.o \ - lsearch.o malloc_wrapper.o memmem.o miscfuncs.o mktemp.o mmap.o msg.o \ - net.o netdb.o nftw.o ntea.o passwd.o path.o pinfo.o pipe.o poll.o \ - pthread.o regcomp.o regerror.o regexec.o regfree.o registry.o resource.o \ - rexec.o rcmd.o scandir.o sched.o sec_acl.o sec_helper.o security.o \ - select.o sem.o shared.o shm.o sigfe.o signal.o sigproc.o smallprint.o \ - spawn.o strace.o strptime.o strsep.o strsig.o sync.o syscalls.o \ - sysconf.o syslog.o termios.o thread.o timelocal.o timer.o times.o tty.o \ - uinfo.o uname.o v8_regexp.o v8_regerror.o v8_regsub.o wait.o wincap.o \ - window.o winf.o \ + lsearch.o malloc_wrapper.o memmem.o minires-os-if.o minires.o \ + miscfuncs.o mktemp.o mmap.o msg.o net.o netdb.o nftw.o ntea.o passwd.o \ + path.o pinfo.o pipe.o poll.o pthread.o regcomp.o regerror.o regexec.o \ + regfree.o registry.o resource.o rexec.o rcmd.o scandir.o sched.o \ + sec_acl.o sec_helper.o security.o select.o sem.o shared.o shm.o sigfe.o \ + signal.o sigproc.o smallprint.o spawn.o strace.o strptime.o strsep.o \ + strsig.o sync.o syscalls.o sysconf.o syslog.o termios.o thread.o \ + timelocal.o timer.o times.o tty.o uinfo.o uname.o v8_regexp.o \ + v8_regerror.o v8_regsub.o wait.o wincap.o window.o winf.o \ $(EXTRA_DLL_OFILES) $(EXTRA_OFILES) $(MALLOC_OFILES) $(MT_SAFE_OBJECTS) GMON_OFILES:=gmon.o mcount.o profil.o @@ -219,7 +219,7 @@ API_VER:=$(srcdir)/include/cygwin/version.h PWD:=${shell pwd} LIB_NAME:=$(PWD)/libcygwin.a LIBSERVER:=@LIBSERVER@ -SUBLIBS:=$(PWD)/libpthread.a $(PWD)/libutil.a $(PWD)/libm.a $(PWD)/libc.a $(PWD)/libdl.a +SUBLIBS:=$(PWD)/libpthread.a $(PWD)/libutil.a $(PWD)/libm.a $(PWD)/libc.a $(PWD)/libdl.a $(PWD)/libresolv.a EXTRALIBS:=libautomode.a libbinmode.a libtextmode.a libtextreadmode.a INSTOBJS:=automode.o binmode.o textmode.o textreadmode.o TARGET_LIBS:=$(LIB_NAME) $(CYGWIN_START) $(GMON_START) $(LIBGMON_A) $(SUBLIBS) $(INSTOBJS) $(EXTRALIBS) @@ -443,6 +443,9 @@ $(PWD)/libc.a: speclib $(LIB_NAME) $(PWD)/libm.a libpthread.a libutil.a $(PWD)/libdl.a: speclib $(LIB_NAME) dlfcn.o /bin/sh ${word 1, $^} $@ "${NM}" "$(AR)" ${wordlist 2, 99, $^} +$(PWD)/libresolv.a: speclib $(LIB_NAME) minires.o + /bin/sh ${word 1, $^} $@ "${NM}" "$(AR)" ${wordlist 2, 99, $^} + lib%.a: %.o $(AR) cru $@ $? diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 1e7fb783a..62e2a3b63 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -492,11 +492,11 @@ LoadDLLfunc (WSASetLastError, 4, ws2_32) // LoadDLLfunc (WSAStartup, 8, ws2_32) LoadDLLfunc (WSAWaitForMultipleEvents, 20, ws2_32) -LoadDLLfuncEx (GetIfTable, 12, iphlpapi, 1) -LoadDLLfuncEx (GetIfEntry, 4, iphlpapi, 1) -LoadDLLfuncEx (GetIpAddrTable, 12, iphlpapi, 1) -LoadDLLfuncEx (GetNetworkParams, 8, iphlpapi, 1) -LoadDLLfuncEx (GetTcpTable, 12, iphlpapi, 1) +// 50 = ERROR_NOT_SUPPORTED. Returned if OS doesn't supprot iphlpapi funcs +LoadDLLfuncEx2 (GetIfEntry, 4, iphlpapi, 1, 50) +LoadDLLfuncEx2 (GetIpAddrTable, 12, iphlpapi, 1, 50) +LoadDLLfuncEx2 (GetNetworkParams, 8, iphlpapi, 1, 50) +LoadDLLfuncEx2 (GetTcpTable, 12, iphlpapi, 1, 50) LoadDLLfunc (CoTaskMemFree, 4, ole32) @@ -559,4 +559,7 @@ LoadDLLfunc (WNetCloseEnum, 4, mpr) LoadDLLfuncEx (UuidCreate, 4, rpcrt4, 1) LoadDLLfuncEx (UuidCreateSequential, 4, rpcrt4, 1) + +LoadDLLfuncEx2 (DnsQuery_A, 24, dnsapi, 1, 127) // ERROR_PROC_NOT_FOUND +LoadDLLfuncEx (DnsRecordListFree, 8, dnsapi, 1) } diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din index e8a40ede2..c47fd46c8 100644 --- a/winsup/cygwin/cygwin.din +++ b/winsup/cygwin/cygwin.din @@ -269,6 +269,12 @@ dll_entry@12 NOSIGFE dll_noncygwin_dllcrt0 NOSIGFE dlopen SIGFE dlsym SIGFE +dn_comp = __dn_comp SIGFE +__dn_comp SIGFE +dn_expand = __dn_expand SIGFE +__dn_expand SIGFE +dn_skipname = __dn_skipname SIGFE +__dn_skipname SIGFE drand48 NOSIGFE _drand48 = drand48 NOSIGFE drem NOSIGFE @@ -1124,6 +1130,35 @@ remquo NOSIGFE remquof NOSIGFE rename SIGFE _rename = rename SIGFE +res_close = __res_close SIGFE +__res_close SIGFE +res_init = __res_init SIGFE +__res_init SIGFE +res_mkquery = __res_mkquery SIGFE +__res_mkquery SIGFE +res_nclose = __res_nclose SIGFE +__res_nclose SIGFE +res_ninit = __res_ninit SIGFE +__res_ninit SIGFE +res_nmkquery = __res_nmkquery SIGFE +__res_nmkquery SIGFE +res_nquery = __res_nquery SIGFE +__res_nquery SIGFE +res_nquerydomain = __res_nquerydomain SIGFE +__res_nquerydomain SIGFE +res_nsearch = __res_nsearch SIGFE +__res_nsearch SIGFE +res_nsend = __res_nsend SIGFE +__res_nsend SIGFE +res_query = __res_query SIGFE +__res_query SIGFE +res_querydomain = __res_querydomain SIGFE +__res_querydomain SIGFE +res_search = __res_search SIGFE +__res_search SIGFE +res_send = __res_send SIGFE +__res_send SIGFE +__res_state SIGFE revoke SIGFE rewind SIGFE _rewind = rewind SIGFE diff --git a/winsup/cygwin/include/arpa/nameser.h b/winsup/cygwin/include/arpa/nameser.h new file mode 100755 index 000000000..3980933f5 --- /dev/null +++ b/winsup/cygwin/include/arpa/nameser.h @@ -0,0 +1,563 @@ +/* + * Copyright (c) 1983, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Copyright (c) 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. + */ + +/* + * $Id$ + */ + +#ifndef _ARPA_NAMESER_H_ +#define _ARPA_NAMESER_H_ + +#ifdef __CYGWIN__ +#define BSD 199903 /* Used inside the .h file */ +#endif + +#define BIND_4_COMPAT + +#include +#if (!defined(BSD)) || (BSD < 199306) +# include +#else +# include +#endif +#include + +/* + * 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 + */ +#define NS_PACKETSZ 512 /* maximum packet size */ +#define NS_MAXDNAME 1025 /* maximum domain name */ +#define NS_MAXCDNAME 255 /* maximum compressed domain name */ +#define NS_MAXLABEL 63 /* maximum length of domain label */ +#define NS_HFIXEDSZ 12 /* #/bytes of fixed data in header */ +#define NS_QFIXEDSZ 4 /* #/bytes of fixed data in query */ +#define NS_RRFIXEDSZ 10 /* #/bytes of fixed data in r record */ +#define NS_INT32SZ 4 /* #/bytes of data in a 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_INADDRSZ 4 /* IPv4 T_A */ +#define NS_IN6ADDRSZ 16 /* IPv6 T_AAAA */ +#define NS_CMPRSFLGS 0xc0 /* Flag bits indicating name compression. */ +#define NS_DEFAULTPORT 53 /* For both TCP and UDP. */ + +/* + * These can be expanded with synonyms, just keep ns_parse.c:ns_parserecord() + * in synch with it. + */ +typedef enum __ns_sect { + ns_s_qd = 0, /* Query: Question. */ + ns_s_zn = 0, /* Update: Zone. */ + ns_s_an = 1, /* Query: Answer. */ + ns_s_pr = 1, /* Update: Prerequisites. */ + ns_s_ns = 2, /* Query: Name servers. */ + ns_s_ud = 2, /* Update: Update. */ + ns_s_ar = 3, /* Query|Update: Additional records. */ + ns_s_max = 4 +} ns_sect; + +/* + * This is a message handle. It is caller allocated and has no dynamic data. + * This structure is intended to be opaque to all but ns_parse.c, thus the + * leading _'s on the member names. Use the accessor functions, not the _'s. + */ +typedef struct __ns_msg { + const 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; +} ns_msg; + +/* Private data structure - do not use from outside library. */ +struct _ns_flagdata { int mask, shift; }; +extern struct _ns_flagdata _ns_flagdata[]; + +/* Accessor macros - this is part of the public interface. */ + +#define ns_msg_id(handle) ((handle)._id + 0) +#define ns_msg_base(handle) ((handle)._msg + 0) +#define ns_msg_end(handle) ((handle)._eom + 0) +#define ns_msg_size(handle) ((handle)._eom - (handle)._msg) +#define ns_msg_count(handle, section) ((handle)._counts[section] + 0) + +/* + * This is a parsed record. It is caller allocated and has no dynamic data. + */ +typedef struct __ns_rr { + char name[NS_MAXDNAME]; + u_int16_t type; + u_int16_t rr_class; + u_int32_t ttl; + u_int16_t rdlength; + const u_char * rdata; +} ns_rr; + +/* Accessor macros - this is part of the public interface. */ +#define ns_rr_name(rr) (((rr).name[0] != '\0') ? (rr).name : ".") +#define ns_rr_type(rr) ((ns_type)((rr).type + 0)) +#define ns_rr_class(rr) ((ns_class)((rr).rr_class + 0)) +#define ns_rr_ttl(rr) ((rr).ttl + 0) +#define ns_rr_rdlen(rr) ((rr).rdlength + 0) +#define ns_rr_rdata(rr) ((rr).rdata + 0) + +/* + * These don't have to be in the same order as in the packet flags word, + * and they can even overlap in some cases, but they will need to be kept + * in synch with ns_parse.c:ns_flagdata[]. + */ +typedef enum __ns_flag { + ns_f_qr, /* Question/Response. */ + ns_f_opcode, /* Operation code. */ + ns_f_aa, /* Authoritative Answer. */ + ns_f_tc, /* Truncation occurred. */ + ns_f_rd, /* Recursion Desired. */ + ns_f_ra, /* Recursion Available. */ + ns_f_z, /* MBZ. */ + ns_f_ad, /* Authentic Data (DNSSEC). */ + ns_f_cd, /* Checking Disabled (DNSSEC). */ + ns_f_rcode, /* Response code. */ + ns_f_max +} ns_flag; + +/* + * Currently defined opcodes. + */ +typedef enum __ns_opcode { + ns_o_query = 0, /* Standard query. */ + ns_o_iquery = 1, /* Inverse query (deprecated/unsupported). */ + ns_o_status = 2, /* Name server status query (unsupported). */ + /* Opcode 3 is undefined/reserved. */ + ns_o_notify = 4, /* Zone change notification. */ + ns_o_update = 5, /* Zone update message. */ + ns_o_max = 6 +} ns_opcode; + +/* + * Currently defined response codes. + */ +typedef enum __ns_rcode { + ns_r_noerror = 0, /* No error occurred. */ + ns_r_formerr = 1, /* Format error. */ + ns_r_servfail = 2, /* Server failure. */ + ns_r_nxdomain = 3, /* Name error. */ + ns_r_notimpl = 4, /* Unimplemented. */ + ns_r_refused = 5, /* Operation refused. */ + /* these are for BIND_UPDATE */ + ns_r_yxdomain = 6, /* Name exists */ + ns_r_yxrrset = 7, /* RRset exists */ + ns_r_nxrrset = 8, /* RRset does not exist */ + ns_r_notauth = 9, /* Not authoritative for zone */ + ns_r_notzone = 10, /* Zone of record different from zone section */ + ns_r_max = 11, + /* The following are TSIG extended errors */ + ns_r_badsig = 16, + ns_r_badkey = 17, + ns_r_badtime = 18 +} ns_rcode; + +/* BIND_UPDATE */ +typedef enum __ns_update_operation { + ns_uop_delete = 0, + ns_uop_add = 1, + ns_uop_max = 2 +} ns_update_operation; + +/* + * This structure is used for TSIG authenticated messages + */ +struct ns_tsig_key { + char name[NS_MAXDNAME], alg[NS_MAXDNAME]; + unsigned char *data; + int len; +}; +typedef struct ns_tsig_key ns_tsig_key; + +/* + * This structure is used for TSIG authenticated TCP messages + */ +struct ns_tcp_tsig_state { + int counter; + struct dst_key *key; + void *ctx; + unsigned char sig[NS_PACKETSZ]; + int siglen; +}; +typedef struct ns_tcp_tsig_state ns_tcp_tsig_state; + +#define NS_TSIG_FUDGE 300 +#define NS_TSIG_TCP_COUNT 100 +#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT" + +#define NS_TSIG_ERROR_NO_TSIG -10 +#define NS_TSIG_ERROR_NO_SPACE -11 +#define NS_TSIG_ERROR_FORMERR -12 + +/* + * Currently defined type values for resources and queries. + */ +typedef enum __ns_type { + ns_t_invalid = 0, /* 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 (deprecates 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_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) + +/* + * Values for class field + */ +typedef enum __ns_class { + ns_c_invalid = 0, /* Cookie. */ + ns_c_in = 1, /* Internet. */ + ns_c_2 = 2, /* unallocated/unsupported. */ + ns_c_chaos = 3, /* MIT Chaos-net. */ + ns_c_hs = 4, /* MIT Hesiod. */ + /* Query class values which do not appear in resource records */ + ns_c_none = 254, /* for prereq. sections in update requests */ + ns_c_any = 255, /* Wildcard match. */ + ns_c_max = 65536 +} ns_class; + +/* 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; + +typedef enum __ns_cert_types { + cert_t_pkix = 1, /* PKIX (X.509v3) */ + cert_t_spki = 2, /* SPKI */ + cert_t_pgp = 3, /* PGP */ + cert_t_url = 253, /* URL private type */ + cert_t_oid = 254 /* OID private type */ +} ns_cert_types; + +/* 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 2552 + /* 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 + +/* + * 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]) \ + ; \ + (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]) \ + ; \ + (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); \ + *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); \ + *t_cp++ = t_l >> 24; \ + *t_cp++ = t_l >> 16; \ + *t_cp++ = t_l >> 8; \ + *t_cp = t_l; \ + (cp) += NS_INT32SZ; \ +} while (0) + +/* + * ANSI C identifier hiding for bind's lib/nameser. + */ +#define ns_msg_getflag __ns_msg_getflag +#define ns_get16 __ns_get16 +#define ns_get32 __ns_get32 +#define ns_put16 __ns_put16 +#define ns_put32 __ns_put32 +#define ns_initparse __ns_initparse +#define ns_skiprr __ns_skiprr +#define ns_parserr __ns_parserr +#define ns_sprintrr __ns_sprintrr +#define ns_sprintrrf __ns_sprintrrf +#define ns_format_ttl __ns_format_ttl +#define ns_parse_ttl __ns_parse_ttl +#define ns_datetosecs __ns_datetosecs +#define ns_name_ntol __ns_name_ntol +#define ns_name_ntop __ns_name_ntop +#define ns_name_pton __ns_name_pton +#define ns_name_unpack __ns_name_unpack +#define ns_name_pack __ns_name_pack +#define ns_name_compress __ns_name_compress +#define ns_name_uncompress __ns_name_uncompress +#define ns_name_skip __ns_name_skip +#define ns_name_rollback __ns_name_rollback +#define ns_sign __ns_sign +#define ns_sign_tcp __ns_sign_tcp +#define ns_sign_tcp_init __ns_sign_tcp_init +#define ns_find_tsig __ns_find_tsig +#define ns_verify __ns_verify +#define ns_verify_tcp __ns_verify_tcp +#define ns_verify_tcp_init __ns_verify_tcp_init +#define ns_samedomain __ns_samedomain +#define ns_subdomain __ns_subdomain +#define ns_makecanon __ns_makecanon +#define ns_samename __ns_samename + +__BEGIN_DECLS +int ns_msg_getflag __P((ns_msg, int)); +u_int ns_get16 __P((const u_char *)); +u_long ns_get32 __P((const u_char *)); +void ns_put16 __P((u_int, u_char *)); +void ns_put32 __P((u_long, u_char *)); +int ns_initparse __P((const u_char *, int, ns_msg *)); +int ns_skiprr __P((const u_char *, const u_char *, ns_sect, int)); +int ns_parserr __P((ns_msg *, ns_sect, int, ns_rr *)); +int ns_sprintrr __P((const ns_msg *, const ns_rr *, + const char *, const char *, char *, size_t)); +int ns_sprintrrf __P((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)); +int ns_format_ttl __P((u_long, char *, size_t)); +int ns_parse_ttl __P((const char *, u_long *)); +u_int32_t ns_datetosecs __P((const char *cp, int *errp)); +int ns_name_ntol __P((const u_char *, u_char *, size_t)); +int ns_name_ntop __P((const u_char *, char *, size_t)); +int ns_name_pton __P((const char *, u_char *, size_t)); +int ns_name_unpack __P((const u_char *, const u_char *, + const u_char *, u_char *, size_t)); +int ns_name_pack __P((const u_char *, u_char *, int, + const u_char **, const u_char **)); +int ns_name_uncompress __P((const u_char *, const u_char *, + const u_char *, char *, size_t)); +int ns_name_compress __P((const char *, u_char *, size_t, + const u_char **, const u_char **)); +int ns_name_skip __P((const u_char **, const u_char *)); +void ns_name_rollback __P((const u_char *, const u_char **, + const u_char **)); +int ns_sign __P((u_char *, int *, int, int, void *, + const u_char *, int, u_char *, int *, time_t)); +int ns_sign_tcp __P((u_char *, int *, int, int, + ns_tcp_tsig_state *, int)); +int ns_sign_tcp_init __P((void *, const u_char *, int, + ns_tcp_tsig_state *)); +u_char *ns_find_tsig __P((u_char *, u_char *)); +int ns_verify __P((u_char *, int *, void *, + const u_char *, int, u_char *, int *, + time_t *, int)); +int ns_verify_tcp __P((u_char *, int *, ns_tcp_tsig_state *, int)); +int ns_verify_tcp_init __P((void *, const u_char *, int, + ns_tcp_tsig_state *)); +int ns_samedomain __P((const char *, const char *)); +int ns_subdomain __P((const char *, const char *)); +int ns_makecanon __P((const char *, char *, size_t)); +int ns_samename __P((const char *, const char *)); +__END_DECLS + +#ifdef BIND_4_COMPAT +#include +#endif + +#endif /* !_ARPA_NAMESER_H_ */ diff --git a/winsup/cygwin/include/arpa/nameser_compat.h b/winsup/cygwin/include/arpa/nameser_compat.h new file mode 100755 index 000000000..a75f9bc13 --- /dev/null +++ b/winsup/cygwin/include/arpa/nameser_compat.h @@ -0,0 +1,231 @@ +/* Copyright (c) 1983, 1989 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 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. + */ + +/* + * from nameser.h 8.1 (Berkeley) 6/2/93 + * $Id$ + */ + +#ifndef _ARPA_NAMESER_COMPAT_ +#define _ARPA_NAMESER_COMPAT_ + +#define __BIND 19950621 /* (DEAD) interface version stamp. */ + +#ifndef BYTE_ORDER +#if (BSD >= 199103) +# include +#else +#ifdef linux +# include +#else +#define LITTLE_ENDIAN 1234 /* least-significant byte first (vax, pc) */ +#define BIG_ENDIAN 4321 /* most-significant byte first (IBM, net) */ +#define PDP_ENDIAN 3412 /* LSB first in word, MSW first in long (pdp)*/ + +#if defined(vax) || defined(ns32000) || defined(sun386) || defined(i386) || \ + defined(MIPSEL) || defined(_MIPSEL) || defined(BIT_ZERO_ON_RIGHT) || \ + defined(__alpha__) || defined(__alpha) || \ + (defined(__Lynx__) && defined(__x86__)) +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +#if defined(sel) || defined(pyr) || defined(mc68000) || defined(sparc) || \ + defined(is68k) || defined(tahoe) || defined(ibm032) || defined(ibm370) || \ + defined(MIPSEB) || defined(_MIPSEB) || defined(_IBMR2) || defined(DGUX) ||\ + defined(apollo) || defined(__convex__) || defined(_CRAY) || \ + defined(__hppa) || defined(__hp9000) || \ + defined(__hp9000s300) || defined(__hp9000s700) || \ + defined(__hp3000s900) || defined(MPE) || \ + defined (BIT_ZERO_ON_LEFT) || defined(m68k) || \ + (defined(__Lynx__) && \ + (defined(__68k__) || defined(__sparc__) || defined(__powerpc__))) +#define BYTE_ORDER BIG_ENDIAN +#endif +#endif /* linux */ +#endif /* BSD */ +#endif /* BYTE_ORDER */ + +#if !defined(BYTE_ORDER) || \ + (BYTE_ORDER != BIG_ENDIAN && BYTE_ORDER != LITTLE_ENDIAN && \ + BYTE_ORDER != PDP_ENDIAN) + /* you must determine what the correct bit order is for + * your compiler - the next line is an intentional error + * which will force your compiles to bomb until you fix + * the above macros. + */ + error "Undefined or invalid BYTE_ORDER"; +#endif + +/* + * Structure for query header. The order of the fields is machine- and + * compiler-dependent, depending on the byte/bit order and the layout + * of bit fields. We use bit fields only in int variables, as this + * is all ANSI requires. This requires a somewhat confusing rearrangement. + */ + +typedef struct { + unsigned id :16; /* query identification number */ +#if BYTE_ORDER == BIG_ENDIAN + /* fields in third byte */ + unsigned qr: 1; /* response flag */ + unsigned opcode: 4; /* purpose of message */ + unsigned aa: 1; /* authoritive answer */ + unsigned tc: 1; /* truncated message */ + unsigned rd: 1; /* recursion desired */ + /* fields in fourth byte */ + unsigned ra: 1; /* recursion available */ + unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned ad: 1; /* authentic data from named */ + unsigned cd: 1; /* checking disabled by resolver */ + unsigned rcode :4; /* response code */ +#endif +#if BYTE_ORDER == LITTLE_ENDIAN || BYTE_ORDER == PDP_ENDIAN + /* fields in third byte */ + unsigned rd :1; /* recursion desired */ + unsigned tc :1; /* truncated message */ + unsigned aa :1; /* authoritive answer */ + unsigned opcode :4; /* purpose of message */ + unsigned qr :1; /* response flag */ + /* fields in fourth byte */ + unsigned rcode :4; /* response code */ + unsigned cd: 1; /* checking disabled by resolver */ + unsigned ad: 1; /* authentic data from named */ + unsigned unused :1; /* unused bits (MBZ as of 4.9.3a3) */ + unsigned ra :1; /* recursion available */ +#endif + /* remaining bytes */ + unsigned qdcount :16; /* number of question entries */ + unsigned ancount :16; /* number of answer entries */ + unsigned nscount :16; /* number of authority entries */ + unsigned arcount :16; /* number of resource entries */ +} HEADER; + +#define PACKETSZ NS_PACKETSZ +#define MAXDNAME NS_MAXDNAME +#define MAXCDNAME NS_MAXCDNAME +#define MAXLABEL NS_MAXLABEL +#define HFIXEDSZ NS_HFIXEDSZ +#define QFIXEDSZ NS_QFIXEDSZ +#define RRFIXEDSZ NS_RRFIXEDSZ +#define INT32SZ NS_INT32SZ +#define INT16SZ NS_INT16SZ +#define INADDRSZ NS_INADDRSZ +#define IN6ADDRSZ NS_IN6ADDRSZ +#define INDIR_MASK NS_CMPRSFLGS +#define NAMESERVER_PORT NS_DEFAULTPORT + +#define S_ZONE ns_s_zn +#define S_PREREQ ns_s_pr +#define S_UPDATE ns_s_ud +#define S_ADDT ns_s_ar + +#define QUERY ns_o_query +#define IQUERY ns_o_iquery +#define STATUS ns_o_status +#define NS_NOTIFY_OP ns_o_notify +#define NS_UPDATE_OP ns_o_update + +#define NOERROR ns_r_noerror +#define FORMERR ns_r_formerr +#define SERVFAIL ns_r_servfail +#define NXDOMAIN ns_r_nxdomain +#define NOTIMP ns_r_notimpl +#define REFUSED ns_r_refused +#define YXDOMAIN ns_r_yxdomain +#define YXRRSET ns_r_yxrrset +#define NXRRSET ns_r_nxrrset +#define NOTAUTH ns_r_notauth +#define NOTZONE ns_r_notzone +/*#define BADSIG ns_r_badsig*/ +/*#define BADKEY ns_r_badkey*/ +/*#define BADTIME ns_r_badtime*/ + + +#define DELETE ns_uop_delete +#define ADD ns_uop_add + +#define T_A ns_t_a +#define T_NS ns_t_ns +#define T_MD ns_t_md +#define T_MF ns_t_mf +#define T_CNAME ns_t_cname +#define T_SOA ns_t_soa +#define T_MB ns_t_mb +#define T_MG ns_t_mg +#define T_MR ns_t_mr +#define T_NULL ns_t_null +#define T_WKS ns_t_wks +#define T_PTR ns_t_ptr +#define T_HINFO ns_t_hinfo +#define T_MINFO ns_t_minfo +#define T_MX ns_t_mx +#define T_TXT ns_t_txt +#define T_RP ns_t_rp +#define T_AFSDB ns_t_afsdb +#define T_X25 ns_t_x25 +#define T_ISDN ns_t_isdn +#define T_RT ns_t_rt +#define T_NSAP ns_t_nsap +#define T_NSAP_PTR ns_t_nsap_ptr +#define T_SIG ns_t_sig +#define T_KEY ns_t_key +#define T_PX ns_t_px +#define T_GPOS ns_t_gpos +#define T_AAAA ns_t_aaaa +#define T_LOC ns_t_loc +#define T_NXT ns_t_nxt +#define T_EID ns_t_eid +#define T_NIMLOC ns_t_nimloc +#define T_SRV ns_t_srv +#define T_ATMA ns_t_atma +#define T_NAPTR ns_t_naptr +#define T_A6 ns_t_a6 +#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 C_IN ns_c_in +#define C_CHAOS ns_c_chaos +#define C_HS ns_c_hs +/* BIND_UPDATE */ +#define C_NONE ns_c_none +#define C_ANY ns_c_any + +#define GETSHORT NS_GET16 +#define GETLONG NS_GET32 +#define PUTSHORT NS_PUT16 +#define PUTLONG NS_PUT32 + +#endif /* _ARPA_NAMESER_COMPAT_ */ diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h index 30ae75800..dd448aef2 100644 --- a/winsup/cygwin/include/cygwin/version.h +++ b/winsup/cygwin/include/cygwin/version.h @@ -295,12 +295,13 @@ details. */ rresvport_af. 159: Export posix_openpt. 160: Export posix_fadvice, posix_fallocate. + 161: Export resolver functions. */ /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ #define CYGWIN_VERSION_API_MAJOR 0 -#define CYGWIN_VERSION_API_MINOR 160 +#define CYGWIN_VERSION_API_MINOR 161 /* There is also a compatibity version number associated with the shared memory regions. It is incremented when incompatible diff --git a/winsup/cygwin/include/resolv.h b/winsup/cygwin/include/resolv.h new file mode 100755 index 000000000..dfefa0f85 --- /dev/null +++ b/winsup/cygwin/include/resolv.h @@ -0,0 +1,464 @@ +/* + * Copyright (c) 1983, 1987, 1989 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions Copyright (c) 1996-1999 by Internet Software Consortium. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS + * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE + * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL + * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR + * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS + * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS + * SOFTWARE. + */ + +/* + * @(#)resolv.h 8.1 (Berkeley) 6/2/93 + * $Id$ + */ + +#ifndef _RESOLV_H_ +#define _RESOLV_H_ + +#include +#if !defined(__CYGWIN__) && ((!defined(BSD)) || (BSD < 199306)) +# include +#else +# include +#endif +#include +#include +#include +#include + +/* + * Revision information. This is the release date in YYYYMMDD format. + * It can change every day so the right thing to do with it is use it + * in preprocessor commands such as "#if (__RES > 19931104)". Do not + * compare for equality; rather, use it to determine whether your resolver + * is new enough to contain a certain feature. + */ + +#define __RES 19991006 + +/* + * This used to be defined in res_query.c, now it's in herror.c. + * [XXX no it's not. It's in irs/irs_data.c] + * It was + * never extern'd by any *.h file before it was placed here. For thread + * aware programs, the last h_errno value set is stored in res->h_errno. + * + * XXX: There doesn't seem to be a good reason for exposing RES_SET_H_ERRNO + * (and __h_errno_set) to the public via . + * XXX: __h_errno_set is really part of IRS, not part of the resolver. + * If somebody wants to build and use a resolver that doesn't use IRS, + * what do they do? Perhaps something like + * #ifdef WANT_IRS + * # define RES_SET_H_ERRNO(r,x) __h_errno_set(r,x) + * #else + * # define RES_SET_H_ERRNO(r,x) (h_errno = (r)->res_h_errno = (x)) + * #endif + */ + +#define RES_SET_H_ERRNO(r,x) __h_errno_set(r,x) +struct __res_state; /* forward */ +__BEGIN_DECLS +void __h_errno_set(struct __res_state *res, int err); +__END_DECLS + +/* + * Resolver configuration file. + * Normally not present, but may contain the address of the + * inital name server(s) to query and the domain search list. + */ + +#ifndef _PATH_RESCONF +#define _PATH_RESCONF "/etc/resolv.conf" +#endif + +typedef enum { res_goahead, res_nextns, res_modified, res_done, res_error } + res_sendhookact; + +typedef res_sendhookact (*res_send_qhook)__P((struct sockaddr * const *ns, + const u_char **query, + int *querylen, + u_char *ans, + int anssiz, + int *resplen)); + +typedef res_sendhookact (*res_send_rhook)__P((const struct sockaddr *ns, + const u_char *query, + int querylen, + u_char *ans, + int anssiz, + int *resplen)); + +struct res_sym { + int number; /* Identifying number, like T_MX */ + const char * name; /* Its symbolic name, like "MX" */ + const char * humanname; /* Its fun name, like "mail exchanger" */ +}; + +/* + * Global defines and variables for resolver stub. + */ +#define MAXNS 3 /* max # name servers we'll track */ +#define MAXDFLSRCH 3 /* # default domain levels to try */ +#define MAXDNSRCH 6 /* max # domains in search path */ +#define LOCALDOMAINPARTS 2 /* min levels in name that is "local" */ + +#define RES_TIMEOUT 5 /* min. seconds between retries */ +#define MAXRESOLVSORT 10 /* number of net to sort on */ +#define RES_MAXNDOTS 15 /* should reflect bit field size */ +#define RES_MAXRETRANS 30 /* only for resolv.conf/RES_OPTIONS */ +#define RES_MAXRETRY 5 /* only for resolv.conf/RES_OPTIONS */ +#define RES_DFLRETRY 2 /* Default #/tries. */ +#define RES_MAXTIME 65535 /* Infinity, in milliseconds. */ + +struct __res_state_ext; + +struct __res_state { + int retrans; /* retransmition time interval */ + int retry; /* number of times to retransmit */ + u_long options; /* option flags - see below. */ + int nscount; /* number of name servers */ + struct sockaddr_in + nsaddr_list[MAXNS]; /* address of name server */ +#define nsaddr nsaddr_list[0] /* for backward compatibility */ + u_short id; /* current message id */ + char *dnsrch[MAXDNSRCH+1]; /* components of domain to search */ + char defdname[256]; /* default domain (deprecated) */ + u_long pfcode; /* RES_PRF_ flags - see below. */ + unsigned ndots:4; /* threshold for initial abs. query */ + unsigned nsort:4; /* number of elements in sort_list[] */ + char unused[3]; + struct { + struct in_addr addr; + u_int32_t mask; + } sort_list[MAXRESOLVSORT]; + res_send_qhook qhook; /* query hook */ + res_send_rhook rhook; /* response hook */ + int res_h_errno; /* last one set for this context */ + int _vcsock; /* PRIVATE: for res_send VC i/o */ + u_int _flags; /* PRIVATE: see below */ + union { + /* On an 32-bit arch this means 512b total. */ + char pad[72 - 3*sizeof (int) - 2*sizeof (void *)]; + struct { + u_int16_t nscount; + u_int16_t nstimes[MAXNS]; /* ms. */ + int nssocks[MAXNS]; + struct __res_state_ext *ext; /* extention for IPv6 */ + } _ext; + } _u; +}; + +typedef struct __res_state *res_state; + +union res_sockaddr_union { + struct sockaddr_in sin; +#ifdef IN6ADDR_ANY_INIT + struct sockaddr_in6 sin6; +#endif +#ifdef ISC_ALIGN64 + int64_t __align; /* 64bit alignment */ +#else + int32_t __align; /* 32bit alignment */ +#endif + char __space[128]; /* max size */ +}; + +/* + * Resolver flags (used to be discrete per-module statics ints). + */ +#define RES_F_VC 0x00000001 /* socket is TCP */ +#define RES_F_CONN 0x00000002 /* socket is connected */ +#define RES_F_EDNS0ERR 0x00000004 /* EDNS0 caused errors */ + +/* res_findzonecut() options */ +#define RES_EXHAUSTIVE 0x00000001 /* always do all queries */ + +/* + * Resolver options (keep these in synch with res_debug.c, please) + */ +#define RES_INIT 0x00000001 /* address initialized */ +#define RES_DEBUG 0x00000002 /* print debug messages */ +#define RES_AAONLY 0x00000004 /* authoritative answers only (!IMPL)*/ +#define RES_USEVC 0x00000008 /* use virtual circuit */ +#define RES_PRIMARY 0x00000010 /* query primary server only (!IMPL) */ +#define RES_IGNTC 0x00000020 /* ignore trucation errors */ +#define RES_RECURSE 0x00000040 /* recursion desired */ +#define RES_DEFNAMES 0x00000080 /* use default domain name */ +#define RES_STAYOPEN 0x00000100 /* Keep TCP socket open */ +#define RES_DNSRCH 0x00000200 /* search up local domain tree */ +#define RES_INSECURE1 0x00000400 /* type 1 security disabled */ +#define RES_INSECURE2 0x00000800 /* type 2 security disabled */ +#define RES_NOALIASES 0x00001000 /* shuts off HOSTALIASES feature */ +#define RES_USE_INET6 0x00002000 /* use/map IPv6 in gethostbyname() */ +#define RES_ROTATE 0x00004000 /* rotate ns list after each query */ +#define RES_NOCHECKNAME 0x00008000 /* do not check names for sanity. */ +#define RES_KEEPTSIG 0x00010000 /* do not strip TSIG records */ +#define RES_BLAST 0x00020000 /* blast all recursive servers */ +#define RES_NO_NIBBLE 0x00040000 /* disable IPv6 nibble mode reverse */ +#define RES_NO_BITSTRING 0x00080000 /* disable IPv6 bit string mode reverse */ +/* KAME extensions: use higher bit to avoid conflict with ISC use */ +#define RES_USE_DNAME 0x10000000 /* use DNAME */ +#define RES_USE_A6 0x20000000 /* use A6 */ +#define RES_USE_EDNS0 0x40000000 /* use EDNS0 if configured */ + +#define RES_DEFAULT (RES_RECURSE | RES_DEFNAMES | RES_DNSRCH) + +/* + * Resolver "pfcode" values. Used by dig. + */ +#define RES_PRF_STATS 0x00000001 +#define RES_PRF_UPDATE 0x00000002 +#define RES_PRF_CLASS 0x00000004 +#define RES_PRF_CMD 0x00000008 +#define RES_PRF_QUES 0x00000010 +#define RES_PRF_ANS 0x00000020 +#define RES_PRF_AUTH 0x00000040 +#define RES_PRF_ADD 0x00000080 +#define RES_PRF_HEAD1 0x00000100 +#define RES_PRF_HEAD2 0x00000200 +#define RES_PRF_TTLID 0x00000400 +#define RES_PRF_HEADX 0x00000800 +#define RES_PRF_QUERY 0x00001000 +#define RES_PRF_REPLY 0x00002000 +#define RES_PRF_INIT 0x00004000 +/* 0x00008000 */ + +/* Things involving an internal (static) resolver context. */ +#if defined(_REENTRANT) || defined(__CYGWIN__) +__BEGIN_DECLS +extern struct __res_state *__res_state(void); +__END_DECLS +#define _res (*__res_state()) +#else +#ifndef __BIND_NOSTATIC +extern struct __res_state _res; +#endif +#endif + +#ifndef __BIND_NOSTATIC +#define fp_nquery __fp_nquery +#define fp_query __fp_query +#define hostalias __hostalias +#define p_query __p_query +#define res_close __res_close +#define res_init __res_init +#define res_isourserver __res_isourserver +#define res_mkquery __res_mkquery +#define res_query __res_query +#define res_querydomain __res_querydomain +#define res_search __res_search +#define res_send __res_send +#define res_sendsigned __res_sendsigned + +__BEGIN_DECLS +void fp_nquery __P((const u_char *, int, FILE *)); +void fp_query __P((const u_char *, FILE *)); +const char * hostalias __P((const char *)); +void p_query __P((const u_char *)); +void res_close __P((void)); +int res_init __P((void)); +int res_isourserver __P((const struct sockaddr_in *)); +int res_mkquery __P((int, const char *, int, int, const u_char *, + int, const u_char *, u_char *, int)); +int res_query __P((const char *, int, int, u_char *, int)); +int res_querydomain __P((const char *, const char *, int, int, + u_char *, int)); +int res_search __P((const char *, int, int, u_char *, int)); +int res_send __P((const u_char *, int, u_char *, int)); +int res_sendsigned __P((const u_char *, int, ns_tsig_key *, + u_char *, int)); +__END_DECLS +#endif + +#if !defined(SHARED_LIBBIND) || defined(LIB) +/* + * If libbind is a shared object (well, DLL anyway) + * these externs break the linker when resolv.h is + * included by a lib client (like named) + * Make them go away if a client is including this + * + */ +extern const struct res_sym __p_key_syms[]; +extern const struct res_sym __p_cert_syms[]; +extern const struct res_sym __p_class_syms[]; +extern const struct res_sym __p_type_syms[]; +extern const struct res_sym __p_rcode_syms[]; +#endif /* SHARED_LIBBIND */ + +#define b64_ntop __b64_ntop +#define b64_pton __b64_pton +#define dn_comp __dn_comp +#define dn_count_labels __dn_count_labels +#define dn_expand __dn_expand +#define dn_skipname __dn_skipname +#define fp_resstat __fp_resstat +#define loc_aton __loc_aton +#define loc_ntoa __loc_ntoa +#define p_cdname __p_cdname +#define p_cdnname __p_cdnname +#define p_class __p_class +#define p_fqname __p_fqname +#define p_fqnname __p_fqnname +#define p_option __p_option +#define p_secstodate __p_secstodate +#define p_section __p_section +#define p_time __p_time +#define p_type __p_type +#define p_rcode __p_rcode +#define putlong __putlong +#define putshort __putshort +#define res_dnok __res_dnok +#define res_findzonecut __res_findzonecut +#define res_hnok __res_hnok +#define res_hostalias __res_hostalias +#define res_mailok __res_mailok +#define res_nameinquery __res_nameinquery +#define res_nclose __res_nclose +#define res_ninit __res_ninit +#define res_nmkquery __res_nmkquery +#define res_pquery __res_pquery +#define res_nquery __res_nquery +#define res_nquerydomain __res_nquerydomain +#define res_nsearch __res_nsearch +#define res_nsend __res_nsend +#define res_nsendsigned __res_nsendsigned +#define res_nisourserver __res_nisourserver +#define res_ownok __res_ownok +#define res_queriesmatch __res_queriesmatch +#define res_randomid __res_randomid +#define sym_ntop __sym_ntop +#define sym_ntos __sym_ntos +#define sym_ston __sym_ston +#define res_nopt __res_nopt +#define res_ndestroy __res_ndestroy +#define res_nametoclass __res_nametoclass +#define res_nametotype __res_nametotype +#define res_setservers __res_setservers +#define res_getservers __res_getservers +__BEGIN_DECLS +int res_hnok __P((const char *)); +int res_ownok __P((const char *)); +int res_mailok __P((const char *)); +int res_dnok __P((const char *)); +int sym_ston __P((const struct res_sym *, const char *, int *)); +const char * sym_ntos __P((const struct res_sym *, int, int *)); +const char * sym_ntop __P((const struct res_sym *, int, int *)); +int b64_ntop __P((u_char const *, size_t, char *, size_t)); +int b64_pton __P((char const *, u_char *, size_t)); +int loc_aton __P((const char *ascii, u_char *binary)); +const char * loc_ntoa __P((const u_char *binary, char *ascii)); +int dn_skipname __P((const u_char *, const u_char *)); +void putlong __P((u_int32_t, u_char *)); +void putshort __P((u_int16_t, u_char *)); +#ifndef __ultrix__ +u_int16_t _getshort __P((const u_char *src)); +u_int32_t _getlong __P((const u_char *src)); +#endif +const char * p_class __P((int)); +const char * p_time __P((u_int32_t)); +const char * p_type __P((int)); +const char * p_rcode __P((int)); +const u_char * p_cdnname __P((const u_char *, const u_char *, int, FILE *)); +const u_char * p_cdname __P((const u_char *, const u_char *, FILE *)); +const u_char * p_fqnname __P((const u_char *cp, const u_char *msg, + int, char *, int)); +const u_char * p_fqname __P((const u_char *, const u_char *, FILE *)); +const char * p_option __P((u_long option)); +char * p_secstodate __P((u_long)); +int dn_count_labels __P((const char *)); +int dn_comp __P((const char *, u_char *, int, + u_char **, u_char **)); +int dn_expand __P((const u_char *, const u_char *, const u_char *, + char *, int)); +u_int res_randomid __P((void)); +int res_nameinquery __P((const char *, int, int, + const u_char *, const u_char *)); +int res_queriesmatch __P((const u_char *, const u_char *, + const u_char *, const u_char *)); +const char * p_section __P((int section, int opcode)); +/* Things involving a resolver context. */ +int res_ninit __P((res_state)); +int res_nisourserver __P((const res_state, + const struct sockaddr_in *)); +void fp_resstat __P((const res_state, FILE *)); +void res_pquery __P((const res_state, const u_char *, int, FILE *)); +const char * res_hostalias __P((const res_state, const char *, + char *, size_t)); +int res_nquery __P((res_state, + const char *, int, int, u_char *, int)); +int res_nsearch __P((res_state, const char *, int, + int, u_char *, int)); +int res_nquerydomain __P((res_state, + const char *, const char *, int, int, + u_char *, int)); +int res_nmkquery __P((res_state, + int, const char *, int, int, const u_char *, + int, const u_char *, u_char *, int)); +int res_nsend __P((res_state, const u_char *, int, u_char *, int)); +int res_nsendsigned __P((res_state, const u_char *, int, + ns_tsig_key *, u_char *, int)); +int res_findzonecut __P((res_state, const char *, ns_class, int, + char *, size_t, struct in_addr *, int)); +void res_nclose __P((res_state)); +int res_nopt __P((res_state, int, u_char *, int, int)); +void res_send_setqhook __P((res_send_qhook hook)); +void res_send_setrhook __P((res_send_rhook hook)); +int __res_vinit __P((res_state, int)); +void res_destroyservicelist __P((void)); +const char * res_servicename __P((u_int16_t port, const char *proto)); +const char * res_protocolname __P((int num)); +void res_destroyprotolist __P((void)); +void res_buildprotolist __P((void)); +const char * res_get_nibblesuffix __P((res_state)); +const char * res_get_bitstringsuffix __P((res_state)); +void res_ndestroy __P((res_state)); +u_int16_t res_nametoclass __P((const char *buf, int *success)); +u_int16_t res_nametotype __P((const char *buf, int *success)); +void res_setservers __P((res_state, + const union res_sockaddr_union *, int)); +int res_getservers __P((res_state, + union res_sockaddr_union *, int)); +__END_DECLS + +#endif /* !_RESOLV_H_ */ diff --git a/winsup/cygwin/libc/minires-os-if.c b/winsup/cygwin/libc/minires-os-if.c new file mode 100644 index 000000000..28676cada --- /dev/null +++ b/winsup/cygwin/libc/minires-os-if.c @@ -0,0 +1,572 @@ +/* minires-os-if.c. Stub synchronous resolver for Cygwin. + + Copyright 2006 Red Hat, Inc. + + Written by Pierre A. Humblet + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#include "minires.h" + +#ifdef __CYGWIN__ +/*********************************************************************** + * + Windows interface code + +***********************************************************************/ + +/* Conflict between Windows definitions and others */ +#undef ERROR +#undef NOERROR +#undef DELETE + +#include +#include +#include +#include + +/*********************************************************************** + * + write_record: Translates a Windows DNS record into a compressed record + + ***********************************************************************/ + +#define PUTDOMAIN(d,p)\ + {int res = dn_comp(d, p, EndPtr - p, dnptrs, lastdnptr); p += res < 0 ? strlen(d) : res; } + +static u_char * write_record(unsigned char * ptr, PDNS_RECORD rr, unsigned char * EndPtr, + unsigned char ** dnptrs, unsigned char ** lastdnptr, int debug) +{ + u_char * rd_length_ptr; + + PUTDOMAIN(rr->pName, ptr); + + if (ptr + 4 > EndPtr) + ptr += 4; + else { + PUTSHORT(rr->wType, ptr); + PUTSHORT(ns_c_in, ptr); + } + if ((rr->Flags.DW & 0x3) == DnsSectionQuestion) + return ptr; + + if (ptr + 4 > EndPtr) + ptr += 4; + else { + PUTLONG(rr->dwTtl, ptr); + } + rd_length_ptr = ptr; + ptr += 2; /* Placeholder for RDLENGTH */ + + /* The default case uses an undocumented feature of the Windows + resolver for types greater than 16. + The DNS_RECORD Data contains the record in wire format. */ + + switch(rr->wType) { + case DNS_TYPE_A: + { + u_char * aptr = (u_char *) & rr->Data.A.IpAddress; + if (ptr + 4 <= EndPtr) { + ptr[0] = aptr[0]; + ptr[1] = aptr[1]; + ptr[2] = aptr[2]; + ptr[3] = aptr[3]; + } + ptr += 4; + break; + } + case DNS_TYPE_NS: + case DNS_TYPE_MD: + case DNS_TYPE_MF: + case DNS_TYPE_CNAME: + case DNS_TYPE_MB: + case DNS_TYPE_MG: + case DNS_TYPE_MR: + case DNS_TYPE_PTR: + PUTDOMAIN(rr->Data.PTR.pNameHost, ptr); + break; + case DNS_TYPE_SOA: + PUTDOMAIN(rr->Data.SOA.pNamePrimaryServer, ptr); + PUTDOMAIN(rr->Data.SOA.pNameAdministrator, ptr); + if (ptr + 20 > EndPtr) + ptr += 20; + else { + PUTLONG(rr->Data.SOA.dwSerialNo, ptr); + PUTLONG(rr->Data.SOA.dwRefresh, ptr); + PUTLONG(rr->Data.SOA.dwRetry, ptr); + PUTLONG(rr->Data.SOA.dwExpire, ptr); + PUTLONG(rr->Data.SOA.dwDefaultTtl, ptr); + } + break; + case DNS_TYPE_NULL: + if (ptr + rr->Data.Null.dwByteCount <= EndPtr) + memcpy(ptr, rr->Data.Null.Data, rr->Data.Null.dwByteCount); + ptr += rr->Data.Null.dwByteCount; + if (rr->Data.Null.dwByteCount == rr->wDataLength - sizeof(DNS_NULL_DATA) + 1) + DPRINTF(debug, "Null byte count has an unexpected value\n"); + break; + case DNS_TYPE_WKS: + if (ptr + rr->wDataLength - sizeof(DNS_WKS_DATA) + 1 + 5 > EndPtr) + ptr += rr->wDataLength - sizeof(DNS_WKS_DATA) + 1 + 5; + else { + PUTLONG(rr->Data.WKS.IpAddress, ptr); + *ptr++ = rr->Data.WKS.chProtocol; + memcpy(ptr, rr->Data.WKS.BitMask, rr->wDataLength - sizeof(DNS_WKS_DATA) + 1); + ptr += rr->wDataLength - sizeof(DNS_WKS_DATA) + 1; + } + break; + case DNS_TYPE_MINFO: + PUTDOMAIN(rr->Data.MINFO.pNameMailbox, ptr); + PUTDOMAIN(rr->Data.MINFO.pNameErrorsMailbox, ptr); + break; + case DNS_TYPE_MX: + if (ptr + 2 > EndPtr) + ptr += 2; + else + PUTSHORT(rr->Data.MX.wPreference, ptr); + PUTDOMAIN(rr->Data.MX.pNameExchange, ptr); + break; + case DNS_TYPE_HINFO: + case DNS_TYPE_TEXT: + { + unsigned int i, len; + for (i = 0; i < rr->Data.TXT.dwStringCount; i++) { + len = strlen(rr->Data.TXT.pStringArray[i]) & 0xFF; + if (ptr + len + 1 > EndPtr) + ptr += len + 1; + else { + *ptr++ = len; + memcpy(ptr, rr->Data.TXT.pStringArray[i], len); + ptr += len; + } + } + break; + } + default: + { + unsigned int len = rr->wDataLength; + DPRINTF(debug, "No structure for wType %d\n", rr->wType); + if (ptr + len <= EndPtr) + memcpy(ptr, (char *) &rr->Data, len); + ptr += len; + break; + } + } + if (rd_length_ptr + 2 <= EndPtr) + PUTSHORT(ptr - rd_length_ptr - 2, rd_length_ptr); + return ptr; +} + +/*********************************************************************** + * + cygwin_query: implements res_nquery by calling DnsQuery + + ***********************************************************************/ +static int cygwin_query(res_state statp, const char * DomName, int Class, int Type, + unsigned char * AnsPtr, int AnsLength) +{ + DNS_STATUS res; + PDNS_RECORD pQueryResultsSet, rr; + int section, len, counts[4] = {0, 0, 0, 0}, debug = statp->options & RES_DEBUG; + unsigned char * dnptrs[256], * ptr; + + dnptrs[0] = AnsPtr; + dnptrs[1] = NULL; + + if (Class != ns_c_in) { + errno = ENOSYS; + statp->res_h_errno = NETDB_INTERNAL; + return -1; + } + + res = DnsQuery_A(DomName, Type, DNS_QUERY_TREAT_AS_FQDN, + NULL, &pQueryResultsSet, NULL); +#if 0 +#define NETDB_INTERNAL -1 /* see errno */ +#define HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ +#define TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */ +#define NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ +#define NO_DATA 4 /* Valid name, no data record of requested type */ +#endif + + DPRINTF(debug, "DnsQuery: %lu (Windows)\n", res); + if (res) { + switch (res) { + case ERROR_PROC_NOT_FOUND: + errno = ENOSYS; + statp->res_h_errno = NO_RECOVERY; + break; + case ERROR_INVALID_NAME: + errno = EINVAL; + statp->res_h_errno = NETDB_INTERNAL;; + break; + case ERROR_TIMEOUT: + statp->res_h_errno = TRY_AGAIN; + break; + case DNS_ERROR_RCODE_NAME_ERROR: + statp->res_h_errno = HOST_NOT_FOUND; + break; + case DNS_ERROR_RCODE_SERVER_FAILURE: + statp->res_h_errno = TRY_AGAIN; + break; + case DNS_ERROR_NO_DNS_SERVERS: + case DNS_ERROR_RCODE_FORMAT_ERROR: + case DNS_ERROR_RCODE_NOT_IMPLEMENTED: + case DNS_ERROR_RCODE_REFUSED: + statp->res_h_errno = NO_RECOVERY; + break; + case DNS_INFO_NO_RECORDS: /* May be returned even if the host doesn't exist */ + statp->res_h_errno = NO_DATA; + break; + default: + DPRINTF(debug, "Unknown code %lu for %s %d\n", res, DomName, Type); + statp->res_h_errno = NO_RECOVERY; + break; + } + len = -1; + goto done; + } + + ptr = AnsPtr + HFIXEDSZ; /* Skip header */ + + rr = pQueryResultsSet; + section = 0; + while (rr) { + if (!counts[0] && (rr->Flags.DW & 0x3)) { + /* No question. Adopt the first name as the name in the question */ + if ((len = dn_comp(rr->pName, ptr, AnsLength - 4, + dnptrs, &dnptrs[DIM(dnptrs) - 1])) < 0) { + ptr = NULL; + break; + } + ptr += len; + PUTSHORT(Type, ptr); + PUTSHORT(ns_c_in, ptr); + counts[0] = 1; + } + + DPRINTF(debug, "%s Section %d Type %u Windows Record Length %u\n", + rr->pName, rr->Flags.DW & 0x3, rr->wType, rr->wDataLength); + + /* Check the records are in correct section order */ + if ((rr->Flags.DW & 0x3) < section) { + DPRINTF(debug, "Unexpected section order %s %d\n", DomName, Type); + continue; + } + section = rr->Flags.DW & 0x3; + + ptr = write_record(ptr, rr, AnsPtr + AnsLength, dnptrs, + &dnptrs[DIM(dnptrs) - 1], debug); + + counts[section]++; + rr = rr->pNext; + } + + DnsRecordListFree(pQueryResultsSet, DnsFreeRecordList); + + len = ptr - AnsPtr; +done: + ptr = AnsPtr; + PUTSHORT(0, ptr); /* Id */ + PUTSHORT((QR << 8) + RA + RD, ptr); + for (section = 0; section < DIM(counts); section++) { + PUTSHORT(counts[section], ptr); + } + return len; +} + +/*********************************************************************** + * + get_registry_items: returns dns items from the registry + + kHey: Handle to registry key + KeyValue: key value to read + what: 0 addresses ; 1 search list + +***********************************************************************/ +static void get_registry_dns_items(HKEY hKey, LPCTSTR KeyValue, + res_state statp, int what) +{ + DWORD size = 0; + LONG res; + LPBYTE list; + int debug = statp->options & RES_DEBUG; + + res = RegQueryValueEx( hKey, KeyValue, NULL, NULL, NULL, &size); + DPRINTF(debug, "value %s, error %lu (Windows), size %lu\n", + KeyValue, res, size); + if ((res == ERROR_SUCCESS) && (size > 1)) { + if (!(list = (LPBYTE) alloca(size))) { + DPRINTF(debug, "alloca: %s\n", strerror(errno)); + } + else if ((res = RegQueryValueEx( hKey, KeyValue, NULL, NULL, list, + &size )) != ERROR_SUCCESS) { + DPRINTF(debug, "RegQueryValueEx: error %lu (Windows)\n", res); + } + else if (what == 0) { /* Get the addresses */ + BYTE *ap, *srch; + int numAddresses = 0; + for (ap = list; ap < list + size && *ap; ap = srch) { + /* The separation character can be 0, ' ', or ','. */ + for (srch = ap; *srch && (isdigit(*srch) || *srch == '.' ); srch++); + *srch++ = 0; + if (numAddresses < DIM(statp->nsaddr_list)) { + DPRINTF(debug, "server \"%s\"\n", ap); + statp->nsaddr_list[numAddresses].sin_addr.s_addr = cygwin_inet_addr(ap); + if ( statp->nsaddr_list[numAddresses].sin_addr.s_addr != 0 ) + numAddresses++; + } + else + DPRINTF(debug, "no space for server \"%s\"\n", ap); + } + statp->nscount = numAddresses; + } + else /* Parse the search line */ + minires_get_search(list, statp); + } + return; +} + +/*********************************************************************** + * + get_registry_dns: + + Read the registry to get dns server addresses in Network Byte Order, + and set statp->nscount + (for Win9x and NT <= 4.0, but not Win95 with DHCP) + Read the registry SearchList + +***********************************************************************/ + +static void get_registry_dns(res_state statp) +{ + HKEY hKey; + DWORD res; + const char *keyName[] = {"SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters", + "System\\CurrentControlSet\\Services\\VxD\\MSTCP"}; + int is9x = !!(GetVersion() & 0x80000000); + + DPRINTF(statp->options & RES_DEBUG, "key %s\n", keyName[is9x]); + if ((res = RegOpenKeyEx( HKEY_LOCAL_MACHINE, keyName[is9x], 0, + KEY_QUERY_VALUE | KEY_READ, &hKey)) != ERROR_SUCCESS) { + DPRINTF(statp->options & RES_DEBUG, "RegOpenKeyEx: error %lu (Windows)\n", res); + return; + } + + if (statp->nscount == 0) + get_registry_dns_items(hKey, "NameServer", statp, 0); + if (statp->nscount == 0 && !is9x) + get_registry_dns_items(hKey, "DhcpNameServer", statp, 0); + if (statp->dnsrch[0] == NULL) + get_registry_dns_items(hKey, "SearchList", statp, 1); + + RegCloseKey(hKey); + + return; +} + +/*********************************************************************** + * + get_dns_info: Get the search list or the domain name + and the dns server addresses in Network Byte Order + Set statp->os_query if DnsQuery is available. + +***********************************************************************/ +void get_dns_info(res_state statp) +{ +#if MAX_HOSTNAME_LEN > MAXHOSTNAMELEN +#define MAX_HOSTNAME_SIZE (MAX_HOSTNAME_LEN + 1) +#else +#define MAX_HOSTNAME_SIZE (MAXHOSTNAMELEN + 1) +#endif +#if MAX_HOSTNAME_SIZE > 256 /* sizeof(defdname) */ +#error stap->defdname too short +#endif + + int res, debug = statp->options & RES_DEBUG; + + ULONG ulOutBufLen = 0; + DWORD dwRetVal; + IP_ADDR_STRING * pIPAddr; + FIXED_INFO * pFixedInfo; + HINSTANCE kerneldll; + typedef DWORD WINAPI (*GNPType)(PFIXED_INFO, PULONG); + GNPType PGetNetworkParams; + int numAddresses = 0; + + if (statp->use_os) { + DPRINTF(debug, "using dnsapi.dll\n"); + statp->os_query = (typeof(statp->os_query)) cygwin_query; + /* We just need the search list. Avoid loading iphlpapi. */ + statp->nscount = -1; + } + + if (statp->nscount != 0) + goto use_registry; + + if (!(kerneldll = LoadLibrary("IPHLPAPI.DLL"))) { + DPRINTF(debug, "LoadLibrary: error %lu (Windows)\n", GetLastError()); + goto use_registry; + } + if (!(PGetNetworkParams = (GNPType) GetProcAddress(kerneldll, + "GetNetworkParams"))) { + DPRINTF(debug, "GetProcAddress: error %lu (Windows)\n", GetLastError()); + goto use_registry; + } + /* First call to get the buffer length we need */ + dwRetVal = PGetNetworkParams((FIXED_INFO *) 0, &ulOutBufLen); + if (dwRetVal != ERROR_BUFFER_OVERFLOW) { + DPRINTF(debug, "GetNetworkParams: error %lu (Windows)\n", dwRetVal); + goto use_registry; + } + if ((pFixedInfo = (FIXED_INFO *) alloca(ulOutBufLen)) == 0) { + DPRINTF(debug, "alloca: %s\n", strerror(errno)); + goto use_registry; + } + if ((dwRetVal = PGetNetworkParams((FIXED_INFO *) pFixedInfo, & ulOutBufLen))) { + DPRINTF(debug, "GetNetworkParams: error %lu (Windows)\n", dwRetVal); + goto use_registry; + } + + DPRINTF(debug, "GetNetworkParams: OK\n"); + /* Record server addresses, up to array size */ + for (pIPAddr = &(pFixedInfo->DnsServerList), numAddresses = 0; + pIPAddr; + pIPAddr = pIPAddr->Next) { + if (numAddresses < DIM(statp->nsaddr_list)) { + DPRINTF(debug, "server \"%s\"\n", pIPAddr->IpAddress.String); + statp->nsaddr_list[numAddresses].sin_addr.s_addr = cygwin_inet_addr(pIPAddr->IpAddress.String); + if (statp->nsaddr_list[numAddresses].sin_addr.s_addr != 0) { + numAddresses++; + statp->nscount++; + } + } + else + DPRINTF(debug, "no space for server \"%s\"\n", pIPAddr->IpAddress.String); + } + + use_registry: + get_registry_dns(statp); + + if (!statp->dnsrch[0]) { + statp->defdname[sizeof(statp->defdname) - 1] = 0; + if (!(res = getdomainname(statp->defdname, sizeof(statp->defdname)))) { + if (statp->defdname[0] && !statp->defdname[sizeof(statp->defdname) - 1]) + statp->dnsrch[0] = statp->defdname; + } + DPRINTF(debug, "getdomainname \"%s\"\n", + (res)? strerror(errno) : statp->defdname); + } +} + +#else +/*********************************************************************** + * + Default interface code + +***********************************************************************/ + +void get_dns_info(res_state statp) +{ + return; +} + +#endif + + + +#if 0 +#define DNS_ERROR_RCODE_FORMAT_ERROR 9001L +#define DNS_ERROR_RCODE_SERVER_FAILURE 9002L +#define DNS_ERROR_RCODE_NAME_ERROR 9003L +#define DNS_ERROR_RCODE_NOT_IMPLEMENTED 9004L +#define DNS_ERROR_RCODE_REFUSED 9005L +#define DNS_ERROR_RCODE_YXDOMAIN 9006L +#define DNS_ERROR_RCODE_YXRRSET 9007L +#define DNS_ERROR_RCODE_NXRRSET 9008L +#define DNS_ERROR_RCODE_NOTAUTH 9009L +#define DNS_ERROR_RCODE_NOTZONE 9010L +#define DNS_ERROR_RCODE_BADSIG 9016L +#define DNS_ERROR_RCODE_BADKEY 9017L +#define DNS_ERROR_RCODE_BADTIME 9018L +#define DNS_INFO_NO_RECORDS 9501L +#define DNS_ERROR_BAD_PACKET 9502L +#define DNS_ERROR_NO_PACKET 9503L +#define DNS_ERROR_RCODE 9504L +#define DNS_ERROR_UNSECURE_PACKET 9505L +#define DNS_ERROR_INVALID_TYPE 9551L +#define DNS_ERROR_INVALID_IP_ADDRESS 9552L +#define DNS_ERROR_INVALID_PROPERTY 9553L +#define DNS_ERROR_TRY_AGAIN_LATER 9554L +#define DNS_ERROR_NOT_UNIQUE 9555L +#define DNS_ERROR_NON_RFC_NAME 9556L +#define DNS_STATUS_FQDN 9557L +#define DNS_STATUS_DOTTED_NAME 9558L +#define DNS_STATUS_SINGLE_PART_NAME 9559L +#define DNS_ERROR_INVALID_NAME_CHAR 9560L +#define DNS_ERROR_NUMERIC_NAME 9561L +#define DNS_ERROR_NOT_LALOWED_ON_ROOT_SERVER 9562L +#define DNS_ERROR_NOT_ALLOWED_UNDER_DELEGATION 9563L +#define DNS_ERROR_CANNOT_FIND_ROOT_HINTS 9564L +#define DNS_ERROR_INCONSISTENT_ROOT_HINTS 9565L +#define DNS_ERROR_ZONE_DOES_NOT_EXIST 9601L +#define DNS_ERROR_NO_ZONE_INFO 9602L +#define DNS_ERROR_INVALID_ZONE_OPERATION 9603L +#define DNS_ERROR_ZONE_CONFIGURATION_ERROR 9604L +#define DNS_ERROR_ZONE_HAS_NO_SOA_RECORD 9605L +#define DNS_ERROR_ZONE_HAS_NO_NS_RECORDS 9606L +#define DNS_ERROR_ZONE_LOCKED 9607L +#define DNS_ERROR_ZONE_CREATION_FAILED 9608L +#define DNS_ERROR_ZONE_ALREADY_EXISTS 9609L +#define DNS_ERROR_AUTOZONE_ALREADY_EXISTS 9610L +#define DNS_ERROR_INVALID_ZONE_TYPE 9611L +#define DNS_ERROR_SECONDARY_REQUIRES_MASTER_IP 9612L +#define DNS_ERROR_ZONE_NOT_SECONDARY 9613L +#define DNS_ERROR_NEED_SECONDARY_ADDRESSES 9614L +#define DNS_ERROR_WINS_INIT_FAILED 9615L +#define DNS_ERROR_NEED_WINS_SERVERS 9616L +#define DNS_ERROR_NBSTAT_INIT_FAILED 9617L +#define DNS_ERROR_SOA_DELETE_INVALID 9618L +#define DNS_ERROR_FORWARDER_ALREADY_EXISTS 9619L +#define DNS_ERROR_ZONE_REQUIRES_MASTER_IP 9620L +#define DNS_ERROR_ZONE_IS_SHUTDOWN 9621L +#define DNS_ERROR_PRIMARY_REQUIRES_DATAFILE 9651L +#define DNS_ERROR_INVALID_DATAFILE_NAME 9652L +#define DNS_ERROR_DATAFILE_OPEN_FAILURE 9653L +#define DNS_ERROR_FILE_WRITEBACK_FAILED 9654L +#define DNS_ERROR_DATAFILE_PARSING 9655L +#define DNS_ERROR_RECORD_DOES_NOT_EXIST 9701L +#define DNS_ERROR_RECORD_FORMAT 9702L +#define DNS_ERROR_NODE_CREATION_FAILED 9703L +#define DNS_ERROR_UNKNOWN_RECORD_TYPE 9704L +#define DNS_ERROR_RECORD_TIMED_OUT 9705L +#define DNS_ERROR_NAME_NOT_IN_ZONE 9706L +#define DNS_ERROR_CNAME_LOOP 9707L +#define DNS_ERROR_NODE_IS_CNAME 9708L +#define DNS_ERROR_CNAME_COLLISION 9709L +#define DNS_ERROR_RECORD_ONLY_AT_ZONE_ROOT 9710L +#define DNS_ERROR_RECORD_ALREADY_EXISTS 9711L +#define DNS_ERROR_SECONDARY_DATA 9712L +#define DNS_ERROR_NO_CREATE_CACHE_DATA 9713L +#define DNS_ERROR_NAME_DOES_NOT_EXIST 9714L +#define DNS_WARNING_PTR_CREATE_FAILED 9715L +#define DNS_WARNING_DOMAIN_UNDELETED 9716L +#define DNS_ERROR_DS_UNAVAILABLE 9717L +#define DNS_ERROR_DS_ZONE_ALREADY_EXISTS 9718L +#define DNS_ERROR_NO_BOOTFILE_IF_DS_ZONE 9719L +#define DNS_INFO_AXFR_COMPLETE 9751L +#define DNS_ERROR_AXFR 9752L +#define DNS_INFO_ADDED_LOCAL_WINS 9753L +#define DNS_STATUS_CONTINUE_NEEDED 9801L +#define DNS_ERROR_NO_TCPIP 9851L +#define DNS_ERROR_NO_DNS_SERVERS 9852L +#define DNS_ERROR_DP_DOES_NOT_EXIST 9901L +#define DNS_ERROR_DP_ALREADY_EXISTS 9902L +#define DNS_ERROR_DP_NOT_ENLISTED 9903L +#define DNS_ERROR_DP_ALREADY_ENLISTED 9904L +#define DNS_ERROR_DP_NOT_AVAILABLE 9905L +#endif diff --git a/winsup/cygwin/libc/minires.c b/winsup/cygwin/libc/minires.c new file mode 100644 index 000000000..4c9495831 --- /dev/null +++ b/winsup/cygwin/libc/minires.c @@ -0,0 +1,916 @@ +/* minires.c. Stub synchronous resolver for Cygwin. + + Copyright 2006 Red Hat, Inc. + + Written by Pierre A. Humblet + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#include "minires.h" + +/*********************************************************************** + +Utilities + +***********************************************************************/ +/*********************************************************************** + +dprintf +***********************************************************************/ +void minires_dprintf(const char * format, ...) +{ + va_list args; + + va_start(args, format); + fprintf(stderr, "Minires: "); + vfprintf(stderr, format, args); + va_end(args); +} + +/*********************************************************************** + +scanline +Put pointers in list[] to the beginning of each space or comma delimited +word in "in", and put the lengths in sizes[] (counting the final 0). +Return the number of words found +***********************************************************************/ +static int scanline(char * in, char **list, int * sizes, int maxnum) +{ + int i; + char * startp; + for (i = 0; i < maxnum; i++) { + while((*in) && (isspace(*in) || *in == ',')) in++; + if (*in == 0) + break; + startp = in++; + while((*in) && !isspace(*in) && *in != ',') in++; + list[i] = startp; + sizes[i] = in - startp + 1; + if (*in) + *in++ = 0; + } + return i; +} + +/*********************************************************************** + +Read the search string. + +***********************************************************************/ +void minires_get_search(char * string, res_state statp) +{ + char * words[MAXDNSRCH+1], * ptr; + int sizes[MAXDNSRCH+1]; + int i, j, debug = statp->options & RES_DEBUG; + + i = scanline(string, words, sizes, MAXDNSRCH+1); + ptr = statp->defdname; + for (j = 0; j < i; j++) { + if (j < MAXDNSRCH + && ptr + sizes[j] < &statp->defdname[DIM(statp->defdname)]) { + statp->dnsrch[j] = strcpy(ptr, words[j]); + statp->dnsrch[j+1] = NULL; + ptr += sizes[j]; + DPRINTF(debug, "search \"%s\"\n", words[j]); + } + else + DPRINTF(debug, "no space for \"%s\"\n", words[j]); + } +} + +/*********************************************************************** + +Read options + + +***********************************************************************/ +static void get_options(res_state statp, int i, char **words) +{ + char *ptr; + int value; + + while (i-- > 0) { + if (!strcasecmp("debug", words[i])) { + statp->options |= RES_DEBUG; + DPRINTF(statp->options & RES_DEBUG, "%s: 1\n", words[i]); + continue; + } + if (!strcasecmp("osquery", words[i])) { + statp->use_os = 1; + DPRINTF(statp->options & RES_DEBUG, "%s: 1\n", words[i]); + continue; + } + + if ((ptr = strchr(words[i], ':'))) { + *ptr++ = 0; + value = atoi(ptr); + /* Not supported + if (!strcasecmp("ndots", words[i])) { + statp->ndots = value; + continue; + } + */ + if (!strcasecmp("retry", words[i])) { + if (value < 1) + value = 1; + statp->retry = value; + DPRINTF(statp->options & RES_DEBUG, "%s: %d\n", words[i], value); + continue; + } + if (!strcasecmp("retrans", words[i])) { + if (value < 1) + value = 1; + statp->retrans = value; + DPRINTF(statp->options & RES_DEBUG, "%s: %d\n", words[i], value); + continue; + } + } + DPRINTF(statp->options & RES_DEBUG, "unknown option: \"%s\"\n", words[i]); + } +} + +/*********************************************************************** + +Read the resolv.conf file. +We only look for nameserver, domain, search and options + +***********************************************************************/ +#if MAXNS > MAXDNSRCH + 1 +#define MAXSIZE MAXNS +#else +#define MAXSIZE MAXDNSRCH + 1 /* Make unused one visible */ +#endif +static void get_resolv(res_state statp) +{ + FILE * fd; + char *words[MAXSIZE + 1], line[4096], *ptr; + int sizes[DIM(words)]; + int i, j, ns = 0, have_search, have_address, debug = statp->options & RES_DEBUG; + + fd = fopen(_PATH_RESCONF, "r"); + DPRINTF(debug, _PATH_RESCONF ": %s\n", fd?"OK":strerror(errno)); + if (fd == NULL) + return; + + statp->use_os = 0; /* Do not use os_query, except if allowed by "options" */ + have_search = (statp->dnsrch[0] != NULL); + have_address = (statp->nscount != 0); + + while ( fgets(line, sizeof(line), fd) != 0) { + DPRINTF(debug, "resolv.conf %s", line); + if ((i = scanline(line, words, sizes, DIM(words))) > 0) { + if (!have_address + && !strncasecmp("nameserver", words[0], sizes[0])) { + for ( j = 1; j < i ; j++) { + unsigned int address; + address = cygwin_inet_addr(words[j]); + if (address == -1) { + DPRINTF(debug, "invalid server \"%s\"\n", words[j]); + } + else if (ns >= MAXNS) { + DPRINTF(debug, "no space for server \"%s\"\n", words[j]); + } + else { + statp->nsaddr_list[ns++].sin_addr.s_addr = address; + statp->nscount++; + DPRINTF(debug, "server \"%s\"\n", words[j]); + } + } + } + else if (!have_search + && (!strncasecmp("search", words[0], sizes[0]) + || !strncasecmp("domain", words[0], sizes[0]))) { + ptr = statp->defdname; + for (j = 0; j + 1 < i; j++) { + if (j < MAXDNSRCH + && ptr + sizes[j + 1] < &statp->defdname[DIM(statp->defdname)]) { + statp->dnsrch[j] = strcpy(ptr, words[j+1]); + statp->dnsrch[j+1] = 0; + ptr += sizes[j+1]; + DPRINTF(debug, "domain|search \"%s\"\n", statp->dnsrch[j]); + } + else { + DPRINTF(debug, "no space for \"%s\"\n", words[j+1]); + } + } + } + /* Options line */ + else if (!strncasecmp("options", words[0], sizes[0])) + get_options(statp, i - 1, &words[1]); + } + } + fclose(fd); + return; +} + +/****************************************************************************/ +/* + open_sock() + Create a datagram socket and call bind. + +****************************************************************************/ + +static int open_sock(struct sockaddr_in *CliAddr, int debug) +{ + int fd; + + DPRINTF(debug, "opening UDP socket\n"); + + /* Create a datagram socket */ + if ((fd = cygwin_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { + DPRINTF(debug, "socket(UDP): %s\n", strerror(errno)); + return -1; + } + CliAddr->sin_family = AF_INET; + CliAddr->sin_addr.s_addr = htonl(INADDR_ANY); + CliAddr->sin_port = htons(0); + bzero(CliAddr->sin_zero, sizeof(CliAddr->sin_zero)); + /* Get a port */ + if (cygwin_bind(fd, (struct sockaddr *) CliAddr, sizeof(*CliAddr)) < 0) { + DPRINTF(debug, "bind: %s\n", strerror(errno)); + return -1; + } + return fd; +} + +/***************************************************************** + * + __res_state() + Undocumented but public. Accessed through _res + + *****************************************************************/ +static struct __res_state res; +struct __res_state *__res_state(void) +{ + return & res; +} + +/***************************************************************** + * + res_init() + + *****************************************************************/ +int res_ninit(res_state statp) +{ + int i; + char * ptr; + + statp->res_h_errno = NETDB_SUCCESS; + statp->nscount = 0; + statp->os_query = NULL; + statp->retrans = RES_TIMEOUT; /* timeout in seconds */ + statp->retry = RES_MAXRETRY; /* max number of retries */ + statp->use_os = 1; /* use os_query if available and allowed by get_resolv */ + statp->mypid = -1; + statp->sockfd = -1; + + for (i = 0; i < DIM(statp->dnsrch); i++) statp->dnsrch[i] = 0; + + /* Get search list from LOCALDOMAIN */ + if ((ptr = getenv("LOCALDOMAIN")) != 0 ) { + DPRINTF(statp->options & RES_DEBUG, "LOCALDOMAIN \"%s\"\n", ptr); + minires_get_search(ptr, statp); /* domain or dnsrch */ + } + /* resolv.conf (dns servers & search list)*/ + get_resolv(statp); + /* Get dns servers and search list from an os-specific routine, set os_query */ + get_dns_info(statp); + + if (statp->nscount == 0 && !statp->os_query) { + errno = ENONET; + statp->res_h_errno = NETDB_INTERNAL; + DPRINTF(statp->options & RES_DEBUG, "no dns server found\n"); + return -1; + } + for (i = 0; i < statp->nscount; i++) { + statp->nsaddr_list[i].sin_family = AF_INET; + statp->nsaddr_list[i].sin_port = htons(NAMESERVER_PORT); + bzero(statp->nsaddr_list[i].sin_zero, sizeof(statp->nsaddr_list[i].sin_zero)); + } + /* Only debug may be set before calling init */ + statp->options &= RES_DEBUG; + statp->options |= RES_INIT | RES_DEFAULT; + return 0; +} + +int res_init() +{ + int r = res_ninit(& res); + h_errno = res.res_h_errno; + return r; +} + +/***************************************************************** + * + res_close() + + *****************************************************************/ +void res_nclose(res_state statp) +{ + int res; + if (statp->sockfd != -1) { + res = close(statp->sockfd); + DPRINTF(statp->options & RES_DEBUG, "close sockfd %d: %s\n", + statp->sockfd, (res == 0)?"OK":strerror(errno)); + statp->sockfd = -1; + } +} + +void res_close() +{ + res_nclose(& res); +} + +/***************************************************************** + * + get_tcp_buf() + + *****************************************************************/ +static int get_tcp_buf(int fd, unsigned char *buf, int size, int debug) +{ + int res; + while (size > 0) { + if ((res = read(fd, buf, size)) < 0) { + DPRINTF(debug, "read: %s\n", strerror(errno)); + return -1; + } + DPRINTF(debug, "read %d out of %d\n", res, size); + size -= res; + buf += res; + } + return 0; +} + +/***************************************************************** + * + get_tcp() + + *****************************************************************/ +static int get_tcp(struct sockaddr_in *CliAddr, + const unsigned char * MsgPtr, int MsgLength, + unsigned char * AnsPtr, int AnsLength, int debug) +{ + int fd, res = -1; + unsigned short ans_length; + union {short len; u_char buf[sizeof(short)];} len_buf; + + DPRINTF(debug, "retrying with TCP\n"); + + /* Create a tcp socket */ + if ((fd = cygwin_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) { + DPRINTF(debug, "socket(TCP): %s\n", strerror(errno)); + return -1; + } + + if (cygwin_connect(fd, (struct sockaddr *) CliAddr, sizeof(* CliAddr)) < 0) { + DPRINTF(debug, "connect: %s\n", strerror(errno)); + goto done; + } + + /* Send the length then the message */ + len_buf.len = htons(MsgLength); + if (write(fd, len_buf.buf, sizeof(len_buf)) != sizeof(len_buf) + || write(fd, MsgPtr, MsgLength) != MsgLength) { + DPRINTF(debug, "write: %s\n", strerror(errno)); + goto done; + } + + /* Read the answer length */ + if (get_tcp_buf(fd, len_buf.buf, sizeof(len_buf), debug)) + goto done; + ans_length = ntohs(len_buf.len); + + /* Read the answer */ + if (get_tcp_buf(fd, AnsPtr, MIN(ans_length, AnsLength), debug)) + goto done; + res = ans_length; + + done: + close (fd); + return res; +} + +/***************************************************************** + ** + res_send + Assumes that the message is a query starting with a short id. + Handles retransmissions until that id is received. + +*****************************************************************/ +int res_nsend( res_state statp, const unsigned char * MsgPtr, + int MsgLength, unsigned char * AnsPtr, int AnsLength) +{ + /* Current server, shared by all tasks */ + volatile static unsigned int SServ = 0XFFFFFFFF; + int tcp; + const int debug = statp->options & RES_DEBUG; + + fd_set fdset_read; + int rslt, addrLen, transNum, wServ; + struct sockaddr_in mySockAddr, dnsSockAddr; + struct timeval timeOut; + + statp->res_h_errno = NETDB_SUCCESS; + if (((statp->options & RES_INIT) == 0) && (res_ninit(statp) != 0)) + return -1; + + /* Close the socket if it had been opened before a fork. + Reuse of pid's cannot hurt */ + if ((statp->sockfd != -1) && (statp->mypid != getpid())) { + res_nclose(statp); + } + + /* Open a socket for this process */ + if (statp->sockfd == -1) { + /* Create a socket and bind it (to any port) */ + statp->sockfd = open_sock(& mySockAddr, debug); + if (statp->sockfd < 0 ) { + statp->res_h_errno = NETDB_INTERNAL; + return -1; + } + /* Set close on exec flag */ + if (fcntl(statp->sockfd, F_SETFD, 1) == -1) { + DPRINTF(debug, "fcntl: %s\n", + strerror(errno)); + statp->res_h_errno = NETDB_INTERNAL; + return -1; + } + statp->mypid = getpid(); + if (SServ == 0XFFFFFFFF) /* Pseudo random */ + SServ = statp->mypid % statp->nscount; + } + + transNum = 0; + while ( transNum++ < statp->retry) { + if ((wServ = SServ + 1) >= statp->nscount) + wServ = 0; + SServ = wServ; + /* Send the message */ + rslt = cygwin_sendto(statp->sockfd, MsgPtr, MsgLength, 0, + (struct sockaddr *) &statp->nsaddr_list[wServ], + sizeof(struct sockaddr_in)); + DPRINTF(debug, "sendto: server %08x sockfd %d %s\n", + statp->nsaddr_list[wServ].sin_addr.s_addr, + statp->sockfd, (rslt == MsgLength)?"OK":strerror(errno)); + if (rslt != MsgLength) { + statp->res_h_errno = NETDB_INTERNAL; + return -1; + }; + /* + Wait for a reply with select() + */ + FD_ZERO(&fdset_read); + FD_SET (statp->sockfd, &fdset_read ); + timeOut.tv_sec = statp->retrans; + timeOut.tv_usec = 0; + rslt = cygwin_select(statp->sockfd + 1, &fdset_read, NULL, NULL, &timeOut); + if ( rslt == 0 ) { /* Timeout */ + DPRINTF(statp->options & RES_DEBUG, "timeout for server %08x\n", + statp->nsaddr_list[wServ].sin_addr.s_addr); + continue; + } + else if ((rslt != 1) || (FD_ISSET(statp->sockfd, &fdset_read) == 0)) { + DPRINTF(debug, "select: %s\n", strerror(errno)); + statp->res_h_errno = NETDB_INTERNAL; + return -1; + } + + addrLen = sizeof(dnsSockAddr); + rslt = cygwin_recvfrom(statp->sockfd, AnsPtr, AnsLength, 0, + (struct sockaddr *) & dnsSockAddr, & addrLen); + if (rslt <= 0) { + DPRINTF(debug, "recvfrom: %s\n", strerror(errno)); + statp->res_h_errno = NETDB_INTERNAL; + return -1; + } + /* + Prepare to retry with tcp + */ + for (tcp = 0; tcp < 2; tcp++) { + /* Check if this is the message we expected */ + if ((*MsgPtr == *AnsPtr) /* Ids match */ + && (*(MsgPtr + 1) == *(AnsPtr + 1)) +/* We have stopped checking this because the question may not be present on error, + in particular when the name in the question is not a valid name. + Simply check that the header is present. */ + && (rslt >= HFIXEDSZ) +/* && (rslt >= MsgLength ) + && (memcmp(MsgPtr + HFIXEDSZ, AnsPtr + HFIXEDSZ, MsgLength - HFIXEDSZ) == 0) */ + && ((AnsPtr[2] & QR) != 0)) { + + DPRINTF(debug, "answer %u from %08x. Error %d. Count %d.\n", + rslt, dnsSockAddr.sin_addr.s_addr, + AnsPtr[3] & ERR_MASK, AnsPtr[6]*256 + AnsPtr[7]); +#if 0 + NETDB_INTERNAL -1 /* see errno */ + NETDB_SUCCESS 0 /* no problem */ + HOST_NOT_FOUND 1 /* Authoritative Answer Host not found */ + TRY_AGAIN 2 /* Non-Authoritive Host not found, or SERVERFAIL */ + Also seen returned by some servers when the name is too long + NO_RECOVERY 3 /* Non recoverable errors, FORMERR, REFUSED, NOTIMP */ + NO_DATA 4 /* Valid name, no data record of requested type */ +#endif + if ((AnsPtr[3] & ERR_MASK) == NOERROR) { + if ((AnsPtr[2] & TC) && !(statp->options & RES_IGNTC)) { /* Truncated. Try TCP */ + rslt = get_tcp(&statp->nsaddr_list[wServ], MsgPtr, MsgLength, + AnsPtr, AnsLength, statp->options & RES_DEBUG); + continue; + } + else if ((AnsPtr[6] | AnsPtr[7])!= 0) + return rslt; + else + statp->res_h_errno = NO_DATA; + } + else { + /* return HOST_NOT_FOUND even for non-authoritative answers */ + if ((AnsPtr[3] & ERR_MASK) == NXDOMAIN) + statp->res_h_errno = HOST_NOT_FOUND; + else if ((AnsPtr[3] & ERR_MASK) == SERVFAIL) + statp->res_h_errno = TRY_AGAIN; + else + statp->res_h_errno = NO_RECOVERY; + } + return -1; + } + else { + DPRINTF(debug, "unexpected answer %u from %x to query to %x\n", + rslt, dnsSockAddr.sin_addr.s_addr, + statp->nsaddr_list[wServ].sin_addr.s_addr); + break; + } + } /* TCP */ + } + DPRINTF(debug, "too many retries\n"); + statp->res_h_errno = TRY_AGAIN; + return -1; +} + +int res_send( const unsigned char * MsgPtr, int MsgLength, + unsigned char * AnsPtr, int AnsLength) +{ + int r = res_nsend(& res, MsgPtr, MsgLength, AnsPtr, AnsLength); + h_errno = res.res_h_errno; + return r; +} + +/***************************************************************** + * + res_mkquery + + Return: packet size + -1 name format is incorrect +*****************************************************************/ +int res_nmkquery (res_state statp, + int op, const char * dnameptr, int qclass, int qtype, + const unsigned char * dataptr, int datalen, + const unsigned char * newrr, unsigned char * buf, int buflen) +{ + int i, len; + short id; + + if (op == QUERY) { + /* Write the name and verify buffer length */ + len = dn_comp(dnameptr, buf + HFIXEDSZ, buflen - HFIXEDSZ - QFIXEDSZ, NULL, NULL); + if (len < 0) { + DPRINTF(statp->options & RES_DEBUG, + "\"%s\" invalid or buffer too short\n", dnameptr); + statp->res_h_errno = NETDB_INTERNAL; + return -1; + } + /* Fill the header */ + id = statp->id; + PUTSHORT(id, buf); + PUTSHORT(RD, buf); + PUTSHORT(1, buf); /* Number of questions */ + for (i = 0; i < 3; i++) + PUTSHORT(0, buf); /* Number of answers */ + + /* Write qtype and qclass */ + buf += len; + PUTSHORT(qtype, buf); + PUTSHORT(qclass, buf); + return len + 16; /* packet size */ + } + else { /* Not implemented */ + errno = ENOSYS; + statp->res_h_errno = NETDB_INTERNAL; + return -1; + } +} + +int res_mkquery (int op, const char * dnameptr, int qclass, int qtype, + const unsigned char * dataptr, int datalen, + const unsigned char * newrr, unsigned char * buf, int buflen) +{ + int r = res_nmkquery (& res, op, dnameptr, qclass, qtype, + dataptr, datalen, newrr, buf, buflen); + h_errno = res.res_h_errno; + return r; + +} + +/***************************************************************** + * + res_query() + + *****************************************************************/ + +int res_nquery( res_state statp, const char * DomName, int Class, int Type, + unsigned char * AnsPtr, int AnsLength) +{ + u_char packet[PACKETSZ]; + int len; + + DPRINTF(statp->options & RES_DEBUG, "query \"%s\" type %d\n", DomName, Type); + statp->res_h_errno = NETDB_SUCCESS; + + /* If a hook exists to a native implementation, use it */ + if (statp->os_query) + return ((os_query_t *) statp->os_query)(statp, DomName, Class, Type, AnsPtr, AnsLength); + + if ((len = res_nmkquery (statp, QUERY, DomName, Class, Type, + 0, 0, 0, packet, PACKETSZ)) < 0) + return -1; + return res_nsend( statp, packet, len, AnsPtr, AnsLength); +} + +int res_query( const char * DomName, int Class, int Type, unsigned char * AnsPtr, int AnsLength) +{ + int r = res_nquery(& res, DomName, Class, Type, AnsPtr, AnsLength); + h_errno = res.res_h_errno; + return r; +} + +/***************************************************************** + * + res_querydomain() + + *****************************************************************/ +int res_nquerydomain( res_state statp, const char * Name, const char * DomName, + int Class, int Type, unsigned char * AnsPtr, int AnsLength) +{ + char fqdn[MAXDNAME], *ptr; + int nlen; + + if (!DomName) + ptr = (char *) Name; + else if ((nlen = strlen(Name)) >= sizeof(fqdn) - 1) + goto error; + else { + strcpy(fqdn, Name); + ptr = &fqdn[nlen]; + if (nlen && *(ptr - 1) != '.') + *(ptr++ - 1) = '.'; + fqdn[sizeof(fqdn) - 1] = 0; + strncpy(ptr, DomName, sizeof(fqdn) - (ptr - fqdn)); + if (fqdn[sizeof(fqdn) - 1]) + goto error; + ptr = fqdn; + } + return res_nquery(statp, ptr, Class, Type, AnsPtr, AnsLength); + + error: + DPRINTF(statp->options & RES_DEBUG, "querydomain: name too long\n"); + errno = EINVAL; + statp->res_h_errno = NETDB_INTERNAL;; + return -1; +} + +int res_querydomain( const char * Name, const char * DomName, int Class, + int Type, unsigned char * AnsPtr, int AnsLength) +{ + int r = res_nquerydomain(& res, Name, DomName, Class, Type, AnsPtr, + AnsLength); + h_errno = res.res_h_errno; + return r; +} + +/***************************************************************** + * + res_search() + + *****************************************************************/ + +int res_nsearch( res_state statp, const char * DomName, int Class, int Type, + unsigned char * AnsPtr, int AnsLength) +{ + int len, stat, i; + char fullDomName[MAXDNAME], *ptr, *sptr; + + DPRINTF(statp->options & RES_DEBUG, "search \"%s\" type %d\n", DomName, Type); + + if (((statp->options & RES_INIT) == 0) && (res_ninit(statp) != 0)) + return -1; + + stat = res_nquery( statp, DomName, Class, Type, AnsPtr, AnsLength); + + /* Check if will skip search */ + if (statp->res_h_errno != HOST_NOT_FOUND /* Success or hard failure */ + || ((ptr = strrchr(DomName, '.')) && (!*(ptr+1))) /* Final dot */ + || (((statp->options & RES_DNSRCH) == 0) /* Or no search */ + && ((ptr != NULL) /* And some dot */ + || ((statp->options & RES_DEFNAMES) == 0)))/* or no def domain */ + || (!(sptr = statp->dnsrch[0]))) + return stat; + + len = strlen(DomName); + if (len >= MAXDNAME - 1) /* Space for next dot */ + goto error; + strcpy(fullDomName, DomName); + fullDomName[len++] = '.'; + fullDomName[MAXDNAME - 1] = 0; /* Overflow indicator */ + i = 0; + do { + strncpy(fullDomName + len, sptr, MAXDNAME - len); + if (fullDomName[MAXDNAME - 1]) + goto error; + stat = res_nquery(statp, fullDomName, Class, Type, AnsPtr, AnsLength); + } while ((sptr = statp->dnsrch[++i]) != NULL + && statp->res_h_errno == HOST_NOT_FOUND + && (statp->options & RES_DNSRCH) != 0); + + /* Return last stat */ + return stat; + + error: + DPRINTF(statp->options & RES_DEBUG, "name too long during search\n"); + errno = EINVAL; + statp->res_h_errno = NETDB_INTERNAL; + return -1; +} + +int res_search( const char * DomName, int Class, int Type, + unsigned char * AnsPtr, int AnsLength) +{ + int r = res_nsearch(& res, DomName, Class, Type, AnsPtr, AnsLength); + h_errno = res.res_h_errno; + return r; +} + +/***************************************************************** + * + dn_expand + + *****************************************************************/ + +int dn_expand(const unsigned char *msg, const unsigned char *eomorig, + const unsigned char *comp_dn, char *exp_dn, int length) +{ + unsigned int len, complen = 0; + const unsigned char *comp_dn_orig = comp_dn; +/* char * exp_start = exp_dn; */ + + errno = EINVAL; + if (comp_dn >= eomorig) + goto expand_fail; + if ((len = *comp_dn++) == 0) /* Weird case */ + exp_dn++; + else do { + if (len <= MAXLABEL) { + if ((length -= (len + 1)) > 0 /* Need space for final . */ + && comp_dn + len <= eomorig) { + do { *exp_dn++ = *comp_dn++; } while (--len != 0); + *exp_dn++ = '.'; + } + else + goto expand_fail; + } + else if (len >= (128+64)) { + if (!complen) /* Still in the original field? */ + complen = (comp_dn - comp_dn_orig) + 1; + comp_dn = msg + (((len & ~(128+64)) << 8) + *comp_dn); + if (comp_dn >= eomorig) + goto expand_fail; + } + else + goto expand_fail; + } while ((len = *comp_dn++) != 0); + /* Replace last . with a 0 */ + *(--exp_dn) = 0; + if (!complen) + complen = comp_dn - comp_dn_orig; +/* fprintf(stderr, "dn_expand %s\n", exp_start); */ + return complen; + +expand_fail: +/* fprintf(stderr, "dn_expand fails\n"); */ + return -1; +} + + +/***************************************************************** + * + dn_comp + + Return -1 in case of overflow, but still fill buffer correctly. + We do not check the alphabet of the host names + nor the length of the compressed name and we + preserve the letter cases. + + *****************************************************************/ +int dn_comp(const char * exp_dn, u_char * comp_dn, int length, + u_char ** dnptrs, u_char ** lastdnptr) +{ + u_char *cptr = comp_dn, *dptr, *lptr, *rptr; + unsigned int i, len; + u_char * const eptr = comp_dn + length - 1; /* Last valid */ + + errno = EINVAL; + + if (*exp_dn == '.' && !*(exp_dn + 1)) + exp_dn++; + while (1) { + if (*exp_dn == '.' || cptr > eptr) + return -1; + if (*exp_dn == 0) { + *cptr++ = 0; + break; + } + /* Try to compress */ + if (dnptrs) { + for (i = 1; dnptrs[i]; i++) { + dptr = dnptrs[i]; + if (dptr >= comp_dn) /* Handle name.name */ + continue; + rptr = (u_char *) exp_dn; + len = *dptr++; + while (1) { + do { + if (*dptr++ != *rptr++) + goto next_dn; + } while (--len); + len = *dptr++; + if (len == 0) { /* last label */ + if (!*rptr || (*rptr == '.' && !*(rptr + 1))) { /* Full match */ + len = (dnptrs[i] - dnptrs[0]) | 0xC000; + /* Write pointer */ + *cptr++ = len >> 8; + if (cptr > eptr) + return -1; + *cptr++ = len; + goto done; + } + goto next_dn; + } + if (*rptr++ != '.') + goto next_dn; + if (len >= 128 + 64) { + dptr = dnptrs[0] + ((len - 128 - 64) << 8) + *dptr; + len = *dptr++; + } + } + next_dn: ; + } + /* Record label if asked and if space is available and if not too far off */ + if (lastdnptr && (lastdnptr != &dnptrs[i]) && (cptr - dnptrs[0]) < 0xC000) { + dnptrs[i] = cptr; + dnptrs[i+1] = NULL; + } + } + /* Write label */ + lptr = cptr++; /* Length byte */ + rptr = (u_char *) exp_dn; + do { + if (cptr <= eptr) + *cptr++ = *rptr; + } while ((*++rptr != '.') && (*rptr != 0)); + len = rptr - (u_char *) exp_dn; + if (len > MAXLABEL) + return -1; + *lptr = len; + exp_dn = (char *) rptr; + if (*exp_dn != 0) + exp_dn++; /* Skip over . */ + } + done: + return cptr - comp_dn; +} + +/***************************************************************** + * + dn_skipname + + Measures the compressed domain name length and returns it. + *****************************************************************/ +int dn_skipname(const unsigned char *comp_dn, const unsigned char *eom) +{ + int len; + const unsigned char *comp_dn_orig = comp_dn; + + do { + len = *comp_dn++; + if (len >= (128 + 64)) { + comp_dn++; + break; + } + if (len > MAXLABEL || + (comp_dn += len) > eom) + return -1; + } while (len != 0); + + return comp_dn - comp_dn_orig; +} diff --git a/winsup/cygwin/libc/minires.h b/winsup/cygwin/libc/minires.h new file mode 100644 index 000000000..ce063d16f --- /dev/null +++ b/winsup/cygwin/libc/minires.h @@ -0,0 +1,68 @@ +/* minires.h. Stub synchronous resolver for Cygwin. + + Copyright 2006 Red Hat, Inc. + + Written by Pierre A. Humblet + +This file is part of Cygwin. + +This software is a copyrighted work licensed under the terms of the +Cygwin license. Please consult the file "CYGWIN_LICENSE" for +details. */ + +#define __INSIDE_CYGWIN_NET__ + +#include "winsup.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern in_addr_t cygwin_inet_addr (const char *); +extern int cygwin_socket (int, int, int); +extern int cygwin_bind (int, const struct sockaddr *, socklen_t); +extern int cygwin_connect (int, const struct sockaddr *, socklen_t); +extern int cygwin_select (int, fd_set *, fd_set *, fd_set *, struct timeval *); +extern int cygwin_sendto (int, const void *, size_t, int, + const struct sockaddr *, socklen_t); +extern int cygwin_recvfrom (int, void *, size_t, int, struct sockaddr *, + socklen_t *); + +/* Number of elements is an array */ +#define DIM(x) (sizeof(x) / sizeof(*(x))) + +/* Definitions to parse the messages */ +#define RD (1<<8) /* Offset in a short */ +#define RA (1<<7) +#define QR (1<<7) /* Offsets in a char */ +#define TC (1<<1) +#define ERR_MASK 0xF + +/* Type for os specific res_lookup */ +typedef int (os_query_t) (res_state, const char *, int, int, u_char *, int); + +/* Special use of state elements */ +#define sockfd _vcsock +#define mypid _flags +#define os_query qhook +#define use_os pfcode + +#define DPRINTF(cond, format...) if (cond) minires_dprintf(format) + +/* Utility functions */ +void minires_dprintf(const char * format, ...); +void minires_get_search(char * string, res_state statp); +void get_dns_info(res_state statp); diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index a8d4a3321..1c485cc1f 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -515,6 +515,7 @@ sigproc_terminate (exit_states es) sigproc_printf ("entering"); sig_send (myself_nowait, __SIGEXIT); proc_terminate (); // clean up process stuff + CloseHandle (my_sendsig); } }