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