]>
Commit | Line | Data |
---|---|---|
30a4f2a8 | 1 | /* |
b510f3a1 | 2 | * DEBUG: section 00 DNS Resolver Daemon |
30a4f2a8 | 3 | * AUTHOR: Harvest Derived |
4 | * | |
2b6662ba | 5 | * SQUID Web Proxy Cache http://www.squid-cache.org/ |
e25c139f | 6 | * ---------------------------------------------------------- |
30a4f2a8 | 7 | * |
2b6662ba | 8 | * Squid is the result of efforts by numerous individuals from |
9 | * the Internet community; see the CONTRIBUTORS file for full | |
10 | * details. Many organizations have provided support for Squid's | |
11 | * development; see the SPONSORS file for full details. Squid is | |
12 | * Copyrighted (C) 2001 by the Regents of the University of | |
13 | * California; see the COPYRIGHT file for full details. Squid | |
14 | * incorporates software developed and/or copyrighted by other | |
15 | * sources; see the CREDITS file for full details. | |
30a4f2a8 | 16 | * |
17 | * This program is free software; you can redistribute it and/or modify | |
18 | * it under the terms of the GNU General Public License as published by | |
19 | * the Free Software Foundation; either version 2 of the License, or | |
20 | * (at your option) any later version. | |
26ac0430 | 21 | * |
30a4f2a8 | 22 | * This program is distributed in the hope that it will be useful, |
23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
25 | * GNU General Public License for more details. | |
26ac0430 | 26 | * |
30a4f2a8 | 27 | * You should have received a copy of the GNU General Public License |
28 | * along with this program; if not, write to the Free Software | |
cbdec147 | 29 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. |
e25c139f | 30 | * |
30a4f2a8 | 31 | */ |
ed43818f | 32 | |
f7f3304a | 33 | #include "squid.h" |
af00901c | 34 | |
35 | #if HAVE_UNISTD_H | |
36 | #include <unistd.h> | |
37 | #endif | |
af00901c | 38 | #if HAVE_STDIO_H |
39 | #include <stdio.h> | |
40 | #endif | |
af00901c | 41 | #if HAVE_CTYPE_H |
42 | #include <ctype.h> | |
43 | #endif | |
44 | #if HAVE_ERRNO_H | |
45 | #include <errno.h> | |
46 | #endif | |
47 | #if HAVE_FCNTL_H | |
48 | #include <fcntl.h> | |
49 | #endif | |
50 | #if HAVE_GRP_H | |
51 | #include <grp.h> | |
52 | #endif | |
88738790 | 53 | #if HAVE_GNUMALLOC_H |
54 | #include <gnumalloc.h> | |
482aa790 | 55 | #elif HAVE_MALLOC_H |
af00901c | 56 | #include <malloc.h> |
57 | #endif | |
58 | #if HAVE_MEMORY_H | |
59 | #include <memory.h> | |
60 | #endif | |
489520a9 | 61 | #if HAVE_NETDB_H |
af00901c | 62 | #include <netdb.h> |
63 | #endif | |
64 | #if HAVE_PWD_H | |
65 | #include <pwd.h> | |
66 | #endif | |
67 | #if HAVE_SIGNAL_H | |
68 | #include <signal.h> | |
69 | #endif | |
70 | #if HAVE_TIME_H | |
71 | #include <time.h> | |
72 | #endif | |
73 | #if HAVE_SYS_PARAM_H | |
74 | #include <sys/param.h> | |
75 | #endif | |
af00901c | 76 | #if HAVE_SYS_SOCKET_H |
77 | #include <sys/socket.h> | |
78 | #endif | |
79 | #if HAVE_NETINET_IN_H | |
80 | #include <netinet/in.h> | |
81 | #endif | |
82 | #if HAVE_ARPA_INET_H | |
83 | #include <arpa/inet.h> | |
84 | #endif | |
85 | #if HAVE_SYS_STAT_H | |
86 | #include <sys/stat.h> | |
87 | #endif | |
88 | #if HAVE_SYS_UN_H | |
89 | #include <sys/un.h> | |
90 | #endif | |
91 | #if HAVE_SYS_WAIT_H | |
92 | #include <sys/wait.h> | |
93 | #endif | |
94 | #if HAVE_LIBC_H | |
95 | #include <libc.h> | |
96 | #endif | |
32d002cb | 97 | #if HAVE_SYS_SYSCALL_H |
af00901c | 98 | #include <sys/syscall.h> |
99 | #endif | |
32d002cb | 100 | #if HAVE_STRING_H |
af00901c | 101 | #include <string.h> |
102 | #endif | |
32d002cb | 103 | #if HAVE_STRINGS_H |
af00901c | 104 | #include <strings.h> |
105 | #endif | |
106 | #if HAVE_BSTRING_H | |
107 | #include <bstring.h> | |
108 | #endif | |
32d002cb | 109 | #if HAVE_CRYPT_H |
af00901c | 110 | #include <crypt.h> |
111 | #endif | |
fcd3a580 | 112 | #if HAVE_GETOPT_H |
113 | #include <getopt.h> | |
114 | #endif | |
af00901c | 115 | |
30a4f2a8 | 116 | #if HAVE_ARPA_NAMESER_H |
117 | #include <arpa/nameser.h> | |
118 | #endif | |
119 | #if HAVE_RESOLV_H | |
120 | #include <resolv.h> | |
121 | #endif | |
090089c4 | 122 | |
63be0a78 | 123 | /** |
124 | \defgroup dnsserver dnsserver | |
125 | \ingroup ExternalPrograms | |
126 | \par | |
127 | Because the standard gethostbyname() library call | |
128 | blocks, Squid must use external processes to actually make | |
129 | these calls. Typically there will be ten dnsserver | |
130 | processes spawned from Squid. Communication occurs via | |
131 | TCP sockets bound to the loopback interface. The functions | |
132 | in dns.cc are primarily concerned with starting and | |
133 | stopping the dnsservers. Reading and writing to and from | |
134 | the dnsservers occurs in the \link IPCacheAPI IP\endlink and | |
135 | \link FQDNCacheAPI FQDN\endlink cache modules. | |
136 | ||
137 | \section dnsserverInterface Command Line Interface | |
138 | \verbatim | |
139 | usage: dnsserver -Dhv -s nameserver | |
140 | -D Enable resolver RES_DEFNAMES and RES_DNSRCH options | |
141 | -h Help | |
142 | -v Version | |
143 | -s nameserver Specify alternate name server(s). 'nameserver' | |
144 | must be an IP address, -s option may be repeated | |
145 | \endverbatim | |
146 | */ | |
147 | ||
6bf65235 | 148 | #if LIBRESOLV_DNS_TTL_HACK |
63be0a78 | 149 | /// \ingroup dnsserver |
28b2f45f | 150 | extern int _dns_ttl_; /* this is a really *dirty* hack - bne */ |
6bf65235 | 151 | #endif |
152 | ||
cc192b50 | 153 | /* |
154 | * res_init() is a macro re-definition of __res_init on: Debian | |
3bf15742 | 155 | */ |
cc192b50 | 156 | #if !defined(HAVE_RES_INIT) && defined(HAVE___RES_INIT) |
157 | #ifndef res_init | |
158 | #define res_init __res_init | |
159 | #endif | |
160 | #define HAVE_RES_INIT HAVE___RES_INIT | |
161 | #endif | |
62e76326 | 162 | |
63be0a78 | 163 | /// \ingroup dnsserver |
88738790 | 164 | #define REQ_SZ 512 |
165 | ||
63be0a78 | 166 | /** |
167 | \ingroup dnsserver | |
168 | */ | |
bd34f258 | 169 | static void |
170 | lookup(const char *buf) | |
171 | { | |
bd34f258 | 172 | int ttl = 0; |
173 | int retry = 0; | |
cc192b50 | 174 | unsigned int i = 0; |
c7e76326 | 175 | char ntoabuf[256]; |
cc192b50 | 176 | struct addrinfo hints; |
177 | struct addrinfo *AI = NULL; | |
178 | struct addrinfo *aiptr = NULL; | |
179 | struct addrinfo *prev_addr = NULL; | |
180 | int res = 0; | |
62e76326 | 181 | |
bd34f258 | 182 | if (0 == strcmp(buf, "$shutdown")) |
62e76326 | 183 | exit(0); |
184 | ||
bd34f258 | 185 | if (0 == strcmp(buf, "$hello")) { |
62e76326 | 186 | printf("$alive\n"); |
187 | return; | |
bd34f258 | 188 | } |
62e76326 | 189 | |
c7e76326 | 190 | /* check if it's already an IP address in text form. */ |
cc192b50 | 191 | memset(&hints, '\0', sizeof(struct addrinfo)); |
192 | hints.ai_family = AF_UNSPEC; | |
c7e76326 AJ |
193 | hints.ai_flags = AI_NUMERICHOST; // only succeed if its numeric. |
194 | const bool isDomain = (getaddrinfo(buf,NULL,&hints,&AI) != 0); | |
195 | ||
196 | // reset for real lookup | |
7a1ddbaf MW |
197 | if (AI != NULL) { |
198 | freeaddrinfo(AI); | |
199 | AI = NULL; | |
200 | } | |
cc192b50 | 201 | |
c7e76326 AJ |
202 | // resolve the address/name |
203 | memset(&hints, '\0', sizeof(struct addrinfo)); | |
204 | hints.ai_family = AF_UNSPEC; | |
205 | hints.ai_flags = AI_CANONNAME; | |
bd34f258 | 206 | for (;;) { |
c8e337c1 AJ |
207 | if (AI != NULL) { |
208 | freeaddrinfo(AI); | |
209 | AI = NULL; | |
210 | } | |
62e76326 | 211 | |
27bc2077 | 212 | if ( 0 == (res = getaddrinfo(buf,NULL,&hints,&AI)) ) |
62e76326 | 213 | break; |
214 | ||
cc192b50 | 215 | if (res != EAI_AGAIN) |
62e76326 | 216 | break; |
217 | ||
218 | if (++retry == 3) | |
219 | break; | |
220 | ||
221 | sleep(1); | |
bd34f258 | 222 | } |
62e76326 | 223 | |
c7e76326 | 224 | if (isDomain) { |
cc192b50 | 225 | /* its a domain name. Use the forward-DNS lookup already done */ |
62e76326 | 226 | |
26ac0430 | 227 | if (res == 0) { |
cc192b50 | 228 | #if LIBRESOLV_DNS_TTL_HACK |
229 | /* DNS TTL handling - bne@CareNet.hu | |
230 | * for first try it's a dirty hack, by hacking getanswer | |
231 | * to place the ttl in a global variable */ | |
232 | if (_dns_ttl_ > -1) | |
233 | ttl = _dns_ttl_; | |
234 | #endif | |
235 | printf("$addr %d", ttl); | |
236 | ||
237 | i = 0; | |
238 | aiptr = AI; | |
26ac0430 | 239 | while (NULL != aiptr && 32 >= i) { |
c7e76326 | 240 | memset(ntoabuf, 0, sizeof(ntoabuf)); |
cc192b50 | 241 | |
242 | /* getaddrinfo given a host has a nasty tendency to return duplicate addr's */ | |
243 | /* BUT sorted fortunately, so we can drop most of them easily */ | |
26ac0430 AJ |
244 | if ( prev_addr && |
245 | prev_addr->ai_family==aiptr->ai_family && | |
246 | memcmp(aiptr->ai_addr, prev_addr->ai_addr, aiptr->ai_addrlen)==0 | |
247 | ) { | |
cc192b50 | 248 | prev_addr = aiptr; |
249 | aiptr = aiptr->ai_next; | |
250 | continue; | |
26ac0430 | 251 | } else { |
cc192b50 | 252 | prev_addr = aiptr; |
253 | } | |
254 | ||
255 | /* annoying inet_ntop breaks the nice code by requiring the in*_addr */ | |
26ac0430 | 256 | switch (aiptr->ai_family) { |
cc192b50 | 257 | case AF_INET: |
c7e76326 | 258 | inet_ntop(aiptr->ai_family, &((struct sockaddr_in*)aiptr->ai_addr)->sin_addr, ntoabuf, sizeof(ntoabuf)); |
cc192b50 | 259 | break; |
cc192b50 | 260 | case AF_INET6: |
c7e76326 | 261 | inet_ntop(aiptr->ai_family, &((struct sockaddr_in6*)aiptr->ai_addr)->sin6_addr, ntoabuf, sizeof(ntoabuf)); |
cc192b50 | 262 | break; |
cc192b50 | 263 | default: |
264 | aiptr = aiptr->ai_next; | |
265 | continue; | |
266 | } | |
267 | printf(" %s", ntoabuf); | |
95dc7ff4 | 268 | ++i; |
cc192b50 | 269 | aiptr = aiptr->ai_next; |
270 | } | |
271 | ||
272 | prev_addr=NULL; | |
273 | printf("\n"); | |
274 | } | |
26ac0430 | 275 | } else { /* its an IPA in text form. perform rDNS */ |
cc192b50 | 276 | /* You'd expect getaddrinfo given AI_CANONNAME would do a lookup on |
277 | * missing FQDN. But no, it only copies the input string to that | |
278 | * position regardless of its content. | |
279 | */ | |
26ac0430 AJ |
280 | if (NULL != AI && NULL != AI->ai_addr) { |
281 | for (;;) { | |
c7e76326 | 282 | if ( 0 == (res = getnameinfo(AI->ai_addr, AI->ai_addrlen, ntoabuf, sizeof(ntoabuf), NULL,0,0)) ) |
cc192b50 | 283 | break; |
284 | ||
285 | if (res != EAI_AGAIN) | |
286 | break; | |
287 | ||
288 | if (++retry == 3) | |
289 | break; | |
290 | ||
291 | sleep(1); | |
292 | } | |
293 | } | |
62e76326 | 294 | |
26ac0430 | 295 | if (res == 0) { |
bd34f258 | 296 | #if LIBRESOLV_DNS_TTL_HACK |
cc192b50 | 297 | /* DNS TTL handling - bne@CareNet.hu |
298 | * for first try it's a dirty hack, by hacking getanswer | |
299 | * to place the ttl in a global variable */ | |
300 | if (_dns_ttl_ > -1) | |
301 | ttl = _dns_ttl_; | |
bd34f258 | 302 | #endif |
62e76326 | 303 | |
cc192b50 | 304 | printf("$name %d %s\n", ttl, ntoabuf); |
305 | } | |
bd34f258 | 306 | } |
62e76326 | 307 | |
26ac0430 AJ |
308 | switch (res) { |
309 | case 0: | |
310 | /* no error. */ | |
311 | break; | |
62e76326 | 312 | |
26ac0430 AJ |
313 | case EAI_AGAIN: |
314 | printf("$fail Name Server for domain '%s' is unavailable.\n", buf); | |
315 | break; | |
62e76326 | 316 | |
26ac0430 | 317 | case EAI_FAIL: |
27bc2077 | 318 | printf("$fail DNS Domain/IP '%s' does not exist: %s.\n", buf, gai_strerror(res)); |
26ac0430 | 319 | break; |
62e76326 | 320 | |
cc192b50 | 321 | #if defined(EAI_NODATA) || defined(EAI_NONAME) |
32d002cb | 322 | #if EAI_NODATA |
cc192b50 | 323 | /* deprecated. obsolete on some OS */ |
26ac0430 | 324 | case EAI_NODATA: |
cc192b50 | 325 | #endif |
32d002cb | 326 | #if EAI_NONAME |
26ac0430 | 327 | case EAI_NONAME: |
cc192b50 | 328 | #endif |
27bc2077 | 329 | printf("$fail DNS Domain/IP '%s' exists without any FQDN/IPs: %s.\n", buf, gai_strerror(res)); |
26ac0430 | 330 | break; |
cc192b50 | 331 | #endif |
26ac0430 | 332 | default: |
27bc2077 | 333 | printf("$fail A system error occured looking up Domain/IP '%s': %s.\n", buf, gai_strerror(res)); |
bd34f258 | 334 | } |
62e76326 | 335 | |
7a1ddbaf MW |
336 | if (AI != NULL) |
337 | freeaddrinfo(AI); | |
bd34f258 | 338 | } |
339 | ||
63be0a78 | 340 | /** |
341 | \ingroup dnsserver | |
342 | */ | |
bd34f258 | 343 | static void |
344 | usage(void) | |
345 | { | |
cc192b50 | 346 | fprintf(stderr, "usage: dnsserver -hv -s nameserver\n" |
62e76326 | 347 | "\t-h Help\n" |
348 | "\t-v Version\n" | |
349 | "\t-s nameserver Specify alternate name server(s). 'nameserver'\n" | |
cc192b50 | 350 | "\t must be an IPv4 address, -s option may be repeated\n" |
26ac0430 | 351 | ); |
bd34f258 | 352 | } |
353 | ||
605f2c3e | 354 | #if defined(_SQUID_RES_NSADDR6_LARRAY) |
63be0a78 | 355 | /// \ingroup dnsserver |
cc192b50 | 356 | #define _SQUID_RES_NSADDR6_LIST(i) _SQUID_RES_NSADDR6_LARRAY[i].sin6_addr |
357 | #endif | |
605f2c3e | 358 | #if defined(_SQUID_RES_NSADDR6_LPTR) |
63be0a78 | 359 | /// \ingroup dnsserver |
cc192b50 | 360 | #define _SQUID_RES_NSADDR6_LIST(i) _SQUID_RES_NSADDR6_LPTR[i]->sin6_addr |
361 | #endif | |
362 | ||
63be0a78 | 363 | /** |
d376ccbf | 364 | * \ingroup dnsserver |
63be0a78 | 365 | * |
d376ccbf AJ |
366 | * Override the system DNS nameservers with some local ones. |
367 | * Equivalent to the bind res_setservers() call but for any | |
368 | * system where we can find the needed _res fields. | |
63be0a78 | 369 | */ |
d376ccbf AJ |
370 | void |
371 | squid_res_setservers(int reset) | |
090089c4 | 372 | { |
605f2c3e | 373 | #if _SQUID_FREEBSD_ && defined(_SQUID_RES_NSADDR6_COUNT) |
cc192b50 | 374 | /* Only seems to be valid on FreeBSD 5.5 where _res_ext was provided without an ns6addr counter! */ |
375 | /* Gone again on FreeBSD 6.2 along with _res_ext itself in any form. */ | |
376 | int ns6count = 0; | |
377 | #endif | |
c7e76326 | 378 | #if HAVE_RES_INIT && defined(_SQUID_RES_NSADDR_LIST) |
09c483ec | 379 | extern char *optarg; |
e6ccf245 | 380 | #endif |
090089c4 | 381 | |
cc192b50 | 382 | #if HAVE_RES_INIT && (defined(_SQUID_RES_NSADDR_LIST) || defined(_SQUID_RES_NSADDR6_LIST)) |
62e76326 | 383 | |
d376ccbf | 384 | if (reset == 0) { |
cc192b50 | 385 | #if defined(_SQUID_RES_NSADDR_COUNT) |
d376ccbf AJ |
386 | _SQUID_RES_NSADDR_COUNT = 0; |
387 | /* because I don't trust the nscount super-count entirely, make sure these are ALL invalid */ | |
388 | memset(_SQUID_RES_NSADDR_LIST, 0, sizeof(struct sockaddr_in)*MAXNS); | |
cc192b50 | 389 | #endif |
390 | #if defined(_SQUID_RES_NSADDR6_COUNT) | |
d376ccbf | 391 | _SQUID_RES_NSADDR6_COUNT = 0; |
62e76326 | 392 | #endif |
d376ccbf | 393 | } |
62e76326 | 394 | |
d376ccbf AJ |
395 | /* AYJ: |
396 | * I experimented with all the permutations of mixed/unmixed nscount/nscount6 IPv4/IPv6/Both/invalid | |
397 | * | |
398 | * I'm not sure if splitting them really helps. | |
399 | * I've seen no evidence of IPv4 resolver *ever* being used when some IPv6 are set (or not even) | |
400 | * BUT, have seen segfault when IPv4 is added to NSADDR6 list (_res._u._ext). | |
401 | * It also appears to not do ANY lookup when _res.nscount==0. | |
402 | * | |
403 | * BUT, even if _res.nsaddrs is memset to NULL, it resolves IFF IPv6 set in _ext. | |
404 | * | |
c7e76326 | 405 | * SO, am splitting the IPv4/v6 into the seperate _res fields |
d376ccbf AJ |
406 | * and making nscount a total of IPv4+IPv6 /w nscount6 the IPv6 sub-counter |
407 | * ie. nscount = count(NSv4)+count(NSv6) & nscount6 = count(NSv6) | |
408 | * | |
409 | * If ANYONE knows better please let us know. | |
410 | */ | |
c7e76326 AJ |
411 | struct addrinfo hints; |
412 | memset(&hints, '\0', sizeof(struct addrinfo)); | |
413 | hints.ai_family = AF_UNSPEC; | |
414 | hints.ai_flags = AI_NUMERICHOST; // prevent repeated DNS lookups! | |
415 | struct addrinfo *AI = NULL; | |
416 | if ( getaddrinfo(optarg, NULL, &hints, &AI) != 0) { | |
d376ccbf | 417 | fprintf(stderr, "%s appears to be a bad nameserver FQDN/IP.\n",optarg); |
c7e76326 | 418 | } else if ( AI->ai_family == AF_INET ) { |
d376ccbf AJ |
419 | if (_SQUID_RES_NSADDR_COUNT == MAXNS) { |
420 | fprintf(stderr, "Too many -s options, only %d are allowed\n", MAXNS); | |
c7e76326 AJ |
421 | } else { |
422 | _SQUID_RES_NSADDR_LIST[_SQUID_RES_NSADDR_COUNT] = _SQUID_RES_NSADDR_LIST[0]; | |
423 | memcpy(&_SQUID_RES_NSADDR_LIST[_SQUID_RES_NSADDR_COUNT++].sin_addr, &((struct sockaddr_in*)AI->ai_addr)->sin_addr, sizeof(struct in_addr)); | |
d376ccbf | 424 | } |
c7e76326 | 425 | } else if ( AI->ai_family == AF_INET6 ) { |
cc192b50 | 426 | #if USE_IPV6 && defined(_SQUID_RES_NSADDR6_LIST) |
04f7fd38 | 427 | /* because things NEVER seem to resolve in tests without _res.nscount being a total. */ |
d376ccbf AJ |
428 | if (_SQUID_RES_NSADDR_COUNT == MAXNS) { |
429 | fprintf(stderr, "Too many -s options, only %d are allowed\n", MAXNS); | |
c7e76326 | 430 | } else { |
95dc7ff4 | 431 | ++ _SQUID_RES_NSADDR_COUNT; |
c7e76326 | 432 | memcpy(&_SQUID_RES_NSADDR6_LIST(_SQUID_RES_NSADDR6_COUNT++), &((struct sockaddr_in6*)AI->ai_addr)->sin6_addr, sizeof(struct in6_addr)); |
d376ccbf | 433 | } |
cc192b50 | 434 | #else |
d376ccbf | 435 | fprintf(stderr, "IPv6 nameservers not supported on this resolver\n"); |
4d62b0af | 436 | #endif |
d376ccbf | 437 | } |
7a1ddbaf MW |
438 | if (AI != NULL) |
439 | freeaddrinfo(AI); | |
cc192b50 | 440 | |
441 | #else /* !HAVE_RES_INIT || !defined(_SQUID_RES_NSADDR_LIST) */ | |
62e76326 | 442 | |
d376ccbf | 443 | fprintf(stderr, "-s is not supported on this resolver\n"); |
62e76326 | 444 | |
df087e68 | 445 | #endif /* HAVE_RES_INIT */ |
d376ccbf AJ |
446 | } |
447 | ||
d376ccbf AJ |
448 | /** |
449 | * \ingroup dnsserver | |
450 | * | |
451 | * This is the external dnsserver process. | |
452 | */ | |
453 | int | |
454 | main(int argc, char *argv[]) | |
455 | { | |
456 | char request[512]; | |
457 | char *t = NULL; | |
458 | int c; | |
ede9c6a6 | 459 | int opt_s = 0; |
62e76326 | 460 | |
d376ccbf | 461 | #if HAVE_RES_INIT |
d376ccbf AJ |
462 | res_init(); |
463 | #endif | |
464 | ||
465 | #if USE_IPV6 | |
466 | /* perform AAAA lookups *before* A lookups in IPv6 mode. */ | |
467 | _res.options |= RES_USE_INET6; | |
468 | #endif | |
469 | ||
470 | while ((c = getopt(argc, argv, "Dhs:v")) != -1) { | |
471 | switch (c) { | |
472 | ||
473 | case 'D': | |
474 | fprintf(stderr, "-D is now default behaviour from this tool.\n"); | |
475 | break; | |
476 | ||
477 | case 's': | |
478 | squid_res_setservers(opt_s); | |
479 | opt_s = 1; | |
62e76326 | 480 | break; |
481 | ||
482 | case 'v': | |
483 | printf("dnsserver version %s\n", VERSION); | |
484 | ||
485 | exit(0); | |
486 | ||
487 | break; | |
488 | ||
489 | case 'h': | |
490 | ||
491 | default: | |
492 | usage(); | |
493 | ||
494 | exit(1); | |
495 | ||
496 | break; | |
497 | } | |
30a4f2a8 | 498 | } |
090089c4 | 499 | |
1191b93b | 500 | #if _SQUID_MSWIN_ |
099a1791 | 501 | { |
62e76326 | 502 | WSADATA wsaData; |
099a1791 | 503 | |
62e76326 | 504 | WSAStartup(2, &wsaData); |
099a1791 | 505 | } |
62e76326 | 506 | |
099a1791 | 507 | fflush(stderr); |
508 | #endif | |
62e76326 | 509 | |
cb0486c3 | 510 | for (;;) { |
62e76326 | 511 | memset(request, '\0', REQ_SZ); |
512 | ||
26ac0430 | 513 | if (fgets(request, REQ_SZ, stdin) == NULL) { |
1191b93b | 514 | #if _SQUID_MSWIN_ |
26ac0430 | 515 | WSACleanup(); |
ec556193 | 516 | #endif |
26ac0430 AJ |
517 | exit(1); |
518 | } | |
62e76326 | 519 | |
520 | t = strrchr(request, '\n'); | |
521 | ||
522 | if (t == NULL) /* Ignore if no newline */ | |
523 | continue; | |
524 | ||
525 | *t = '\0'; /* strip NL */ | |
526 | ||
527 | if ((t = strrchr(request, '\r')) != NULL) | |
528 | *t = '\0'; /* strip CR */ | |
529 | ||
530 | lookup(request); | |
531 | ||
532 | fflush(stdout); | |
090089c4 | 533 | } |
62e76326 | 534 | |
b44c0fb4 | 535 | /* NOTREACHED */ |
7690e8eb | 536 | return 0; |
090089c4 | 537 | } |