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   */
47 struct 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   */
61 struct 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 
101 extern void freeaddrinfo(struct addrinfo *);
102 extern 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   */
141 typedef struct {
142     char    buf[MAI_HOSTNAME_STRSIZE];
143 } MAI_HOSTNAME_STR;
144 
145 typedef struct {
146     char    buf[MAI_HOSTADDR_STRSIZE];
147 } MAI_HOSTADDR_STR;
148 
149 typedef struct {
150     char    buf[MAI_SERVNAME_STRSIZE];
151 } MAI_SERVNAME_STR;
152 
153 typedef struct {
154     char    buf[MAI_SERVPORT_STRSIZE];
155 } MAI_SERVPORT_STR;
156 
157 extern int WARN_UNUSED_RESULT hostname_to_sockaddr_pf(const char *,
158 			        int, const char *, int, struct addrinfo **);
159 extern int WARN_UNUSED_RESULT hostaddr_to_sockaddr(const char *,
160 			             const char *, int, struct addrinfo **);
161 extern int WARN_UNUSED_RESULT sockaddr_to_hostaddr(const struct sockaddr *,
162 	        SOCKADDR_SIZE, MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *, int);
163 extern int WARN_UNUSED_RESULT sockaddr_to_hostname(const struct sockaddr *,
164 	        SOCKADDR_SIZE, MAI_HOSTNAME_STR *, MAI_SERVNAME_STR *, int);
165 extern 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 /*	Wietse Venema
224 /*	Google, Inc.
225 /*	111 8th Avenue
226 /*	New York, NY 10011, USA
227 /*--*/
228 
229 #endif
230