1/*++ 2/* NAME 3/* inet_addr_host 3 4/* SUMMARY 5/* determine all host internet interface addresses 6/* SYNOPSIS 7/* #include <inet_addr_host.h> 8/* 9/* int inet_addr_host(addr_list, hostname) 10/* INET_ADDR_LIST *addr_list; 11/* const char *hostname; 12/* DESCRIPTION 13/* inet_addr_host() determines all interface addresses of the 14/* named host. The host may be specified as a symbolic name, 15/* or as a numerical address. An empty host expands as the 16/* wild-card address. Address results are appended to 17/* the specified address list. The result value is the number 18/* of addresses appended to the list. 19/* DIAGNOSTICS 20/* Fatal errors: out of memory. 21/* BUGS 22/* This code uses the name service, so it talks to the network, 23/* and that may not be desirable. 24/* SEE ALSO 25/* inet_addr_list(3) address list management 26/* LICENSE 27/* .ad 28/* .fi 29/* The Secure Mailer license must be distributed with this software. 30/* AUTHOR(S) 31/* Wietse Venema 32/* IBM T.J. Watson Research 33/* P.O. Box 704 34/* Yorktown Heights, NY 10598, USA 35/*--*/ 36 37/* System library. */ 38 39#include <sys_defs.h> 40#include <netinet/in.h> 41#include <arpa/inet.h> 42#include <sys/socket.h> 43#include <netdb.h> 44#include <stdlib.h> 45#include <string.h> 46#include <unistd.h> 47 48/* Utility library. */ 49 50#include <mymalloc.h> 51#include <inet_addr_list.h> 52#include <inet_addr_host.h> 53#include <myaddrinfo.h> 54#include <sock_addr.h> 55#include <inet_proto.h> 56#include <msg.h> 57 58/* inet_addr_host - look up address list for host */ 59 60int inet_addr_host(INET_ADDR_LIST *addr_list, const char *hostname) 61{ 62 const char *myname = "inet_addr_host"; 63 int sock; 64 struct addrinfo *res0; 65 struct addrinfo *res; 66 int aierr; 67 ssize_t hostnamelen; 68 const char *hname; 69 const char *serv; 70 int initial_count = addr_list->used; 71 INET_PROTO_INFO *proto_info; 72 73 /* 74 * The use of square brackets around an IPv6 addresses is required, even 75 * though we don't enforce it as it'd make the code unnecessarily 76 * complicated. 77 * 78 * XXX AIX 5.1 getaddrinfo() does not allow "0" as service, regardless of 79 * whether or not a host is specified. 80 */ 81 if (*hostname == 0) { 82 hname = 0; 83 serv = "1"; 84 } else if (*hostname == '[' 85 && hostname[(hostnamelen = strlen(hostname)) - 1] == ']') { 86 hname = mystrndup(hostname + 1, hostnamelen - 2); 87 serv = 0; 88 } else { 89 hname = hostname; 90 serv = 0; 91 } 92 93 proto_info = inet_proto_info(); 94 if ((aierr = hostname_to_sockaddr(hname, serv, SOCK_STREAM, &res0)) == 0) { 95 for (res = res0; res; res = res->ai_next) { 96 97 /* 98 * Safety net. 99 */ 100 if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) { 101 msg_info("%s: skipping address family %d for host \"%s\"", 102 myname, res->ai_family, hostname); 103 continue; 104 } 105 106 /* 107 * On Linux systems it is not unusual for user-land to be out of 108 * sync with kernel-land. When this is the case we try to be 109 * helpful and filter out address families that the library 110 * claims to understand but that are not supported by the kernel. 111 */ 112 if ((sock = socket(res->ai_family, SOCK_STREAM, 0)) < 0) { 113 msg_warn("%s: skipping address family %d: %m", 114 myname, res->ai_family); 115 continue; 116 } 117 if (close(sock)) 118 msg_warn("%s: close socket: %m", myname); 119 120 inet_addr_list_append(addr_list, res->ai_addr); 121 } 122 freeaddrinfo(res0); 123 } 124 if (hname && hname != hostname) 125 myfree((char *) hname); 126 127 return (addr_list->used - initial_count); 128} 129 130#ifdef TEST 131 132#include <msg.h> 133#include <vstream.h> 134#include <msg_vstream.h> 135#include <sock_addr.h> 136 137int main(int argc, char **argv) 138{ 139 INET_ADDR_LIST list; 140 struct sockaddr_storage *sa; 141 MAI_HOSTADDR_STR hostaddr; 142 INET_PROTO_INFO *proto_info; 143 144 msg_vstream_init(argv[0], VSTREAM_ERR); 145 146 if (argc < 3) 147 msg_fatal("usage: %s protocols hostname...", argv[0]); 148 149 proto_info = inet_proto_init(argv[0], argv[1]); 150 argv += 1; 151 152 while (--argc && *++argv) { 153 inet_addr_list_init(&list); 154 if (inet_addr_host(&list, *argv) == 0) 155 msg_fatal("not found: %s", *argv); 156 157 for (sa = list.addrs; sa < list.addrs + list.used; sa++) { 158 SOCKADDR_TO_HOSTADDR(SOCK_ADDR_PTR(sa), SOCK_ADDR_LEN(sa), 159 &hostaddr, (MAI_SERVPORT_STR *) 0, 0); 160 vstream_printf("%s\t%s\n", *argv, hostaddr.buf); 161 } 162 vstream_fflush(VSTREAM_OUT); 163 inet_addr_list_free(&list); 164 } 165 return (0); 166} 167 168#endif 169