From 887fe9b150a69e7dbfb55b3e56b901d59cab053e Mon Sep 17 00:00:00 2001 From: Matti Aarnio Date: Thu, 28 Feb 2008 12:15:01 +0000 Subject: [PATCH] IPv6 resolver API compability library codes from ZMailer by OH2MQK git-svn-id: http://repo.ham.fi/svn/aprsc/trunk@10 3ce903b1-3385-4e86-93cd-f9a4a239f7ac --- src/gai_strerror.c | 67 ++++++++++ src/getnameinfo.c | 319 +++++++++++++++++++++++++++++++++++++++++++++ src/inet_ntop.c | 217 ++++++++++++++++++++++++++++++ src/inet_pton.c | 238 +++++++++++++++++++++++++++++++++ src/netdb6.h | 70 ++++++++++ 5 files changed, 911 insertions(+) create mode 100644 src/gai_strerror.c create mode 100644 src/getnameinfo.c create mode 100644 src/inet_ntop.c create mode 100644 src/inet_pton.c create mode 100644 src/netdb6.h diff --git a/src/gai_strerror.c b/src/gai_strerror.c new file mode 100644 index 0000000..0c182bf --- /dev/null +++ b/src/gai_strerror.c @@ -0,0 +1,67 @@ +/* + Libc fill-in for ZMailer using IPv6 API + by Matti Aarnio 1997, 2001 + + The original Craig Metz code is deeply Linux specific, + this adaptation tries to be way more generic.. +*/ + +#include "../config.h" +#include +#include +#include +#ifndef EAI_BADFLAGS +# include "netdb6.h" +#endif + +#ifndef __STDC__ +# define const +#endif + +#ifndef HAVE_GAI_STRERROR + +/* +%%% copyright-cmetz-97 +This software is Copyright 1997 by Craig Metz, All Rights Reserved. +The Inner Net License Version 2 applies to this software. +You should have received a copy of the license with this software. If +you didn't get a copy, you may request one from . + +*/ + +const char *gai_strerror(errnum) +int errnum; +{ + static char buffer[24]; + switch(errnum) { + case 0: + return "no error"; + case EAI_BADFLAGS: + return "invalid value for ai_flags"; + case EAI_NONAME: + return "name or service is not known"; + case EAI_AGAIN: + return "temporary failure in name resolution"; + case EAI_FAIL: + return "non-recoverable failure in name resolution"; + case EAI_NODATA: + return "no address associated with name"; + case EAI_FAMILY: + return "ai_family not supported"; + case EAI_SOCKTYPE: + return "ai_socktype not supported"; + case EAI_SERVICE: + return "service not supported for ai_socktype"; + case EAI_ADDRFAMILY: + return "address family for name not supported"; + case EAI_MEMORY: + return "memory allocation failure"; + case EAI_SYSTEM: + return "system error"; + default: + sprintf(buffer,"gai_error_%02x", errnum); + return buffer; + } +} + +#endif diff --git a/src/getnameinfo.c b/src/getnameinfo.c new file mode 100644 index 0000000..248f3cf --- /dev/null +++ b/src/getnameinfo.c @@ -0,0 +1,319 @@ +/* + * Generalized adaptation to ZMailer libc fill-in use by + * Matti Aarnio 2000 + * + * The original version taken from glibc-2.1.92 on 1-Aug-2000 + * + * This is SERIOUSLY LOBOTIMIZED to be usable in environments WITHOUT + * threaded versions of getservbyname(), and friends, plus ridding + * __alloca() calls as they are VERY GCC specific, which isn't a good + * thing for ZMailer. (Also DE-ANSIfied to K&R style..) + * + * Original reason for having getaddrinfo() API in ZMailer was + * to support IPv6 universe -- and that is still the reason. This + * adaptation module is primarily for those systems which don't have + * this IPv6 API, but there are also some systems (all those using + * the original INNER NET code -- glibc 2.0/2.1/2.2(?) especially) + * which have faulty error condition processing in them. Specifically + * plain simple TIMEOUTS on queries are not handled properly! + * + * Now that Linuxes have caught up at libc level, we no longer have + * a reason to support kernel things which don't exist at libc level. + * (Running ZMailer on Linux with libc5 is not supported in sense of + * supporting IPv6 at the kernel..) + * + * + * THIS getnameinfo() FUNCTION IS NOT USED IN ZMAILER, BUT IS + * SUPPLIED JUST TO COMPLETE THE API IN CASE IT WILL SOMETIME BECOME + * USED... + * + */ + +/* The Inner Net License, Version 2.00 + + The author(s) grant permission for redistribution and use in source and +binary forms, with or without modification, of the software and documentation +provided that the following conditions are met: + +0. If you receive a version of the software that is specifically labelled + as not being for redistribution (check the version message and/or README), + you are not permitted to redistribute that version of the software in any + way or form. +1. All terms of the all other applicable copyrights and licenses must be + followed. +2. Redistributions of source code must retain the authors' copyright + notice(s), this list of conditions, and the following disclaimer. +3. Redistributions in binary form must reproduce the authors' copyright + notice(s), this list of conditions, and the following disclaimer in the + documentation and/or other materials provided with the distribution. +4. All advertising materials mentioning features or use of this software + must display the following acknowledgement with the name(s) of the + authors as specified in the copyright notice(s) substituted where + indicated: + + This product includes software developed by , The Inner + Net, and other contributors. + +5. Neither the name(s) of the author(s) 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 ITS AUTHORS 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 AUTHORS 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. + + If these license terms cause you a real problem, contact the author. */ + +/* This software is Copyright 1996 by Craig Metz, All Rights Reserved. */ + +# include "ac-defs.h" /* autoconfig environment */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include /* Sol 2.6 barfs without this.. */ +#include +#ifdef HAVE_SYS_UN_H +#include +#endif +#include +#include +#if !defined(EAI_AGAIN) || !defined(AI_NUMERICHOST) +# include "netdb6.h" +#endif + + +#ifndef min +# define min(x,y) (((x) > (y)) ? (y) : (x)) +#endif /* min */ + +#ifndef AF_LOCAL +# ifdef AF_UNIX +# define AF_LOCAL AF_UNIX +# define PF_LOCAL PF_UNIX +# endif +#endif + +static char * nrl_domainname __((void)); +static char * +nrl_domainname () +{ + static char *domain; + static int not_first; + char hostnamebuf[MAXHOSTNAMELEN]; + + if (! not_first) { + char *c; + struct hostent *h; + + not_first = 1; + + h = gethostbyname ("localhost"); + + if (h && (c = strchr (h->h_name, '.'))) + domain = strdup (++c); + else { + /* The name contains no domain information. Use the name + now to get more information. */ + gethostname (hostnamebuf, MAXHOSTNAMELEN); + + c = strchr (hostnamebuf, '.'); + if (c) + domain = strdup (++c); + else { + h = gethostbyname(hostnamebuf); + + if (h && (c = strchr(h->h_name, '.'))) + domain = strdup (++c); + else { + struct in_addr in_addr; + + in_addr.s_addr = htonl (0x7f000001); + + + h = gethostbyaddr((const char *) &in_addr, + sizeof (struct in_addr), + AF_INET); + + if (h && (c = strchr (h->h_name, '.'))) + domain = strdup (++c); + } + } + } + } + + return domain; +} + +/* This is NASTY, GLIBC has changed the type after instroducing + this function, Sol (2.)8 has 'int', of upcoming POSIX standard + revision I don't know.. */ + +#ifndef GETNAMEINFOFLAGTYPE +# if defined(__GLIBC__) && defined(__GLIBC_MINOR__) +# if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 2 + /* I am not sure that it was already 2.2(.0) that had + this change, but 2.2.2 has it... */ +# define GETNAMEINFOFLAGTYPE unsigned int +# else +# define GETNAMEINFOFLAGTYPE int +# endif +# else +# define GETNAMEINFOFLAGTYPE int +# endif +#endif + +#if 0 + +int +getnameinfo __((const struct sockaddr *sa, size_t addrlen, char *host, + size_t hostlen, char *serv, size_t servlen, + GETNAMEINFOFLAGTYPE flags)); + +int +getnameinfo (sa, addrlen, host, hostlen, serv, servlen, flags) + const struct sockaddr *sa; + size_t addrlen; + char *host; + size_t hostlen; + char *serv; + size_t servlen; + GETNAMEINFOFLAGTYPE flags; +{ + int serrno = errno; + int ok = 0; + + if (sa == NULL || addrlen < sizeof (sa->sa_family)) + return -1; + + switch (sa->sa_family) { +#ifdef AF_LOCAL + case AF_LOCAL: + if (addrlen < (size_t) (((struct sockaddr_un *) NULL)->sun_path)) + return -1; + break; +#endif + case AF_INET: + if (addrlen < sizeof (struct sockaddr_in)) + return -1; + break; + default: + return -1; + } + + if (host != NULL && hostlen > 0) + switch (sa->sa_family) { + case AF_INET: + if (!(flags & NI_NUMERICHOST)) { + struct hostent *h; + + h = gethostbyaddr((void *) &(((struct sockaddr_in *)sa)->sin_addr), + sizeof(struct in_addr), AF_INET); + if (h) { + if (flags & NI_NOFQDN) { + char *c; + if ((c = nrl_domainname ()) && (c = strstr(h->h_name, c)) + && (c != h->h_name) && (*(--c) == '.')) { + strncpy (host, h->h_name, + min(hostlen, (size_t) (c - h->h_name))); + host[min(hostlen - 1, (size_t) (c - h->h_name))] = '\0'; + ok = 1; + } else { + strncpy (host, h->h_name, hostlen); + ok = 1; + } + } else { + strncpy (host, h->h_name, hostlen); + ok = 1; + } + } + } + + if (!ok) { + if (flags & NI_NAMEREQD) { + return -1; + } else { + const char *c; + c = inet_ntop (AF_INET, + (void *) &(((struct sockaddr_in *) sa)->sin_addr), + host, hostlen); + if (!c) { + return -1; + } + } + ok = 1; + } + break; + +#ifdef AF_LOCAL + case AF_LOCAL: + if (!(flags & NI_NUMERICHOST)) { + struct utsname utsname; + + if (!uname (&utsname)) { + strncpy (host, utsname.nodename, hostlen); + break; + } + } + + if (flags & NI_NAMEREQD) { + return -1; + } + + strncpy (host, "localhost", hostlen); + break; +#endif + + default: + return -1; + } + + if (serv && (servlen > 0)) + switch (sa->sa_family) { + case AF_INET: + if (!(flags & NI_NUMERICSERV)) { + struct servent *s; + s = getservbyport(((struct sockaddr_in *) sa)->sin_port, + ((flags & NI_DGRAM) ? "udp" : "tcp")); + if (s) { + strncpy (serv, s->s_name, servlen); + break; + } + } + { + char decbuf[30]; + sprintf(decbuf, "%d", ntohs (((struct sockaddr_in *) sa)->sin_port)); + strncpy(serv, decbuf, servlen); + serv[servlen-1] = 0; + } + break; + +#ifdef AF_LOCAL + case AF_LOCAL: + strncpy (serv, ((struct sockaddr_un *) sa)->sun_path, servlen); + break; +#endif + } + + if (host && (hostlen > 0)) + host[hostlen-1] = 0; + if (serv && (servlen > 0)) + serv[servlen-1] = 0; + errno = serrno; + return 0; +} +#endif diff --git a/src/inet_ntop.c b/src/inet_ntop.c new file mode 100644 index 0000000..6da86a2 --- /dev/null +++ b/src/inet_ntop.c @@ -0,0 +1,217 @@ +/* Copyright (c) 1996 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: inet_ntop.c,v 1.2 2006/10/23 21:36:28 mea Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "hostenv.h" + +#include +#include +#include /* For AF_**** */ +#if 0 +#include /* Actually not needed.. */ +#include +#include +#endif +#include +#include +#include +/* #include "portability.h" */ + +#ifdef SPRINTF_CHAR +# define SPRINTF(x) strlen(sprintf/**/x) +#else +# define SPRINTF(x) sprintf x +#endif + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static const char *inet_ntop4 __((const u_char *src, char *dst, size_t size)); +#if defined(AF_INET6) && defined(INET6) +static const char *inet_ntop6 __((const u_char *src, char *dst, size_t size)); +#endif + +/* char * + * inet_ntop(af, src, dst, size) + * convert a network format address to presentation format. + * return: + * pointer to presentation format address (`dst'), or NULL (see errno). + * author: + * Paul Vixie, 1996. + */ + +const char * inet_ntop __((int, const void *, char *, size_t)); + +const char * +inet_ntop(af, src, dst, size) + int af; + const void *src; + char *dst; + size_t size; +{ + switch (af) { + case AF_INET: + return (inet_ntop4(src, dst, size)); +#if defined(AF_INET6) && defined(INET6) + case AF_INET6: + return (inet_ntop6(src, dst, size)); +#endif + default: + errno = EAFNOSUPPORT; + return (NULL); + } + /* NOTREACHED */ +} + +/* const char * + * inet_ntop4(src, dst, size) + * format an IPv4 address, more or less like inet_ntoa() + * return: + * `dst' (as a const) + * notes: + * (1) uses no statics + * (2) takes a u_char* not an in_addr as input + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop4(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + static const char fmt[] = "%u.%u.%u.%u"; + char tmp[sizeof "255.255.255.255"]; + + if (SPRINTF((tmp, fmt, src[0], src[1], src[2], src[3])) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} + +#if defined(AF_INET6) && defined(INET6) + +#ifndef IN6ADDRSZ +#define IN6ADDRSZ 16 +#endif +#ifndef INT16SZ +#define INT16SZ 2 +#endif + +/* const char * + * inet_ntop6(src, dst, size) + * convert IPv6 binary address into presentation (printable) format + * author: + * Paul Vixie, 1996. + */ +static const char * +inet_ntop6(src, dst, size) + const u_char *src; + char *dst; + size_t size; +{ + /* + * Note that int32_t and int16_t need only be "at least" large enough + * to contain a value of the specified size. On some systems, like + * Crays, there is no such thing as an integer variable with 16 bits. + * Keep this in mind if you think this function should have been coded + * to use pointer overlays. All the world's not a VAX. + */ + char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp; + struct { int base, len; } best, cur; + u_int words[IN6ADDRSZ / INT16SZ]; + int i; + + /* + * Preprocess: + * Copy the input (bytewise) array into a wordwise array. + * Find the longest run of 0x00's in src[] for :: shorthanding. + */ + memset(words, '\0', sizeof words); + for (i = 0; i < IN6ADDRSZ; i++) + words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3)); + best.base = -1; + cur.base = -1; + best.len = cur.len = 0; + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + if (words[i] == 0) { + if (cur.base == -1) + cur.base = i, cur.len = 1; + else + cur.len++; + } else { + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + cur.base = -1; + } + } + } + if (cur.base != -1) { + if (best.base == -1 || cur.len > best.len) + best = cur; + } + if (best.base != -1 && best.len < 2) + best.base = -1; + + /* + * Format the result. + */ + tp = tmp; + for (i = 0; i < (IN6ADDRSZ / INT16SZ); i++) { + /* Are we inside the best run of 0x00's? */ + if (best.base != -1 && i >= best.base && + i < (best.base + best.len)) { + if (i == best.base) + *tp++ = ':'; + continue; + } + /* Are we following an initial run of 0x00s or any real hex? */ + if (i != 0) + *tp++ = ':'; + /* Is this address an encapsulated IPv4? */ + if (i == 6 && best.base == 0 && + (best.len == 6 || (best.len == 5 && words[5] == 0xffff))) { + if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp))) + return (NULL); + tp += strlen(tp); + break; + } + tp += SPRINTF((tp, "%x", words[i])); + } + /* Was it a trailing run of 0x00's? */ + if (best.base != -1 && (best.base + best.len) == (IN6ADDRSZ / INT16SZ)) + *tp++ = ':'; + *tp++ = '\0'; + + /* + * Check for overflow, copy, and we're done. + */ + if ((tp - tmp) > size) { + errno = ENOSPC; + return (NULL); + } + strcpy(dst, tmp); + return (dst); +} +#endif diff --git a/src/inet_pton.c b/src/inet_pton.c new file mode 100644 index 0000000..683db03 --- /dev/null +++ b/src/inet_pton.c @@ -0,0 +1,238 @@ +/* Copyright (c) 1996 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. + */ + +#if defined(LIBC_SCCS) && !defined(lint) +static char rcsid[] = "$Id: inet_pton.c,v 1.1.1.1 1998/02/10 21:01:46 mea Exp $"; +#endif /* LIBC_SCCS and not lint */ + +#include "hostenv.h" + +#include +#include +#include /* For AF_**** */ +#if 0 +#include +#include +#include +#endif +#include +#include +/* #include "portability.h" */ + +#ifndef INADDRSZ +#define INADDRSZ 4 +#endif +#ifndef IN6ADDRSZ +#define IN6ADDRSZ 16 +#endif +#ifndef INT16SZ +#define INT16SZ 2 +#endif + +/* + * WARNING: Don't even consider trying to compile this on a system where + * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX. + */ + +static int inet_pton4 __((const char *src, u_char *dst)); +#if defined(AF_INET6) && defined(INET6) +static int inet_pton6 __((const char *src, u_char *dst)); +#endif + +/* int + * inet_pton(af, src, dst) + * convert from presentation format (which usually means ASCII printable) + * to network format (which is usually some kind of binary format). + * return: + * 1 if the address was valid for the specified address family + * 0 if the address wasn't valid (`dst' is untouched in this case) + * -1 if some other error occurred (`dst' is untouched in this case, too) + * author: + * Paul Vixie, 1996. + */ + +int inet_pton __((int, const char *, void *)); + +int +inet_pton(af, src, dst) + int af; + const char *src; + void *dst; +{ + switch (af) { + case AF_INET: + return (inet_pton4(src, dst)); +#if defined(AF_INET6) && defined(INET6) + case AF_INET6: + return (inet_pton6(src, dst)); +#endif + default: + errno = EAFNOSUPPORT; + return (-1); + } + /* NOTREACHED */ +} + +/* int + * inet_pton4(src, dst) + * like inet_aton() but without all the hexadecimal and shorthand. + * return: + * 1 if `src' is a valid dotted quad, else 0. + * notice: + * does not touch `dst' unless it's returning 1. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton4(src, dst) + const char *src; + u_char *dst; +{ + static const char digits[] = "0123456789"; + int saw_digit, octets, ch; + u_char tmp[INADDRSZ], *tp; + + saw_digit = 0; + octets = 0; + *(tp = tmp) = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr(digits, ch)) != NULL) { + u_int new = *tp * 10 + (pch - digits); + + if (new > 255) + return (0); + *tp = new; + if (! saw_digit) { + if (++octets > 4) + return (0); + saw_digit = 1; + } + } else if (ch == '.' && saw_digit) { + if (octets == 4) + return (0); + *++tp = 0; + saw_digit = 0; + } else + return (0); + } + if (octets < 4) + return (0); + memcpy(dst, tmp, INADDRSZ); + return (1); +} + +#if defined(AF_INET6) && defined(INET6) + +/* int + * inet_pton6(src, dst) + * convert presentation level address to network order binary form. + * return: + * 1 if `src' is a valid [RFC1884 2.2] address, else 0. + * notice: + * (1) does not touch `dst' unless it's returning 1. + * (2) :: in a full address is silently ignored. + * credit: + * inspired by Mark Andrews. + * author: + * Paul Vixie, 1996. + */ +static int +inet_pton6(src, dst) + const char *src; + u_char *dst; +{ + static const char xdigits_l[] = "0123456789abcdef", + xdigits_u[] = "0123456789ABCDEF"; + u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp; + const char *xdigits, *curtok; + int ch, saw_xdigit; + u_int val; + + memset((tp = tmp), 0, IN6ADDRSZ); + endp = tp + IN6ADDRSZ; + colonp = NULL; + /* Leading :: requires some special handling. */ + if (*src == ':') + if (*++src != ':') + return (0); + curtok = src; + saw_xdigit = 0; + val = 0; + while ((ch = *src++) != '\0') { + const char *pch; + + if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL) + pch = strchr((xdigits = xdigits_u), ch); + if (pch != NULL) { + val <<= 4; + val |= (pch - xdigits); + if (val > 0xffff) + return (0); + saw_xdigit = 1; + continue; + } + if (ch == ':') { + curtok = src; + if (!saw_xdigit) { + if (colonp) + return (0); + colonp = tp; + continue; + } + if (tp + INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + saw_xdigit = 0; + val = 0; + continue; + } + if (ch == '.' && ((tp + INADDRSZ) <= endp) && + inet_pton4(curtok, tp) > 0) { + tp += INADDRSZ; + saw_xdigit = 0; + break; /* '\0' was seen by inet_pton4(). */ + } + return (0); + } + if (saw_xdigit) { + if (tp + INT16SZ > endp) + return (0); + *tp++ = (u_char) (val >> 8) & 0xff; + *tp++ = (u_char) val & 0xff; + } + if (colonp != NULL) { + /* + * Since some memmove()'s erroneously fail to handle + * overlapping regions, we'll do the shift by hand. + */ + const int n = tp - colonp; + int i; + + for (i = 1; i <= n; i++) { + endp[- i] = colonp[n - i]; + colonp[n - i] = 0; + } + tp = endp; + } + if (tp != endp) + return (0); + memcpy(dst, tmp, IN6ADDRSZ); + return (1); +} +#endif diff --git a/src/netdb6.h b/src/netdb6.h new file mode 100644 index 0000000..ba37746 --- /dev/null +++ b/src/netdb6.h @@ -0,0 +1,70 @@ +/* + IPv6 API additions for the ZMailer at those machines + without proper libraries and includes. + By Matti Aarnio 1997,2004 + */ + +#ifndef __ +# ifdef __STDC__ +# define __(x) x +# else +# define __(x) () +# endif +#endif + +#ifndef HAVE_GETADDRINFO +#ifndef AI_PASSIVE + +struct addrinfo { + int ai_flags; /* AI_PASSIVE | AI_CANONNAME */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0, or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* Length of ai_addr */ + char *ai_canonname; /* canonical name for hostname */ + struct sockaddr *ai_addr; /* binary address */ + struct addrinfo *ai_next; /* next structure in linked list */ +}; + + +extern int getaddrinfo __(( const char *node, const char *service, + const struct addrinfo *hints, + struct addrinfo **res )); +extern void freeaddrinfo __(( struct addrinfo *res )); +extern const char *gai_strerror __((int errcode)); + +#define AI_PASSIVE 1 /* Socket address is intended for `bind'. */ +#endif +#ifndef AI_CANONNAME +#define AI_CANONNAME 2 /* Request for canonical name. */ +#endif +#ifndef AI_NUMERICHOST +#define AI_NUMERICHOST 4 /* Don't use name resolution. */ +#endif + +#ifndef EAI_ADDRFAMILY +/* Error values for `getaddrinfo' function. */ +#define EAI_BADFLAGS -1 /* Invalid value for `ai_flags' field. */ +#define EAI_NONAME -2 /* NAME or SERVICE is unknown. */ +#define EAI_AGAIN -3 /* Temporary failure in name resolution. */ +#define EAI_FAIL -4 /* Non-recoverable failure in name res. */ +#define EAI_NODATA -5 /* No address associated with NAME. */ +#define EAI_FAMILY -6 /* `ai_family' not supported. */ +#define EAI_SOCKTYPE -7 /* `ai_socktype' not supported. */ +#define EAI_SERVICE -8 /* SERVICE not supported for `ai_socktype'. */ +#define EAI_ADDRFAMILY -9 /* Address family for NAME not supported. */ +#define EAI_MEMORY -10 /* Memory allocation failure. */ +#define EAI_SYSTEM -11 /* System error returned in `errno'. */ +#endif + +#ifndef NI_MAXHOST +#define NI_MAXHOST 1025 +#define NI_MAXSERV 32 + +#define NI_NUMERICHOST 0x01 +#define NI_NUMERICSERV 0x02 +#define NI_NAMEREQD 0x04 +#define NI_NOFQDN 0x08 +#define NI_DGRAM 0x10 +#endif +#endif /* ndef HAVE_GETADDRINFO */