]>
Commit | Line | Data |
---|---|---|
88840341 | 1 | /* |
88840341 RC |
2 | chronyd/chronyc - Programs for keeping computer clocks accurate. |
3 | ||
4 | ********************************************************************** | |
6672f045 | 5 | * Copyright (C) Richard P. Curnow 1997-2003 |
e63cba05 | 6 | * Copyright (C) Miroslav Lichvar 2009-2011 |
88840341 RC |
7 | * |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of version 2 of the GNU General Public License as | |
10 | * published by the Free Software Foundation. | |
11 | * | |
12 | * This program is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 | * General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License along | |
18 | * with this program; if not, write to the Free Software Foundation, Inc., | |
8e23110a | 19 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
88840341 RC |
20 | * |
21 | ********************************************************************** | |
22 | ||
23 | ======================================================================= | |
24 | ||
25 | Functions to do name to IP address conversion | |
26 | ||
27 | */ | |
28 | ||
da2c8d90 ML |
29 | #include "config.h" |
30 | ||
88840341 RC |
31 | #include "sysincl.h" |
32 | ||
4169e94b ML |
33 | #include <netdb.h> |
34 | #include <resolv.h> | |
35 | ||
88840341 | 36 | #include "nameserv.h" |
47e4cb31 | 37 | #include "socket.h" |
8265ff28 | 38 | #include "util.h" |
88840341 RC |
39 | |
40 | /* ================================================== */ | |
41 | ||
fbd20c42 ML |
42 | static int address_family = IPADDR_UNSPEC; |
43 | ||
44 | void | |
45 | DNS_SetAddressFamily(int family) | |
46 | { | |
47 | address_family = family; | |
48 | } | |
49 | ||
3d260d41 | 50 | DNS_Status |
4d1a754e | 51 | DNS_Name2IPAddress(const char *name, IPAddr *ip_addrs, int max_addrs) |
88840341 | 52 | { |
d243f1f8 | 53 | #ifdef HAVE_GETADDRINFO |
8265ff28 | 54 | struct addrinfo hints, *res, *ai; |
4d1a754e | 55 | int i, result; |
c6554bfd ML |
56 | |
57 | max_addrs = MIN(max_addrs, DNS_MAX_ADDRESSES); | |
58 | ||
8265ff28 | 59 | memset(&hints, 0, sizeof (hints)); |
f6539449 ML |
60 | |
61 | switch (address_family) { | |
62 | case IPADDR_INET4: | |
63 | hints.ai_family = AF_INET; | |
64 | break; | |
65 | #ifdef FEAT_IPV6 | |
66 | case IPADDR_INET6: | |
67 | hints.ai_family = AF_INET6; | |
68 | break; | |
69 | #endif | |
70 | default: | |
71 | hints.ai_family = AF_UNSPEC; | |
72 | } | |
d30e73d0 | 73 | hints.ai_socktype = SOCK_DGRAM; |
8265ff28 | 74 | |
8265ff28 | 75 | result = getaddrinfo(name, NULL, &hints, &res); |
88840341 | 76 | |
8265ff28 | 77 | if (result) { |
598c04ee ML |
78 | #ifdef FORCE_DNSRETRY |
79 | return DNS_TryAgain; | |
80 | #else | |
3d260d41 | 81 | return result == EAI_AGAIN ? DNS_TryAgain : DNS_Failure; |
598c04ee | 82 | #endif |
8265ff28 ML |
83 | } |
84 | ||
4d1a754e | 85 | for (ai = res, i = 0; i < max_addrs && ai != NULL; ai = ai->ai_next) { |
8265ff28 ML |
86 | switch (ai->ai_family) { |
87 | case AF_INET: | |
4d1a754e ML |
88 | if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET4) |
89 | continue; | |
90 | ip_addrs[i].family = IPADDR_INET4; | |
91 | ip_addrs[i].addr.in4 = ntohl(((struct sockaddr_in *)ai->ai_addr)->sin_addr.s_addr); | |
92 | i++; | |
8265ff28 | 93 | break; |
285fae85 | 94 | #ifdef FEAT_IPV6 |
8265ff28 | 95 | case AF_INET6: |
4d1a754e ML |
96 | if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET6) |
97 | continue; | |
98 | ip_addrs[i].family = IPADDR_INET6; | |
99 | memcpy(&ip_addrs[i].addr.in6, &((struct sockaddr_in6 *)ai->ai_addr)->sin6_addr.s6_addr, | |
100 | sizeof (ip_addrs->addr.in6)); | |
101 | i++; | |
8265ff28 ML |
102 | break; |
103 | #endif | |
104 | } | |
105 | } | |
106 | ||
4d1a754e ML |
107 | for (; i < max_addrs; i++) |
108 | ip_addrs[i].family = IPADDR_UNSPEC; | |
109 | ||
8265ff28 | 110 | freeaddrinfo(res); |
4d1a754e ML |
111 | |
112 | return !max_addrs || ip_addrs[0].family != IPADDR_UNSPEC ? DNS_Success : DNS_Failure; | |
8265ff28 ML |
113 | #else |
114 | struct hostent *host; | |
4d1a754e | 115 | int i; |
8265ff28 | 116 | |
69968080 ML |
117 | if (address_family != IPADDR_UNSPEC && address_family != IPADDR_INET4) |
118 | return DNS_Failure; | |
119 | ||
c6554bfd ML |
120 | max_addrs = MIN(max_addrs, DNS_MAX_ADDRESSES); |
121 | ||
88840341 | 122 | host = gethostbyname(name); |
8265ff28 | 123 | |
88840341 | 124 | if (host == NULL) { |
3d260d41 ML |
125 | if (h_errno == TRY_AGAIN) |
126 | return DNS_TryAgain; | |
88840341 | 127 | } else { |
69968080 ML |
128 | if (host->h_addrtype != AF_INET || !host->h_addr_list[0]) |
129 | return DNS_Failure; | |
130 | ||
4d1a754e ML |
131 | for (i = 0; host->h_addr_list[i] && i < max_addrs; i++) { |
132 | ip_addrs[i].family = IPADDR_INET4; | |
133 | ip_addrs[i].addr.in4 = ntohl(*(uint32_t *)host->h_addr_list[i]); | |
134 | } | |
135 | ||
136 | for (; i < max_addrs; i++) | |
137 | ip_addrs[i].family = IPADDR_UNSPEC; | |
138 | ||
3d260d41 | 139 | return DNS_Success; |
88840341 RC |
140 | } |
141 | ||
598c04ee ML |
142 | #ifdef FORCE_DNSRETRY |
143 | return DNS_TryAgain; | |
144 | #else | |
3d260d41 | 145 | return DNS_Failure; |
8265ff28 | 146 | #endif |
598c04ee ML |
147 | |
148 | #endif | |
0148ecae | 149 | } |
88840341 | 150 | |
0148ecae ML |
151 | /* ================================================== */ |
152 | ||
b4b24910 | 153 | int |
8265ff28 | 154 | DNS_IPAddress2Name(IPAddr *ip_addr, char *name, int len) |
0148ecae | 155 | { |
b4b24910 ML |
156 | char *result = NULL; |
157 | ||
285fae85 | 158 | #ifdef FEAT_IPV6 |
8265ff28 | 159 | struct sockaddr_in6 in6; |
47e4cb31 | 160 | IPSockAddr ip_saddr; |
55a22656 | 161 | socklen_t slen; |
b4b24910 | 162 | char hbuf[NI_MAXHOST]; |
8265ff28 | 163 | |
47e4cb31 ML |
164 | ip_saddr.ip_addr = *ip_addr; |
165 | ip_saddr.port = 0; | |
166 | ||
167 | slen = SCK_IPSockAddrToSockaddr(&ip_saddr, (struct sockaddr *)&in6, sizeof (in6)); | |
55a22656 ML |
168 | if (!getnameinfo((struct sockaddr *)&in6, slen, hbuf, sizeof (hbuf), NULL, 0, 0)) |
169 | result = hbuf; | |
8265ff28 | 170 | #else |
88840341 | 171 | struct hostent *host; |
fd2641bc | 172 | uint32_t addr; |
88840341 | 173 | |
8265ff28 ML |
174 | switch (ip_addr->family) { |
175 | case IPADDR_INET4: | |
176 | addr = htonl(ip_addr->addr.in4); | |
177 | host = gethostbyaddr((const char *) &addr, sizeof (ip_addr), AF_INET); | |
178 | break; | |
285fae85 | 179 | #ifdef FEAT_IPV6 |
8265ff28 ML |
180 | case IPADDR_INET6: |
181 | host = gethostbyaddr((const void *) ip_addr->addr.in6, sizeof (ip_addr->addr.in6), AF_INET6); | |
182 | break; | |
183 | #endif | |
184 | default: | |
185 | host = NULL; | |
88840341 | 186 | } |
b4b24910 ML |
187 | if (host) |
188 | result = host->h_name; | |
8265ff28 | 189 | #endif |
b4b24910 ML |
190 | |
191 | if (result == NULL) | |
192 | result = UTI_IPToString(ip_addr); | |
193 | if (snprintf(name, len, "%s", result) >= len) | |
194 | return 0; | |
195 | ||
196 | return 1; | |
88840341 RC |
197 | } |
198 | ||
199 | /* ================================================== */ | |
200 | ||
3d260d41 ML |
201 | void |
202 | DNS_Reload(void) | |
203 | { | |
204 | res_init(); | |
205 | } | |
206 | ||
207 | /* ================================================== */ | |
208 |