Home | History | Annotate | Line # | Download | only in util
      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