xref: /freebsd/contrib/ntp/libntp/is_ip_address.c (revision a70cba95822f662d3f9da5119b6a0c433e8f70af)
1 /*
2  * is_ip_address
3  *
4  */
5 
6 #ifdef HAVE_CONFIG_H
7 # include <config.h>
8 #endif
9 
10 #if 0
11 #include <stdio.h>
12 #include <signal.h>
13 #ifdef HAVE_FNMATCH_H
14 # include <fnmatch.h>
15 # if !defined(FNM_CASEFOLD) && defined(FNM_IGNORECASE)
16 #  define FNM_CASEFOLD FNM_IGNORECASE
17 # endif
18 #endif
19 #ifdef HAVE_SYS_PARAM_H
20 # include <sys/param.h>
21 #endif
22 #ifdef HAVE_SYS_IOCTL_H
23 # include <sys/ioctl.h>
24 #endif
25 #ifdef HAVE_SYS_SOCKIO_H	/* UXPV: SIOC* #defines (Frank Vance <fvance@waii.com>) */
26 # include <sys/sockio.h>
27 #endif
28 #ifdef HAVE_SYS_UIO_H
29 # include <sys/uio.h>
30 #endif
31 #endif
32 
33 #include "ntp_assert.h"
34 #include "ntp_stdlib.h"
35 #include "safecast.h"
36 
37 #if 0
38 #include "ntp_machine.h"
39 #include "ntpd.h"
40 #include "ntp_io.h"
41 #include "iosignal.h"
42 #include "ntp_lists.h"
43 #include "ntp_refclock.h"
44 #include "ntp_worker.h"
45 #include "ntp_request.h"
46 #include "timevalops.h"
47 #include "timespecops.h"
48 #include "ntpd-opts.h"
49 #endif
50 
51 /* Don't include ISC's version of IPv6 variables and structures */
52 #define ISC_IPV6_H 1
53 #include <isc/mem.h>
54 #include <isc/interfaceiter.h>
55 #include <isc/netaddr.h>
56 #include <isc/result.h>
57 #include <isc/sockaddr.h>
58 
59 
60 /*
61  * Code to tell if we have an IP address
62  * If we have then return the sockaddr structure
63  * and set the return value
64  * see the bind9/getaddresses.c for details
65  */
66 int
67 is_ip_address(
68 	const char *	host,
69 	u_short		af,
70 	sockaddr_u *	addr
71 	)
72 {
73 	struct in_addr in4;
74 	struct addrinfo hints;
75 	struct addrinfo *result;
76 	struct sockaddr_in6 *resaddr6;
77 	char tmpbuf[128];
78 	char *pch;
79 
80 	REQUIRE(host != NULL);
81 	REQUIRE(addr != NULL);
82 
83 	ZERO_SOCK(addr);
84 
85 	/*
86 	 * Try IPv4, then IPv6.  In order to handle the extended format
87 	 * for IPv6 scoped addresses (address%scope_ID), we'll use a local
88 	 * working buffer of 128 bytes.  The length is an ad-hoc value, but
89 	 * should be enough for this purpose; the buffer can contain a string
90 	 * of at least 80 bytes for scope_ID in addition to any IPv6 numeric
91 	 * addresses (up to 46 bytes), the delimiter character and the
92 	 * terminating NULL character.
93 	 */
94 	if (AF_UNSPEC == af || AF_INET == af)
95 		if (inet_pton(AF_INET, host, &in4) == 1) {
96 			AF(addr) = AF_INET;
97 			SET_ADDR4N(addr, in4.s_addr);
98 
99 			return TRUE;
100 		}
101 
102 	if (AF_UNSPEC == af || AF_INET6 == af)
103 		if (sizeof(tmpbuf) > strlen(host)) {
104 			if ('[' == host[0]) {
105 				strlcpy(tmpbuf, &host[1], sizeof(tmpbuf));
106 				pch = strchr(tmpbuf, ']');
107 				if (pch != NULL)
108 					*pch = '\0';
109 			} else {
110 				strlcpy(tmpbuf, host, sizeof(tmpbuf));
111 			}
112 			ZERO(hints);
113 			hints.ai_family = AF_INET6;
114 			hints.ai_flags |= AI_NUMERICHOST;
115 			if (getaddrinfo(tmpbuf, NULL, &hints, &result) == 0) {
116 				AF(addr) = AF_INET6;
117 				resaddr6 = UA_PTR(struct sockaddr_in6, result->ai_addr);
118 				SET_ADDR6N(addr, resaddr6->sin6_addr);
119 				SET_SCOPE(addr, resaddr6->sin6_scope_id);
120 
121 				freeaddrinfo(result);
122 				return TRUE;
123 			}
124 		}
125 	/*
126 	 * If we got here it was not an IP address
127 	 */
128 	return FALSE;
129 }
130