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