1 /* $NetBSD: myaddrinfo.h,v 1.5 2026/05/09 18:49:22 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 sa_family_t ss_family; 65 struct sockaddr_in dummy; /* alignment!! */ 66 }; 67 68 /* 69 * Result codes. See gai_strerror() for text. Undefine already imported 70 * definitions so that we can test the IPv4-only emulation on a modern 71 * system without getting a ton of compiler warnings. 72 */ 73 #undef EAI_ADDRFAMILY 74 #define EAI_ADDRFAMILY 1 75 #undef EAI_AGAIN 76 #define EAI_AGAIN 2 77 #undef EAI_BADFLAGS 78 #define EAI_BADFLAGS 3 79 #undef EAI_FAIL 80 #define EAI_FAIL 4 81 #undef EAI_FAMILY 82 #define EAI_FAMILY 5 83 #undef EAI_MEMORY 84 #define EAI_MEMORY 6 85 #undef EAI_NODATA 86 #define EAI_NODATA 7 87 #undef EAI_NONAME 88 #define EAI_NONAME 8 89 #undef EAI_SERVICE 90 #define EAI_SERVICE 9 91 #undef EAI_SOCKTYPE 92 #define EAI_SOCKTYPE 10 93 #undef EAI_SYSTEM 94 #define EAI_SYSTEM 11 95 #undef EAI_BADHINTS 96 #define EAI_BADHINTS 12 97 #undef EAI_PROTOCOL 98 #define EAI_PROTOCOL 13 99 #undef EAI_RESNULL 100 #define EAI_RESNULL 14 101 #undef EAI_MAX 102 #define EAI_MAX 15 103 104 extern void freeaddrinfo(struct addrinfo *); 105 extern char *gai_strerror(int); 106 107 #endif 108 109 /* 110 * Bounds grow in leaps. These macros attempt to keep non-library code free 111 * from IPV6 #ifdef pollution. Avoid macro names that end in STRLEN because 112 * they suggest that space for the null terminator is not included. 113 */ 114 #ifdef HAS_IPV6 115 #define MAI_HOSTADDR_STRSIZE INET6_ADDRSTRLEN 116 #else 117 #ifndef INET_ADDRSTRLEN 118 #define INET_ADDRSTRLEN 16 119 #endif 120 #define MAI_HOSTADDR_STRSIZE INET_ADDRSTRLEN 121 #endif 122 123 #define MAI_HOSTNAME_STRSIZE 1025 124 #define MAI_SERVNAME_STRSIZE 32 125 #define MAI_SERVPORT_STRSIZE sizeof("65535") 126 127 #define MAI_V4ADDR_BITS 32 128 #define MAI_V6ADDR_BITS 128 129 #define MAI_V4ADDR_BYTES ((MAI_V4ADDR_BITS + (CHAR_BIT - 1))/CHAR_BIT) 130 #define MAI_V6ADDR_BYTES ((MAI_V6ADDR_BITS + (CHAR_BIT - 1))/CHAR_BIT) 131 132 /* 133 * Routines and data structures to hide some of the complexity of the 134 * addrinfo API. They still don't hide that we may get results for address 135 * families that we aren't interested in. 136 * 137 * Note: the getnameinfo() and inet_ntop() system library functions use unsafe 138 * APIs with separate pointer and length arguments. To avoid buffer overflow 139 * problems with these functions, Postfix uses pointers to structures 140 * internally. This way the compiler can enforce that callers provide 141 * buffers with the appropriate length, instead of having to trust that 142 * callers will never mess up some length calculation. 143 */ 144 typedef struct { 145 char buf[MAI_HOSTNAME_STRSIZE]; 146 } MAI_HOSTNAME_STR; 147 148 typedef struct { 149 char buf[MAI_HOSTADDR_STRSIZE]; 150 } MAI_HOSTADDR_STR; 151 152 typedef struct { 153 char buf[MAI_SERVNAME_STRSIZE]; 154 } MAI_SERVNAME_STR; 155 156 typedef struct { 157 char buf[MAI_SERVPORT_STRSIZE]; 158 } MAI_SERVPORT_STR; 159 160 extern int WARN_UNUSED_RESULT hostname_to_sockaddr_pf(const char *, 161 int, const char *, int, struct addrinfo **); 162 extern int WARN_UNUSED_RESULT hostaddr_to_sockaddr(const char *, 163 const char *, int, struct addrinfo **); 164 extern int WARN_UNUSED_RESULT sockaddr_to_hostaddr(const struct sockaddr *, 165 SOCKADDR_SIZE, MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *, int); 166 extern int WARN_UNUSED_RESULT sockaddr_to_hostname(const struct sockaddr *, 167 SOCKADDR_SIZE, MAI_HOSTNAME_STR *, MAI_SERVNAME_STR *, int); 168 extern void myaddrinfo_control(int,...); 169 170 #define MAI_CTL_END 0 /* list terminator */ 171 172 #define MAI_STRERROR(e) ((e) == EAI_SYSTEM ? strerror(errno) : gai_strerror(e)) 173 174 #define hostname_to_sockaddr(host, serv, sock, res) \ 175 hostname_to_sockaddr_pf((host), PF_UNSPEC, (serv), (sock), (res)) 176 177 /* 178 * Macros for the case where we really don't want to be bothered with things 179 * that may fail. 180 */ 181 #define HOSTNAME_TO_SOCKADDR_PF(host, pf, serv, sock, res) \ 182 do { \ 183 int _aierr; \ 184 _aierr = hostname_to_sockaddr_pf((host), (pf), (serv), (sock), (res)); \ 185 if (_aierr) \ 186 msg_fatal("hostname_to_sockaddr_pf: %s", MAI_STRERROR(_aierr)); \ 187 } while (0) 188 189 #define HOSTNAME_TO_SOCKADDR(host, serv, sock, res) \ 190 HOSTNAME_TO_SOCKADDR_PF((host), PF_UNSPEC, (serv), (sock), (res)) 191 192 #define HOSTADDR_TO_SOCKADDR(host, serv, sock, res) \ 193 do { \ 194 int _aierr; \ 195 _aierr = hostaddr_to_sockaddr((host), (serv), (sock), (res)); \ 196 if (_aierr) \ 197 msg_fatal("hostaddr_to_sockaddr: %s", MAI_STRERROR(_aierr)); \ 198 } while (0) 199 200 #define SOCKADDR_TO_HOSTADDR(sa, salen, host, port, sock) \ 201 do { \ 202 int _aierr; \ 203 _aierr = sockaddr_to_hostaddr((sa), (salen), (host), (port), (sock)); \ 204 if (_aierr) \ 205 msg_fatal("sockaddr_to_hostaddr: %s", MAI_STRERROR(_aierr)); \ 206 } while (0) 207 208 #define SOCKADDR_TO_HOSTNAME(sa, salen, host, service, sock) \ 209 do { \ 210 int _aierr; \ 211 _aierr = sockaddr_to_hostname((sa), (salen), (host), (service), (sock)); \ 212 if (_aierr) \ 213 msg_fatal("sockaddr_to_hostname: %s", MAI_STRERROR(_aierr)); \ 214 } while (0) 215 216 /* 217 * sane_sockaddr_to_hostaddr.c 218 */ 219 extern int WARN_UNUSED_RESULT sane_sockaddr_to_hostaddr(struct sockaddr *, 220 SOCKADDR_SIZE *, MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *, int); 221 222 /* LICENSE 223 /* .ad 224 /* .fi 225 /* The Secure Mailer license must be distributed with this software. 226 /* AUTHOR(S) 227 /* Wietse Venema 228 /* IBM T.J. Watson Research 229 /* P.O. Box 704 230 /* Yorktown Heights, NY 10598, USA 231 /* 232 /* Wietse Venema 233 /* Google, Inc. 234 /* 111 8th Avenue 235 /* New York, NY 10011, USA 236 /*--*/ 237 238 #endif 239