From 0d417fc2dcbc0609e46e5a88c301a40e35ded82a Mon Sep 17 00:00:00 2001 From: ian Date: Sun, 7 May 2000 13:50:08 +0000 Subject: [PATCH] Embryonic IPv6 support. --- INSTALL | 16 +++++++++ src/adns-in6fake.h | 88 +++++++++++++++++++++++++++++++++++++++++++++++++ src/adns.h | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++++- src/types.c | 3 ++ 4 files changed, 203 insertions(+), 1 deletion(-) create mode 100644 src/adns-in6fake.h diff --git a/INSTALL b/INSTALL index 45bb1e3..8ece646 100644 --- 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 +, 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 index 0000000..1cd14c8 --- /dev/null +++ b/src/adns-in6fake.h @@ -0,0 +1,88 @@ +/* + * adns-in6fake.h + * - adns declarations for IPv6 compatibility on systems without it + */ +/* + * + * This file is + * Copyright (C) 2000 Ian Jackson + * + * It is part of adns, which is + * Copyright (C) 1997-1999 Ian Jackson + * Copyright (C) 1999 Tony Finch + * + * 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 diff --git a/src/adns.h b/src/adns.h index 343501d..fd27c93 100644 --- a/src/adns.h +++ b/src/adns.h @@ -68,6 +68,10 @@ extern "C" { /* I really dislike this - iwj. */ #include #include +#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, diff --git a/src/types.c b/src/types.c index 668986f..77a11c6 100644 --- a/src/types.c +++ b/src/types.c @@ -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 ), -- 2.11.0