Embryonic IPv6 support. abandon.2000-05-07.ipv6
authorian <ian>
Sun, 7 May 2000 13:50:08 +0000 (13:50 +0000)
committerian <ian>
Sun, 7 May 2000 13:50:08 +0000 (13:50 +0000)
INSTALL
src/adns-in6fake.h [new file with mode: 0644]
src/adns.h
src/types.c

diff --git a/INSTALL b/INSTALL
index 45bb1e3..8ece646 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -32,6 +32,22 @@ perform badly.
 You will probably find that GNU Make is required.
 
 
+IPv6 SUPPORT
+
+If you build adns on a system without a definition for AF_INET6 in
+<netinet/in.h>, you will (probably) still be able to do lookups for
+IPv6 addresses, etc.  However, adns will do this by including the
+header file adns-in6fake.h, which contains definitions of various
+IPv6-related structures (those in RFC2133) which I have just made up.
+They may not be the same as those which a later version of your system
+actually includes, which means that the versions of adns built
+before and after IPv6 support on your platform might not be binary
+compatible - EVEN FOR PROGRAMS WHICH DO NOT DO IPv6 LOOKUPS !
+
+On platforms with a `sa_len' field this feature will not work
+properly.
+
+
 SECURITY AND PERFORMANCE - AN IMPORTANT NOTE
 
 adns is not a full-service resolver.  It does no caching of responses
diff --git a/src/adns-in6fake.h b/src/adns-in6fake.h
new file mode 100644 (file)
index 0000000..1cd14c8
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * adns-in6fake.h
+ * - adns declarations for IPv6 compatibility on systems without it
+ */
+/*
+ *
+ *  This file is
+ *    Copyright (C) 2000 Ian Jackson <ian@davenant.greenend.org.uk>
+ *
+ *  It is part of adns, which is
+ *    Copyright (C) 1997-1999 Ian Jackson <ian@davenant.greenend.org.uk>
+ *    Copyright (C) 1999 Tony Finch <dot@dotat.at>
+ *  
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ * 
+ *  For the benefit of certain LGPL'd `omnibus' software which provides
+ *  a uniform interface to various things including adns, I make the
+ *  following additional licence.  I do this because the GPL would
+ *  otherwise force either the omnibus software to be GPL'd or for the
+ *  adns-using part to be distributed separately.
+ *  
+ *  So, you may also redistribute and/or modify adns.h (but only the
+ *  public header file adns.h and not any other part of adns) under the
+ *  terms of the GNU Library General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at
+ *  your option) any later version.
+ *  
+ *  Note that adns itself is GPL'd.  Authors of adns-using applications
+ *  with GPL-incompatible licences, and people who distribute adns with
+ *  applications where the whole distribution is not GPL'd, are still
+ *  likely to be in violation of the GPL.  Anyone who wants to do this
+ *  should contact Ian Jackson.  Please note that to avoid encouraging
+ *  people to infringe the GPL as it applies the body of adns, I think
+ *  that if you take advantage of the special exception to redistribute
+ *  just adns.h under the LGPL, you should retain this paragraph in its
+ *  place in the appropriate copyright statements.
+ *
+ *
+ *  You should have received a copy of the GNU General Public License,
+ *  or the GNU Library General Public License, as appropriate, along
+ *  with this program; if not, write to the Free Software Foundation,
+ *  Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ *
+ *  $Id$
+ */
+
+#ifndef ADNS_IN6FAKE_H_INCLUDED
+#define ADNS_IN6FAKE_H_INCLUDED
+
+#define AF_INET6 10 /* copied from the Linux headers -iwj */
+
+struct in6_addr { unsigned char s6_addr[16]; };
+
+struct sockaddr_in6 {
+  /* Bezerkely invented a useless sa_len member whose effect is to
+   * pointlessly mess up the layout of this struct.  The hackery below
+   * is to try to make sure that the struct sockaddr_in6 we make up
+   * here probably has the same location and size for sin6_family
+   * as both a struct sockaddr and as any putative future real
+   * struct sockadr_in6.
+   */
+  union {
+    struct sockaddr adns__in6fake_sa;
+    struct {
+      unsigned short adns__in6fake_sin6_family;
+      unsigned short adns__in6fake_sin6_port;
+      unsigned long adns__in6fake_sin6_flowinfo;
+      struct in6_addr adns__in6fake_sin6_addr;
+    } adns__in6fake_sin6;
+  } adns__in6fake_union;
+};
+
+#define sin6_family   adns__in6fake_union.adns__in6fake_sa.sa_family
+#define sin6_port     adns__in6fake_union.adns__in6fake_sin6.adns__in6fake_sin6_port;
+#define sin6_flowinfo adns__in6fake_union.adns__in6fake_sin6.adns__in6fake_sin6_addr;
+#define sin6_addr     adns__in6fake_union.adns__in6fake_sin6.adns__in6fake_sin6_addr;
+
+#endif
index 343501d..fd27c93 100644 (file)
@@ -68,6 +68,10 @@ extern "C" { /* I really dislike this - iwj. */
 #include <sys/time.h>
 #include <unistd.h>
 
+#ifndef AF_INET6
+#include "adns-in6fake.h"
+#endif
+
 /* All struct in_addr anywhere in adns are in NETWORK byte order. */
 
 typedef struct adns__state *adns_state;
@@ -84,6 +88,7 @@ typedef enum {
   adns_if_nosigpipe=    0x0040, /* applic has SIGPIPE set to SIG_IGN, do not protect */
   adns_if_checkc_entex= 0x0100, /* do consistency checks on entry/exit to adns funcs */
   adns_if_checkc_freq=  0x0300  /* do consistency checks very frequently (slow!) */
+  adns_if_ip6=          0x1000  /* make default be adns_qf_ip6 */
 } adns_initflags;
 
 typedef enum {
@@ -96,9 +101,44 @@ typedef enum {
   adns_qf_quotefail_cname= 0x00000080, /* refuse if quote-req chars in CNAME we go via */
   adns_qf_cname_loose=     0x00000100, /* allow refs to CNAMEs - without, get _s_cname */
   adns_qf_cname_forbid=    0x00000200, /* don't follow CNAMEs, instead give _s_cname */
+  adns_qf_ip6=             0x00001000, /* return addrs as AF_INET6 in all cases */
+  adns_qf_ip6mixed=        0x00002000, /* return mixture of AF_INET4 and AF_INET6 */
+  adns_qf_ip4=             0x00003000, /* never return AF_INET6, even with _if_ip6 */
   adns__qf_internalmask=   0x0ff00000
 } adns_queryflags;
 
+/* IPv6 support:
+ *  adns_if_ip6 has the effect of changing the default from
+ *  adns_qf_ip4 to adns_qf_ip6.
+ *
+ * query type   _qf__ip4             _qf_ip6mixed           _qf_ip6
+ *
+ * _r_addr      A? => AF_INET        AAAA? => AF_INET6      AAAA? => AF_INET6
+ *              else fail            else A? => AF_INET     else A? => AF_INET6
+ *
+ * _r_a         A => AF_INET         A => AF_INET           A => AF_INET6
+ *
+ * _r_aaaa      AAAA => AF_INET6     AAAA => AF_INET6       AAAA => AF_INET6
+ *
+ * Ie,
+ *  _ip4:      only A lookups will be done, and everything is
+ *             returned as AF_INET addresses;
+ *  _ip6mixed: will look for AAAA records first, and if there
+ *             are any, return them as AF_INET6, otherwise like _ip4.
+ *  _ip6:      like _ip6mixed, but will return even IPv4 addresses in
+ *             IPv6-mapped form inside AF_INET6, for all query types.
+ *
+ * Furthermore, there are configuration options which can prevent the
+ * use of either AAAA or A records for _r_addr; so it is safe to use
+ * _qf_ip6 and _r_addr without checking explicitly whether the host
+ * has IPv6 connectivity.
+ *
+ * Applications which do not support IPv4 should set none of these
+ * flags.  Applications which have been `naively' converted to use
+ * AF_INET6 throughout should set adns_if_ip6.  Applications which
+ * know what they are doing should know which flags to set :-).
+ */
+
 typedef enum {
   adns__rrt_typemask=  0x0ffff,
   adns__qtf_deref=     0x10000, /* dereference domains and perhaps produce extra data */
@@ -129,6 +169,11 @@ typedef enum {
   adns_r_rp_raw=            17,
   adns_r_rp=                    adns_r_rp_raw|adns__qtf_mail822,
 
+  adns_r_aaaa=              28,
+
+  adns_r_srv_raw=           33,
+  adns_r_srv=                   adns_r_srv_raw|adns__qtf_deref,
+  
   adns_r_addr=                  adns_r_a|adns__qtf_deref
   
 } adns_rrtype;
@@ -251,6 +296,7 @@ typedef struct {
   union {
     struct sockaddr sa;
     struct sockaddr_in inet;
+    struct sockaddr_in6 inet6;
   } addr;
 } adns_rr_addr;
 
@@ -290,6 +336,20 @@ typedef struct {
 } adns_rr_soa;
 
 typedef struct {
+  unsigned short priority;
+  unsigned short weight;
+  unsigned short port;
+  adns_rr_hostaddr ha;
+} adns_rr_srv;
+
+typedef struct {
+  unsigned short priority;
+  unsigned short weight;
+  unsigned short port;
+  char *target;
+} adns_rr_srvraw;
+
+typedef struct {
   adns_status status;
   char *cname; /* always NULL if query was for CNAME records */
   char *owner; /* only set if requested in query flags, and may be 0 on error anyway */
@@ -303,12 +363,15 @@ typedef struct {
     adns_rr_intstr *(*manyistr);      /* txt (list of strings ends with i=-1, str=0) */
     adns_rr_addr *addr;               /* addr */
     struct in_addr *inaddr;           /* a */
+    struct in6_addr *inaddr6;         /* aaaa */
     adns_rr_hostaddr *hostaddr;       /* ns */
     adns_rr_intstrpair *intstrpair;   /* hinfo */
     adns_rr_strpair *strpair;         /* rp, rp_raw */
     adns_rr_inthostaddr *inthostaddr; /* mx */
     adns_rr_intstr *intstr;           /* mx_raw */
     adns_rr_soa *soa;                 /* soa, soa_raw */
+    adns_rr_srv *srv;                 /* srv */
+    adns_rr_srvraw *srvraw;           /* srv_raw */
   } rrs;
 } adns_answer;
 
@@ -424,6 +487,13 @@ int adns_init_strcfg(adns_state *newstate_r, adns_initflags flags,
  *   Changes the consistency checking frequency; this overrides the
  *   setting of adns_if_check_entex, adns_if_check_freq, or neither,
  *   in the flags passed to adns_init.
+ *
+ *  in6only
+ *  in4only
+ *   Return only IPv6, respectively only IPv4 addresses, in
+ *   _rr_addr's.  This may result in an adns_s_nodata error, if the
+ *   application only supports, or the remote host only has, the wrong
+ *   kind of address.
  * 
  * There are a number of environment variables which can modify the
  * behaviour of adns.  They take effect only if adns_init is used, and
@@ -508,7 +578,32 @@ int adns_submit_reverse(adns_state ads,
                        void *context,
                        adns_query *query_r);
 /* type must be _r_ptr or _r_ptr_raw.  _qf_search is ignored.
- * addr->sa_family must be AF_INET or you get ENOSYS.
+ * addr->sa_family must be AF_INET or AF_INET6 you get ENOSYS.
+ */
+
+int adns_getaddrinfo(adns_state ads,
+                    const char *name,           /* Eg, "www.example.coom" */
+                    const char *service,        /* Eg, "http" */
+                    const char *protocol,       /* Eg, "tcp" */
+                    unsigned short defaultport, /* Eg, 80 */
+                    adns_queryflags flags,
+                    adns_answer **answer_r, int *invented_r);
+/* Does an SRV lookup (RFC2052).  If this fails, tries an AAAA or A
+ * lookup instead, and if found uses getservbyname to find the port
+ * number (or failing that, uses defaultport).  In the `fallback'
+ * case, will invent an SRV record with have priority and weight == 0
+ * and set *invented_r to 1; if real SRV records were found, will set
+ * *invented_r to 0.  invented_r may be null but answer_r may not be.
+ * If _getaddrinfo returns nonzero, *answer_r and/or *invented_r may
+ * or may not have been overwritten and should not be used.
+ *
+ * NB, like adns_synchronous, can fail either by returning an errno
+ * value, or by returning an adns_answer with ->nrrs==0 and
+ * ->status!=0.
+ *
+ * You have to write two loops when using the returned value, an outer
+ * one to loop over the returned SRV's, and an inner one to loop over
+ * the addresses for each one.
  */
 
 int adns_submit_reverse_any(adns_state ads,
index 668986f..77a11c6 100644 (file)
@@ -1009,11 +1009,14 @@ DEEP_TYPE(hinfo,  "HINFO", 0,     intstrpair, pa_hinfo,   0,          cs_hinfo
 DEEP_TYPE(mx_raw, "MX",   "raw",  intstr,     pa_mx_raw,  di_mx_raw,  cs_inthost    ),
 DEEP_TYPE(txt,    "TXT",   0,     manyistr,   pa_txt,     0,          cs_txt        ),
 DEEP_TYPE(rp_raw, "RP",   "raw",  strpair,    pa_rp,      0,          cs_rp         ),
+FLAT_TYPE(aaaa,   "AAAA",  0,     inaddr6,    pa_inaddr6, di_inaddr6, cs_inaddr6    ),
+DEEP_TYPE(srv_raw,"SRV",  "raw",  srvraw,     pa_srvraw,  di_srvraw,  cs_srvraw     ),
                                                                                       
 FLAT_TYPE(addr,   "A",  "addr",   addr,       pa_addr,    di_addr,    cs_addr       ),
 DEEP_TYPE(ns,     "NS", "+addr",  hostaddr,   pa_hostaddr,di_hostaddr,cs_hostaddr   ),
 DEEP_TYPE(ptr,    "PTR","checked",str,        pa_ptr,     0,          cs_domain     ),
 DEEP_TYPE(mx,     "MX", "+addr",  inthostaddr,pa_mx,      di_mx,      cs_inthostaddr),
+DEEP_TYPE(srv,    "SRV","+addr",  srv,        pa_srv,     di_srv,     cs_srv        ),
                                                                              
 DEEP_TYPE(soa,    "SOA","822",    soa,        pa_soa,     0,          cs_soa        ),
 DEEP_TYPE(rp,     "RP", "822",    strpair,    pa_rp,      0,          cs_rp         ),