Merge lp:~hloeung/ubuntu/utopic/mtr/fix-ipv6-nameservers into lp:ubuntu/utopic/mtr

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
Reviewer Review Type Date Requested Status
Ubuntu Development Team Pending
Review via email: mp+230920@code.launchpad.net

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].

[1]https://github.com/traviscross/mtr/pull/56

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

Subscribers

People subscribed via source and target branches

to all changes: