Merge lp:~hloeung/ubuntu/utopic/mtr/fix-ipv6-nameservers into lp:ubuntu/utopic/mtr
- Utopic (14.10)
- fix-ipv6-nameservers
- Merge into utopic
Proposed by
Haw Loeung
Status: | Rejected |
---|---|
Rejected by: | Haw Loeung |
Proposed branch: | lp:~hloeung/ubuntu/utopic/mtr/fix-ipv6-nameservers |
Merge into: | lp:ubuntu/utopic/mtr |
Diff against target: |
1593 lines (+1547/-0) 8 files modified
.pc/.quilt_patches (+1/-0) .pc/.quilt_series (+1/-0) .pc/.version (+1/-0) .pc/0001-fix-only-ipv6-nameservers.patch/dns.c (+1506/-0) .pc/applied-patches (+1/-0) debian/changelog (+13/-0) debian/patches/0001-fix-only-ipv6-nameservers.patch (+23/-0) debian/patches/series (+1/-0) |
To merge this branch: | bzr merge lp:~hloeung/ubuntu/utopic/mtr/fix-ipv6-nameservers |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Development Team | Pending | ||
Review via email: mp+230920@code.launchpad.net |
Commit message
Description of the change
My attempt at getting a patch I submitted upstream applied to the mtr package.
It basically fixes LP: #752583 where IPv6 nameservers specified in /etc/resolv.conf aren't counted and therefore mtr aborts when there are *only* IPv6 nameservers specified.
A pull request has been submitted on GitHub to have this change merged upstream[1].
To post a comment you must log in.
- 17. By Haw Loeung
-
Use NSCOUNT6 like what's used elsewhere.
Unmerged revisions
- 17. By Haw Loeung
-
Use NSCOUNT6 like what's used elsewhere.
- 16. By Haw Loeung
-
Added patch to include count of IPv6 nameservers fixing LP:#752583.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === added directory '.pc' |
2 | === added file '.pc/.quilt_patches' |
3 | --- .pc/.quilt_patches 1970-01-01 00:00:00 +0000 |
4 | +++ .pc/.quilt_patches 2014-08-15 07:33:32 +0000 |
5 | @@ -0,0 +1,1 @@ |
6 | +debian/patches |
7 | |
8 | === added file '.pc/.quilt_series' |
9 | --- .pc/.quilt_series 1970-01-01 00:00:00 +0000 |
10 | +++ .pc/.quilt_series 2014-08-15 07:33:32 +0000 |
11 | @@ -0,0 +1,1 @@ |
12 | +series |
13 | |
14 | === added file '.pc/.version' |
15 | --- .pc/.version 1970-01-01 00:00:00 +0000 |
16 | +++ .pc/.version 2014-08-15 07:33:32 +0000 |
17 | @@ -0,0 +1,1 @@ |
18 | +2 |
19 | |
20 | === added directory '.pc/0001-fix-only-ipv6-nameservers.patch' |
21 | === added file '.pc/0001-fix-only-ipv6-nameservers.patch/.timestamp' |
22 | === added file '.pc/0001-fix-only-ipv6-nameservers.patch/dns.c' |
23 | --- .pc/0001-fix-only-ipv6-nameservers.patch/dns.c 1970-01-01 00:00:00 +0000 |
24 | +++ .pc/0001-fix-only-ipv6-nameservers.patch/dns.c 2014-08-15 07:33:32 +0000 |
25 | @@ -0,0 +1,1506 @@ |
26 | +/* |
27 | + mtr -- a network diagnostic tool |
28 | + Copyright (C) 1997,1998 Matt Kimball |
29 | + |
30 | + This program is free software; you can redistribute it and/or modify |
31 | + it under the terms of the GNU General Public License version 2 as |
32 | + published by the Free Software Foundation. |
33 | + |
34 | + This program is distributed in the hope that it will be useful, |
35 | + but WITHOUT ANY WARRANTY; without even the implied warranty of |
36 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
37 | + GNU General Public License for more details. |
38 | + |
39 | + You should have received a copy of the GNU General Public License |
40 | + along with this program; if not, write to the Free Software |
41 | + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
42 | +*/ |
43 | + |
44 | +/* |
45 | + Non-blocking DNS portion -- |
46 | + Copyright (C) 1998 by Simon Kirby <sim@neato.org> |
47 | + Released under GPL, as above. |
48 | +*/ |
49 | + |
50 | +#include <config.h> |
51 | +#include <sys/types.h> |
52 | +#include <sys/time.h> |
53 | +#include <sys/select.h> |
54 | +#include <sys/stat.h> |
55 | +#include <sys/errno.h> |
56 | +#include <sys/socket.h> |
57 | +#include <netinet/in.h> |
58 | +#include <arpa/inet.h> |
59 | + |
60 | +#ifndef __APPLE__ |
61 | +#define BIND_8_COMPAT |
62 | +#endif |
63 | +#include <arpa/nameser.h> |
64 | +#ifdef HAVE_ARPA_NAMESER_COMPAT_H |
65 | +#include <arpa/nameser_compat.h> |
66 | +#endif |
67 | +#include <netdb.h> |
68 | +#include <resolv.h> |
69 | +#include <unistd.h> |
70 | +#include <fcntl.h> |
71 | +#include <ctype.h> |
72 | +#include <string.h> |
73 | +#include <stdio.h> |
74 | +#include <stdlib.h> |
75 | +#include <errno.h> |
76 | +#include <time.h> |
77 | + |
78 | +#include "mtr.h" |
79 | +#include "dns.h" |
80 | +#include "net.h" |
81 | + |
82 | +#ifdef ENABLE_IPV6 |
83 | +#ifdef __GLIBC__ |
84 | +#define NSCOUNT6 myres._u._ext.nscount6 |
85 | +#define NSSOCKADDR6(i) (myres._u._ext.nsaddrs[i]) |
86 | +#else |
87 | +#define NSCOUNT6 myres.nscount |
88 | +#define NSSOCKADDR6(i) (&(myres._u._ext.ext->nsaddrs[i].sin6)) |
89 | +#endif |
90 | +#endif |
91 | + |
92 | + |
93 | +#ifdef NO_STRERROR |
94 | +extern int sys_nerr; |
95 | +extern char *sys_errlist[]; |
96 | +#define strerror(errno) (((errno) >= 0 && (errno) < sys_nerr) ? sys_errlist[errno] : "unlisted error") |
97 | +#endif |
98 | + |
99 | +#if !HAVE_DECL_ERRNO |
100 | +/* Hmm, it seems Irix requires this */ |
101 | +extern int errno; |
102 | +#endif |
103 | + |
104 | +extern int af; |
105 | + |
106 | +/* Defines */ |
107 | + |
108 | +#undef Debug |
109 | + |
110 | +#undef CorruptCheck |
111 | +#undef WipeFrees |
112 | +#undef WipeMallocs |
113 | + |
114 | +#define BashSize 8192 /* Size of hash tables */ |
115 | +#define BashModulo(x) ((x) & 8191) /* Modulo for hash table size: */ |
116 | +#define HostnameLength 255 /* From RFC */ |
117 | +#define ResRetryDelay1 3 |
118 | +#define ResRetryDelay2 4 |
119 | +#define ResRetryDelay3 5 |
120 | + |
121 | +/* Macros */ |
122 | + |
123 | +#define nonull(s) (s) ? s : nullstring |
124 | + |
125 | +/* Structures */ |
126 | + |
127 | +struct resolve { |
128 | + struct resolve *next; |
129 | + struct resolve *previous; |
130 | + struct resolve *nextid; |
131 | + struct resolve *previousid; |
132 | + struct resolve *nextip; |
133 | + struct resolve *previousip; |
134 | + struct resolve *nexthost; |
135 | + struct resolve *previoushost; |
136 | + float expiretime; /* Fucking HPUX has a problem with "double" here. */ |
137 | + char *hostname; |
138 | + ip_t ip; |
139 | + word id; |
140 | + byte state; |
141 | +}; |
142 | + |
143 | +/* Non-blocking nameserver interface routines */ |
144 | + |
145 | +#define MaxPacketsize (PACKETSZ) |
146 | +#define DomainLength (MAXDNAME) |
147 | + |
148 | +#define OpcodeCount 3 |
149 | +char *opcodes[OpcodeCount+1] = { |
150 | + "standard query", |
151 | + "inverse query", |
152 | + "server status request", |
153 | + "unknown", |
154 | +}; |
155 | + |
156 | +#define ResponsecodeCount 6 |
157 | +char *responsecodes[ResponsecodeCount+1] = { |
158 | + "no error", |
159 | + "format error in query", |
160 | + "server failure", |
161 | + "queried domain name does not exist", |
162 | + "requested query type not implemented", |
163 | + "refused by name server", |
164 | + "unknown error", |
165 | +}; |
166 | + |
167 | +#define ResourcetypeCount 17 |
168 | +char *resourcetypes[ResourcetypeCount+1] = { |
169 | + "unknown type", |
170 | + "A: host address", |
171 | + "NS: authoritative name server", |
172 | + "MD: mail destination (OBSOLETE)", |
173 | + "MF: mail forwarder (OBSOLETE)", |
174 | + "CNAME: name alias", |
175 | + "SOA: authority record", |
176 | + "MB: mailbox domain name (EXPERIMENTAL)", |
177 | + "MG: mail group member (EXPERIMENTAL)", |
178 | + "MR: mail rename domain name (EXPERIMENTAL)", |
179 | + "NULL: NULL RR (EXPERIMENTAL)", |
180 | + "WKS: well known service description", |
181 | + "PTR: domain name pointer", |
182 | + "HINFO: host information", |
183 | + "MINFO: mailbox or mail list information", |
184 | + "MX: mail exchange", |
185 | + "TXT: text string", |
186 | + "unknown type", |
187 | +}; |
188 | + |
189 | +#define ClasstypeCount 5 |
190 | +char *classtypes[ClasstypeCount+1] = { |
191 | + "unknown class", |
192 | + "IN: the Internet", |
193 | + "CS: CSNET (OBSOLETE)", |
194 | + "CH: CHAOS", |
195 | + "HS: Hesoid [Dyer 87]", |
196 | + "unknown class" |
197 | +}; |
198 | + |
199 | +char *rrtypes[] = { |
200 | + "Unknown", |
201 | + "Query", |
202 | + "Answer", |
203 | + "Authority reference", |
204 | + "Resource reference", |
205 | +}; |
206 | + |
207 | + |
208 | +/* Please don't use a trailing comma in enumerations: It doesn't |
209 | + work on all compilers */ |
210 | +enum { |
211 | + RR_UNKNOWN, |
212 | + RR_QUERY, |
213 | + RR_ANSWER, |
214 | + RR_AUTHORITY, |
215 | + RR_RESOURCE |
216 | +}; |
217 | + |
218 | +typedef struct { |
219 | + word id; /* Packet id */ |
220 | + byte databyte_a; |
221 | + /* rd:1 recursion desired |
222 | + * tc:1 truncated message |
223 | + * aa:1 authoritive answer |
224 | + * opcode:4 purpose of message |
225 | + * qr:1 response flag |
226 | + */ |
227 | + byte databyte_b; |
228 | + /* rcode:4 response code |
229 | + * unassigned:2 unassigned bits |
230 | + * pr:1 primary server required (non standard) |
231 | + * ra:1 recursion available |
232 | + */ |
233 | + word qdcount; /* Query record count */ |
234 | + word ancount; /* Answer record count */ |
235 | + word nscount; /* Authority reference record count */ |
236 | + word arcount; /* Resource reference record count */ |
237 | +} packetheader; |
238 | + |
239 | +#ifndef HFIXEDSZ |
240 | +#define HFIXEDSZ (sizeof(packetheader)) |
241 | +#endif |
242 | + |
243 | +/* |
244 | + * Byte order independent macros for packetheader |
245 | + */ |
246 | +#define getheader_rd(x) (x->databyte_a & 1) |
247 | +#define getheader_tc(x) ((x->databyte_a >> 1) & 1) |
248 | +#define getheader_aa(x) ((x->databyte_a >> 2) & 1) |
249 | +#define getheader_opcode(x) ((x->databyte_a >> 3) & 15) |
250 | +#define getheader_qr(x) (x->databyte_a >> 7) |
251 | +#define getheader_rcode(x) (x->databyte_b & 15) |
252 | +#define getheader_pr(x) ((x->databyte_b >> 6) & 1) |
253 | +#define getheader_ra(x) (x->databyte_b >> 7) |
254 | + |
255 | +#if 0 |
256 | + |
257 | +/* The execution order inside an expression is undefined! That means that |
258 | + this might work, but then again, it might not... */ |
259 | + |
260 | +#define sucknetword(x) (((word)*(x) << 8) | (((x)+= 2)[-1])) |
261 | +#define sucknetshort(x) (((short)*(x) << 8) | (((x)+= 2)[-1])) |
262 | +#define sucknetdword(x) (((dword)*(x) << 24) | ((x)[1] << 16) | ((x)[2] << 8) | (((x)+= 4)[-1])) |
263 | +#define sucknetlong(x) (((long)*(x) << 24) | ((x)[1] << 16) | ((x)[2] << 8) | (((x)+= 4)[-1])) |
264 | +#else |
265 | + |
266 | +#define sucknetword(x) ((x)+=2,((word) (((x)[-2] << 8) | ((x)[-1] << 0)))) |
267 | +#define sucknetshort(x) ((x)+=2,((short) (((x)[-2] << 8) | ((x)[-1] << 0)))) |
268 | +#define sucknetdword(x) ((x)+=4,((dword) (((x)[-4] << 24) | ((x)[-3] << 16) | \ |
269 | + ((x)[-2] << 8) | ((x)[-1] << 0)))) |
270 | +#define sucknetlong(x) ((x)+=4,((long) (((x)[-4] << 24) | ((x)[-3] << 16) | \ |
271 | + ((x)[-2] << 8) | ((x)[-1] << 0)))) |
272 | +#endif |
273 | + |
274 | +enum { |
275 | + STATE_FINISHED, |
276 | + STATE_FAILED, |
277 | + STATE_PTRREQ1, |
278 | + STATE_PTRREQ2, |
279 | + STATE_PTRREQ3 |
280 | +}; |
281 | + |
282 | +#define Is_PTR(x) ((x->state == STATE_PTRREQ1) || (x->state == STATE_PTRREQ2) || (x->state == STATE_PTRREQ3)) |
283 | + |
284 | +dword resrecvbuf[(MaxPacketsize + 7) >> 2]; /* MUST BE DWORD ALIGNED */ |
285 | + |
286 | +struct resolve *idbash[BashSize]; |
287 | +struct resolve *ipbash[BashSize]; |
288 | +struct resolve *hostbash[BashSize]; |
289 | +struct resolve *expireresolves = NULL; |
290 | +struct resolve *lastresolve = NULL; |
291 | +struct logline *streamlog = NULL; |
292 | +struct logline *lastlog = NULL; |
293 | + |
294 | +ip_t alignedip; |
295 | +ip_t localhost; |
296 | +#ifdef ENABLE_IPV6 |
297 | +ip_t localhost6; |
298 | +#endif |
299 | + |
300 | +double sweeptime; |
301 | + |
302 | +#ifdef Debug |
303 | +int debug = 1; |
304 | +#else |
305 | +int debug = 0; |
306 | +#endif |
307 | + |
308 | +dword mem = 0; |
309 | + |
310 | +dword res_iplookupsuccess = 0; |
311 | +dword res_reversesuccess = 0; |
312 | +dword res_nxdomain = 0; |
313 | +dword res_nserror = 0; |
314 | +dword res_hostipmismatch = 0; |
315 | +dword res_unknownid = 0; |
316 | +dword res_resend = 0; |
317 | +dword res_timeout = 0; |
318 | + |
319 | +dword resolvecount = 0; |
320 | + |
321 | +long idseed = 0xdeadbeef; |
322 | +long aseed; |
323 | + |
324 | +#ifdef ENABLE_IPV6 |
325 | +struct sockaddr_storage from_sastruct; |
326 | +struct sockaddr_in6 * from6 = (struct sockaddr_in6 *) &from_sastruct; |
327 | +#else |
328 | +struct sockaddr_in from_sastruct; |
329 | +#endif |
330 | + |
331 | +struct sockaddr_in * from4 = (struct sockaddr_in *) &from_sastruct; |
332 | +struct sockaddr * from = (struct sockaddr *) &from_sastruct; |
333 | + |
334 | +int resfd; |
335 | +#ifdef ENABLE_IPV6 |
336 | +int resfd6; |
337 | +#endif |
338 | +socklen_t fromlen = sizeof from_sastruct; |
339 | + |
340 | +char tempstring[16384+1+1]; |
341 | +char sendstring[1024+1]; |
342 | +char namestring[1024+1]; |
343 | +char stackstring[1024+1]; |
344 | + |
345 | +char nullstring[] = ""; |
346 | + |
347 | +int use_dns = 1; |
348 | + |
349 | +#ifdef res_ninit |
350 | +#define MY_RES_INIT() res_ninit(&myres); |
351 | +#define RES_MKQUERY(a, b, c, d, e, f, g, h, i) \ |
352 | + res_nmkquery(&myres, a, b, c, d, e, f, g, h, i) |
353 | +struct __res_state myres; |
354 | +#else |
355 | +#define MY_RES_INIT() res_init(); |
356 | +#define RES_MKQUERY(a, b, c, d, e, f, g, h, i) \ |
357 | + res_mkquery(a, b, c, d, e, f, g, h, i) |
358 | +#define myres _res |
359 | +#endif |
360 | + |
361 | +/* Code */ |
362 | +#ifdef CorruptCheck |
363 | +#define TOT_SLACK 2 |
364 | +#define HEAD_SLACK 1 |
365 | +/* Need an entry for sparc systems here too. |
366 | + Don't try this on Sparc for now. */ |
367 | +#else |
368 | +#ifdef sparc |
369 | +#define TOT_SLACK 2 |
370 | +#define HEAD_SLACK 2 |
371 | +#else |
372 | +#define TOT_SLACK 1 |
373 | +#define HEAD_SLACK 1 |
374 | +#endif |
375 | +#endif |
376 | + |
377 | + |
378 | +void *statmalloc(size_t size) |
379 | +{ |
380 | + void *p; |
381 | + size_t mallocsize; |
382 | + |
383 | + mem+= size; |
384 | + mallocsize = size + TOT_SLACK * sizeof(dword); |
385 | + |
386 | + p = malloc(mallocsize); |
387 | + if (!p) { |
388 | + fprintf(stderr,"malloc() of %u bytes failed: %s\n", (unsigned int)size, strerror(errno)); |
389 | + exit(-1); |
390 | + } |
391 | + *((dword *)p) = (dword)size; |
392 | +#ifdef CorruptCheck |
393 | + *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 0) = 0xde; |
394 | + *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 1) = 0xad; |
395 | + *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 2) = 0xbe; |
396 | + *(byte *)((char *)p + size + sizeof(dword) + sizeof(byte) * 3) = 0xef; |
397 | +#endif |
398 | + p = (void *)((dword *)p + HEAD_SLACK); |
399 | +#ifdef WipeMallocs |
400 | + memset(p,0xf0,size); |
401 | +#endif |
402 | + return p; |
403 | +} |
404 | + |
405 | + |
406 | +void statfree(void *p) |
407 | +{ |
408 | + if (p) { |
409 | + if (*((dword *)p - HEAD_SLACK) == 0) { |
410 | + fprintf(stderr,"ERROR: Attempt to free pointer twice.\n"); |
411 | + abort(); |
412 | + exit(-1); |
413 | + } else { |
414 | + if (*((dword *)p - HEAD_SLACK) > 8192) { |
415 | + fprintf (stderr,"ERROR: Corrupted free() buffer. (header)\n"); |
416 | + abort(); |
417 | + exit(-1); |
418 | + } |
419 | +#ifdef CorruptCheck |
420 | + if ((*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 0) != 0xde) || |
421 | + (*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 1) != 0xad) || |
422 | + (*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 2) != 0xbe) || |
423 | + (*(byte *)((char *)p + (*((dword *)p - 1)) + sizeof(byte) * 3) != 0xef)) { |
424 | + fprintf(stderr,"ERROR: Corrupted free() buffer. (footer)\n"); |
425 | + abort(); |
426 | + exit(-1); |
427 | + } |
428 | +#endif |
429 | + mem-= *((dword *)p - HEAD_SLACK); |
430 | +#ifdef WipeFrees |
431 | + memset(p,0xfe,*((dword *)p - HEAD_SLACK)); |
432 | + *((dword *)p - 1) = 0; |
433 | +#endif |
434 | + free((dword *)p - HEAD_SLACK); |
435 | + } |
436 | + } |
437 | +} |
438 | + |
439 | + |
440 | +char *strtdiff(char *d,long signeddiff) |
441 | +{ |
442 | + dword diff; |
443 | + dword seconds,minutes,hours; |
444 | + long days; |
445 | + |
446 | + if ((diff = labs(signeddiff))) { |
447 | + seconds = diff % 60; diff/= 60; |
448 | + minutes = diff % 60; diff/= 60; |
449 | + hours = diff % 24; |
450 | + days = signeddiff / (60 * 60 * 24); |
451 | + if (days) |
452 | + sprintf(d,"%lid",days); |
453 | + else |
454 | + *d = '\0'; |
455 | + if (hours) |
456 | + sprintf(d + strlen(d),"%luh",hours); |
457 | + if (minutes) |
458 | + sprintf(d + strlen(d),"%lum",minutes); |
459 | + if (seconds) |
460 | + sprintf(d + strlen(d),"%lus",seconds); |
461 | + } else |
462 | + sprintf(d,"0s"); |
463 | + return d; |
464 | +} |
465 | + |
466 | + |
467 | +int issetfd(fd_set *set,int fd) |
468 | +{ |
469 | + return (int)((FD_ISSET(fd,set)) && 1); |
470 | +} |
471 | + |
472 | + |
473 | +void setfd(fd_set *set,int fd) |
474 | +{ |
475 | + FD_SET(fd,set); |
476 | +} |
477 | + |
478 | + |
479 | +void clearfd(fd_set *set,int fd) |
480 | +{ |
481 | + FD_CLR(fd,set); |
482 | +} |
483 | + |
484 | + |
485 | +void clearset(fd_set *set) |
486 | +{ |
487 | + FD_ZERO(set); |
488 | +} |
489 | + |
490 | + |
491 | +char *strlongip(ip_t * ip) |
492 | +{ |
493 | +#ifdef ENABLE_IPV6 |
494 | + static char addrstr[INET6_ADDRSTRLEN]; |
495 | + |
496 | + return (char *) inet_ntop( af, ip, addrstr, sizeof addrstr ); |
497 | +#else |
498 | + return inet_ntoa( *ip ); |
499 | +#endif |
500 | +} |
501 | + |
502 | + |
503 | +int longipstr( char *s, ip_t *dst, int af ) |
504 | +{ |
505 | +#ifdef ENABLE_IPV6 |
506 | + return inet_pton( af, s, dst ); |
507 | +#else |
508 | + return inet_aton( s, dst ); |
509 | +#endif |
510 | +} |
511 | + |
512 | + |
513 | +struct hostent * dns_forward(const char *name) |
514 | +{ |
515 | + struct hostent *host; |
516 | + |
517 | + if ((host = gethostbyname(name))) |
518 | + return host; |
519 | + else |
520 | + return NULL; |
521 | +} |
522 | + |
523 | + |
524 | +int dns_waitfd(void) |
525 | +{ |
526 | + return resfd; |
527 | +} |
528 | +#ifdef ENABLE_IPV6 |
529 | +int dns_waitfd6(void) |
530 | +{ |
531 | + return resfd6; |
532 | +} |
533 | +#endif |
534 | + |
535 | + |
536 | +void dns_open(void) |
537 | +{ |
538 | + int option,i; |
539 | + |
540 | + if (!dns) return; |
541 | + MY_RES_INIT(); |
542 | + if (!myres.nscount) { |
543 | + fprintf(stderr,"No nameservers defined.\n"); |
544 | + exit(-1); |
545 | + } |
546 | + myres.options|= RES_RECURSE | RES_DEFNAMES | RES_DNSRCH; |
547 | + resfd = socket(AF_INET, SOCK_DGRAM, 0); |
548 | + if (resfd == -1) { |
549 | + fprintf(stderr, |
550 | + "Unable to allocate IPv4 socket for nameserver communication: %s\n", |
551 | + strerror(errno)); |
552 | + exit(-1); |
553 | + } |
554 | +#ifdef ENABLE_IPV6 |
555 | + resfd6 = socket(AF_INET6, SOCK_DGRAM, 0); |
556 | + if (resfd6 == -1) { |
557 | + fprintf(stderr, |
558 | + "Unable to allocate IPv6 socket for nameserver communication: %s\n", |
559 | + strerror(errno)); |
560 | + exit(-1); |
561 | + } |
562 | +#endif |
563 | + option = 1; |
564 | + if (setsockopt(resfd,SOL_SOCKET,SO_BROADCAST,(char *)&option,sizeof(option))) { |
565 | + fprintf(stderr, |
566 | + "Unable to setsockopt() on IPv4 nameserver communication socket: %s\n", |
567 | + strerror(errno)); |
568 | + exit(-1); |
569 | + } |
570 | +#ifdef ENABLE_IPV6 |
571 | + if (setsockopt(resfd6,SOL_SOCKET,SO_BROADCAST,(char *)&option,sizeof(option))) { |
572 | + fprintf(stderr, |
573 | + "Unable to setsockopt() on IPv6 nameserver communication socket: %s\n", |
574 | + strerror(errno)); |
575 | + exit(-1); |
576 | + } |
577 | +#endif |
578 | + longipstr( "127.0.0.1", &localhost, AF_INET ); |
579 | +#ifdef ENABLE_IPV6 |
580 | + longipstr( "::1", &localhost6, AF_INET6 ); |
581 | +#endif |
582 | + aseed = time(NULL) ^ (time(NULL) << 3) ^ (dword)getpid(); |
583 | + for (i = 0;i < BashSize;i++) { |
584 | + idbash[i] = NULL; |
585 | + hostbash[i] = NULL; |
586 | + } |
587 | +} |
588 | + |
589 | + |
590 | +struct resolve *allocresolve(void) |
591 | +{ |
592 | + struct resolve *rp; |
593 | + |
594 | + rp = (struct resolve *)statmalloc(sizeof(struct resolve)); |
595 | + if (!rp) { |
596 | + fprintf(stderr,"statmalloc() failed: %s\n",strerror(errno)); |
597 | + exit(-1); |
598 | + } |
599 | + memset(rp,0, sizeof(struct resolve)); |
600 | + return rp; |
601 | +} |
602 | + |
603 | + |
604 | +dword getidbash(word id) |
605 | +{ |
606 | + return (dword)BashModulo(id); |
607 | +} |
608 | + |
609 | + |
610 | +dword getipbash(ip_t * ip) |
611 | +{ |
612 | + char *p = (char *) ip; |
613 | + int i, len = 0; |
614 | + dword bashvalue = 0; |
615 | + |
616 | + switch ( af ) { |
617 | + case AF_INET: |
618 | + len = sizeof (struct in_addr); |
619 | + break; |
620 | +#ifdef ENABLE_IPV6 |
621 | + case AF_INET6: |
622 | + len = sizeof (struct in6_addr); |
623 | + break; |
624 | +#endif |
625 | + } |
626 | + for (i = 0; i < len; i++, p++) { |
627 | + bashvalue^= *p; |
628 | + bashvalue+= (*p >> 1) + (bashvalue >> 1); |
629 | + } |
630 | + return BashModulo(bashvalue); |
631 | +} |
632 | + |
633 | + |
634 | +dword gethostbash(char *host) |
635 | +{ |
636 | + dword bashvalue = 0; |
637 | + |
638 | + for (;*host;host++) { |
639 | + bashvalue^= *host; |
640 | + bashvalue+= (*host >> 1) + (bashvalue >> 1); |
641 | + } |
642 | + return BashModulo(bashvalue); |
643 | +} |
644 | + |
645 | + |
646 | +void linkresolveid(struct resolve *addrp) |
647 | +{ |
648 | + struct resolve *rp; |
649 | + dword bashnum; |
650 | + |
651 | + bashnum = getidbash(addrp->id); |
652 | + rp = idbash[bashnum]; |
653 | + if (rp) { |
654 | + while ((rp->nextid) && (addrp->id > rp->nextid->id)) |
655 | + rp = rp->nextid; |
656 | + while ((rp->previousid) && (addrp->id < rp->previousid->id)) |
657 | + rp = rp->previousid; |
658 | + if (rp->id < addrp->id) { |
659 | + addrp->previousid = rp; |
660 | + addrp->nextid = rp->nextid; |
661 | + if (rp->nextid) |
662 | + rp->nextid->previousid = addrp; |
663 | + rp->nextid = addrp; |
664 | + } else { |
665 | + addrp->previousid = rp->previousid; |
666 | + addrp->nextid = rp; |
667 | + if (rp->previousid) |
668 | + rp->previousid->nextid = addrp; |
669 | + rp->previousid = addrp; |
670 | + } |
671 | + } else |
672 | + addrp->nextid = addrp->previousid = NULL; |
673 | + idbash[bashnum] = addrp; |
674 | +} |
675 | + |
676 | + |
677 | +void unlinkresolveid(struct resolve *rp) |
678 | +{ |
679 | + dword bashnum; |
680 | + |
681 | + bashnum = getidbash(rp->id); |
682 | + if (idbash[bashnum] == rp) |
683 | + idbash[bashnum] = (rp->previousid)? rp->previousid : rp->nextid; |
684 | + if (rp->nextid) |
685 | + rp->nextid->previousid = rp->previousid; |
686 | + if (rp->previousid) |
687 | + rp->previousid->nextid = rp->nextid; |
688 | +} |
689 | + |
690 | + |
691 | +void linkresolvehost(struct resolve *addrp) |
692 | +{ |
693 | + struct resolve *rp; |
694 | + dword bashnum; |
695 | + |
696 | + bashnum = gethostbash(addrp->hostname); |
697 | + rp = hostbash[bashnum]; |
698 | + if (rp) { |
699 | + while ((rp->nexthost) && (strcasecmp(addrp->hostname,rp->nexthost->hostname) < 0)) |
700 | + rp = rp->nexthost; |
701 | + while ((rp->previoushost) && (strcasecmp(addrp->hostname,rp->previoushost->hostname) > 0)) |
702 | + rp = rp->previoushost; |
703 | + if (strcasecmp(addrp->hostname,rp->hostname) < 0) { |
704 | + addrp->previoushost = rp; |
705 | + addrp->nexthost = rp->nexthost; |
706 | + if (rp->nexthost) |
707 | + rp->nexthost->previoushost = addrp; |
708 | + rp->nexthost = addrp; |
709 | + } else { |
710 | + addrp->previoushost = rp->previoushost; |
711 | + addrp->nexthost = rp; |
712 | + if (rp->previoushost) |
713 | + rp->previoushost->nexthost = addrp; |
714 | + rp->previoushost = addrp; |
715 | + } |
716 | + } else |
717 | + addrp->nexthost = addrp->previoushost = NULL; |
718 | + hostbash[bashnum] = addrp; |
719 | +} |
720 | + |
721 | + |
722 | +void unlinkresolvehost(struct resolve *rp) |
723 | +{ |
724 | + dword bashnum; |
725 | + |
726 | + bashnum = gethostbash(rp->hostname); |
727 | + if (hostbash[bashnum] == rp) |
728 | + hostbash[bashnum] = (rp->previoushost)? rp->previoushost : rp->nexthost; |
729 | + if (rp->nexthost) |
730 | + rp->nexthost->previoushost = rp->previoushost; |
731 | + if (rp->previoushost) |
732 | + rp->previoushost->nexthost = rp->nexthost; |
733 | + statfree(rp->hostname); |
734 | +} |
735 | + |
736 | + |
737 | +void linkresolveip(struct resolve *addrp) |
738 | +{ |
739 | + struct resolve *rp; |
740 | + dword bashnum; |
741 | + |
742 | + bashnum = getipbash( &(addrp->ip) ); |
743 | + rp = ipbash[bashnum]; |
744 | + if (rp) { |
745 | + while ((rp->nextip) && |
746 | + ( addrcmp( (void *) &(addrp->ip), |
747 | + (void *) &(rp->nextip->ip), af ) > 0 )) |
748 | + rp = rp->nextip; |
749 | + while ((rp->previousip) && |
750 | + ( addrcmp( (void *) &(addrp->ip), |
751 | + (void *) &(rp->previousip->ip), af ) < 0 )) |
752 | + rp = rp->previousip; |
753 | + if ( addrcmp( (void *) &(rp->ip), (void *) &(addrp->ip), af ) < 0 ) { |
754 | + addrp->previousip = rp; |
755 | + addrp->nextip = rp->nextip; |
756 | + if (rp->nextip) |
757 | + rp->nextip->previousip = addrp; |
758 | + rp->nextip = addrp; |
759 | + } else { |
760 | + addrp->previousip = rp->previousip; |
761 | + addrp->nextip = rp; |
762 | + if (rp->previousip) |
763 | + rp->previousip->nextip = addrp; |
764 | + rp->previousip = addrp; |
765 | + } |
766 | + } else |
767 | + addrp->nextip = addrp->previousip = NULL; |
768 | + ipbash[bashnum] = addrp; |
769 | +} |
770 | + |
771 | + |
772 | +void unlinkresolveip(struct resolve *rp) |
773 | +{ |
774 | + dword bashnum; |
775 | + |
776 | + bashnum = getipbash( &(rp->ip) ); |
777 | + if (ipbash[bashnum] == rp) |
778 | + ipbash[bashnum] = (rp->previousip)? rp->previousip : rp->nextip; |
779 | + if (rp->nextip) |
780 | + rp->nextip->previousip = rp->previousip; |
781 | + if (rp->previousip) |
782 | + rp->previousip->nextip = rp->nextip; |
783 | +} |
784 | + |
785 | + |
786 | +void linkresolve(struct resolve *rp) |
787 | +{ |
788 | + struct resolve *irp; |
789 | + |
790 | + if (expireresolves) { |
791 | + irp = expireresolves; |
792 | + while ((irp->next) && (rp->expiretime >= irp->expiretime)) irp = irp->next; |
793 | + if (rp->expiretime >= irp->expiretime) { |
794 | + rp->next = NULL; |
795 | + rp->previous = irp; |
796 | + irp->next = rp; |
797 | + lastresolve = rp; |
798 | + } else { |
799 | + rp->previous = irp->previous; |
800 | + rp->next = irp; |
801 | + if (irp->previous) |
802 | + irp->previous->next = rp; |
803 | + else |
804 | + expireresolves = rp; |
805 | + irp->previous = rp; |
806 | + } |
807 | + } else { |
808 | + rp->next = NULL; |
809 | + rp->previous = NULL; |
810 | + expireresolves = lastresolve = rp; |
811 | + } |
812 | + resolvecount++; |
813 | +} |
814 | + |
815 | + |
816 | +void lastlinkresolve(struct resolve *rp) |
817 | +{ |
818 | + struct resolve *irp; |
819 | + |
820 | + if (lastresolve) { |
821 | + irp = lastresolve; |
822 | + while ((irp->previous) && (rp->expiretime < irp->expiretime)) irp = irp->previous; |
823 | + while ((irp->next) && (rp->expiretime >= irp->expiretime)) irp = irp->next; |
824 | + if (rp->expiretime >= irp->expiretime) { |
825 | + rp->next = NULL; |
826 | + rp->previous = irp; |
827 | + irp->next = rp; |
828 | + lastresolve = rp; |
829 | + } else { |
830 | + rp->previous = irp->previous; |
831 | + rp->next = irp; |
832 | + if (irp->previous) |
833 | + irp->previous->next = rp; |
834 | + else |
835 | + expireresolves = rp; |
836 | + irp->previous = rp; |
837 | + } |
838 | + } else { |
839 | + rp->next = NULL; |
840 | + rp->previous = NULL; |
841 | + expireresolves = lastresolve = rp; |
842 | + } |
843 | + resolvecount++; |
844 | +} |
845 | + |
846 | + |
847 | +void untieresolve(struct resolve *rp) |
848 | +{ |
849 | + if (rp->previous) |
850 | + rp->previous->next = rp->next; |
851 | + else |
852 | + expireresolves = rp->next; |
853 | + if (rp->next) |
854 | + rp->next->previous = rp->previous; |
855 | + else |
856 | + lastresolve = rp->previous; |
857 | + resolvecount--; |
858 | +} |
859 | + |
860 | + |
861 | +void unlinkresolve(struct resolve *rp) |
862 | +{ |
863 | + untieresolve(rp); |
864 | + unlinkresolveid(rp); |
865 | + unlinkresolveip(rp); |
866 | + if (rp->hostname) |
867 | + unlinkresolvehost(rp); |
868 | +} |
869 | + |
870 | + |
871 | +struct resolve *findid(word id) |
872 | +{ |
873 | + struct resolve *rp; |
874 | + int bashnum; |
875 | + |
876 | + bashnum = getidbash(id); |
877 | + rp = idbash[bashnum]; |
878 | + if (rp) { |
879 | + while ((rp->nextid) && (id >= rp->nextid->id)) |
880 | + rp = rp->nextid; |
881 | + while ((rp->previousid) && (id <= rp->previousid->id)) |
882 | + rp = rp->previousid; |
883 | + if (id == rp->id) { |
884 | + idbash[bashnum] = rp; |
885 | + return rp; |
886 | + } else |
887 | + return NULL; |
888 | + } |
889 | + return rp; /* NULL */ |
890 | +} |
891 | + |
892 | + |
893 | +struct resolve *findhost(char *hostname) |
894 | +{ |
895 | + struct resolve *rp; |
896 | + int bashnum; |
897 | + |
898 | + bashnum = gethostbash(hostname); |
899 | + rp = hostbash[bashnum]; |
900 | + if (rp) { |
901 | + while ((rp->nexthost) && (strcasecmp(hostname,rp->nexthost->hostname) >= 0)) |
902 | + rp = rp->nexthost; |
903 | + while ((rp->previoushost) && (strcasecmp(hostname,rp->nexthost->hostname) <= 0)) |
904 | + rp = rp->previoushost; |
905 | + if (strcasecmp(hostname,rp->hostname)) |
906 | + return NULL; |
907 | + else { |
908 | + hostbash[bashnum] = rp; |
909 | + return rp; |
910 | + } |
911 | + } |
912 | + return rp; /* NULL */ |
913 | +} |
914 | + |
915 | + |
916 | +struct resolve *findip(ip_t * ip) |
917 | +{ |
918 | + struct resolve *rp; |
919 | + dword bashnum; |
920 | + |
921 | + bashnum = getipbash(ip); |
922 | + rp = ipbash[bashnum]; |
923 | + if (rp) { |
924 | + while ((rp->nextip) && |
925 | + ( addrcmp( (void *) ip, (void *) &(rp->nextip->ip), af ) >= 0 )) |
926 | + rp = rp->nextip; |
927 | + while ((rp->previousip) && |
928 | + ( addrcmp( (void *) ip, (void *) &(rp->previousip->ip), af ) <= 0 )) |
929 | + rp = rp->previousip; |
930 | + if ( addrcmp( (void *) ip, (void *) &(rp->ip), af ) == 0 ) { |
931 | + ipbash[bashnum] = rp; |
932 | + return rp; |
933 | + } else |
934 | + return NULL; |
935 | + } |
936 | + return rp; /* NULL */ |
937 | +} |
938 | + |
939 | + |
940 | +void restell(char *s) |
941 | +{ |
942 | + fputs(s,stderr); |
943 | + fputs("\r",stderr); |
944 | +} |
945 | + |
946 | + |
947 | +void dorequest(char *s,int type,word id) |
948 | +{ |
949 | + packetheader *hp; |
950 | + int r,i; |
951 | + unsigned char buf[MaxPacketsize]; |
952 | + |
953 | + r = RES_MKQUERY(QUERY,s,C_IN,type,NULL,0,NULL,(unsigned char*)buf,MaxPacketsize); |
954 | + if (r == -1) { |
955 | + restell("Resolver error: Query too large."); |
956 | + return; |
957 | + } |
958 | + hp = (packetheader *)buf; |
959 | + hp->id = id; /* htons() deliberately left out (redundant) */ |
960 | +#ifdef ENABLE_IPV6 |
961 | + for (i = 0;i < NSCOUNT6;i++) { |
962 | + if (!NSSOCKADDR6(i)) |
963 | + continue; |
964 | + if (NSSOCKADDR6(i)->sin6_family == AF_INET6) |
965 | + (void)sendto(resfd6,buf,r,0,(struct sockaddr *) NSSOCKADDR6(i), |
966 | + sizeof(struct sockaddr_in6)); |
967 | + } |
968 | +#endif |
969 | + for (i = 0;i < myres.nscount;i++) |
970 | + if (myres.nsaddr_list[i].sin_family == AF_INET) |
971 | + (void)sendto(resfd,buf,r,0,(struct sockaddr *)&myres.nsaddr_list[i], |
972 | + sizeof(struct sockaddr)); |
973 | +} |
974 | + |
975 | +void resendrequest(struct resolve *rp,int type) |
976 | +{ |
977 | + if (type == T_A) { |
978 | + dorequest(rp->hostname,type,rp->id); |
979 | + if (debug) { |
980 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Sent reverse authentication request for \"%s\".", |
981 | + rp->hostname); |
982 | + restell(tempstring); |
983 | + } |
984 | + } else if (type == T_PTR) { |
985 | + switch ( af ) { |
986 | + case AF_INET: |
987 | + sprintf(tempstring,"%u.%u.%u.%u.in-addr.arpa", |
988 | + ((byte *)&rp->ip)[3], |
989 | + ((byte *)&rp->ip)[2], |
990 | + ((byte *)&rp->ip)[1], |
991 | + ((byte *)&rp->ip)[0]); |
992 | + break; |
993 | +#ifdef ENABLE_IPV6 |
994 | + case AF_INET6: |
995 | + addr2ip6arpa( &(rp->ip), tempstring ); |
996 | + break; |
997 | +#endif |
998 | + } |
999 | + dorequest(tempstring,type,rp->id); |
1000 | + if (debug) { |
1001 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Sent domain lookup request for \"%s\".", |
1002 | + strlongip( &(rp->ip) )); |
1003 | + restell(tempstring); |
1004 | + } |
1005 | + } |
1006 | +} |
1007 | + |
1008 | +void sendrequest(struct resolve *rp,int type) |
1009 | +{ |
1010 | + do { |
1011 | + idseed = (((idseed + idseed) | (long)time(NULL)) + idseed - 0x54bad4a) ^ aseed; |
1012 | + aseed^= idseed; |
1013 | + rp->id = (word)idseed; |
1014 | + } while (findid(rp->id)); |
1015 | + linkresolveid(rp); |
1016 | + resendrequest(rp,type); |
1017 | +} |
1018 | + |
1019 | + |
1020 | +void failrp(struct resolve *rp) |
1021 | +{ |
1022 | + if (rp->state == STATE_FINISHED) |
1023 | + return; |
1024 | + rp->state = STATE_FAILED; |
1025 | + untieresolve(rp); |
1026 | + if (debug) |
1027 | + restell("Resolver: Lookup failed.\n"); |
1028 | +} |
1029 | + |
1030 | + |
1031 | +void passrp(struct resolve *rp,long ttl) |
1032 | +{ |
1033 | + rp->state = STATE_FINISHED; |
1034 | + rp->expiretime = sweeptime + (double)ttl; |
1035 | + untieresolve(rp); |
1036 | + if (debug) { |
1037 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Lookup successful: %s\n",rp->hostname); |
1038 | + restell(tempstring); |
1039 | + } |
1040 | +} |
1041 | + |
1042 | + |
1043 | +void parserespacket(byte *s, int l) |
1044 | +{ |
1045 | + struct resolve *rp; |
1046 | + packetheader *hp; |
1047 | + byte *eob; |
1048 | + byte *c; |
1049 | + long ttl; |
1050 | + int r,usefulanswer; |
1051 | + word rr,datatype,class,qdatatype,qclass; |
1052 | + byte rdatalength; |
1053 | + |
1054 | + if (l < (int) sizeof(packetheader)) { |
1055 | + restell("Resolver error: Packet smaller than standard header size."); |
1056 | + return; |
1057 | + } |
1058 | + if (l == (int) sizeof(packetheader)) { |
1059 | + restell("Resolver error: Packet has empty body."); |
1060 | + return; |
1061 | + } |
1062 | + hp = (packetheader *)s; |
1063 | + /* Convert data to host byte order */ |
1064 | + /* hp->id does not need to be redundantly byte-order flipped, it is only echoed by nameserver */ |
1065 | + rp = findid(hp->id); |
1066 | + if (!rp) { |
1067 | + res_unknownid++; |
1068 | + return; |
1069 | + } |
1070 | + if ((rp->state == STATE_FINISHED) || (rp->state == STATE_FAILED)) |
1071 | + return; |
1072 | + hp->qdcount = ntohs(hp->qdcount); |
1073 | + hp->ancount = ntohs(hp->ancount); |
1074 | + hp->nscount = ntohs(hp->nscount); |
1075 | + hp->arcount = ntohs(hp->arcount); |
1076 | + if (getheader_tc(hp)) { /* Packet truncated */ |
1077 | + restell("Resolver error: Nameserver packet truncated."); |
1078 | + return; |
1079 | + } |
1080 | + if (!getheader_qr(hp)) { /* Not a reply */ |
1081 | + restell("Resolver error: Query packet received on nameserver communication socket."); |
1082 | + return; |
1083 | + } |
1084 | + if (getheader_opcode(hp)) { /* Not opcode 0 (standard query) */ |
1085 | + restell("Resolver error: Invalid opcode in response packet."); |
1086 | + return; |
1087 | + } |
1088 | + eob = s + l; |
1089 | + c = s + HFIXEDSZ; |
1090 | + switch (getheader_rcode(hp)) { |
1091 | + case NOERROR: |
1092 | + if (hp->ancount) { |
1093 | + if (debug) { |
1094 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Received nameserver reply. (qd:%u an:%u ns:%u ar:%u)", |
1095 | + hp->qdcount,hp->ancount,hp->nscount,hp->arcount); |
1096 | + restell(tempstring); |
1097 | + } |
1098 | + if (hp->qdcount != 1) { |
1099 | + restell("Resolver error: Reply does not contain one query."); |
1100 | + return; |
1101 | + } |
1102 | + if (c > eob) { |
1103 | + restell("Resolver error: Reply too short."); |
1104 | + return; |
1105 | + } |
1106 | + switch (rp->state) { /* Construct expected query reply */ |
1107 | + case STATE_PTRREQ1: |
1108 | + case STATE_PTRREQ2: |
1109 | + case STATE_PTRREQ3: |
1110 | + switch ( af ) { |
1111 | + case AF_INET: |
1112 | + sprintf(stackstring,"%u.%u.%u.%u.in-addr.arpa", |
1113 | + ((byte *)&rp->ip)[3], |
1114 | + ((byte *)&rp->ip)[2], |
1115 | + ((byte *)&rp->ip)[1], |
1116 | + ((byte *)&rp->ip)[0]); |
1117 | + break; |
1118 | +#ifdef ENABLE_IPV6 |
1119 | + case AF_INET6: |
1120 | + addr2ip6arpa( &(rp->ip), stackstring ); |
1121 | + break; |
1122 | +#endif |
1123 | + } |
1124 | + } |
1125 | + *namestring = '\0'; |
1126 | + r = dn_expand(s,s + l,c,namestring,MAXDNAME); |
1127 | + if (r == -1) { |
1128 | + restell("Resolver error: dn_expand() failed while expanding query domain."); |
1129 | + return; |
1130 | + } |
1131 | + namestring[strlen(stackstring)] = '\0'; |
1132 | + if (strcasecmp(stackstring,namestring)) { |
1133 | + if (debug) { |
1134 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Unknown query packet dropped. (\"%s\" does not match \"%s\")", |
1135 | + stackstring,namestring); |
1136 | + restell(tempstring); |
1137 | + } |
1138 | + return; |
1139 | + } |
1140 | + if (debug) { |
1141 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Queried domain name: \"%s\"",namestring); |
1142 | + restell(tempstring); |
1143 | + } |
1144 | + c+= r; |
1145 | + if (c + 4 > eob) { |
1146 | + restell("Resolver error: Query resource record truncated."); |
1147 | + return; |
1148 | + } |
1149 | + qdatatype = sucknetword(c); |
1150 | + qclass = sucknetword(c); |
1151 | + if (qclass != C_IN) { |
1152 | + snprintf(tempstring, sizeof(tempstring), "Resolver error: Received unsupported query class: %u (%s)", |
1153 | + qclass,qclass < ClasstypeCount ? classtypes[qclass] : |
1154 | + classtypes[ClasstypeCount]); |
1155 | + restell(tempstring); |
1156 | + } |
1157 | + switch (qdatatype) { |
1158 | + case T_PTR: |
1159 | + if (!Is_PTR(rp)) |
1160 | + if (debug) { |
1161 | + restell("Resolver warning: Ignoring response with unexpected query type \"PTR\"."); |
1162 | + return; |
1163 | + } |
1164 | + break; |
1165 | + default: |
1166 | + snprintf(tempstring, sizeof(tempstring), "Resolver error: Received unimplemented query type: %u (%s)", |
1167 | + qdatatype,qdatatype < ResourcetypeCount ? |
1168 | + resourcetypes[qdatatype] : resourcetypes[ResourcetypeCount]); |
1169 | + restell(tempstring); |
1170 | + } |
1171 | + for (rr = hp->ancount + hp->nscount + hp->arcount;rr;rr--) { |
1172 | + if (c > eob) { |
1173 | + restell("Resolver error: Packet does not contain all specified resouce records."); |
1174 | + return; |
1175 | + } |
1176 | + *namestring = '\0'; |
1177 | + r = dn_expand(s,s + l,c,namestring,MAXDNAME); |
1178 | + if (r == -1) { |
1179 | + restell("Resolver error: dn_expand() failed while expanding answer domain."); |
1180 | + return; |
1181 | + } |
1182 | + namestring[strlen(stackstring)] = '\0'; |
1183 | + if (strcasecmp(stackstring,namestring)) |
1184 | + usefulanswer = 0; |
1185 | + else |
1186 | + usefulanswer = 1; |
1187 | + if (debug) { |
1188 | + snprintf(tempstring, sizeof(tempstring), "Resolver: answered domain query: \"%s\"",namestring); |
1189 | + restell(tempstring); |
1190 | + } |
1191 | + c+= r; |
1192 | + if (c + 10 > eob) { |
1193 | + restell("Resolver error: Resource record truncated."); |
1194 | + return; |
1195 | + } |
1196 | + datatype = sucknetword(c); |
1197 | + class = sucknetword(c); |
1198 | + ttl = sucknetlong(c); |
1199 | + rdatalength = sucknetword(c); |
1200 | + if (class != qclass) { |
1201 | + snprintf(tempstring, sizeof(tempstring), "query class: %u (%s)",qclass,qclass < ClasstypeCount ? |
1202 | + classtypes[qclass] : classtypes[ClasstypeCount]); |
1203 | + restell(tempstring); |
1204 | + snprintf(tempstring, sizeof(tempstring), "rr class: %u (%s)",class,class < ClasstypeCount ? |
1205 | + classtypes[class] : classtypes[ClasstypeCount]); |
1206 | + restell(tempstring); |
1207 | + restell("Resolver error: Answered class does not match queried class."); |
1208 | + return; |
1209 | + } |
1210 | + if (!rdatalength) { |
1211 | + restell("Resolver error: Zero size rdata."); |
1212 | + return; |
1213 | + } |
1214 | + if (c + rdatalength > eob) { |
1215 | + restell("Resolver error: Specified rdata length exceeds packet size."); |
1216 | + return; |
1217 | + } |
1218 | + if (datatype == qdatatype || datatype == T_CNAME) { |
1219 | + if (debug) { |
1220 | + snprintf(tempstring, sizeof(tempstring), "Resolver: TTL: %s",strtdiff(sendstring,ttl)); |
1221 | + restell(tempstring); |
1222 | + } |
1223 | + if (usefulanswer) |
1224 | + switch (datatype) { |
1225 | + case T_A: |
1226 | + if (rdatalength != 4) { |
1227 | + snprintf(tempstring, sizeof(tempstring), "Resolver error: Unsupported rdata format for \"A\" type. (%u bytes)", |
1228 | + rdatalength); |
1229 | + restell(tempstring); |
1230 | + return; |
1231 | + } |
1232 | + if ( addrcmp( (void *) &(rp->ip), (void *) c, af ) == 0 ) { |
1233 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Reverse authentication failed: %s != ", |
1234 | + strlongip( &(rp->ip) )); |
1235 | + addrcpy( (void *) &alignedip, (void *) c, af ); |
1236 | + strcat(tempstring,strlongip( &alignedip )); |
1237 | + restell(tempstring); |
1238 | + res_hostipmismatch++; |
1239 | + failrp(rp); |
1240 | + } else { |
1241 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Reverse authentication complete: %s == \"%s\".", |
1242 | + strlongip( &(rp->ip) ),nonull(rp->hostname)); |
1243 | + restell(tempstring); |
1244 | + res_reversesuccess++; |
1245 | + passrp(rp,ttl); |
1246 | + return; |
1247 | + } |
1248 | + break; |
1249 | + case T_PTR: |
1250 | + case T_CNAME: |
1251 | + *namestring = '\0'; |
1252 | + r = dn_expand(s,s + l,c,namestring,MAXDNAME); |
1253 | + if (r == -1) { |
1254 | + restell("Resolver error: dn_expand() failed while expanding domain in rdata."); |
1255 | + return; |
1256 | + } |
1257 | + if (debug) { |
1258 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Answered domain: \"%s\"",namestring); |
1259 | + restell(tempstring); |
1260 | + } |
1261 | + if (r > HostnameLength) { |
1262 | + restell("Resolver error: Domain name too long."); |
1263 | + failrp(rp); |
1264 | + return; |
1265 | + } |
1266 | + if (datatype == T_CNAME) { |
1267 | + strcpy(stackstring,namestring); |
1268 | + break; |
1269 | + } |
1270 | + if (!rp->hostname) { |
1271 | + rp->hostname = (char *)statmalloc(strlen(namestring) + 1); |
1272 | + if (!rp->hostname) { |
1273 | + fprintf(stderr,"statmalloc() error: %s\n",strerror(errno)); |
1274 | + exit(-1); |
1275 | + } |
1276 | + strcpy(rp->hostname,namestring); |
1277 | + linkresolvehost(rp); |
1278 | + passrp(rp,ttl); |
1279 | + res_iplookupsuccess++; |
1280 | + } |
1281 | + break; |
1282 | + default: |
1283 | + snprintf(tempstring, sizeof(tempstring), "Resolver error: Received unimplemented data type: %u (%s)", |
1284 | + datatype,datatype < ResourcetypeCount ? |
1285 | + resourcetypes[datatype] : resourcetypes[ResourcetypeCount]); |
1286 | + restell(tempstring); |
1287 | + } |
1288 | + } else { |
1289 | + if (debug) { |
1290 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Ignoring resource type %u. (%s)", |
1291 | + datatype,datatype < ResourcetypeCount ? |
1292 | + resourcetypes[datatype] : resourcetypes[ResourcetypeCount]); |
1293 | + restell(tempstring); |
1294 | + } |
1295 | + } |
1296 | + c+= rdatalength; |
1297 | + } |
1298 | + } else |
1299 | + restell("Resolver error: No error returned but no answers given."); |
1300 | + break; |
1301 | + case NXDOMAIN: |
1302 | + if (debug) |
1303 | + restell("Resolver: Host not found."); |
1304 | + res_nxdomain++; |
1305 | + failrp(rp); |
1306 | + break; |
1307 | + default: |
1308 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Received error response %u. (%s)", |
1309 | + getheader_rcode(hp),getheader_rcode(hp) < ResponsecodeCount ? |
1310 | + responsecodes[getheader_rcode(hp)] : responsecodes[ResponsecodeCount]); |
1311 | + restell(tempstring); |
1312 | + res_nserror++; |
1313 | + } |
1314 | +} |
1315 | + |
1316 | + |
1317 | +void dns_ack(void) |
1318 | +{ |
1319 | + int r,i; |
1320 | + |
1321 | + r = recvfrom(resfd,(byte *)resrecvbuf,MaxPacketsize,0, |
1322 | + from, &fromlen); |
1323 | + if (r > 0) { |
1324 | + /* Check to see if this server is actually one we sent to */ |
1325 | + if ( addrcmp( (void *) &(from4->sin_addr), (void *) &localhost, |
1326 | + (int) AF_INET ) == 0 ) { |
1327 | + for (i = 0;i < myres.nscount;i++) |
1328 | + if ( addrcmp( (void *) &(myres.nsaddr_list[i].sin_addr), |
1329 | + (void *) &(from4->sin_addr), (int) AF_INET ) == 0 || |
1330 | + addrcmp( (void *) &(myres.nsaddr_list[i].sin_addr), |
1331 | + (void *) &unspec_addr, (int) AF_INET ) == 0 ) /* 0.0.0.0 replies as 127.0.0.1 */ |
1332 | + break; |
1333 | + } else |
1334 | + for (i = 0;i < myres.nscount;i++) |
1335 | + if ( addrcmp( (void *) &(myres.nsaddr_list[i].sin_addr), |
1336 | + (void *) &(from4->sin_addr), AF_INET ) == 0 ) |
1337 | + break; |
1338 | + if (i == myres.nscount) { |
1339 | + snprintf(tempstring, sizeof(tempstring), "Resolver error: Received reply from unknown source: %s", |
1340 | + inet_ntoa(from4->sin_addr )); |
1341 | + restell(tempstring); |
1342 | + } else |
1343 | + parserespacket((byte *)resrecvbuf,r); |
1344 | + } else { |
1345 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Socket error: %s",strerror(errno)); |
1346 | + restell(tempstring); |
1347 | + } |
1348 | +} |
1349 | +#ifdef ENABLE_IPV6 |
1350 | +void dns_ack6(void) |
1351 | +{ |
1352 | + int r,i; |
1353 | + static char addrstr[INET6_ADDRSTRLEN]; |
1354 | + |
1355 | + r = recvfrom(resfd6,(byte *)resrecvbuf,MaxPacketsize,0, |
1356 | + from, &fromlen); |
1357 | + if (r > 0) { |
1358 | + /* Check to see if this server is actually one we sent to */ |
1359 | + if ( addrcmp( (void *) &(from6->sin6_addr), (void *) &localhost6, |
1360 | + (int) AF_INET6 ) == 0 ) { |
1361 | + for (i = 0;i < NSCOUNT6;i++) { |
1362 | + if (!NSSOCKADDR6(i)) |
1363 | + continue; |
1364 | + |
1365 | + if ( addrcmp( (void *) &(NSSOCKADDR6(i)->sin6_addr), |
1366 | + (void *) &(from6->sin6_addr), (int) AF_INET6 ) == 0 || |
1367 | + addrcmp( (void *) &(NSSOCKADDR6(i)->sin6_addr), |
1368 | + (void *) &unspec_addr, (int) AF_INET6 ) == 0 ) /* 0.0.0.0 replies as 127.0.0.1 */ |
1369 | + break; |
1370 | + } |
1371 | + } else |
1372 | + for (i = 0;i < NSCOUNT6;i++) { |
1373 | + if (!NSSOCKADDR6(i)) |
1374 | + continue; |
1375 | + if ( addrcmp( (void *) &(NSSOCKADDR6(i)->sin6_addr), |
1376 | + (void *) &(from6->sin6_addr), AF_INET6 ) == 0 ) |
1377 | + break; |
1378 | + } |
1379 | + if (i == NSCOUNT6) { |
1380 | + snprintf(tempstring, sizeof(tempstring), |
1381 | + "Resolver error: Received reply from unknown source: %s", |
1382 | + inet_ntop( AF_INET6, &(from6->sin6_addr), addrstr, |
1383 | + sizeof addrstr )); |
1384 | + restell(tempstring); |
1385 | + } else |
1386 | + parserespacket((byte *)resrecvbuf,r); |
1387 | + } else { |
1388 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Socket error: %s",strerror(errno)); |
1389 | + restell(tempstring); |
1390 | + } |
1391 | +} |
1392 | +#endif |
1393 | + |
1394 | + |
1395 | +int istime(double x,double *sinterval) |
1396 | +{ |
1397 | + if (x) { |
1398 | + if (x > sweeptime) { |
1399 | + if (*sinterval > x - sweeptime) |
1400 | + *sinterval = x - sweeptime; |
1401 | + } else |
1402 | + return 1; |
1403 | + } |
1404 | + return 0; |
1405 | +} |
1406 | + |
1407 | + |
1408 | +void dns_events(double *sinterval) |
1409 | +{ |
1410 | + struct resolve *rp,*nextrp; |
1411 | + |
1412 | + for (rp = expireresolves;(rp) && (sweeptime >= rp->expiretime);rp = nextrp) { |
1413 | + nextrp = rp->next; |
1414 | + switch (rp->state) { |
1415 | + case STATE_FINISHED: /* TTL has expired */ |
1416 | + case STATE_FAILED: /* Fake TTL has expired */ |
1417 | + if (debug) { |
1418 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Cache record for \"%s\" (%s) has expired. (state: %u) Marked for expire at: %g, time: %g.", |
1419 | + nonull(rp->hostname), strlongip( &(rp->ip) ), |
1420 | + rp->state, rp->expiretime, sweeptime); |
1421 | + restell(tempstring); |
1422 | + } |
1423 | + unlinkresolve(rp); |
1424 | + break; |
1425 | + case STATE_PTRREQ1: /* First T_PTR send timed out */ |
1426 | + resendrequest(rp,T_PTR); |
1427 | + restell("Resolver: Send #2 for \"PTR\" query..."); |
1428 | + rp->state++; |
1429 | + rp->expiretime = sweeptime + ResRetryDelay2; |
1430 | + (void)istime(rp->expiretime,sinterval); |
1431 | + res_resend++; |
1432 | + break; |
1433 | + case STATE_PTRREQ2: /* Second T_PTR send timed out */ |
1434 | + resendrequest(rp,T_PTR); |
1435 | + restell("Resolver: Send #3 for \"PTR\" query..."); |
1436 | + rp->state++; |
1437 | + rp->expiretime = sweeptime + ResRetryDelay3; |
1438 | + (void)istime(rp->expiretime,sinterval); |
1439 | + res_resend++; |
1440 | + break; |
1441 | + case STATE_PTRREQ3: /* Third T_PTR timed out */ |
1442 | + restell("Resolver: \"PTR\" query timed out."); |
1443 | + failrp(rp); |
1444 | + (void)istime(rp->expiretime,sinterval); |
1445 | + res_timeout++; |
1446 | + break; |
1447 | + } |
1448 | + } |
1449 | + if (expireresolves) |
1450 | + (void)istime(expireresolves->expiretime,sinterval); |
1451 | +} |
1452 | + |
1453 | + |
1454 | +char *dns_lookup2(ip_t * ip) |
1455 | +{ |
1456 | + struct resolve *rp; |
1457 | + |
1458 | + if ((rp = findip(ip))) { |
1459 | + if ((rp->state == STATE_FINISHED) || (rp->state == STATE_FAILED)) { |
1460 | + if ((rp->state == STATE_FINISHED) && (rp->hostname)) { |
1461 | + if (debug) { |
1462 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Used cached record: %s == \"%s\".\n", |
1463 | + strlongip(ip),rp->hostname); |
1464 | + restell(tempstring); |
1465 | + } |
1466 | + return rp->hostname; |
1467 | + } else { |
1468 | + if (debug) { |
1469 | + snprintf(tempstring, sizeof(tempstring), "Resolver: Used failed record: %s == ???\n", |
1470 | + strlongip(ip)); |
1471 | + restell(tempstring); |
1472 | + } |
1473 | + return NULL; |
1474 | + } |
1475 | + } |
1476 | + return NULL; |
1477 | + } |
1478 | + if (debug) |
1479 | + fprintf(stderr,"Resolver: Added to new record.\n"); |
1480 | + rp = allocresolve(); |
1481 | + rp->state = STATE_PTRREQ1; |
1482 | + rp->expiretime = sweeptime + ResRetryDelay1; |
1483 | + addrcpy( (void *) &(rp->ip), (void *) ip, af ); |
1484 | + linkresolve(rp); |
1485 | + addrcpy( (void *) &(rp->ip), (void *) ip, af ); |
1486 | + linkresolveip(rp); |
1487 | + sendrequest(rp,T_PTR); |
1488 | + return NULL; |
1489 | +} |
1490 | + |
1491 | + |
1492 | +char *dns_lookup(ip_t * ip) |
1493 | +{ |
1494 | + char *t; |
1495 | + |
1496 | + if (!dns) return NULL; |
1497 | + t = dns_lookup2(ip); |
1498 | + return (t && use_dns) ? t : NULL; |
1499 | +} |
1500 | + |
1501 | +#ifdef ENABLE_IPV6 |
1502 | +/* Returns an ip6.arpa character string. */ |
1503 | +void addr2ip6arpa( ip_t * ip, char * buf ) { |
1504 | + unsigned char * p = (unsigned char *) ip; |
1505 | + char * b = buf; |
1506 | + int i; |
1507 | + |
1508 | + for ( i = sizeof (struct in6_addr) - 1; i >= 0; i-- ) { |
1509 | + sprintf( b, "%x.%x.", p[i] % 16, p[i] >> 4 ); |
1510 | + b += 4; |
1511 | + } |
1512 | + sprintf( b, "ip6.arpa" ); |
1513 | + return; |
1514 | +} |
1515 | +#endif |
1516 | + |
1517 | +/* Resolve an IP address to a hostname. */ |
1518 | +struct hostent *addr2host( const char *addr, int af ) { |
1519 | + int len = 0; |
1520 | + switch ( af ) { |
1521 | + case AF_INET: |
1522 | + len = sizeof( struct in_addr ); |
1523 | + break; |
1524 | +#ifdef ENABLE_IPV6 |
1525 | + case AF_INET6: |
1526 | + len = sizeof( struct in6_addr ); |
1527 | + break; |
1528 | +#endif |
1529 | + } |
1530 | + return gethostbyaddr( addr, len, af ); |
1531 | +} |
1532 | |
1533 | === added file '.pc/applied-patches' |
1534 | --- .pc/applied-patches 1970-01-01 00:00:00 +0000 |
1535 | +++ .pc/applied-patches 2014-08-15 07:33:32 +0000 |
1536 | @@ -0,0 +1,1 @@ |
1537 | +0001-fix-only-ipv6-nameservers.patch |
1538 | |
1539 | === modified file 'debian/changelog' |
1540 | --- debian/changelog 2013-07-24 19:53:47 +0000 |
1541 | +++ debian/changelog 2014-08-15 07:33:32 +0000 |
1542 | @@ -1,3 +1,16 @@ |
1543 | +mtr (0.85-4ubuntu1) unstable; urgency=medium |
1544 | + |
1545 | + * Use NSCOUNT6 like what's used elsewhere. |
1546 | + |
1547 | + -- Haw Loeung (hloeung) <haw.loeung@canonical.com> Fri, 15 Aug 2014 17:32:17 +1000 |
1548 | + |
1549 | +mtr (0.85-4) unstable; urgency=medium |
1550 | + |
1551 | + * Added patch to include count of IPv6 nameservers fixing |
1552 | + LP:#752583. |
1553 | + |
1554 | + -- Haw Loeung (hloeung) <haw.loeung@canonical.com> Fri, 15 Aug 2014 12:37:12 +1000 |
1555 | + |
1556 | mtr (0.85-2) unstable; urgency=low |
1557 | |
1558 | * Added patch by Hideki Yamane to use autoreconf instead of |
1559 | |
1560 | === added directory 'debian/patches' |
1561 | === added file 'debian/patches/0001-fix-only-ipv6-nameservers.patch' |
1562 | --- debian/patches/0001-fix-only-ipv6-nameservers.patch 1970-01-01 00:00:00 +0000 |
1563 | +++ debian/patches/0001-fix-only-ipv6-nameservers.patch 2014-08-15 07:33:32 +0000 |
1564 | @@ -0,0 +1,23 @@ |
1565 | +Index: mtr/dns.c |
1566 | +=================================================================== |
1567 | +--- mtr.orig/dns.c |
1568 | ++++ mtr/dns.c |
1569 | +@@ -510,11 +510,16 @@ int dns_waitfd6(void) |
1570 | + |
1571 | + void dns_open(void) |
1572 | + { |
1573 | +- int option,i; |
1574 | ++ int option,i,nscount; |
1575 | + |
1576 | + if (!dns) return; |
1577 | + MY_RES_INIT(); |
1578 | +- if (!myres.nscount) { |
1579 | ++#ifdef ENABLE_IPV6 |
1580 | ++ nscount = myres.nscount + NSCOUNT6; |
1581 | ++#else |
1582 | ++ nscount = myres.nscount; |
1583 | ++#endif |
1584 | ++ if (!nscount) { |
1585 | + fprintf(stderr,"No nameservers defined.\n"); |
1586 | + exit(-1); |
1587 | + } |
1588 | |
1589 | === added file 'debian/patches/series' |
1590 | --- debian/patches/series 1970-01-01 00:00:00 +0000 |
1591 | +++ debian/patches/series 2014-08-15 07:33:32 +0000 |
1592 | @@ -0,0 +1,1 @@ |
1593 | +0001-fix-only-ipv6-nameservers.patch |