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