home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1994 March / Source_Code_CD-ROM_Walnut_Creek_March_1994.iso / compsrcs / misc / volume40 / dnswalk / patch01 < prev    next >
Encoding:
Text File  |  1993-11-13  |  37.1 KB  |  971 lines

  1. Newsgroups: comp.sources.misc
  2. From: barr@pop.psu.edu (David Barr)
  3. Subject: v40i129:  dnswalk - A DNS Debugger, Patch01
  4. Message-ID: <1993Nov14.031012.1218@sparky.sterling.com>
  5. X-Md4-Signature: 4decc66c358b3cb822e28ddda4959ef5
  6. Sender: kent@sparky.sterling.com (Kent Landfield)
  7. Organization: Sterling Software
  8. Date: Sun, 14 Nov 1993 03:10:12 GMT
  9. Approved: kent@sparky.sterling.com
  10.  
  11. Submitted-by: barr@pop.psu.edu (David Barr)
  12. Posting-number: Volume 40, Issue 129
  13. Archive-name: dnswalk/patch01
  14. Environment: Perl, Dig, DNS
  15. Patch-To: dnswalk: Volume 39, Issue 45
  16.  
  17. The following patch brings dnswalk 1.6 to version 1.7.  Note
  18. that a new file is created, 'dnswalk.1'.
  19.  
  20. *** dnswalk.1.6/CHANGES    Wed Nov 10 16:16:45 1993
  21. --- CHANGES    Sat Oct 30 15:19:49 1993
  22. ***************
  23. *** 1,5 ****
  24. ! $Id: CHANGES,v 1.2 1993/07/21 14:38:47 barr Exp barr $
  25.   
  26.   Version 1.6
  27.   removed -c switch, since I thought it would work a long time ago, but
  28.   later found out it could never be made to work.  Well, it could, just
  29. --- 1,23 ----
  30. ! $Id: CHANGES,v 1.3 1993/10/15 22:02:28 barr Exp barr $
  31. ! Version 1.7
  32. ! Added "_" to list of invalid characters in a hostname.  (Painful
  33. ! because we have hundreds of PCs and Macs here with one.)  Can
  34. ! now be supressed with '-i' option (whew).
  35.   
  36. + Fixed wildcard RR's being marked as having invalid characters.
  37. + (Thanks to Paul Turner <turner@telstar.kodak.com> for reporting it)
  38. + Changed how the return codes for gethostby*() routines were being
  39. + checked.  Added caveat in README about herror().  Thanks to Bill Fenner
  40. + Suppresses duplicate error message per zone.  Idea from Paul Turner.
  41. + Checks for dom.ain.dom.ain. in data, in case someone forgot the
  42. + trailing '.'.
  43. + Finally added a man page.  Trimmed out redundant information
  44. + from the README file.
  45.   Version 1.6
  46.   removed -c switch, since I thought it would work a long time ago, but
  47.   later found out it could never be made to work.  Well, it could, just
  48. *** dnswalk.1.6/TODO    Wed Nov 10 16:16:46 1993
  49. --- TODO    Wed Nov 10 16:18:17 1993
  50. ***************
  51. *** 3,6 ****
  52.   
  53.   Better error checking so it doesn't create a foo/bar/baz directory
  54.   when the baz/bar/foo domain doesn't exist.
  55. --- 3,5 ----
  56. *** dnswalk.1.6/TIPS    Wed Nov 10 16:16:46 1993
  57. --- TIPS    Sat Oct 30 20:37:46 1993
  58. ***************
  59. *** 3,29 ****
  60.   
  61.   * Every Internet host should have a name.  Enough said.
  62.   
  63.   * You shouldn't have any A records in an in-addr.arpa zone file.
  64.     This includes NS glue records.  Just put the nameserver name in
  65.     there and be done with it.  Why?  It's unnecessary, and just makes
  66.     things harder when that nameserver changes its IP address.  You'll
  67.     spend hours trying to figure out why random people still see the old
  68. !   address for some machine.
  69.   
  70.   * Verify the data you just entered or changed by querying the
  71.     resolver with 'dig' (or your favorite DNS tool) after a change.  A
  72.     few seconds spent double checking can save hours of trouble, lost
  73. !   mail, and headaches.
  74.   
  75.   * Don't forget to change the serial number.  Also, even though BIND
  76. ! allows you to use a decimal in a serial number, don't use them.  If you
  77. ! want to know why, read "DNS & BIND" (see below).
  78.   
  79.   * Always remember your $ORIGIN.  If you don't put a '.' at the end
  80.     of an FQDN, it's not an FQDN.  Double check, triple check, those dots.
  81.   
  82.   * BE CONSISTENT!  If your $ORIGIN is "foo.org.", don't have entries
  83. ! like:
  84.   
  85.   tron        in    a    1.2.3.1
  86.   mcp.foo.org.    in    a    1.2.3.2
  87. --- 3,35 ----
  88.   
  89.   * Every Internet host should have a name.  Enough said.
  90.   
  91. + * Allowable characters in a name are ONLY letters, digits, and
  92. +   the '-' character (separated by '.' of course).  Domain names
  93. +   may not be all numbers, but may have a leading digit.  (e.g. 3com.com)
  94. +   (See RFC 1035 and 1123)
  95.   * You shouldn't have any A records in an in-addr.arpa zone file.
  96.     This includes NS glue records.  Just put the nameserver name in
  97.     there and be done with it.  Why?  It's unnecessary, and just makes
  98.     things harder when that nameserver changes its IP address.  You'll
  99.     spend hours trying to figure out why random people still see the old
  100. !   address for some machine.  BIND 4.9.x handles this better, however.
  101.   
  102.   * Verify the data you just entered or changed by querying the
  103.     resolver with 'dig' (or your favorite DNS tool) after a change.  A
  104.     few seconds spent double checking can save hours of trouble, lost
  105. !   mail, and headaches.  Also be sure to check syslog output when you
  106. !   reload the nameserver.
  107.   
  108.   * Don't forget to change the serial number.  Also, even though BIND
  109. !   allows you to use a decimal in a serial number, don't use them.  If you
  110. !   want to know why, read "DNS & BIND" (see below).
  111.   
  112.   * Always remember your $ORIGIN.  If you don't put a '.' at the end
  113.     of an FQDN, it's not an FQDN.  Double check, triple check, those dots.
  114.   
  115.   * BE CONSISTENT!  If your $ORIGIN is "foo.org.", don't have entries
  116. !   like:
  117.   
  118.   tron        in    a    1.2.3.1
  119.   mcp.foo.org.    in    a    1.2.3.2
  120. ***************
  121. *** 73,84 ****
  122.   
  123.   * Wildcard MX's are only useful for non IP-connected sites.  If
  124.     a site has any records, a wildcard MX won't apply to it.
  125.   e.g.
  126.   *.podunk.edu    in    mx    mail.podunk.edu.
  127.   mary.podunk.edu    in    A    1.2.3.4
  128.   
  129.     Mail for "mary.podunk.edu" will be sent to mary, while mail for
  130. !   "jane.podunk.edu" will be sent to mail.podunk.edu.
  131.   
  132.   * Don't go overboard with CNAMEs.  Use them when moving/renaming machines,
  133.     but plan to get rid of them.  (And inform your users)
  134. --- 79,91 ----
  135.   
  136.   * Wildcard MX's are only useful for non IP-connected sites.  If
  137.     a site has any records, a wildcard MX won't apply to it.
  138.   e.g.
  139.   *.podunk.edu    in    mx    mail.podunk.edu.
  140.   mary.podunk.edu    in    A    1.2.3.4
  141.   
  142.     Mail for "mary.podunk.edu" will be sent to mary, while mail for
  143. !   "jane.podunk.edu" will be sent to mail.podunk.edu.  Really.
  144.   
  145.   * Don't go overboard with CNAMEs.  Use them when moving/renaming machines,
  146.     but plan to get rid of them.  (And inform your users)
  147. *** dnswalk.1.6/README    Wed Nov 10 16:16:46 1993
  148. --- README    Wed Nov 10 16:09:29 1993
  149. ***************
  150. *** 1,7 ****
  151. !         dnswalk 1.6 - July 1993
  152.   
  153.   Author: David Barr <barr@pop.psu.edu>
  154. ! $Id: README,v 1.1 1993/07/21 14:39:25 barr Exp barr $
  155.   
  156.   INTRO
  157.   
  158. --- 1,7 ----
  159. !         dnswalk 1.7 - Oct 1993
  160.   
  161.   Author: David Barr <barr@pop.psu.edu>
  162. ! $Id: README,v 1.2 1993/11/10 21:09:23 barr Exp barr $
  163.   
  164.   INTRO
  165.   
  166. ***************
  167. *** 45,60 ****
  168.   and documentation are distributed with the program.  This program is
  169.   released as-is, with no warranty expressed or implied.  Some assembly
  170.   required, contents may settle during shipment.  This program can be
  171. ! found at ftp.pop.psu.edu:/pub/src/dnswalk/dnswalk.1.6.tar.Z,
  172. ! ftp.univ-lyon1.fr:/pub/mirrors/unix/dnswalk, and probably also in
  173. ! ftp.uu.net:/networking/ip/dns.
  174.   
  175. - USAGE
  176. -     Invoke dnswalk as follows:
  177. - dnswalk [-fradm] domain [> logfile]
  178.       dnswalk tends to produce lots of output, so I'd suggest
  179.   redirecting this into a file of your choice.  I debated using doc's
  180.   strategy of automatically putting it in a logfile, but decided not
  181. --- 45,55 ----
  182.   and documentation are distributed with the program.  This program is
  183.   released as-is, with no warranty expressed or implied.  Some assembly
  184.   required, contents may settle during shipment.  This program can be
  185. ! found in:
  186. ! ftp.pop.psu.edu:/pub/src/dnswalk/
  187. ! ftp.univ-lyon1.fr:/pub/mirrors/unix/dnswalk/
  188. ! ftp.uu.net:/networking/ip/dns/dnswalk/
  189.   
  190.       dnswalk tends to produce lots of output, so I'd suggest
  191.   redirecting this into a file of your choice.  I debated using doc's
  192.   strategy of automatically putting it in a logfile, but decided not
  193. ***************
  194. *** 62,209 ****
  195.   mostly-correct domains it is pretty manageable, however.  For larger
  196.   domains, use the included 'do-dnswalk' script as a guide.
  197.   
  198. ! Options:
  199. !     -f    Force a zone transfer from an authoritative nameserver.
  200. !         dnswalk normally will look in its saved 'axfr' file
  201. !         for each domain and use that. (if it exists)
  202. !     -r    Recursively descend sub-domains of the specified
  203. !         domain.  Use with caution and care.
  204. !     -a    Turn on warning of duplicate A records.  (see below)
  205. !     -d    Some debugging.  (Use only if redirecting stdout)
  206. !     -m    Perform checks only if the zone has been modified since
  207. !         the previous run.
  208. !     -F    perform "fascist" checking.  When checking an A record,
  209. !         compare the PTR name for each IP address with the forward
  210. !         name and report mismatches.  (see below)  I recommend
  211. !         you try this option at least once to see what sorts of
  212. !         errors pop up - you might be surprised!.
  213. !     -l    Perform "lame delegation" checking.  For every NS record,
  214. !         check to see that the listed host is indeed returning
  215. !         authoritative answers for this domain.  Inspiration for
  216. !         this comes from the guys at the Univ. of Michigan.
  217. ! The domain name specified on the command line MUST end with a '.'.
  218. ! You can specify a forward domain, such as "dnswalk pop.psu.edu."
  219. ! or a reverse domain, such as "dnswalk 155.118.128.in-addr.arpa."
  220. ! What dnswalk will do is if it is checking "pop.psu.edu.", it will
  221. ! do a zone transfer of the data from the authoritative nameserver and
  222. ! put it in the file "edu/psu/pop/axfr".  (relative to the current directory)
  223. ! If dnswalk is run again, it will use this file instead of asking the
  224. ! nameserver again.  You can override this with the '-f' switch.  It
  225. ! will also do a zone transfer again later if the serial number in the
  226. ! file is less than what is returned from the server.
  227. ! As a result, if you use the recursive option, you will get a directory
  228. ! tree corresponding exactly to the DNS hierarchy.  Again, I must stress
  229. ! that you use the recursive option with care, and the author calls you
  230. ! a slime-ball again if you use this for evil purposes.
  231. ! WHAT DNSWALK CHECKS FOR..
  232. ! *  all PTR records that look like a full IP address point back to a
  233. ! forward name.  In other words, "3.155.118.128.in-addr.arpa."
  234. ! will be checked, but "155.118.128.in-addr.arpa." will NOT be checked.
  235. ! (For those people who give their subnets a name)  Addresses ending
  236. ! in .0 are also NOT checked.
  237. ! [ reports error as "X PTR Y: unknown host" ]
  238. ! *  PTR records are listed as IP addresses in forward name.  In other
  239. ! words if 4.3.2.1.in-addr.arpa. points to "foo.org", but "foo.org"
  240. ! doesn't have "1.2.3.4" listed in its forward A records then it will
  241. !  be an error.
  242. ! [ reports error as "X PTR Y: forward matching A record not found" ]
  243. ! *  PTR records do not point to a CNAME.
  244. ! [ reports error as "X PTR Y: CNAME (to Z)" ]
  245. ! *  CNAMEs point to a host with an A record.
  246. ! [ reports error as "X CNAME Y: unknown host" ]
  247. ! *  CNAMEs do not point to another CNAME.
  248. ! [ reports error as "X CNAME Y: CNAME (to Z)" ]
  249. ! *  MXs point to a host with an A record.
  250. ! [ reports error as "X MX Y: unknown host" ]
  251. ! *  MXs do not point to a CNAME.
  252. ! [ reports error as "X MX Y: CNAME (to Z)" ]
  253. ! *  A records have some corresponding PTR record.  (Not necessarily
  254. ! of the same name, of course)
  255. ! [ reports error as "X A Y: no PTR record" ]
  256. ! *  Reports any packet size errors listed in dig zone transfer output
  257. ! (Could be caused by a corrupted zone file, or invalid syntax used)
  258. ! *  That there is more than one authoritative nameserver for a zone.
  259. ! It does not check if the machine is on a separate network (yet).
  260. ! A site should ALWAYS have a secondary nameserver.  It SHOULD be
  261. ! on a different network than the primary.
  262. ! (with -a switch)
  263. ! *  duplicate A records listed for a given host.  NOTE: this is most
  264. ! often caused by the practice of always putting A records for all
  265. ! secondaries after NS glue records.  While this is not an error, it is
  266. ! usually redundant and makes changing IP addresses later more difficult,
  267. ! since they occur more than one time in the file (and in multiple
  268. ! files).  This checking needs more work.  (Mostly because of a quirk in
  269. ! BIND that reports cached A records in a zone transfer even though they
  270. ! don't exist in the original zone file.  I might just end up skipping this
  271. ! check altogether.)
  272. ! [ reports error as "X: possible duplicate A record (glue of Z?)" 
  273. ! where Z is the previous zone listed in the file ]
  274. ! (with -F switch)
  275. ! * perform "fascist" checking.  When checking an A record, compare the PTR
  276. !   name for each IP address with the forward name.  This WILL result in
  277. !   needless errors (like if you have an A record for your domain name
  278. !   pointing to your main server, or have A records like "mailhost" or
  279. !   "ns" defined to point to your mail or DNS server) but will catch little
  280. !   errors that may have crept in if you have an A record pointing to a host
  281. !   that you didn't intend to.
  282. ! [ reports error as "X A Y: points to Z" where Z is the "canonical" name
  283. !   as returned by gethostbyaddr() ]
  284. ! (with -l switch)
  285. ! * Lame delegations.  A lame delegation is when a domain says "this
  286. ! server is a secondary for zone Z" but the listed server is not giving
  287. ! out authoritative data for zone Z.  This is usually the result of
  288. ! a lack of communication on the part of the respective hostmasters.
  289. ! Lame delegations are not fatal problems, they just tend to create
  290. ! significant increases in DNS traffic.
  291. ! [ reports error as "X NS Y: lame NS delegation" where X is the domain,
  292. ! and Y is the lame nameserver ]
  293. ! * Nameserver errors.  Any errors while contacting other nameservers
  294. ! (like connection refused or timeout) will be reported.  This could
  295. ! mean a lame delegation, or simply that the host is temporarily
  296. ! unreachable.
  297. ! [ reports error as "X NS Y: nameserver error (lame?)" followed by the
  298. ! error message from dig]
  299.   
  300.   *** NOTICE ***
  301. !     I fully realize that while some of the above rules are not
  302. ! in violation of an RFC, it might be wise to reconsider their usage anyway.
  303. ! dnswalk was written to be a tool to let the hostmaster decide what are 
  304. ! troublesome areas, not as a program that has all the answers.
  305.   *** NOTICE ***
  306.   
  307. - CAVEATS
  308. -     If a domain "foo.edu" lists "ns.bar.foo.edu" as authoritative for
  309. - a zone "bar.foo.edu", but "ns.bar.foo.edu" isn't, then the the dig of
  310. - the zone transfer will hang.  (This was the case here for a subdomain
  311. - that moved into a new set of IP addresses, but the parent nameserver still
  312. - had the old authority records pointing to their nameservers which weren't
  313. - answering to the old reverse domain anymore.)  If this happens, you can
  314. - hit ^C while the transfer is going on and dnswalk will abort that server.
  315. - (It will also remove the partial axfr file)  Hopefully I can figure a
  316. - more elegant way around this.  (or fix dig so that it doesn't hang)
  317.   This program was tested with data from the psu.edu domain.  If your
  318.   site does things differently than the way we do things, then you
  319.   may see it report things as errors, when in fact they are "okay".
  320. --- 57,77 ----
  321.   mostly-correct domains it is pretty manageable, however.  For larger
  322.   domains, use the included 'do-dnswalk' script as a guide.
  323.   
  324. ! If you use the recursive option, you will get a directory tree
  325. ! corresponding exactly to the DNS hierarchy.  I must stress that
  326. ! you use the recursive option with care, and the author calls you a
  327. ! slime-ball again if you use this for evil purposes.
  328.   
  329. + Please refer to the man page on what dnswalk checks for, and
  330. + the format of the output.
  331.   *** NOTICE ***
  332. !     I fully realize that while some of the rules are not in
  333. ! violation of an RFC, it might be wise to reconsider their usage
  334. ! anyway.  dnswalk was written to be a tool to let the hostmaster decide
  335. ! what are troublesome areas, not as a program that has all the answers.
  336.   *** NOTICE ***
  337.   
  338.   This program was tested with data from the psu.edu domain.  If your
  339.   site does things differently than the way we do things, then you
  340.   may see it report things as errors, when in fact they are "okay".
  341. ***************
  342. *** 213,248 ****
  343.   my personal feelings about what "nice" DNS databases look like.  Others
  344.   are free to differ.  (and tell me so)
  345.   
  346. ! BUGS
  347. !     I should get around to writing a real man page.
  348. !     dnswalk will make the directory tree before it has a chance to
  349. ! find out that you gave it a bogus domain name.
  350. !     When checking lots of hosts and lots of options, it is very
  351. ! slow.  Running dnswalk on a machine with a local nameserver helps
  352. ! considerably.
  353. !     Perl's gethostby{name,addr}() routine doesn't seem to
  354. ! consistently return an error whenever it is unable to resolve an
  355. ! address.  Argh.  This will mean lots of "no PTR record" and "host unknown"
  356. ! errors if a server is unavailable, or for some reason the lookup fails.
  357. !     I really need to rewrite this all to not rely on dig, and use
  358. ! bind.pl instead.
  359. ! OTHER SOURCES
  360. ! RFC 1034 - "DOMAIN NAMES - CONCEPTS AND FACILITIES"
  361. ! RFC 1035 - "DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION"
  362. ! RFC 1123 - "Requirements for Internet Hosts -- Application and Support"
  363. ! Paul Albits, Cricket Liu: "DNS and BIND" O'Reilly & Associates.
  364. ! [the author recommends copies by your favorite bathroom and/or nightstand]
  365.   David Barr - System Administrator
  366.   The Pennsylvania State University Population Research Institute
  367.   <barr@pop.psu.edu>
  368. --- 81,87 ----
  369.   my personal feelings about what "nice" DNS databases look like.  Others
  370.   are free to differ.  (and tell me so)
  371.   
  372. ! Author:
  373.   David Barr - System Administrator
  374.   The Pennsylvania State University Population Research Institute
  375.   <barr@pop.psu.edu>
  376. *** dnswalk.1.6/dnswalk    Wed Nov 10 16:16:46 1993
  377. --- dnswalk    Wed Nov 10 16:10:58 1993
  378. ***************
  379. *** 2,8 ****
  380.   # dnswalk    Walk through a DNS tree, pulling out zone data and
  381.   # dumping it in a directory tree
  382.   #
  383. ! # $Id: dnswalk,v 1.4 1993/07/18 00:46:05 barr Exp $
  384.   #
  385.   # check data collected for legality using standard resolver
  386.   #
  387. --- 2,8 ----
  388.   # dnswalk    Walk through a DNS tree, pulling out zone data and
  389.   # dumping it in a directory tree
  390.   #
  391. ! # $Id: dnswalk,v 1.6 1993/11/10 21:10:55 barr Exp barr $
  392.   #
  393.   # check data collected for legality using standard resolver
  394.   #
  395. ***************
  396. *** 19,25 ****
  397.   
  398.   require "getopts.pl";
  399.   
  400. ! do Getopts(":rfcadmFl");
  401.   
  402.   
  403.   $basedir = ".";
  404. --- 19,25 ----
  405.   
  406.   require "getopts.pl";
  407.   
  408. ! do Getopts(":rfiadmFl");
  409.   
  410.   
  411.   $basedir = ".";
  412. ***************
  413. *** 65,71 ****
  414.                   # error handling
  415.       ($path=&host2path($domain)) =~ tr/A-Z/a-z/;
  416.       local(@servers) = &getauthservers($domain);
  417. !     print "warning: $domain has only one authoratative nameserver\n" if (scalar(@servers) == 1);
  418.       if ((-f "$basedir/$path/axfr") && (!$main'opt_f)) {
  419.           open(DIG,"<$basedir/$path/axfr");
  420.           while (<DIG>) {
  421. --- 65,71 ----
  422.                   # error handling
  423.       ($path=&host2path($domain)) =~ tr/A-Z/a-z/;
  424.       local(@servers) = &getauthservers($domain);
  425. !     &printerr("warning: $domain has only one authoratative nameserver\n") if (scalar(@servers) == 1);
  426.       if ((-f "$basedir/$path/axfr") && (!$main'opt_f)) {
  427.           open(DIG,"<$basedir/$path/axfr");
  428.           while (<DIG>) {
  429. ***************
  430. *** 179,184 ****
  431. --- 179,185 ----
  432.   # here's where the fun begins
  433.   sub checkfile {
  434.       open(FILE,"<$_[0]");
  435. +     undef $errlist;
  436.       print "Checking $domain\n";
  437.       local (%glues)=();    # look for duplicate glue (A) records
  438.       local ($name, $aliases, $addrtype, $length, @addrs);
  439. ***************
  440. *** 187,192 ****
  441. --- 188,195 ----
  442.       local ($lastns);    # last NS record we saw
  443.       local (@keys);    # temp variable
  444.       $soa=undef;
  445. +     $doubledom = $domain . $domain;
  446. +     $doubledom =~ s/(\W)/\\\1/g;    # quote string so it's a regexp
  447.       while (<FILE>) {
  448.           chop;
  449.           if (/^;/) {
  450. ***************
  451. *** 197,212 ****
  452.               }
  453.           }
  454.           next if /^$/;    # skip blanks
  455.           split(/\t/);
  456.           # 0=key 2=rrtype 3=value (4=value if 2=MX)
  457.           next if ($_[0] =~ /;/);
  458. !         if ($_[0] =~ /[^-A-Za-z0-9._]/) {
  459. !         # I know, underscores aren't kosher but ....
  460. !             print " $_[0]: invalid character(s) in name\n";
  461.           }
  462.           if ($_[2] eq "SOA") {
  463.               print STDERR 's' if $opt_d;
  464. !         if (! $soa) {  # aviod duplicate SOA's.  Argh.
  465.                  ($soa,$contact) = $_[3] =~ /(\S+)\s+(\S+)/;
  466.                  print "SOA=$soa    contact=$contact\n";
  467.           }
  468. --- 200,219 ----
  469.               }
  470.           }
  471.           next if /^$/;    # skip blanks
  472. +     # check to see if there is a "foo.bar.baz.bar.baz."
  473. +     # probably a trailing-dot death.
  474. +     if (/$doubledom/) {
  475. +         &printerr("$_: domain occurred twice, forgot trailing '.'?");
  476. +     }
  477.           split(/\t/);
  478.           # 0=key 2=rrtype 3=value (4=value if 2=MX)
  479.           next if ($_[0] =~ /;/);
  480. !         if (($_[0] =~ /[^\*][^-A-Za-z0-9.]/) && (!$opt_i)) {
  481. !             &printerr(" $_[0]: invalid character(s) in name\n");
  482.           }
  483.           if ($_[2] eq "SOA") {
  484.               print STDERR 's' if $opt_d;
  485. !         if (! $soa) {  # avoid duplicate SOA's.  Argh.
  486.                  ($soa,$contact) = $_[3] =~ /(\S+)\s+(\S+)/;
  487.                  print "SOA=$soa    contact=$contact\n";
  488.           }
  489. ***************
  490. *** 217,234 ****
  491.                   # a full IP addr
  492.                   # skip ".0" networks
  493.                   if ($keys[0] ne "0") {
  494. !                     if (!(($name, $aliases, $addrtype, $length, @addrs)=gethostbyname($_[3])) && $!) {
  495. !                         print " gethostbyname($_[3]): $!\n";
  496.                       }
  497.                       else {
  498.                           if (!$name) {
  499. !                             print " $_[0] PTR $_[3]: unknown host\n";
  500.                           }
  501.                           elsif (!&equal(($name.'.'),$_[3])) {
  502. !                             print " $_[0] PTR $_[3]: CNAME (to $name)\n";
  503.                           }    
  504.                           elsif (!&matchaddrlist($_[0])) {
  505. !                             print " $_[0] PTR $_[3]: A record not found\n";
  506.                           }
  507.                       }
  508.                   }
  509. --- 224,241 ----
  510.                   # a full IP addr
  511.                   # skip ".0" networks
  512.                   if ($keys[0] ne "0") {
  513. !                     if (!(($name, $aliases, $addrtype, $length, @addrs)=gethostbyname($_[3])) && !$?) {
  514. !                         &printerr(" gethostbyname($_[3]): $!\n");
  515.                       }
  516.                       else {
  517.                           if (!$name) {
  518. !                             &printerr(" $_[0] PTR $_[3]: unknown host\n");
  519.                           }
  520.                           elsif (!&equal(($name.'.'),$_[3])) {
  521. !                             &printerr(" $_[0] PTR $_[3]: CNAME (to $name)\n");
  522.                           }    
  523.                           elsif (!&matchaddrlist($_[0])) {
  524. !                             &printerr(" $_[0] PTR $_[3]: A record not found\n");
  525.                           }
  526.                       }
  527.                   }
  528. ***************
  529. *** 236,250 ****
  530.           } elsif (($_[2] eq "A") ) {
  531.               print STDERR 'a' if $opt_d;
  532.   # check to see that a reverse PTR record exists
  533. !             if (!(($name,$aliases,$addrtype,$length,@addrs)=gethostbyaddr(pack('C4', split(/\./,$_[3])),2)) && $!) {
  534. !                 print " gethostbyaddr($_[3]): $!\n";
  535.               }
  536.               else {
  537.                   if (!$name) {
  538. !                     print " $_[0] A $_[3]: no PTR record\n";
  539.                   }
  540.                   elsif ($opt_F && !&equal($name.".",$_[0])) {
  541. !                     print " $_[0] A $_[3]: points to $name\n" if ((split(/\./,$name,1))[0] ne "localhost");
  542.                   }
  543.                   if ($main'opt_a) {
  544.                       # keep list in %glues, report any duplicates
  545. --- 243,257 ----
  546.           } elsif (($_[2] eq "A") ) {
  547.               print STDERR 'a' if $opt_d;
  548.   # check to see that a reverse PTR record exists
  549. !             if (!(($name,$aliases,$addrtype,$length,@addrs)=gethostbyaddr(pack('C4', split(/\./,$_[3])),2)) && !$?) {
  550. !                 &printerr(" gethostbyaddr($_[3]): $!\n");
  551.               }
  552.               else {
  553.                   if (!$name) {
  554. !                     &printerr(" $_[0] A $_[3]: no PTR record\n");
  555.                   }
  556.                   elsif ($opt_F && !&equal($name.".",$_[0])) {
  557. !                     &printerr(" $_[0] A $_[3]: points to $name\n") if ((split(/\./,$name,1))[0] ne "localhost");
  558.                   }
  559.                   if ($main'opt_a) {
  560.                       # keep list in %glues, report any duplicates
  561. ***************
  562. *** 252,258 ****
  563.                           $glues{$_[3]}=$_[0];
  564.                       }
  565.                       elsif (($glues{$_[3]} eq $_[0]) && (!&equal($lastns,$domain))) {
  566. !                             print " $_[0]: possible duplicate A record (glue of $lastns?)\n";
  567.                       }
  568.                   }
  569.               }
  570. --- 259,265 ----
  571.                           $glues{$_[3]}=$_[0];
  572.                       }
  573.                       elsif (($glues{$_[3]} eq $_[0]) && (!&equal($lastns,$domain))) {
  574. !                             &printerr(" $_[0]: possible duplicate A record (glue of $lastns?)\n");
  575.                       }
  576.                   }
  577.               }
  578. ***************
  579. *** 261,301 ****
  580.               print STDERR 'n' if $opt_d;
  581.               # check to see if object of NS is real
  582.               &checklamer($_[0],$_[3]) if ($main'opt_l);
  583. !             if (!(($name, $aliases, $addrtype, $length, @addrs)=gethostbyname($_[3])) && $!) {
  584. !                 print " gethostbyname($_[3]): $!\n";
  585.               }
  586.               else {
  587.                   if (!$name) {
  588. !                     print " $_[0] NS $_[3]: unknown host\n";
  589.                   } elsif (!&equal(($name.'.'),$_[3])) {
  590. !                     print " $_[0] NS $_[3]: CNAME (to $name)\n";
  591.                   }
  592.               }
  593.           } elsif ($_[2] eq "MX") {
  594.               print STDERR 'm' if $opt_d;
  595.               # check to see if object of mx is real
  596.               ($prio,$mx)=split(/ /,$_[3]);
  597. !             if (!(($name, $aliases, $addrtype, $length, @addrs)=gethostbyname($mx)) && $!) {
  598. !                 print " gethostbyname($mx): $!\n";
  599.               }
  600.               else {
  601.                   if (!$name) {
  602. !                     print " $_[0] MX $_[3]: unknown host\n";
  603.                   }
  604.                   elsif (!&equal(($name.'.'),$mx)) {
  605. !                     print " $_[0] MX $_[3]: CNAME (to $name)\n";
  606.                   }
  607.               }
  608.           } elsif ($_[2] eq "CNAME") {
  609.               print STDERR 'c' if $opt_d;
  610. !             if (!(($name, $aliases, $addrtype, $length, @addrs)=gethostbyname($_[3])) && $!) {
  611. !                 print " gethostbyname($_[3]): $!\n";
  612.               }
  613.               else {
  614.                   if (!$name) {
  615. !                     print " $_[0] CNAME $_[3]: unknown host\n";
  616.                   } elsif (!&equal(($name.'.'),$_[3])) {
  617. !                     print " $_[0] CNAME $_[3]: CNAME (to $name)\n";
  618.                   }
  619.               }
  620.           }
  621. --- 268,308 ----
  622.               print STDERR 'n' if $opt_d;
  623.               # check to see if object of NS is real
  624.               &checklamer($_[0],$_[3]) if ($main'opt_l);
  625. !             if (!(($name, $aliases, $addrtype, $length, @addrs)=gethostbyname($_[3])) && !$?) {
  626. !                 &printerr(" gethostbyname($_[3]): $!\n");
  627.               }
  628.               else {
  629.                   if (!$name) {
  630. !                     &printerr(" $_[0] NS $_[3]: unknown host\n");
  631.                   } elsif (!&equal(($name.'.'),$_[3])) {
  632. !                     &printerr(" $_[0] NS $_[3]: CNAME (to $name)\n");
  633.                   }
  634.               }
  635.           } elsif ($_[2] eq "MX") {
  636.               print STDERR 'm' if $opt_d;
  637.               # check to see if object of mx is real
  638.               ($prio,$mx)=split(/ /,$_[3]);
  639. !             if (!(($name, $aliases, $addrtype, $length, @addrs)=gethostbyname($mx)) && !$?) {
  640. !                 &printerr(" gethostbyname($mx): $!\n");
  641.               }
  642.               else {
  643.                   if (!$name) {
  644. !                     &printerr(" $_[0] MX $_[3]: unknown host\n");
  645.                   }
  646.                   elsif (!&equal(($name.'.'),$mx)) {
  647. !                     &printerr(" $_[0] MX $_[3]: CNAME (to $name)\n");
  648.                   }
  649.               }
  650.           } elsif ($_[2] eq "CNAME") {
  651.               print STDERR 'c' if $opt_d;
  652. !             if (!(($name, $aliases, $addrtype, $length, @addrs)=gethostbyname($_[3])) && !$?) {
  653. !                 &printerr(" gethostbyname($_[3]): $!\n");
  654.               }
  655.               else {
  656.                   if (!$name) {
  657. !                     &printerr(" $_[0] CNAME $_[3]: unknown host\n");
  658.                   } elsif (!&equal(($name.'.'),$_[3])) {
  659. !                     &printerr(" $_[0] CNAME $_[3]: CNAME (to $name)\n");
  660.                   }
  661.               }
  662.           }
  663. ***************
  664. *** 303,308 ****
  665. --- 310,327 ----
  666.       print STDERR "\n" if $opt_d;
  667.       close(FILE);
  668.   }
  669. + # prints an error message, suppressing duplicates
  670. + sub printerr {
  671. +     local ($err)=$_[0];
  672. +     if ($errlist{$err}==undef) {
  673. +     print $err;
  674. +     print STDERR "!" if $opt_d;
  675. +     $errlist{$err}=1;
  676. +     } else {
  677. +     print STDERR "." if $opt_d;
  678. +     }
  679. + }
  680.   
  681.   sub equal {
  682.       # Do case-insensitive string comparisons
  683. *** /dev/null    Wed Nov 10 16:08:44 1993
  684. --- dnswalk.1    Wed Nov 10 16:12:33 1993
  685. ***************
  686. *** 0 ****
  687. --- 1,230 ----
  688. + .TH DNSWALK 1
  689. + .SH NAME
  690. + dnswalk \- A DNS database debugger
  691. + .SH SYNOPSIS
  692. + .B dnswalk
  693. + [
  694. + .BR \- adilrfFm
  695. + ]
  696. + .I domain.
  697. + .SH "DESCRIPTION"
  698. + .B dnswalk
  699. + is a DNS debugger.  It performs zone transfers of specified domains,
  700. + and checks the database in numerous ways for internal consistency, as
  701. + well as for correctness according to accepted practices with the Domain
  702. + Name System.
  703. + .PP
  704. + The
  705. + .I domain
  706. + name specified on the command line MUST end with a '.'.
  707. + You can specify a forward domain, such as
  708. + .B dnswalk pop.psu.edu.
  709. + or a reverse domain, such as
  710. + .B dnswalk 155.118.128.in-addr.arpa.
  711. + .SH OPTIONS
  712. + .PD 0
  713. + .TP
  714. + .BI \-f
  715. + Force a zone transfer from an authoritative nameserver.
  716. + dnswalk normally will look in its saved 'axfr' file
  717. + for each domain and use that. (if it exists, and the serial
  718. + number has not increased)
  719. + .TP
  720. + .BI \-r
  721. + Recursively descend sub-domains of the specified
  722. + domain.  Use with care.
  723. + .TP
  724. + .BI \-a
  725. + Turn on warning of duplicate A records.  (see below)
  726. + .TP
  727. + .BI \-d
  728. + Print debugging and 'status' information to stderr.
  729. + (Use only if redirecting stdout)  See DIAGNOSTICS section.
  730. + .TP
  731. + .BI \-m
  732. + Perform checks only if the zone has been modified since the previous run.
  733. + .TP
  734. + .BI \-F
  735. + perform "fascist" checking.  When checking an A record,
  736. + compare the PTR name for each IP address with the forward
  737. + name and report mismatches.  (see below)  I recommend
  738. + you try this option at least once to see what sorts of
  739. + errors pop up - you might be surprised!.
  740. + .TP
  741. + .BI \-i
  742. + Supress check for invalid characters in a domain name.  (see below)
  743. + .TP
  744. + .BI \-l
  745. + Perform "lame delegation" checking.  For every NS record,
  746. + check to see that the listed host is indeed returning
  747. + authoritative answers for this domain.
  748. + .SH ERRORS
  749. + The following the list of error messages that dnswalk will return
  750. + if it sees a potential problem with the database.  Duplicate messages
  751. + will be suppressed automatically for each zone.
  752. + .TP
  753. + .PD 0
  754. + .BI "X PTR Y: unknown host"
  755. + X is a PTR record to Y, but Y is not a valid host (no A record).
  756. + .TP
  757. + .BI "X PTR Y: forward matching A record not found"
  758. + X is a PTR record to Y, but the IP address associated with the PTR
  759. + record is not listed as an address for Y.  There should be an A
  760. + record for every valid IP adddress for a host.
  761. + .TP
  762. + .BI "X PTR Y: CNAME (to Z)"
  763. + X is a PTR record to Y, but Y is a CNAME to Z.  PTR records MUST point
  764. + to the canonical name of a host, not an alias.
  765. + .TP
  766. + .BI "X CNAME Y: unknown host"
  767. + X is aliased to Y, but Y is not a valid host (no A record).
  768. + .TP
  769. + .BI "X CNAME Y: CNAME (to Z)"
  770. + X is alised to Y, but Y is aliased to Z.  CNAMEs should not be chained.
  771. + .TP
  772. + .BI "X MX Y: unknown host"
  773. + X is an MX to Y, but Y is not a valid host (no A record).
  774. + .TP
  775. + .BI "X MX Y: CNAME (to Z)"
  776. + X is an MX to Y, but Y is an alias for Z.  MX records must point to
  777. + the canonical name, not an alias.
  778. + .TP
  779. + .BI "X A Y: no PTR record"
  780. + X has an IP address Y, but there is no record to map the IP address
  781. + Y back to a hostname (usually X).
  782. + .TP
  783. + .BI ";; packet size error (found xxx, dlen was yyy)"
  784. + These are error messages from dig.  They indicate a format error
  785. + in the DNS response.  Most often they are caused by records which have
  786. + an incorrect number of fields.  For example, HINFO records require
  787. + exactly two fields.
  788. + .TP
  789. + .BI "warning: X has only one authoritative nameserver"
  790. + Zones must have at least one authoritative nameserver, in case
  791. + one is down or unreachable.  Make sure the parent and child domains
  792. + list all authoritative nameservers for a zone.
  793. + .TP
  794. + .BI "X: invalid character(s) in name"
  795. + Allowable characters in a domain name are the ASCII letters a through Z,
  796. + and the "-" character.  A "." may be used only as a domain separator.
  797. + (checking can be suppressed with
  798. + .B \-i
  799. + )
  800. + .TP
  801. + .BI "X: domain occurred twice, forgot trailing '.'?"
  802. + A sanity check which looks for "dom.ain.dom.ain." in a name.  This
  803. + is often caused by forgetting to put a trailing '.' on the end of
  804. + a name.
  805. + .TP
  806. + (with -a switch)
  807. + .TP
  808. + .BI "X: possible duplicate A record (glue of Z?)"
  809. + A duplicate A records is listed for X.  NOTE: this is most
  810. + often caused by the practice of always putting A records for all
  811. + secondaries after NS glue records.  While this is not an error, it is
  812. + usually redundant and makes changing IP addresses later more difficult,
  813. + since they occur more than one time in the file (and in multiple
  814. + files).  You may get spurious errors, mostly because of a quirk in
  815. + BIND releases before 4.9.x that reports cached glue A records in a zone
  816. + transfer even though they don't exist in the original zone file.
  817. + .TP
  818. + (with -F switch)
  819. + .TP
  820. + .BI "X A Y: points to Z"
  821. + X has Y for an IP address, but the PTR record associated with Y
  822. + returns "Z" as the name associated with that host.  This is not
  823. + necessarily an error (for example if you have an A record for your
  824. + domain name), but can be useful to check for A records which point
  825. + to the wrong host, or PTR records that point to the wrong host.
  826. + .TP
  827. + (with -l switch)
  828. + .TP
  829. + .BI "X NS Y: lame NS delegation"
  830. + Y is a listed nameserver for zone X, but Y is not returning
  831. + authoritative data for zone X.  This is usually the result of a
  832. + lack of communication on the part of the respective hostmasters.  Lame
  833. + delegations are not fatal problems except in severe cases, they just
  834. + tend to create significant increases in DNS traffic.  NS records for
  835. + the parent and child domains should be consistent, and each server
  836. + listed in the NS record MUST be able to answer with authoritative data,
  837. + either by being a primary or secondary for the zone.
  838. + .TP
  839. + .BI "X NS Y: nameserver error (lame?)"
  840. + Any errors returned from dig while contacting other nameservers
  841. + (like connection refused or timeout) will be reported.  This could
  842. + mean a lame delegation, or simply that the host is temporarily
  843. + unreachable.
  844. + .SH FILES
  845. + .br
  846. + .nf
  847. + .\" set tabstop to longest possible filename, plus a wee bit
  848. + .ta \w'xxxxxxxxxxxxxxxxxxxxxxxx   'u
  849. + \fIbar/foo/axfr\fR  saved zone transfer information for "foo.bar"
  850. + .SH "SEE ALSO"
  851. + .nf
  852. + RFC 1034 - "DOMAIN NAMES - CONCEPTS AND FACILITIES"
  853. + RFC 1035 - "DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION"
  854. + RFC 1123 - "Requirements for Internet Hosts -- Application and Support"
  855. + Paul Albits, Cricket Liu: "DNS and BIND" O'Reilly & Associates.
  856. + .SH NOTES
  857. + This package was tested under Perl 4.036, dig 2.0, as well as the dig
  858. + shipped with BIND 4.9.x.
  859. + .SH CAVEATS
  860. + If a domain "foo.edu" lists "ns.bar.foo.edu" as authoritative for
  861. + a zone "bar.foo.edu", but "ns.bar.foo.edu" isn't, then the the dig of
  862. + the zone transfer will hang.  (This was the case here for a subdomain
  863. + that moved into a new set of IP addresses, but the parent nameserver still
  864. + had the old authority records pointing to their nameservers which weren't
  865. + answering to the old reverse domain anymore.)  If this happens, you can
  866. + hit ^C while the transfer is going on and dnswalk will abort that server.
  867. + (It will also remove the partial axfr file)  Hopefully I can figure a
  868. + more elegant way around this.  (or fix dig so that it doesn't hang)
  869. + .SH DIAGNOSTICS
  870. + When invoked with the
  871. + .B \-d
  872. + option,
  873. + .B dnswalk
  874. + will print status information to stderr.  It consists of information
  875. + about what zone is being checked, and a single letter corresponding
  876. + to the resource record checked, and any errors.
  877. + .TP
  878. + .BI a
  879. + A record
  880. + .TP
  881. + .BI c
  882. + CNAME record
  883. + .TP
  884. + .BI p
  885. + PTR record
  886. + .TP
  887. + .BI m
  888. + MX record
  889. + .TP
  890. + .BI s
  891. + SOA record
  892. + .TP
  893. + .BI !
  894. + An error occurred
  895. + .TP
  896. + .BI .
  897. + A previous error in the zone was repeated, but suppressed.
  898. + .PP
  899. + .SH BUGS
  900. + dnswalk will make the directory tree before it has a chance to
  901. + find out that you gave it a bogus domain name.
  902. + .PP
  903. + When checking lots of hosts and lots of options, it is very
  904. + slow.  Running dnswalk on a machine with a local nameserver helps
  905. + considerably.
  906. + .PP
  907. + Perl's gethostby{name,addr}() routine doesn't seem to
  908. + consistently return an error whenever it is unable to resolve an
  909. + address.  Argh.  This will mean lots of "no PTR record" and "host unknown"
  910. + errors if a server is unavailable, or for some reason the lookup fails.
  911. + You may get strange error messages if your perl was compiled without
  912. + support for herror().
  913. + .PP
  914. + I really need to rewrite this all to not rely on dig, and use
  915. + bind.pl instead.
  916. + .SH AUTHOR
  917. + David Barr <barr@pop.psu.edu>
  918. -- 
  919. "The wisest man I have ever known once said to me: 'Nine out of every ten
  920. people improve on acquaintance,' and I have found his words true."
  921. - Frank Swinnerton
  922.  
  923. exit 0 # Just in case...
  924.