1#ifndef _MYADDRINFO_H_INCLUDED_
2#define _MYADDRINFO_H_INCLUDED_
3
4/*++
5/* NAME
6/*	myaddrinfo 3h
7/* SUMMARY
8/*	addrinfo encapsulation and emulation
9/* SYNOPSIS
10/*	#include <myaddrinfo.h>
11/* DESCRIPTION
12/* .nf
13
14 /*
15  * System library.
16  */
17#include <sys/types.h>
18#include <sys/socket.h>
19#include <netinet/in.h>
20#include <netdb.h>
21#include <string.h>
22#include <errno.h>			/* MAI_STRERROR() */
23#include <limits.h>			/* CHAR_BIT */
24
25 /*
26  * Backwards compatibility support for IPV4 systems without addrinfo API.
27  */
28#ifdef EMULATE_IPV4_ADDRINFO
29
30 /*
31  * Avoid clashes with global symbols, just in case some third-party library
32  * provides its own addrinfo() implementation. This also allows us to test
33  * the IPV4 emulation code on an IPV6 enabled system.
34  */
35#undef  freeaddrinfo
36#define freeaddrinfo	mai_freeaddrinfo
37#undef  gai_strerror
38#define gai_strerror	mai_strerror
39#undef  addrinfo
40#define addrinfo	mai_addrinfo
41#undef  sockaddr_storage
42#define sockaddr_storage mai_sockaddr_storage
43
44 /*
45  * Modern systems define this in <netdb.h>.
46  */
47struct addrinfo {
48    int     ai_flags;			/* AI_PASSIVE|CANONNAME|NUMERICHOST */
49    int     ai_family;			/* PF_xxx */
50    int     ai_socktype;		/* SOCK_xxx */
51    int     ai_protocol;		/* 0 or IPPROTO_xxx */
52    size_t  ai_addrlen;			/* length of ai_addr */
53    char   *ai_canonname;		/* canonical name for nodename */
54    struct sockaddr *ai_addr;		/* binary address */
55    struct addrinfo *ai_next;		/* next structure in linked list */
56};
57
58 /*
59  * Modern systems define this in <sys/socket.h>.
60  */
61struct sockaddr_storage {
62    struct sockaddr_in dummy;		/* alignment!! */
63};
64
65 /*
66  * Result codes. See gai_strerror() for text. Undefine already imported
67  * definitions so that we can test the IPv4-only emulation on a modern
68  * system without getting a ton of compiler warnings.
69  */
70#undef  EAI_ADDRFAMILY
71#define EAI_ADDRFAMILY   1
72#undef  EAI_AGAIN
73#define EAI_AGAIN        2
74#undef  EAI_BADFLAGS
75#define EAI_BADFLAGS     3
76#undef  EAI_FAIL
77#define EAI_FAIL         4
78#undef  EAI_FAMILY
79#define EAI_FAMILY       5
80#undef  EAI_MEMORY
81#define EAI_MEMORY       6
82#undef  EAI_NODATA
83#define EAI_NODATA       7
84#undef  EAI_NONAME
85#define EAI_NONAME       8
86#undef  EAI_SERVICE
87#define EAI_SERVICE      9
88#undef  EAI_SOCKTYPE
89#define EAI_SOCKTYPE    10
90#undef  EAI_SYSTEM
91#define EAI_SYSTEM      11
92#undef  EAI_BADHINTS
93#define EAI_BADHINTS    12
94#undef  EAI_PROTOCOL
95#define EAI_PROTOCOL    13
96#undef  EAI_RESNULL
97#define EAI_RESNULL     14
98#undef  EAI_MAX
99#define EAI_MAX         15
100
101extern void freeaddrinfo(struct addrinfo *);
102extern char *gai_strerror(int);
103
104#endif
105
106 /*
107  * Bounds grow in leaps. These macros attempt to keep non-library code free
108  * from IPV6 #ifdef pollution. Avoid macro names that end in STRLEN because
109  * they suggest that space for the null terminator is not included.
110  */
111#ifdef HAS_IPV6
112# define MAI_HOSTADDR_STRSIZE	INET6_ADDRSTRLEN
113#else
114# ifndef INET_ADDRSTRLEN
115#  define INET_ADDRSTRLEN	16
116# endif
117# define MAI_HOSTADDR_STRSIZE	INET_ADDRSTRLEN
118#endif
119
120#define MAI_HOSTNAME_STRSIZE	1025
121#define MAI_SERVNAME_STRSIZE	32
122#define MAI_SERVPORT_STRSIZE	sizeof("65535")
123
124#define MAI_V4ADDR_BITS		32
125#define MAI_V6ADDR_BITS		128
126#define MAI_V4ADDR_BYTES	((MAI_V4ADDR_BITS + (CHAR_BIT - 1))/CHAR_BIT)
127#define MAI_V6ADDR_BYTES	((MAI_V6ADDR_BITS + (CHAR_BIT - 1))/CHAR_BIT)
128
129 /*
130  * Routines and data structures to hide some of the complexity of the
131  * addrinfo API. They still don't hide that we may get results for address
132  * families that we aren't interested in.
133  *
134  * Note: the getnameinfo() and inet_ntop() system library functions use unsafe
135  * APIs with separate pointer and length arguments. To avoid buffer overflow
136  * problems with these functions, Postfix uses pointers to structures
137  * internally. This way the compiler can enforce that callers provide
138  * buffers with the appropriate length, instead of having to trust that
139  * callers will never mess up some length calculation.
140  */
141typedef struct {
142    char    buf[MAI_HOSTNAME_STRSIZE];
143} MAI_HOSTNAME_STR;
144
145typedef struct {
146    char    buf[MAI_HOSTADDR_STRSIZE];
147} MAI_HOSTADDR_STR;
148
149typedef struct {
150    char    buf[MAI_SERVNAME_STRSIZE];
151} MAI_SERVNAME_STR;
152
153typedef struct {
154    char    buf[MAI_SERVPORT_STRSIZE];
155} MAI_SERVPORT_STR;
156
157extern int hostname_to_sockaddr_pf(const char *, int, const char *, int,
158				           struct addrinfo **);
159extern int hostaddr_to_sockaddr(const char *, const char *, int,
160				        struct addrinfo **);
161extern int sockaddr_to_hostaddr(const struct sockaddr *, SOCKADDR_SIZE,
162		               MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *, int);
163extern int sockaddr_to_hostname(const struct sockaddr *, SOCKADDR_SIZE,
164		               MAI_HOSTNAME_STR *, MAI_SERVNAME_STR *, int);
165extern void myaddrinfo_control(int,...);
166
167#define MAI_CTL_END	0		/* list terminator */
168
169#define MAI_STRERROR(e) ((e) == EAI_SYSTEM ? strerror(errno) : gai_strerror(e))
170
171#define hostname_to_sockaddr(host, serv, sock, res) \
172	hostname_to_sockaddr_pf((host), PF_UNSPEC, (serv), (sock), (res))
173
174 /*
175  * Macros for the case where we really don't want to be bothered with things
176  * that may fail.
177  */
178#define HOSTNAME_TO_SOCKADDR_PF(host, pf, serv, sock, res) \
179    do { \
180	int _aierr; \
181	_aierr = hostname_to_sockaddr_pf((host), (pf), (serv), (sock), (res)); \
182	if (_aierr) \
183	    msg_fatal("hostname_to_sockaddr_pf: %s", MAI_STRERROR(_aierr)); \
184    } while (0)
185
186#define HOSTNAME_TO_SOCKADDR(host, serv, sock, res) \
187	HOSTNAME_TO_SOCKADDR_PF((host), PF_UNSPEC, (serv), (sock), (res))
188
189#define HOSTADDR_TO_SOCKADDR(host, serv, sock, res) \
190    do { \
191	int _aierr; \
192	_aierr = hostaddr_to_sockaddr((host), (serv), (sock), (res)); \
193	if (_aierr) \
194	    msg_fatal("hostaddr_to_sockaddr: %s", MAI_STRERROR(_aierr)); \
195    } while (0)
196
197#define SOCKADDR_TO_HOSTADDR(sa, salen, host, port, sock) \
198    do { \
199	int _aierr; \
200	_aierr = sockaddr_to_hostaddr((sa), (salen), (host), (port), (sock)); \
201	if (_aierr) \
202	    msg_fatal("sockaddr_to_hostaddr: %s", MAI_STRERROR(_aierr)); \
203    } while (0)
204
205#define SOCKADDR_TO_HOSTNAME(sa, salen, host, service, sock) \
206    do { \
207	int _aierr; \
208	_aierr = sockaddr_to_hostname((sa), (salen), (host), (service), (sock)); \
209	if (_aierr) \
210	    msg_fatal("sockaddr_to_hostname: %s", MAI_STRERROR(_aierr)); \
211    } while (0)
212
213/* LICENSE
214/* .ad
215/* .fi
216/*	The Secure Mailer license must be distributed with this software.
217/* AUTHOR(S)
218/*	Wietse Venema
219/*	IBM T.J. Watson Research
220/*	P.O. Box 704
221/*	Yorktown Heights, NY 10598, USA
222/*--*/
223
224#endif
225