1*33881f77Schristos /* $NetBSD: myaddrinfo.h,v 1.3 2020/03/18 19:05:21 christos Exp $ */ 241fbaed0Stron 341fbaed0Stron #ifndef _MYADDRINFO_H_INCLUDED_ 441fbaed0Stron #define _MYADDRINFO_H_INCLUDED_ 541fbaed0Stron 641fbaed0Stron /*++ 741fbaed0Stron /* NAME 841fbaed0Stron /* myaddrinfo 3h 941fbaed0Stron /* SUMMARY 1041fbaed0Stron /* addrinfo encapsulation and emulation 1141fbaed0Stron /* SYNOPSIS 1241fbaed0Stron /* #include <myaddrinfo.h> 1341fbaed0Stron /* DESCRIPTION 1441fbaed0Stron /* .nf 1541fbaed0Stron 1641fbaed0Stron /* 1741fbaed0Stron * System library. 1841fbaed0Stron */ 1941fbaed0Stron #include <sys/types.h> 2041fbaed0Stron #include <sys/socket.h> 2141fbaed0Stron #include <netinet/in.h> 2241fbaed0Stron #include <netdb.h> 2341fbaed0Stron #include <string.h> 2441fbaed0Stron #include <errno.h> /* MAI_STRERROR() */ 2541fbaed0Stron #include <limits.h> /* CHAR_BIT */ 2641fbaed0Stron 2741fbaed0Stron /* 2841fbaed0Stron * Backwards compatibility support for IPV4 systems without addrinfo API. 2941fbaed0Stron */ 3041fbaed0Stron #ifdef EMULATE_IPV4_ADDRINFO 3141fbaed0Stron 3241fbaed0Stron /* 3341fbaed0Stron * Avoid clashes with global symbols, just in case some third-party library 3441fbaed0Stron * provides its own addrinfo() implementation. This also allows us to test 3541fbaed0Stron * the IPV4 emulation code on an IPV6 enabled system. 3641fbaed0Stron */ 3741fbaed0Stron #undef freeaddrinfo 3841fbaed0Stron #define freeaddrinfo mai_freeaddrinfo 3941fbaed0Stron #undef gai_strerror 4041fbaed0Stron #define gai_strerror mai_strerror 4141fbaed0Stron #undef addrinfo 4241fbaed0Stron #define addrinfo mai_addrinfo 4341fbaed0Stron #undef sockaddr_storage 4441fbaed0Stron #define sockaddr_storage mai_sockaddr_storage 4541fbaed0Stron 4641fbaed0Stron /* 4741fbaed0Stron * Modern systems define this in <netdb.h>. 4841fbaed0Stron */ 4941fbaed0Stron struct addrinfo { 5041fbaed0Stron int ai_flags; /* AI_PASSIVE|CANONNAME|NUMERICHOST */ 5141fbaed0Stron int ai_family; /* PF_xxx */ 5241fbaed0Stron int ai_socktype; /* SOCK_xxx */ 5341fbaed0Stron int ai_protocol; /* 0 or IPPROTO_xxx */ 5441fbaed0Stron size_t ai_addrlen; /* length of ai_addr */ 5541fbaed0Stron char *ai_canonname; /* canonical name for nodename */ 5641fbaed0Stron struct sockaddr *ai_addr; /* binary address */ 5741fbaed0Stron struct addrinfo *ai_next; /* next structure in linked list */ 5841fbaed0Stron }; 5941fbaed0Stron 6041fbaed0Stron /* 6141fbaed0Stron * Modern systems define this in <sys/socket.h>. 6241fbaed0Stron */ 6341fbaed0Stron struct sockaddr_storage { 6441fbaed0Stron struct sockaddr_in dummy; /* alignment!! */ 6541fbaed0Stron }; 6641fbaed0Stron 6741fbaed0Stron /* 6841fbaed0Stron * Result codes. See gai_strerror() for text. Undefine already imported 6941fbaed0Stron * definitions so that we can test the IPv4-only emulation on a modern 7041fbaed0Stron * system without getting a ton of compiler warnings. 7141fbaed0Stron */ 7241fbaed0Stron #undef EAI_ADDRFAMILY 7341fbaed0Stron #define EAI_ADDRFAMILY 1 7441fbaed0Stron #undef EAI_AGAIN 7541fbaed0Stron #define EAI_AGAIN 2 7641fbaed0Stron #undef EAI_BADFLAGS 7741fbaed0Stron #define EAI_BADFLAGS 3 7841fbaed0Stron #undef EAI_FAIL 7941fbaed0Stron #define EAI_FAIL 4 8041fbaed0Stron #undef EAI_FAMILY 8141fbaed0Stron #define EAI_FAMILY 5 8241fbaed0Stron #undef EAI_MEMORY 8341fbaed0Stron #define EAI_MEMORY 6 8441fbaed0Stron #undef EAI_NODATA 8541fbaed0Stron #define EAI_NODATA 7 8641fbaed0Stron #undef EAI_NONAME 8741fbaed0Stron #define EAI_NONAME 8 8841fbaed0Stron #undef EAI_SERVICE 8941fbaed0Stron #define EAI_SERVICE 9 9041fbaed0Stron #undef EAI_SOCKTYPE 9141fbaed0Stron #define EAI_SOCKTYPE 10 9241fbaed0Stron #undef EAI_SYSTEM 9341fbaed0Stron #define EAI_SYSTEM 11 9441fbaed0Stron #undef EAI_BADHINTS 9541fbaed0Stron #define EAI_BADHINTS 12 9641fbaed0Stron #undef EAI_PROTOCOL 9741fbaed0Stron #define EAI_PROTOCOL 13 9841fbaed0Stron #undef EAI_RESNULL 9941fbaed0Stron #define EAI_RESNULL 14 10041fbaed0Stron #undef EAI_MAX 10141fbaed0Stron #define EAI_MAX 15 10241fbaed0Stron 10341fbaed0Stron extern void freeaddrinfo(struct addrinfo *); 10441fbaed0Stron extern char *gai_strerror(int); 10541fbaed0Stron 10641fbaed0Stron #endif 10741fbaed0Stron 10841fbaed0Stron /* 10941fbaed0Stron * Bounds grow in leaps. These macros attempt to keep non-library code free 11041fbaed0Stron * from IPV6 #ifdef pollution. Avoid macro names that end in STRLEN because 11141fbaed0Stron * they suggest that space for the null terminator is not included. 11241fbaed0Stron */ 11341fbaed0Stron #ifdef HAS_IPV6 11441fbaed0Stron # define MAI_HOSTADDR_STRSIZE INET6_ADDRSTRLEN 11541fbaed0Stron #else 11641fbaed0Stron # ifndef INET_ADDRSTRLEN 11741fbaed0Stron # define INET_ADDRSTRLEN 16 11841fbaed0Stron # endif 11941fbaed0Stron # define MAI_HOSTADDR_STRSIZE INET_ADDRSTRLEN 12041fbaed0Stron #endif 12141fbaed0Stron 12241fbaed0Stron #define MAI_HOSTNAME_STRSIZE 1025 12341fbaed0Stron #define MAI_SERVNAME_STRSIZE 32 12441fbaed0Stron #define MAI_SERVPORT_STRSIZE sizeof("65535") 12541fbaed0Stron 12641fbaed0Stron #define MAI_V4ADDR_BITS 32 12741fbaed0Stron #define MAI_V6ADDR_BITS 128 12841fbaed0Stron #define MAI_V4ADDR_BYTES ((MAI_V4ADDR_BITS + (CHAR_BIT - 1))/CHAR_BIT) 12941fbaed0Stron #define MAI_V6ADDR_BYTES ((MAI_V6ADDR_BITS + (CHAR_BIT - 1))/CHAR_BIT) 13041fbaed0Stron 13141fbaed0Stron /* 13241fbaed0Stron * Routines and data structures to hide some of the complexity of the 13341fbaed0Stron * addrinfo API. They still don't hide that we may get results for address 13441fbaed0Stron * families that we aren't interested in. 13541fbaed0Stron * 13641fbaed0Stron * Note: the getnameinfo() and inet_ntop() system library functions use unsafe 13741fbaed0Stron * APIs with separate pointer and length arguments. To avoid buffer overflow 13841fbaed0Stron * problems with these functions, Postfix uses pointers to structures 13941fbaed0Stron * internally. This way the compiler can enforce that callers provide 14041fbaed0Stron * buffers with the appropriate length, instead of having to trust that 14141fbaed0Stron * callers will never mess up some length calculation. 14241fbaed0Stron */ 14341fbaed0Stron typedef struct { 14441fbaed0Stron char buf[MAI_HOSTNAME_STRSIZE]; 14541fbaed0Stron } MAI_HOSTNAME_STR; 14641fbaed0Stron 14741fbaed0Stron typedef struct { 14841fbaed0Stron char buf[MAI_HOSTADDR_STRSIZE]; 14941fbaed0Stron } MAI_HOSTADDR_STR; 15041fbaed0Stron 15141fbaed0Stron typedef struct { 15241fbaed0Stron char buf[MAI_SERVNAME_STRSIZE]; 15341fbaed0Stron } MAI_SERVNAME_STR; 15441fbaed0Stron 15541fbaed0Stron typedef struct { 15641fbaed0Stron char buf[MAI_SERVPORT_STRSIZE]; 15741fbaed0Stron } MAI_SERVPORT_STR; 15841fbaed0Stron 159e262b48eSchristos extern int WARN_UNUSED_RESULT hostname_to_sockaddr_pf(const char *, 160e262b48eSchristos int, const char *, int, struct addrinfo **); 161e262b48eSchristos extern int WARN_UNUSED_RESULT hostaddr_to_sockaddr(const char *, 162e262b48eSchristos const char *, int, struct addrinfo **); 163e262b48eSchristos extern int WARN_UNUSED_RESULT sockaddr_to_hostaddr(const struct sockaddr *, 164e262b48eSchristos SOCKADDR_SIZE, MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *, int); 165e262b48eSchristos extern int WARN_UNUSED_RESULT sockaddr_to_hostname(const struct sockaddr *, 166e262b48eSchristos SOCKADDR_SIZE, MAI_HOSTNAME_STR *, MAI_SERVNAME_STR *, int); 16741fbaed0Stron extern void myaddrinfo_control(int,...); 16841fbaed0Stron 16941fbaed0Stron #define MAI_CTL_END 0 /* list terminator */ 17041fbaed0Stron 17141fbaed0Stron #define MAI_STRERROR(e) ((e) == EAI_SYSTEM ? strerror(errno) : gai_strerror(e)) 17241fbaed0Stron 173ff6d749dStron #define hostname_to_sockaddr(host, serv, sock, res) \ 174ff6d749dStron hostname_to_sockaddr_pf((host), PF_UNSPEC, (serv), (sock), (res)) 175ff6d749dStron 17641fbaed0Stron /* 17741fbaed0Stron * Macros for the case where we really don't want to be bothered with things 17841fbaed0Stron * that may fail. 17941fbaed0Stron */ 180ff6d749dStron #define HOSTNAME_TO_SOCKADDR_PF(host, pf, serv, sock, res) \ 18141fbaed0Stron do { \ 18241fbaed0Stron int _aierr; \ 183ff6d749dStron _aierr = hostname_to_sockaddr_pf((host), (pf), (serv), (sock), (res)); \ 18441fbaed0Stron if (_aierr) \ 185ff6d749dStron msg_fatal("hostname_to_sockaddr_pf: %s", MAI_STRERROR(_aierr)); \ 18641fbaed0Stron } while (0) 18741fbaed0Stron 188ff6d749dStron #define HOSTNAME_TO_SOCKADDR(host, serv, sock, res) \ 189ff6d749dStron HOSTNAME_TO_SOCKADDR_PF((host), PF_UNSPEC, (serv), (sock), (res)) 190ff6d749dStron 19141fbaed0Stron #define HOSTADDR_TO_SOCKADDR(host, serv, sock, res) \ 19241fbaed0Stron do { \ 19341fbaed0Stron int _aierr; \ 19441fbaed0Stron _aierr = hostaddr_to_sockaddr((host), (serv), (sock), (res)); \ 19541fbaed0Stron if (_aierr) \ 19641fbaed0Stron msg_fatal("hostaddr_to_sockaddr: %s", MAI_STRERROR(_aierr)); \ 19741fbaed0Stron } while (0) 19841fbaed0Stron 19941fbaed0Stron #define SOCKADDR_TO_HOSTADDR(sa, salen, host, port, sock) \ 20041fbaed0Stron do { \ 20141fbaed0Stron int _aierr; \ 20241fbaed0Stron _aierr = sockaddr_to_hostaddr((sa), (salen), (host), (port), (sock)); \ 20341fbaed0Stron if (_aierr) \ 20441fbaed0Stron msg_fatal("sockaddr_to_hostaddr: %s", MAI_STRERROR(_aierr)); \ 20541fbaed0Stron } while (0) 20641fbaed0Stron 20741fbaed0Stron #define SOCKADDR_TO_HOSTNAME(sa, salen, host, service, sock) \ 20841fbaed0Stron do { \ 20941fbaed0Stron int _aierr; \ 21041fbaed0Stron _aierr = sockaddr_to_hostname((sa), (salen), (host), (service), (sock)); \ 21141fbaed0Stron if (_aierr) \ 21241fbaed0Stron msg_fatal("sockaddr_to_hostname: %s", MAI_STRERROR(_aierr)); \ 21341fbaed0Stron } while (0) 21441fbaed0Stron 21541fbaed0Stron /* LICENSE 21641fbaed0Stron /* .ad 21741fbaed0Stron /* .fi 21841fbaed0Stron /* The Secure Mailer license must be distributed with this software. 21941fbaed0Stron /* AUTHOR(S) 22041fbaed0Stron /* Wietse Venema 22141fbaed0Stron /* IBM T.J. Watson Research 22241fbaed0Stron /* P.O. Box 704 22341fbaed0Stron /* Yorktown Heights, NY 10598, USA 224*33881f77Schristos /* 225*33881f77Schristos /* Wietse Venema 226*33881f77Schristos /* Google, Inc. 227*33881f77Schristos /* 111 8th Avenue 228*33881f77Schristos /* New York, NY 10011, USA 22941fbaed0Stron /*--*/ 23041fbaed0Stron 23141fbaed0Stron #endif 232