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