xref: /netbsd-src/external/ibm-public/postfix/dist/src/util/myaddrinfo.h (revision b62fc9e20372b08e1785ff6d769312d209fa2005)
1 /*	$NetBSD: myaddrinfo.h,v 1.1.1.1 2009/06/23 10:09:00 tron 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 hostname_to_sockaddr(const char *, const char *, int,
160 				        struct addrinfo **);
161 extern int hostaddr_to_sockaddr(const char *, const char *, int,
162 				        struct addrinfo **);
163 extern int sockaddr_to_hostaddr(const struct sockaddr *, SOCKADDR_SIZE,
164 		               MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *, int);
165 extern int sockaddr_to_hostname(const struct sockaddr *, SOCKADDR_SIZE,
166 		               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  /*
174   * Macros for the case where we really don't want to be bothered with things
175   * that may fail.
176   */
177 #define HOSTNAME_TO_SOCKADDR(host, serv, sock, res) \
178     do { \
179 	int _aierr; \
180 	_aierr = hostname_to_sockaddr((host), (serv), (sock), (res)); \
181 	if (_aierr) \
182 	    msg_fatal("hostname_to_sockaddr: %s", MAI_STRERROR(_aierr)); \
183     } while (0)
184 
185 #define HOSTADDR_TO_SOCKADDR(host, serv, sock, res) \
186     do { \
187 	int _aierr; \
188 	_aierr = hostaddr_to_sockaddr((host), (serv), (sock), (res)); \
189 	if (_aierr) \
190 	    msg_fatal("hostaddr_to_sockaddr: %s", MAI_STRERROR(_aierr)); \
191     } while (0)
192 
193 #define SOCKADDR_TO_HOSTADDR(sa, salen, host, port, sock) \
194     do { \
195 	int _aierr; \
196 	_aierr = sockaddr_to_hostaddr((sa), (salen), (host), (port), (sock)); \
197 	if (_aierr) \
198 	    msg_fatal("sockaddr_to_hostaddr: %s", MAI_STRERROR(_aierr)); \
199     } while (0)
200 
201 #define SOCKADDR_TO_HOSTNAME(sa, salen, host, service, sock) \
202     do { \
203 	int _aierr; \
204 	_aierr = sockaddr_to_hostname((sa), (salen), (host), (service), (sock)); \
205 	if (_aierr) \
206 	    msg_fatal("sockaddr_to_hostname: %s", MAI_STRERROR(_aierr)); \
207     } while (0)
208 
209 /* LICENSE
210 /* .ad
211 /* .fi
212 /*	The Secure Mailer license must be distributed with this software.
213 /* AUTHOR(S)
214 /*	Wietse Venema
215 /*	IBM T.J. Watson Research
216 /*	P.O. Box 704
217 /*	Yorktown Heights, NY 10598, USA
218 /*--*/
219 
220 #endif
221