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 */ 47struct 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 */ 61struct 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 101extern void freeaddrinfo(struct addrinfo *); 102extern 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 */ 141typedef struct { 142 char buf[MAI_HOSTNAME_STRSIZE]; 143} MAI_HOSTNAME_STR; 144 145typedef struct { 146 char buf[MAI_HOSTADDR_STRSIZE]; 147} MAI_HOSTADDR_STR; 148 149typedef struct { 150 char buf[MAI_SERVNAME_STRSIZE]; 151} MAI_SERVNAME_STR; 152 153typedef struct { 154 char buf[MAI_SERVPORT_STRSIZE]; 155} MAI_SERVPORT_STR; 156 157extern int hostname_to_sockaddr_pf(const char *, int, const char *, int, 158 struct addrinfo **); 159extern int hostaddr_to_sockaddr(const char *, const char *, int, 160 struct addrinfo **); 161extern int sockaddr_to_hostaddr(const struct sockaddr *, SOCKADDR_SIZE, 162 MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *, int); 163extern int sockaddr_to_hostname(const struct sockaddr *, SOCKADDR_SIZE, 164 MAI_HOSTNAME_STR *, MAI_SERVNAME_STR *, int); 165extern 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 224#endif 225