summaryrefslogtreecommitdiff
path: root/gnu/dist/postfix/src/util/myaddrinfo.h
blob: 7dab560971498ac330a1f370b3251ad6945bf2a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
/*	$NetBSD: myaddrinfo.h,v 1.1.1.1 2005/08/18 21:10:58 rpaulo Exp $	*/

#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.
  */
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 hostname_to_sockaddr(const char *, const char *, int,
				        struct addrinfo **);
extern int hostaddr_to_sockaddr(const char *, const char *, int,
				        struct addrinfo **);
extern int sockaddr_to_hostaddr(const struct sockaddr *, SOCKADDR_SIZE,
		               MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *, int);
extern int 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))

 /*
  * Macros for the case where we really don't want to be bothered with things
  * that may fail.
  */
#define HOSTNAME_TO_SOCKADDR(host, serv, sock, res) \
    do { \
	int _aierr; \
	_aierr = hostname_to_sockaddr((host), (serv), (sock), (res)); \
	if (_aierr) \
	    msg_fatal("hostname_to_sockaddr: %s", MAI_STRERROR(_aierr)); \
    } while (0)

#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
/*--*/

#endif