1294491Sdelphij/* 2294491Sdelphij * is_ip_address 3294491Sdelphij * 4294491Sdelphij */ 5294491Sdelphij 6294491Sdelphij#ifdef HAVE_CONFIG_H 7294491Sdelphij# include <config.h> 8294491Sdelphij#endif 9294491Sdelphij 10294491Sdelphij#include "ntp_assert.h" 11294491Sdelphij#include "ntp_stdlib.h" 12294491Sdelphij#include "safecast.h" 13294491Sdelphij 14294491Sdelphij/* Don't include ISC's version of IPv6 variables and structures */ 15294491Sdelphij#define ISC_IPV6_H 1 16294491Sdelphij#include <isc/netaddr.h> 17294491Sdelphij#include <isc/sockaddr.h> 18294491Sdelphij 19294491Sdelphij 20294491Sdelphij/* 21294491Sdelphij * Code to tell if we have an IP address 22294491Sdelphij * If we have then return the sockaddr structure 23294491Sdelphij * and set the return value 24294491Sdelphij * see the bind9/getaddresses.c for details 25294491Sdelphij */ 26294491Sdelphijint 27294491Sdelphijis_ip_address( 28294491Sdelphij const char * host, 29294491Sdelphij u_short af, 30294491Sdelphij sockaddr_u * addr 31294491Sdelphij ) 32294491Sdelphij{ 33294491Sdelphij struct in_addr in4; 34294491Sdelphij struct addrinfo hints; 35294491Sdelphij struct addrinfo *result; 36294491Sdelphij struct sockaddr_in6 *resaddr6; 37294491Sdelphij char tmpbuf[128]; 38294491Sdelphij char *pch; 39294491Sdelphij 40294491Sdelphij REQUIRE(host != NULL); 41294491Sdelphij REQUIRE(addr != NULL); 42294491Sdelphij 43294491Sdelphij ZERO_SOCK(addr); 44294491Sdelphij 45294491Sdelphij /* 46294491Sdelphij * Try IPv4, then IPv6. In order to handle the extended format 47294491Sdelphij * for IPv6 scoped addresses (address%scope_ID), we'll use a local 48294491Sdelphij * working buffer of 128 bytes. The length is an ad-hoc value, but 49294491Sdelphij * should be enough for this purpose; the buffer can contain a string 50294491Sdelphij * of at least 80 bytes for scope_ID in addition to any IPv6 numeric 51294491Sdelphij * addresses (up to 46 bytes), the delimiter character and the 52294491Sdelphij * terminating NULL character. 53294491Sdelphij */ 54294491Sdelphij if (AF_UNSPEC == af || AF_INET == af) 55294491Sdelphij if (inet_pton(AF_INET, host, &in4) == 1) { 56294491Sdelphij AF(addr) = AF_INET; 57294491Sdelphij SET_ADDR4N(addr, in4.s_addr); 58294491Sdelphij 59294491Sdelphij return TRUE; 60294491Sdelphij } 61294491Sdelphij 62294491Sdelphij if (AF_UNSPEC == af || AF_INET6 == af) 63294491Sdelphij if (sizeof(tmpbuf) > strlen(host)) { 64294491Sdelphij if ('[' == host[0]) { 65294491Sdelphij strlcpy(tmpbuf, &host[1], sizeof(tmpbuf)); 66294491Sdelphij pch = strchr(tmpbuf, ']'); 67294491Sdelphij if (pch != NULL) 68294491Sdelphij *pch = '\0'; 69294491Sdelphij } else { 70294491Sdelphij strlcpy(tmpbuf, host, sizeof(tmpbuf)); 71294491Sdelphij } 72294491Sdelphij ZERO(hints); 73294491Sdelphij hints.ai_family = AF_INET6; 74294491Sdelphij hints.ai_flags |= AI_NUMERICHOST; 75294491Sdelphij if (getaddrinfo(tmpbuf, NULL, &hints, &result) == 0) { 76294491Sdelphij AF(addr) = AF_INET6; 77294491Sdelphij resaddr6 = UA_PTR(struct sockaddr_in6, result->ai_addr); 78294491Sdelphij SET_ADDR6N(addr, resaddr6->sin6_addr); 79294491Sdelphij SET_SCOPE(addr, resaddr6->sin6_scope_id); 80294491Sdelphij 81294491Sdelphij freeaddrinfo(result); 82294491Sdelphij return TRUE; 83294491Sdelphij } 84294491Sdelphij } 85294491Sdelphij /* 86294491Sdelphij * If we got here it was not an IP address 87294491Sdelphij */ 88294491Sdelphij return FALSE; 89294491Sdelphij} 90