1*68ba7e87SXin LI /*
2*68ba7e87SXin LI * is_ip_address
3*68ba7e87SXin LI *
4*68ba7e87SXin LI */
5*68ba7e87SXin LI
6*68ba7e87SXin LI #ifdef HAVE_CONFIG_H
7*68ba7e87SXin LI # include <config.h>
8*68ba7e87SXin LI #endif
9*68ba7e87SXin LI
10*68ba7e87SXin LI #include "ntp_assert.h"
11*68ba7e87SXin LI #include "ntp_stdlib.h"
12*68ba7e87SXin LI #include "safecast.h"
13*68ba7e87SXin LI
14*68ba7e87SXin LI /* Don't include ISC's version of IPv6 variables and structures */
15*68ba7e87SXin LI #define ISC_IPV6_H 1
16*68ba7e87SXin LI #include <isc/netaddr.h>
17*68ba7e87SXin LI #include <isc/sockaddr.h>
18*68ba7e87SXin LI
19*68ba7e87SXin LI
20*68ba7e87SXin LI /*
21*68ba7e87SXin LI * Code to tell if we have an IP address
22*68ba7e87SXin LI * If we have then return the sockaddr structure
23*68ba7e87SXin LI * and set the return value
24*68ba7e87SXin LI * see the bind9/getaddresses.c for details
25*68ba7e87SXin LI */
26*68ba7e87SXin LI int
is_ip_address(const char * host,u_short af,sockaddr_u * addr)27*68ba7e87SXin LI is_ip_address(
28*68ba7e87SXin LI const char * host,
29*68ba7e87SXin LI u_short af,
30*68ba7e87SXin LI sockaddr_u * addr
31*68ba7e87SXin LI )
32*68ba7e87SXin LI {
33*68ba7e87SXin LI struct in_addr in4;
34*68ba7e87SXin LI struct addrinfo hints;
35*68ba7e87SXin LI struct addrinfo *result;
36*68ba7e87SXin LI struct sockaddr_in6 *resaddr6;
37*68ba7e87SXin LI char tmpbuf[128];
38*68ba7e87SXin LI char *pch;
39*68ba7e87SXin LI
40*68ba7e87SXin LI REQUIRE(host != NULL);
41*68ba7e87SXin LI REQUIRE(addr != NULL);
42*68ba7e87SXin LI
43*68ba7e87SXin LI ZERO_SOCK(addr);
44*68ba7e87SXin LI
45*68ba7e87SXin LI /*
46*68ba7e87SXin LI * Try IPv4, then IPv6. In order to handle the extended format
47*68ba7e87SXin LI * for IPv6 scoped addresses (address%scope_ID), we'll use a local
48*68ba7e87SXin LI * working buffer of 128 bytes. The length is an ad-hoc value, but
49*68ba7e87SXin LI * should be enough for this purpose; the buffer can contain a string
50*68ba7e87SXin LI * of at least 80 bytes for scope_ID in addition to any IPv6 numeric
51*68ba7e87SXin LI * addresses (up to 46 bytes), the delimiter character and the
52*68ba7e87SXin LI * terminating NULL character.
53*68ba7e87SXin LI */
54*68ba7e87SXin LI if (AF_UNSPEC == af || AF_INET == af)
55*68ba7e87SXin LI if (inet_pton(AF_INET, host, &in4) == 1) {
56*68ba7e87SXin LI AF(addr) = AF_INET;
57*68ba7e87SXin LI SET_ADDR4N(addr, in4.s_addr);
58*68ba7e87SXin LI
59*68ba7e87SXin LI return TRUE;
60*68ba7e87SXin LI }
61*68ba7e87SXin LI
62*68ba7e87SXin LI if (AF_UNSPEC == af || AF_INET6 == af)
63*68ba7e87SXin LI if (sizeof(tmpbuf) > strlen(host)) {
64*68ba7e87SXin LI if ('[' == host[0]) {
65*68ba7e87SXin LI strlcpy(tmpbuf, &host[1], sizeof(tmpbuf));
66*68ba7e87SXin LI pch = strchr(tmpbuf, ']');
67*68ba7e87SXin LI if (pch != NULL)
68*68ba7e87SXin LI *pch = '\0';
69*68ba7e87SXin LI } else {
70*68ba7e87SXin LI strlcpy(tmpbuf, host, sizeof(tmpbuf));
71*68ba7e87SXin LI }
72*68ba7e87SXin LI ZERO(hints);
73*68ba7e87SXin LI hints.ai_family = AF_INET6;
74*68ba7e87SXin LI hints.ai_flags |= AI_NUMERICHOST;
75*68ba7e87SXin LI if (getaddrinfo(tmpbuf, NULL, &hints, &result) == 0) {
76*68ba7e87SXin LI AF(addr) = AF_INET6;
77*68ba7e87SXin LI resaddr6 = UA_PTR(struct sockaddr_in6, result->ai_addr);
78*68ba7e87SXin LI SET_ADDR6N(addr, resaddr6->sin6_addr);
79*68ba7e87SXin LI SET_SCOPE(addr, resaddr6->sin6_scope_id);
80*68ba7e87SXin LI
81*68ba7e87SXin LI freeaddrinfo(result);
82*68ba7e87SXin LI return TRUE;
83*68ba7e87SXin LI }
84*68ba7e87SXin LI }
85*68ba7e87SXin LI /*
86*68ba7e87SXin LI * If we got here it was not an IP address
87*68ba7e87SXin LI */
88*68ba7e87SXin LI return FALSE;
89*68ba7e87SXin LI }
90