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
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
|
#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.
*
* Note: the getnameinfo() and inet_ntop() system library functions use unsafe
* APIs with separate pointer and length arguments. To avoid buffer overflow
* problems with these functions, Postfix uses pointers to structures
* internally. This way the compiler can enforce that callers provide
* buffers with the appropriate length, instead of having to trust that
* callers will never mess up some length calculation.
*/
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 WARN_UNUSED_RESULT hostname_to_sockaddr_pf(const char *,
int, const char *, int, struct addrinfo **);
extern int WARN_UNUSED_RESULT hostaddr_to_sockaddr(const char *,
const char *, int, struct addrinfo **);
extern int WARN_UNUSED_RESULT sockaddr_to_hostaddr(const struct sockaddr *,
SOCKADDR_SIZE, MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *, int);
extern int WARN_UNUSED_RESULT 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))
#define hostname_to_sockaddr(host, serv, sock, res) \
hostname_to_sockaddr_pf((host), PF_UNSPEC, (serv), (sock), (res))
/*
* Macros for the case where we really don't want to be bothered with things
* that may fail.
*/
#define HOSTNAME_TO_SOCKADDR_PF(host, pf, serv, sock, res) \
do { \
int _aierr; \
_aierr = hostname_to_sockaddr_pf((host), (pf), (serv), (sock), (res)); \
if (_aierr) \
msg_fatal("hostname_to_sockaddr_pf: %s", MAI_STRERROR(_aierr)); \
} while (0)
#define HOSTNAME_TO_SOCKADDR(host, serv, sock, res) \
HOSTNAME_TO_SOCKADDR_PF((host), PF_UNSPEC, (serv), (sock), (res))
#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
/*
/* Wietse Venema
/* Google, Inc.
/* 111 8th Avenue
/* New York, NY 10011, USA
/*--*/
#endif
|