summaryrefslogtreecommitdiffstats
path: root/src/util/myaddrinfo.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/util/myaddrinfo.h')
-rw-r--r--src/util/myaddrinfo.h229
1 files changed, 229 insertions, 0 deletions
diff --git a/src/util/myaddrinfo.h b/src/util/myaddrinfo.h
new file mode 100644
index 0000000..94f1e9f
--- /dev/null
+++ b/src/util/myaddrinfo.h
@@ -0,0 +1,229 @@
+#ifndef _MYADDRINFO_H_INCLUDED_
+#define _MYADDRINFO_H_INCLUDED_
+
+/*++
+/* NAME
+/* myaddrinfo 3h
+/* SUMMARY
+/* addrinfo encapsulation and emulation
+/* SYNOPSIS
+/* #include <myaddrinfo.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+ * System library.
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <string.h>
+#include <errno.h> /* MAI_STRERROR() */
+#include <limits.h> /* CHAR_BIT */
+
+ /*
+ * Backwards compatibility support for IPV4 systems without addrinfo API.
+ */
+#ifdef EMULATE_IPV4_ADDRINFO
+
+ /*
+ * Avoid clashes with global symbols, just in case some third-party library
+ * provides its own addrinfo() implementation. This also allows us to test
+ * the IPV4 emulation code on an IPV6 enabled system.
+ */
+#undef freeaddrinfo
+#define freeaddrinfo mai_freeaddrinfo
+#undef gai_strerror
+#define gai_strerror mai_strerror
+#undef addrinfo
+#define addrinfo mai_addrinfo
+#undef sockaddr_storage
+#define sockaddr_storage mai_sockaddr_storage
+
+ /*
+ * Modern systems define this in <netdb.h>.
+ */
+struct addrinfo {
+ int ai_flags; /* AI_PASSIVE|CANONNAME|NUMERICHOST */
+ int ai_family; /* PF_xxx */
+ int ai_socktype; /* SOCK_xxx */
+ int ai_protocol; /* 0 or IPPROTO_xxx */
+ size_t ai_addrlen; /* length of ai_addr */
+ char *ai_canonname; /* canonical name for nodename */
+ struct sockaddr *ai_addr; /* binary address */
+ struct addrinfo *ai_next; /* next structure in linked list */
+};
+
+ /*
+ * Modern systems define this in <sys/socket.h>.
+ */
+struct sockaddr_storage {
+ struct sockaddr_in dummy; /* alignment!! */
+};
+
+ /*
+ * Result codes. See gai_strerror() for text. Undefine already imported
+ * definitions so that we can test the IPv4-only emulation on a modern
+ * system without getting a ton of compiler warnings.
+ */
+#undef EAI_ADDRFAMILY
+#define EAI_ADDRFAMILY 1
+#undef EAI_AGAIN
+#define EAI_AGAIN 2
+#undef EAI_BADFLAGS
+#define EAI_BADFLAGS 3
+#undef EAI_FAIL
+#define EAI_FAIL 4
+#undef EAI_FAMILY
+#define EAI_FAMILY 5
+#undef EAI_MEMORY
+#define EAI_MEMORY 6
+#undef EAI_NODATA
+#define EAI_NODATA 7
+#undef EAI_NONAME
+#define EAI_NONAME 8
+#undef EAI_SERVICE
+#define EAI_SERVICE 9
+#undef EAI_SOCKTYPE
+#define EAI_SOCKTYPE 10
+#undef EAI_SYSTEM
+#define EAI_SYSTEM 11
+#undef EAI_BADHINTS
+#define EAI_BADHINTS 12
+#undef EAI_PROTOCOL
+#define EAI_PROTOCOL 13
+#undef EAI_RESNULL
+#define EAI_RESNULL 14
+#undef EAI_MAX
+#define EAI_MAX 15
+
+extern void freeaddrinfo(struct addrinfo *);
+extern char *gai_strerror(int);
+
+#endif
+
+ /*
+ * Bounds grow in leaps. These macros attempt to keep non-library code free
+ * from IPV6 #ifdef pollution. Avoid macro names that end in STRLEN because
+ * they suggest that space for the null terminator is not included.
+ */
+#ifdef HAS_IPV6
+# define MAI_HOSTADDR_STRSIZE INET6_ADDRSTRLEN
+#else
+# ifndef INET_ADDRSTRLEN
+# define INET_ADDRSTRLEN 16
+# endif
+# define MAI_HOSTADDR_STRSIZE INET_ADDRSTRLEN
+#endif
+
+#define MAI_HOSTNAME_STRSIZE 1025
+#define MAI_SERVNAME_STRSIZE 32
+#define MAI_SERVPORT_STRSIZE sizeof("65535")
+
+#define MAI_V4ADDR_BITS 32
+#define MAI_V6ADDR_BITS 128
+#define MAI_V4ADDR_BYTES ((MAI_V4ADDR_BITS + (CHAR_BIT - 1))/CHAR_BIT)
+#define MAI_V6ADDR_BYTES ((MAI_V6ADDR_BITS + (CHAR_BIT - 1))/CHAR_BIT)
+
+ /*
+ * Routines and data structures to hide some of the complexity of the
+ * addrinfo API. They still don't hide that we may get results for address
+ * families that we aren't interested in.
+ *
+ * Note: the getnameinfo() and inet_ntop() system library functions use unsafe
+ * APIs with separate pointer and length arguments. To avoid buffer overflow
+ * problems with these functions, Postfix uses pointers to structures
+ * internally. This way the compiler can enforce that callers provide
+ * buffers with the appropriate length, instead of having to trust that
+ * callers will never mess up some length calculation.
+ */
+typedef struct {
+ char buf[MAI_HOSTNAME_STRSIZE];
+} MAI_HOSTNAME_STR;
+
+typedef struct {
+ char buf[MAI_HOSTADDR_STRSIZE];
+} MAI_HOSTADDR_STR;
+
+typedef struct {
+ char buf[MAI_SERVNAME_STRSIZE];
+} MAI_SERVNAME_STR;
+
+typedef struct {
+ char buf[MAI_SERVPORT_STRSIZE];
+} MAI_SERVPORT_STR;
+
+extern int WARN_UNUSED_RESULT hostname_to_sockaddr_pf(const char *,
+ int, const char *, int, struct addrinfo **);
+extern int WARN_UNUSED_RESULT hostaddr_to_sockaddr(const char *,
+ const char *, int, struct addrinfo **);
+extern int WARN_UNUSED_RESULT sockaddr_to_hostaddr(const struct sockaddr *,
+ SOCKADDR_SIZE, MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *, int);
+extern int WARN_UNUSED_RESULT sockaddr_to_hostname(const struct sockaddr *,
+ SOCKADDR_SIZE, MAI_HOSTNAME_STR *, MAI_SERVNAME_STR *, int);
+extern void myaddrinfo_control(int,...);
+
+#define MAI_CTL_END 0 /* list terminator */
+
+#define MAI_STRERROR(e) ((e) == EAI_SYSTEM ? strerror(errno) : gai_strerror(e))
+
+#define hostname_to_sockaddr(host, serv, sock, res) \
+ hostname_to_sockaddr_pf((host), PF_UNSPEC, (serv), (sock), (res))
+
+ /*
+ * Macros for the case where we really don't want to be bothered with things
+ * that may fail.
+ */
+#define HOSTNAME_TO_SOCKADDR_PF(host, pf, serv, sock, res) \
+ do { \
+ int _aierr; \
+ _aierr = hostname_to_sockaddr_pf((host), (pf), (serv), (sock), (res)); \
+ if (_aierr) \
+ msg_fatal("hostname_to_sockaddr_pf: %s", MAI_STRERROR(_aierr)); \
+ } while (0)
+
+#define HOSTNAME_TO_SOCKADDR(host, serv, sock, res) \
+ HOSTNAME_TO_SOCKADDR_PF((host), PF_UNSPEC, (serv), (sock), (res))
+
+#define HOSTADDR_TO_SOCKADDR(host, serv, sock, res) \
+ do { \
+ int _aierr; \
+ _aierr = hostaddr_to_sockaddr((host), (serv), (sock), (res)); \
+ if (_aierr) \
+ msg_fatal("hostaddr_to_sockaddr: %s", MAI_STRERROR(_aierr)); \
+ } while (0)
+
+#define SOCKADDR_TO_HOSTADDR(sa, salen, host, port, sock) \
+ do { \
+ int _aierr; \
+ _aierr = sockaddr_to_hostaddr((sa), (salen), (host), (port), (sock)); \
+ if (_aierr) \
+ msg_fatal("sockaddr_to_hostaddr: %s", MAI_STRERROR(_aierr)); \
+ } while (0)
+
+#define SOCKADDR_TO_HOSTNAME(sa, salen, host, service, sock) \
+ do { \
+ int _aierr; \
+ _aierr = sockaddr_to_hostname((sa), (salen), (host), (service), (sock)); \
+ if (_aierr) \
+ msg_fatal("sockaddr_to_hostname: %s", MAI_STRERROR(_aierr)); \
+ } while (0)
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*
+/* Wietse Venema
+/* Google, Inc.
+/* 111 8th Avenue
+/* New York, NY 10011, USA
+/*--*/
+
+#endif