1294904Sdelphij/* 2294904Sdelphij * is_ip_address 3294904Sdelphij * 4294904Sdelphij */ 5294904Sdelphij 6294904Sdelphij#ifdef HAVE_CONFIG_H 7294904Sdelphij# include <config.h> 8294904Sdelphij#endif 9294904Sdelphij 10294904Sdelphij#include "ntp_assert.h" 11294904Sdelphij#include "ntp_stdlib.h" 12294904Sdelphij#include "safecast.h" 13294904Sdelphij 14294904Sdelphij/* Don't include ISC's version of IPv6 variables and structures */ 15294904Sdelphij#define ISC_IPV6_H 1 16294904Sdelphij#include <isc/netaddr.h> 17294904Sdelphij#include <isc/sockaddr.h> 18294904Sdelphij 19294904Sdelphij 20294904Sdelphij/* 21294904Sdelphij * Code to tell if we have an IP address 22294904Sdelphij * If we have then return the sockaddr structure 23294904Sdelphij * and set the return value 24294904Sdelphij * see the bind9/getaddresses.c for details 25294904Sdelphij */ 26294904Sdelphijint 27294904Sdelphijis_ip_address( 28294904Sdelphij const char * host, 29294904Sdelphij u_short af, 30294904Sdelphij sockaddr_u * addr 31294904Sdelphij ) 32294904Sdelphij{ 33294904Sdelphij struct in_addr in4; 34294904Sdelphij struct addrinfo hints; 35294904Sdelphij struct addrinfo *result; 36294904Sdelphij struct sockaddr_in6 *resaddr6; 37294904Sdelphij char tmpbuf[128]; 38294904Sdelphij char *pch; 39294904Sdelphij 40294904Sdelphij REQUIRE(host != NULL); 41294904Sdelphij REQUIRE(addr != NULL); 42294904Sdelphij 43294904Sdelphij ZERO_SOCK(addr); 44294904Sdelphij 45294904Sdelphij /* 46294904Sdelphij * Try IPv4, then IPv6. In order to handle the extended format 47294904Sdelphij * for IPv6 scoped addresses (address%scope_ID), we'll use a local 48294904Sdelphij * working buffer of 128 bytes. The length is an ad-hoc value, but 49294904Sdelphij * should be enough for this purpose; the buffer can contain a string 50294904Sdelphij * of at least 80 bytes for scope_ID in addition to any IPv6 numeric 51294904Sdelphij * addresses (up to 46 bytes), the delimiter character and the 52294904Sdelphij * terminating NULL character. 53294904Sdelphij */ 54294904Sdelphij if (AF_UNSPEC == af || AF_INET == af) 55294904Sdelphij if (inet_pton(AF_INET, host, &in4) == 1) { 56294904Sdelphij AF(addr) = AF_INET; 57294904Sdelphij SET_ADDR4N(addr, in4.s_addr); 58294904Sdelphij 59294904Sdelphij return TRUE; 60294904Sdelphij } 61294904Sdelphij 62294904Sdelphij if (AF_UNSPEC == af || AF_INET6 == af) 63294904Sdelphij if (sizeof(tmpbuf) > strlen(host)) { 64294904Sdelphij if ('[' == host[0]) { 65294904Sdelphij strlcpy(tmpbuf, &host[1], sizeof(tmpbuf)); 66294904Sdelphij pch = strchr(tmpbuf, ']'); 67294904Sdelphij if (pch != NULL) 68294904Sdelphij *pch = '\0'; 69294904Sdelphij } else { 70294904Sdelphij strlcpy(tmpbuf, host, sizeof(tmpbuf)); 71294904Sdelphij } 72294904Sdelphij ZERO(hints); 73294904Sdelphij hints.ai_family = AF_INET6; 74294904Sdelphij hints.ai_flags |= AI_NUMERICHOST; 75294904Sdelphij if (getaddrinfo(tmpbuf, NULL, &hints, &result) == 0) { 76294904Sdelphij AF(addr) = AF_INET6; 77294904Sdelphij resaddr6 = UA_PTR(struct sockaddr_in6, result->ai_addr); 78294904Sdelphij SET_ADDR6N(addr, resaddr6->sin6_addr); 79294904Sdelphij SET_SCOPE(addr, resaddr6->sin6_scope_id); 80294904Sdelphij 81294904Sdelphij freeaddrinfo(result); 82294904Sdelphij return TRUE; 83294904Sdelphij } 84294904Sdelphij } 85294904Sdelphij /* 86294904Sdelphij * If we got here it was not an IP address 87294904Sdelphij */ 88294904Sdelphij return FALSE; 89294904Sdelphij} 90