jdresolve-0.6.1.orig/0040755000175000001440000000000007532647140013511 5ustar mvelausersjdresolve-0.6.1.orig/BUGS0100644000175000001440000000053107172547275014200 0ustar mvelausers Know bugs: * The host count is not accurate for logs that don't fit in the line cache. This is due to the fact that we can't tell if a host has shown up before during the resolve process. A per-session database could be used for this, but would slow down the process and also require extra database support. jdresolve-0.6.1.orig/BUGS.html0100644000175000001440000000051507163120213015120 0ustar mvelausers

Know bugs:

jdresolve-0.6.1.orig/CHANGELOG0100644000175000001440000001074307172547275014735 0ustar mvelausers * 2000-09-23: 0.6.1 + Increased performance on recursive operation. Now classes are only checked if the host lookup fails (based on a patch by James H. Thompson) + New "-p" or "--progress" command line option. This will print a dot for each line that is resolved, showing the status of the resolve process + Fixed the "oops" assertion bug introduced in 0.6.0 + Code cleanup (better separation of host and class handling functions) + Now searches the full Perl @INC path for Net::DNS * 2000-06-17: 0.6.0 + Improved performance (lines/s) and less cpu usage + Better line caching algorithm + Reduced memory footprint + The code is now fully commented + A new ./configure script (locates Perl, Net::DNS, etc) + Now supports virtually any log format, and many IPs per line (thanks Gary) + More internal debugging messages + Class octects are not inverted anymore in the database, and also shows how the entry was resolved and at what time (WARNING: this means the database format has changed) + Doesn't abort anymore if a machine runs out of sockets (will continue processing and wait for free sockets) + Added the "--dbfirst" and "dbonly" options to check the database before sending DNS queries or not to send queries at all + Now uses NS queries for recursion (instead of SOA) (suggested by Gary) + Integrated the "--dumpdb", "--mergedb" and "--unresolved" options and killed the corresponding external programs + Added option "--expiredb=" to expire database entries older than hours * 1999-08-26: 0.5.2 + Fixed memory leak when the --database option was not in use + Fixed warning messages when the --recursive option was not in use * 1999-08-16: 0.5.1 + Fixed warning messages on FreeBSD + Format of jdresolve-dumpdb dumps have changed. Now classes are dumped in truncated IP format (not in-addr.arpa format as before) + Added jdresolve-mergedb and jdresolve-unresolved utils * 1999-07-27: 0.5 + Added database support. Tested DB_File, but any db variant (dbm, gdbm, sdbm, etc) should work. The main purpose of this option is to offer fallback in case DNS servers are down and allow a general performace increase by allowing you to lower your timeout value without sacrificing resolved percentage + New support program "jdresolve-dumpdb" to dump the databases created with the "--database" switch * 1999-07-14: 0.4 + Changed name to jdresolve not to cause confusion with other projects + GNU compliance changes: added long command line options thru Getopts::Long, no warranties warning, copyright notice + Fixed a division by zero bug with statistics (thanks to John Croft and Andrezj Tobola for pointing this out) + Made available RPM and SRPM packages for jdresolve and Net::DNS * 1999-07-09: 0.3 + Totally redesigned main loop algorithm + Now supports _huge_ log files (low memory usage) + Input from STDIN if file is '-' since we only need 1 pass now + New "-l" switch to control memory line caching + Quick script 'rhost' to resolve single hosts with recursion + Added more statistics (total time, lines/s, etc) + No more warnings with Perl 5.004_04 + Code cleanup, now uses a more modular approach + Updated documentation * 1999-07-02: 0.2 + Added debug levels 1 and 2 + Only warns about invalid/resolved IPs if debug level >= 2 + You can now run logresolve.pl on partly/fully resolved logs with no warning messages + Added statistics at end of run + New option -n to supress statistics + New option -m to specify a custom mask to apply to IPs resolved by recurrence. accepts %i for IP and %c for class name + Packaged as a .tar.gz file with COPYING, INSTALL, README, CREDITS, CHANGELOG and logresolve.pl files. Documentation is a Good Thing. * 1999-06-29: 0.1 + Initial release jdresolve-0.6.1.orig/CHANGELOG.html0100644000175000001440000000767107172547145015702 0ustar mvelausers jdresolve-0.6.1.orig/COPYING0100644000175000001440000004312707126534007014544 0ustar mvelausers GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. jdresolve-0.6.1.orig/CREDITS0100644000175000001440000000632607172547275014545 0ustar mvelausers I'd like to thank the following people who have helped me during the development process of jdresolve. The list is ordered chronologically. * Michael Fuhr + Author of the excellent Net::DNS module * [1]Pekka Savola + [test] Perl 5.004m7 warning messages + [test] the "Are we out of sockets" abort + [sugg] the --anywhere functionality * Mark Roedel + [sugg] Configurable name mask when recursing (-n ) + [test] unresolved IPs * Hugo Haas + [patch] Tentative line caching + [test] Testing on huge log files + [test] Re-resolving logs with v0.3pre2 * Renaud Bruyeron + [patch] Initial fix for bgsend error handling + [test] Testing on huge log files * Johannes la Poutre + [test] Perl 5.004_04 warning messages + [test] Unresolved IPs + [bench] On Ultrasparc 10 * John Croft + [patch] Division by zero in statistics + [bench] Against logresolve * Andrezj Tobola + [patch] Division by zero in statistics * Dominique Bongard + [test] unresolved IPs + [sugg] whois lookups (not implemented yet) * [2]Michael A. Alderete + [test] warnings on FreeBSD * [3]Skip Horine + [test] a bug when not using the -r option * [4]Mads Kiilerich + [sugg] the --dbonly option * [5]Craig Sanders + [patch] man pages for all programs + Craig is the maintainer for the jdresolve Debian package * [6]Ken Chase + [sugg] the --dbonly option (also) + [sugg] expiring the database + [sugg] marking recurses entries + [sugg] negative caching * [7]Gary Gurevich + [patch] the --anywhere option + [patch] use NS records instead of SOA * [8]Alexander Bruch + [test] hang when resolving '0.0.0.0' * [9]Alex Howansky + [patch] created the Reptor program based on jdresolve * [10]Matthias Ivers + [patch] another variation of the --anywhere option * [11]Steve Klassen + [patch] a variation of --anywhere for NT logs * [12]Jrg Siegenthaler + [test] warnings with ActiveState Perl 5.6.0.613 * [13]James H. Thompson + [patch] A fix for the "oops" assertion bug, new "--processstatus" option (not merged, I went with the existing "--debug" option and a new "--progress" option) * [14]Dennis Boone + [sugg] Search the full Perl @INC path for Net::DNS [test] = testing [sugg] = suggestion [patch] = patch Note: I didn't keep track of some email addresses, if you'd like to have your email updated please let me know References 1. mailto:Pekka.Savola@netcore.fi 2. mailto:alderete@be.com 3. mailto:atc@atc.nethosting.net 4. mailto:Mads@Kiilerich.com 5. mailto:cas@taz.net.au 6. mailto:mathboy@velocet.cat 7. mailto:gary@dls.net 8. mailto:abruch@mail.ffm.plusline.de 9. mailto:alex@wankwood.com 10. mailto:ivers@realophob.de 11. mailto:sklassen@concentric.com 12. mailto:Juerg.Siegenthaler@gmx.ch 13. mailto:jht@mail.off-road.com 14. mailto:drb@msu.edu jdresolve-0.6.1.orig/CREDITS.html0100644000175000001440000000657207172547272015510 0ustar mvelausers

I'd like to thank the following people who have helped me during the development process of jdresolve. The list is ordered chronologically.

  • Michael Fuhr

    • Author of the excellent Net::DNS module

  • Pekka Savola

    • [test] Perl 5.004m7 warning messages
    • [test] the "Are we out of sockets" abort
    • [sugg] the --anywhere functionality

  • Mark Roedel

    • [sugg] Configurable name mask when recursing (-n <mask>)
    • [test] unresolved IPs

  • Hugo Haas

    • [patch] Tentative line caching
    • [test] Testing on huge log files
    • [test] Re-resolving logs with v0.3pre2

  • Renaud Bruyeron

    • [patch] Initial fix for bgsend error handling
    • [test] Testing on huge log files

  • Johannes la Poutre

    • [test] Perl 5.004_04 warning messages
    • [test] Unresolved IPs
    • [bench] On Ultrasparc 10

  • John Croft

    • [patch] Division by zero in statistics
    • [bench] Against logresolve

  • Andrezj Tobola

    • [patch] Division by zero in statistics

  • Dominique Bongard

    • [test] unresolved IPs
    • [sugg] whois lookups (not implemented yet)

  • Michael A. Alderete

    • [test] warnings on FreeBSD

  • Skip Horine

    • [test] a bug when not using the -r option

  • Mads Kiilerich

    • [sugg] the --dbonly option

  • Craig Sanders

    • [patch] man pages for all programs
    • Craig is the maintainer for the jdresolve Debian package

  • Ken Chase

    • [sugg] the --dbonly option (also)
    • [sugg] expiring the database
    • [sugg] marking recurses entries
    • [sugg] negative caching

  • Gary Gurevich

    • [patch] the --anywhere option
    • [patch] use NS records instead of SOA

  • Alexander Bruch

    • [test] hang when resolving '0.0.0.0'

  • Alex Howansky

    • [patch] created the Reptor program based on jdresolve

  • Matthias Ivers

    • [patch] another variation of the --anywhere option

  • Steve Klassen

    • [patch] a variation of --anywhere for NT logs

  • Jrg Siegenthaler

    • [test] warnings with ActiveState Perl 5.6.0.613

  • James H. Thompson

    • [patch] A fix for the "oops" assertion bug, new "--processstatus" option (not merged, I went with the existing "--debug" option and a new "--progress" option)

  • Dennis Boone

    • [sugg] Search the full Perl @INC path for Net::DNS

[test] = testing [sugg] = suggestion [patch] = patch

Note: I didn't keep track of some email addresses, if you'd like to have your email updated please let me know

jdresolve-0.6.1.orig/INSTALL0100644000175000001440000000423707172547275014555 0ustar mvelausers PREREQUISITES * A decent Perl distribution (IO::Select, etc). Tested with Perl 5.005_03, 5.004m7 and 5.004_04, all run without warnings * The Net::DNS module USING DEBIAN This couldn't be easier: apt-get install jdresolve No need to download anything by hand, as jdresolve is now a Debian app. That'll install any dependencies too :) Debian kicks ass. USING THE RPM PACKAGES (RedHat, Mandrake, etc) Just use the following commands: rpm -Uvh perl-Net-DNS-0.12-1.noarch.rpm rpm -Uvh jdresolve-0.6.1-1.noarch.rpm USING THE .TAR.GZ OR .TAR.BZ2 PACKAGES (Any distro) To install the Net::DNS module, fetch it from a CPAN mirror (http://www.cpan.org), or use the CPAN module to do it automagically. Using the CPAN modules is simple. You can run it from the command line or interactively: * command line: perl -MCPAN -e "command" * interactive: perl -MCPAN -e shell To keep you Perl distribution updated, you should issue command like "install Bundle::CPAN" regularly. Here is some sample output: [root@xhost /root]# perl -MCPAN -e "install Bundle::CPAN" CPAN: LWP::UserAgent loaded ok Fetching with LWP: ftp://cpan.if.usp.br/pub/mirror/CPAN/authors/01mailrc.txt.gz Going to read /root/.cpan/sources/authors/01mailrc.txt.gz CPAN: Compress::Zlib loaded ok Going to read /root/.cpan/sources/modules/02packages.details.txt.gz Scanning cache /root/.cpan/build for sizes Fetching with LWP: ftp://cpan.if.usp.br/pub/mirror/CPAN/modules/03modlist.data.gz Going to read /root/.cpan/sources/modules/03modlist.data.gz MD5 is up to date. File::Spec is up to date. Compress::Zlib is up to date. Archive::Tar is up to date. Data::Dumper is up to date. Net::Telnet is up to date. Net::Cmd is up to date. Term::ReadKey is up to date. Term::ReadLine::Perl is up to date. CPAN::WAIT is up to date. CPAN is up to date. So for jdresolve to work, you should at least issue an "install Net::DNS". After that just go back to where you unpacked jdresolve and run './configure' and then 'make install' as root. jdresolve-0.6.1.orig/INSTALL.html0100644000175000001440000000436707172541162015511 0ustar mvelausers

PREREQUISITES

  • A decent Perl distribution (IO::Select, etc). Tested with Perl 5.005_03, 5.004m7 and 5.004_04, all run without warnings
  • The Net::DNS module

USING DEBIAN

This couldn't be easier:

apt-get install jdresolve

No need to download anything by hand, as jdresolve is now a Debian app. That'll install any dependencies too :) Debian kicks ass.

USING THE RPM PACKAGES (RedHat, Mandrake, etc)

Just use the following commands:

rpm -Uvh perl-Net-DNS-0.12-1.noarch.rpm rpm -Uvh jdresolve-0.6.1-1.noarch.rpm

USING THE .TAR.GZ OR .TAR.BZ2 PACKAGES (Any distro)

To install the Net::DNS module, fetch it from a CPAN mirror (http://www.cpan.org), or use the CPAN module to do it automagically.

Using the CPAN modules is simple. You can run it from the command line or interactively:

  • command line: perl -MCPAN -e "command"
  • interactive: perl -MCPAN -e shell

To keep you Perl distribution updated, you should issue command like "install Bundle::CPAN" regularly. Here is some sample output:

   [root@xhost /root]# perl -MCPAN -e "install Bundle::CPAN"
   CPAN: LWP::UserAgent loaded ok
   Fetching with LWP:
     ftp://cpan.if.usp.br/pub/mirror/CPAN/authors/01mailrc.txt.gz
   Going to read /root/.cpan/sources/authors/01mailrc.txt.gz
   CPAN: Compress::Zlib loaded ok
   Going to read /root/.cpan/sources/modules/02packages.details.txt.gz
   Scanning cache /root/.cpan/build for sizes
   Fetching with LWP:
     ftp://cpan.if.usp.br/pub/mirror/CPAN/modules/03modlist.data.gz
   Going to read /root/.cpan/sources/modules/03modlist.data.gz
   MD5 is up to date.
   File::Spec is up to date.
   Compress::Zlib is up to date.
   Archive::Tar is up to date.
   Data::Dumper is up to date.
   Net::Telnet is up to date.
   Net::Cmd is up to date.
   Term::ReadKey is up to date.
   Term::ReadLine::Perl is up to date.
   CPAN::WAIT is up to date.
   CPAN is up to date.

So for jdresolve to work, you should at least issue an "install Net::DNS".

After that just go back to where you unpacked jdresolve and run './configure' and then 'make install' as root.

jdresolve-0.6.1.orig/Makefile0100644000175000001440000000142707172546703015155 0ustar mvelausersprefix=/usr INSTALL=/usr/bin/install BINDIR=$(prefix)/bin MANDIR=$(prefix)/man/man1 none: man: pod2man jdresolve > jdresolve.1 cat jdresolve.1 | gzip - > jdresolve.1.gz cat rhost.1 | gzip - > rhost.1.gz for FILE in AUTHORS README BUGS CHANGELOG CREDITS INSTALL TODO; do lynx --dump "$$FILE.html" | perl -ne "! /^Looking/ and print" > "$$FILE"; done install: $(INSTALL) -m 755 -o bin -g bin jdresolve $(DESTDIR)$(BINDIR) $(INSTALL) -m 755 -o bin -g bin rhost $(DESTDIR)$(BINDIR) mkdir -p $(DESTDIR)$(MANDIR) $(INSTALL) -m 644 -o bin -g bin jdresolve.1 $(DESTDIR)$(MANDIR) $(INSTALL) -m 644 -o bin -g bin rhost.1 $(DESTDIR)$(MANDIR) uninstall: rm $(DESTDIR)$(BINDIR)/jdresolve rm $(DESTDIR)$(BINDIR)/rhost rm $(DESTDIR)$(MANDIR)/jdresolve.1 rm $(DESTDIR)$(MANDIR)/rhost.1 jdresolve-0.6.1.orig/Makefile.in0100644000175000001440000000142707126574150015556 0ustar mvelausersprefix=/usr INSTALL=/usr/bin/install BINDIR=$(prefix)/bin MANDIR=$(prefix)/man/man1 none: man: pod2man jdresolve > jdresolve.1 cat jdresolve.1 | gzip - > jdresolve.1.gz cat rhost.1 | gzip - > rhost.1.gz for FILE in AUTHORS README BUGS CHANGELOG CREDITS INSTALL TODO; do lynx --dump "$$FILE.html" | perl -ne "! /^Looking/ and print" > "$$FILE"; done install: $(INSTALL) -m 755 -o bin -g bin jdresolve $(DESTDIR)$(BINDIR) $(INSTALL) -m 755 -o bin -g bin rhost $(DESTDIR)$(BINDIR) mkdir -p $(DESTDIR)$(MANDIR) $(INSTALL) -m 644 -o bin -g bin jdresolve.1 $(DESTDIR)$(MANDIR) $(INSTALL) -m 644 -o bin -g bin rhost.1 $(DESTDIR)$(MANDIR) uninstall: rm $(DESTDIR)$(BINDIR)/jdresolve rm $(DESTDIR)$(BINDIR)/rhost rm $(DESTDIR)$(MANDIR)/jdresolve.1 rm $(DESTDIR)$(MANDIR)/rhost.1 jdresolve-0.6.1.orig/README0100644000175000001440000002424507172547274014404 0ustar mvelausers _________________________________________________________________ Application: jdresolve 0.6.1 Author: [1]John D. Rowell Homepage: [2]http://www.jdrowell.com/Linux/Projects/jdresolve _________________________________________________________________ FOR THE IMPATIENT ./configure make install Try: jdresolve > i.e. jdresolve access_log > resolved.log To use recursion, just use the "-r" command line option. DESCRIPTION jdresolve resolves IP addresses to hostnames. Any file format is supported, including those where the line does not begin with the IP address. One of the strongest features of the program is the support for recursion, which can drastically reduce the number of unresolved hosts by faking a hostname based on the network that the IP belongs to. DNS queries are sent in parallel, which means that you can decrease run time by increasing the number of simultaneous sockets used (given a fast enough machine and available bandwidth). By using the database support, performance can be increased even further, by using cached data from previous runs. HOW IT USED TO WORK jdresolve used the algorithms describe below up to version 0.2. The initial version of jdresolve tried to only speed up the name resolution by implementing numerous concurrent requests. I The first problem was: how to resolve the maximum possible number of IPs concurrently without reading the whole log file into memory (they can get quite _huge_)? I figured I'd need a 2 pass approach, collecting all distinct host IPs that needing resolving in the first step, then resolving them efficiently inside a loop, and finally just replacing the resolved IPs on the second pass through the log file. This way we can garantee that the resolve queue will always be full with no need to weight that against how many lines of buffered log entries we would need to cache. The number of distinct IP addresses tend to be quite lower than the number of lines in the log file, and the IP part takes about only 1/20th of the log line, so we can't be using too much memory just by putting a few hundred or thousand small strings into a hash. After looking thru [3]CPAN, I came across the excellent Net::DNS module and was more than happy to note that it already provide a subroutine and examples for background queries. Just add IO::Select to that and you have a full non-blocking aproach to multiple concurrent queries. You can even specify the timeouts to make the name resolving even more efficient. Having this much done, I was quite happy to have the fastest log resolving routine I have come accross. By setting the numbers of concurrent sockets and timeouts you could fine tune the beast to resolve names _very_ rapidly. But still there where about 25% of the IPs left unresolved... "This is not much help", I thought. I need to know _at least_ from what country these people are accessing from. After a few not very scientifical aproaches, I realized that by recurring thru the DNS classes (C, B and finally A) and checking for the host listed in the SOA record I could be pretty sure this was a father domain to the IP. The implementation goes like this: find out all distinct IP addresses, then determine which C, B and A classes contain these addresses. Make up a list from these queries and send them thru a resolver in chuncks of 32 (configurable via the command line). If a socket times out, leave that request unresolved. After running a big log file against the recursive aproach, I determined it didn't take much longer to resolve it at all. Full class domains tend to have decently configured DNS servers, and you get a lot of repeated classes when resolving your logs. The best was still to come: 0 unresolved IPs :) And since that I haven't found an IP that can't be determined at least to it's A class. HOW IT WORKS NOW The above algorithm works extremely well except for the case of very large logs (>100Mb). The hashes containing IPs and their parent A/B/C classes gets pretty huge doesn't fit in memory any more. So as of v0.3, we have a new 1 pass approach. We have a line cache that holds 10000 lines (configurable with -l, don't set it much lower). Using my test base it looks like each 10000 lines take about 4Mb of RAM during processing (that's the log lines themselves plus the hashes and arrays used for caching/processing). Each IP and class to be resolved has a count value, which is increased every time a line with that number is read, and decreased after we print out a resolved line with that reference value. Think of it as a "moving window" method, and that we do our own garbage collection. The process pauses if the first line in our line cache is still unresolved, we don't have any more sockets, or we're waiting for socket data. We can't control the last two items, but to minimize the pauses do to yet unresolved lines, increase the -l value if you notice pauses during resolving. There should be enough lines cached so that even if we have timeouts on sockets we are still waiting for other socket data to come in, not just for 1 single socket to time out. Using this method the memory usage during executing is almost constant. So you can determine how much RAM you wish to use for resolving names and set your -l value and forget about it. There's really no performance loss when compared to the <=v0.2 algorithm if you have a big enough line cache. HOW TO USE IT Example: jdresolve access_log > resolved.log If you simply run the script as you would with the Apache logresolve program, you get the same results, only much faster. But if you want really take advantage of jdresolve, you should at least turn on the -r option for recursive resolves. As of version 0.2, the -m option takes a mask as an argument. The valid substitutions are %i for the IP address and %c for the resolved class. So an IP like 1.2.3.4 with a mask of "%i.%c" (the default) would become something like "1.2.3.4.some.domain". A mask of "somewhere.in.%c" would turn it into "somewhere.in.some.domain". The -h switch shows you basic help information. The -v switch will display version information. Use -d 1 or -d 2 (more verbose) to debug the resolving process and get extra statistics. If you don't care for the default statistics, use -n to disable them. After some runs you may want to change your timeout value. The -t option accepts a new value in seconds. For even better performance, use the -s switch with a value greater then 32, but remember that many operating systems have a hard coded default for open files of 256 or 1024. Check your system's limit with "ulimit -a". New in v0.3 is the -l switch, which specified how many lines we will cache for resolving. The default is 10000, but can be vastly incremented without using too much RAM, as explained in "HOW IT WORKS". After you used jdresolve on the log file, you can check which ips where left unresolved by using the --unresolved option on the file that was generated. WHAT DOES RHOST DO? 'rhost' is a quick script to take advantage of the new STDIN functionality of jdresolve. Many times you use the 'host' command to resolve a single IP (like 'host 200.246.224.10'). As with standard log resolvers, 'host' doesn't do recursion. So 'rhost' just calls jdresolve with the apropriate parameters to resolve that single IP number. The syntax is 'rhost '. DATABASE SUPPORT As of version 0.5, jdresolve provides simple database support thru db (dbm, gdbm, sdbm, etc) files. You can use the --database switch to specify the db file and that will allow for fallback in case some DNS servers are down and also performance improvements since you can lower your timeout value without sacrificing resolved percentage. To use the database support, just supply a database name (i.e. 'hosts.db') using the --database option. If it does not yet exist, a new database with that name will be created. All resolved hosts and classes during a jdresolve run will be cached to the database. After you have some data in a db, you can use --dumpdb to look at it. With --mergedb to add new information to it (the format of the input file is the same as the one from a dump using --dumpdb, e.g. an ip/class followed by the hostname/classname, separated by white space) Ex: echo "0.0.0.0 testip" | jdresolve --database hosts.db --mergedb - ...adds and IP entry to the db Ex: echo "0.0.0 classname" | jdresolve --database hosts.db --mergedb - ...adds a class entry to the db Note: Since when recursing the resolved hostnames are stored to the database (even when resolved by recursion), you _may_ not want to use the same database for normal and recursed runs. That is because a cached host from a resolved run will show up as a "real" IP if you don't recurse and use the --dbfirst or --dbonly options, or just use the database and the lookup times out. Nothing too serious, but this detail may be important to some people. SOME NOTES ON NET::DNS It seems that Net::DNS can perform suboptimally on non-Linux machines, even on *BSD (this is based on some bug reports I got from people using jdresolve in those environments). Also, on Windows NT (yes, some people still use that), you should make sure there is a 'resolv.conf' file somewhere (I'm no NT expert, read the docs). Since we use so little of the functionality of Net::DNS, I may replace it with standard sockets some time in the future. It is still a very very nice module though :) SUPPORT If you have dificulties using this program or would like to request a new feature, feel free to reach me at me@jdrowell.com. LICENSING jdresolve is licensed under the GPL. See the COPYING file for details. References 1. mailto:me@jdrowell.com 2. http://www.jdrowell.com/Linux/Projects/jdresolve 3. http://www.cpan.org/ jdresolve-0.6.1.orig/README.html0100644000175000001440000002366207126534202015333 0ustar mvelausers

Application: jdresolve 0.6.1
Author: John D. Rowell
Homepage: http://www.jdrowell.com/Linux/Projects/jdresolve


FOR THE IMPATIENT

./configure
make install
 
Try: jdresolve <log file> > <resolved file>
i.e. jdresolve access_log > resolved.log

To use recursion, just use the "-r" command line option.

DESCRIPTION

jdresolve resolves IP addresses to hostnames. Any file format is supported, including those where the line does not begin with the IP address. One of the strongest features of the program is the support for recursion, which can drastically reduce the number of unresolved hosts by faking a hostname based on the network that the IP belongs to. DNS queries are sent in parallel, which means that you can decrease run time by increasing the number of simultaneous sockets used (given a fast enough machine and available bandwidth). By using the database support, performance can be increased even further, by using cached data from previous runs.

HOW IT USED TO WORK

jdresolve used the algorithms describe below up to version 0.2.

The initial version of jdresolve tried to only speed up the name resolution by implementing numerous concurrent requests. I The first problem was: how to resolve the maximum possible number of IPs concurrently without reading the whole log file into memory (they can get quite _huge_)? I figured I'd need a 2 pass approach, collecting all distinct host IPs that needing resolving in the first step, then resolving them efficiently inside a loop, and finally just replacing the resolved IPs on the second pass through the log file.

This way we can garantee that the resolve queue will always be full with no need to weight that against how many lines of buffered log entries we would need to cache. The number of distinct IP addresses tend to be quite lower than the number of lines in the log file, and the IP part takes about only 1/20th of the log line, so we can't be using too much memory just by putting a few hundred or thousand small strings into a hash.

After looking thru CPAN, I came across the excellent Net::DNS module and was more than happy to note that it already provide a subroutine and examples for background queries. Just add IO::Select to that and you have a full non-blocking aproach to multiple concurrent queries. You can even specify the timeouts to make the name resolving even more efficient.

Having this much done, I was quite happy to have the fastest log resolving routine I have come accross. By setting the numbers of concurrent sockets and timeouts you could fine tune the beast to resolve names _very_ rapidly. But still there where about 25% of the IPs left unresolved...

"This is not much help", I thought. I need to know _at least_ from what country these people are accessing from. After a few not very scientifical aproaches, I realized that by recurring thru the DNS classes (C, B and finally A) and checking for the host listed in the SOA record I could be pretty sure this was a father domain to the IP. The implementation goes like this: find out all distinct IP addresses, then determine which C, B and A classes contain these addresses. Make up a list from these queries and send them thru a resolver in chuncks of 32 (configurable via the command line). If a socket times out, leave that request unresolved.

After running a big log file against the recursive aproach, I determined it didn't take much longer to resolve it at all. Full class domains tend to have decently configured DNS servers, and you get a lot of repeated classes when resolving your logs. The best was still to come: 0 unresolved IPs :) And since that I haven't found an IP that can't be determined at least to it's A class.

HOW IT WORKS NOW

The above algorithm works extremely well except for the case of very large logs (>100Mb). The hashes containing IPs and their parent A/B/C classes gets pretty huge doesn't fit in memory any more.

So as of v0.3, we have a new 1 pass approach. We have a line cache that holds 10000 lines (configurable with -l, don't set it much lower). Using my test base it looks like each 10000 lines take about 4Mb of RAM during processing (that's the log lines themselves plus the hashes and arrays used for caching/processing). Each IP and class to be resolved has a count value, which is increased every time a line with that number is read, and decreased after we print out a resolved line with that reference value.

Think of it as a "moving window" method, and that we do our own garbage collection. The process pauses if the first line in our line cache is still unresolved, we don't have any more sockets, or we're waiting for socket data. We can't control the last two items, but to minimize the pauses do to yet unresolved lines, increase the -l value if you notice pauses during resolving. There should be enough lines cached so that even if we have timeouts on sockets we are still waiting for other socket data to come in, not just for 1 single socket to time out.

Using this method the memory usage during executing is almost constant. So you can determine how much RAM you wish to use for resolving names and set your -l value and forget about it. There's really no performance loss when compared to the <=v0.2 algorithm if you have a big enough line cache.

HOW TO USE IT

Example: jdresolve access_log > resolved.log

If you simply run the script as you would with the Apache logresolve program, you get the same results, only much faster. But if you want really take advantage of jdresolve, you should at least turn on the -r option for recursive resolves. As of version 0.2, the -m option takes a mask as an argument. The valid substitutions are %i for the IP address and %c for the resolved class. So an IP like 1.2.3.4 with a mask of "%i.%c" (the default) would become something like "1.2.3.4.some.domain". A mask of "somewhere.in.%c" would turn it into "somewhere.in.some.domain".

The -h switch shows you basic help information. The -v switch will display version information. Use -d 1 or -d 2 (more verbose) to debug the resolving process and get extra statistics. If you don't care for the default statistics, use -n to disable them.

After some runs you may want to change your timeout value. The -t option accepts a new value in seconds. For even better performance, use the -s switch with a value greater then 32, but remember that many operating systems have a hard coded default for open files of 256 or 1024. Check your system's limit with "ulimit -a".

New in v0.3 is the -l switch, which specified how many lines we will cache for resolving. The default is 10000, but can be vastly incremented without using too much RAM, as explained in "HOW IT WORKS".

After you used jdresolve on the log file, you can check which ips where left unresolved by using the --unresolved option on the file that was generated.

WHAT DOES RHOST DO?

'rhost' is a quick script to take advantage of the new STDIN functionality of jdresolve. Many times you use the 'host' command to resolve a single IP (like 'host 200.246.224.10'). As with standard log resolvers, 'host' doesn't do recursion. So 'rhost' just calls jdresolve with the apropriate parameters to resolve that single IP number. The syntax is 'rhost <ip>'.

DATABASE SUPPORT

As of version 0.5, jdresolve provides simple database support thru db (dbm, gdbm, sdbm, etc) files. You can use the --database switch to specify the db file and that will allow for fallback in case some DNS servers are down and also performance improvements since you can lower your timeout value without sacrificing resolved percentage.

To use the database support, just supply a database name (i.e. 'hosts.db') using the --database option. If it does not yet exist, a new database with that name will be created. All resolved hosts and classes during a jdresolve run will be cached to the database.

After you have some data in a db, you can use --dumpdb to look at it. With --mergedb to add new information to it (the format of the input file is the same as the one from a dump using --dumpdb, e.g. an ip/class followed by the hostname/classname, separated by white space)

Ex: echo "0.0.0.0 testip" | jdresolve --database hosts.db --mergedb -
...adds and IP entry to the db
Ex: echo "0.0.0 classname" | jdresolve --database hosts.db --mergedb -
...adds a class entry to the db

Note: Since when recursing the resolved hostnames are stored to the database (even when resolved by recursion), you _may_ not want to use the same database for normal and recursed runs. That is because a cached host from a resolved run will show up as a "real" IP if you don't recurse and use the --dbfirst or --dbonly options, or just use the database and the lookup times out. Nothing too serious, but this detail may be important to some people.

SOME NOTES ON NET::DNS

It seems that Net::DNS can perform suboptimally on non-Linux machines, even on *BSD (this is based on some bug reports I got from people using jdresolve in those environments). Also, on Windows NT (yes, some people still use that), you should make sure there is a 'resolv.conf' file somewhere (I'm no NT expert, read the docs). Since we use so little of the functionality of Net::DNS, I may replace it with standard sockets some time in the future. It is still a very very nice module though :)

SUPPORT

If you have dificulties using this program or would like to request a new feature, feel free to reach me at me@jdrowell.com.

LICENSING

jdresolve is licensed under the GPL. See the COPYING file for details.

jdresolve-0.6.1.orig/TODO0100644000175000001440000000117207172547275014207 0ustar mvelausers * To do: + negative caching + progress bar (with ETA) + resolve the last few unresolved IPs. I'm looking into a whois lookup or a "closest hop" approach + arrange benchmarks into a comprehensive table + test with Perl 5.6.0 (waiting for woody packages :P) * Done: + direct STDIN input (0.3) + add ability to edit databases create with "--database" (0.5.1) + clean up "dangling" A/B/C class sockets during run (0.6.0) + expire database entries (0.6.0) + further optimizations (getresolved()) (0.6.0) jdresolve-0.6.1.orig/TODO.html0100644000175000001440000000107407172541254015142 0ustar mvelausers
  • To do:

    • negative caching
    • progress bar (with ETA)
    • resolve the last few unresolved IPs. I'm looking into a whois lookup or a "closest hop" approach
    • arrange benchmarks into a comprehensive table
    • test with Perl 5.6.0 (waiting for woody packages :P)

  • Done:

    • direct STDIN input (0.3)
    • add ability to edit databases create with "--database" (0.5.1)
    • clean up "dangling" A/B/C class sockets during run (0.6.0)
    • expire database entries (0.6.0)
    • further optimizations (getresolved()) (0.6.0)

    jdresolve-0.6.1.orig/configure0100755000175000001440000000365707172546702015432 0ustar mvelausers#!/bin/sh ### Check for Perl echo -n "checking for Perl... " PERL="" PERLVERSION="0" for i in [ /usr/bin/perl /usr/local/bin/perl /bin/perl ]; do if test -x $i; then PERL=$i PERLVERSION=`$PERL -e "print $]" 2>&1` echo "found $PERLVERSION ($PERL)" break fi done; if [ "$PERL" == "" ]; then echo "missing" echo "You can get Perl at http://www.perl.org" exit fi if [ "$PERLVERSION" \< "5.00400" ]; then echo "We need Perl >= 5.004. You can get Perl at http://www.perl.org" exit fi ### Check for Net::DNS echo -n "checking for Net::DNS... " NETDNS="" NETDNSVERSION="0" INC=`$PERL -e "print join(' ', @INC)"` for i in $INC; do i=$i/Net/DNS.pm if test -f $i; then NETDNS=$i NETDNSVERSION=`$PERL -e "use Net::DNS;print Net::DNS->version" 2>&1` echo "found $NETDNSVERSION ($NETDNS)" break fi done; if [ "$NETDNS" == "" ]; then echo "missing" echo "You can get Net::DNS at http://www.cpan.org" exit fi if [ "$NETDNSVERSION" \< "0.12" ]; then echo "We need Net::DNS >= 0.12. You can get Net::DNS at http://www.cpan.org" exit fi ### Check for install echo -n "checking for install... " INSTALL="" INSTALLVERSION="" for i in [ /usr/bin/install /usr/local/bin/install /bin/install ]; do if test -x $i; then INSTALL=$i INSTALLVERSION=`install --version | head -n 1 | sed -e "s/[^0-9]*\([0-9]*\.[0-9]*[a-z]*\)$/\1/" 2>&1 ` echo "found $INSTALLVERSION ($INSTALL)" break fi done; if [ "$INSTALL" == "" ]; then echo "missing" echo "You can get install from the fileutils package at ftp://ftp.gnu.org" exit fi if [ "$INSTALLVERSION" \< "3.0" ]; then echo "We need install >= 3.0. You can get install from the fileutils package at ftp://ftp.gnu.org" exit fi ### Create the output files echo "creating Makefile" cp Makefile.in Makefile echo "creating jdresolve" sed -e "s|^#\!/usr/bin/perl|#\!$PERL|" < jdresolve.in > jdresolve chmod 755 jdresolve echo "" echo "Done. Type \"make install\" to install jdresolve." jdresolve-0.6.1.orig/jdresolve0100755000175000001440000006372407172546703015450 0ustar mvelausers#!/usr/bin/perl -w # jdresolve - Resolves IP addresses into hostnames # # Copyright (c) 1999-2000 John D. Rowell # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. =head1 NAME jdresolve - resolves IP addresses into hostnames =head1 SYNOPSIS B [-h] [-v] [-n] [-r] [-a] [-d ] [-m ] [-l ] [-t ] [-p] [-s ] [--database=] > B [--help] [--version] [--nostats] [--recursive] [--anywhere] [--debug=] [--mask=] [--linecache=] [--timeout=] [--sockets=] [--database=] [--dbfirst] [--dbonly] [--dumpdb] [--mergedb] [--expiredb=] [--unresolved] [--progress] > =head1 DESCRIPTION B resolves IP addresses to hostnames. Any file format is supported, including those where the line does not begin with the IP address. One of the strongest features of the program is the support for recursion, which can drastically reduce the number of unresolved hosts by faking a hostname based on the network that the IP belongs to. DNS queries are sent in parallel, which means that you can decrease run time by increasing the number of simultaneous sockets used (given a fast enough machine and available bandwidth ). By using the database support, performance can be increased even further, by using cached data from previous runs. =head1 OPTIONS =over 8 =item B<-h, --help> produces a short help message =item B<-v, --version> display version information =item B<-n, --no-stats> don't display stats after processing =item B<-r, --recursive> recurse into C, B and A classes when there is no PTR (default is no recursion) =item B<-d, --debug=> debug mode - no file output, just statistics during run (verbosity level range: 1-3) =item B<-t, --timeout=> timeout in seconds for each host resolution (default is 30 seconds) =item B<-l, --line-cache=> numbers of lines to cache in memory (default is 10000 =item B<-s, --sockets=> maximum number of concurrent sockets (use ulimit -a to check the max allowed for your operating system - defaults to 64) =item B<-m, --mask=> accepts %i for IP and %c for class owner, e.g. "somewhere.in.%c" or "%i.in.%c" (default is "%i.%c") =item B<-a, --anywhere> resolves IPs found anywhere on a line (will resolve all IPs if there is more than one) =item B<-p, --progress> prints a nice progress bar indicating the status of the resolve operations =item B<--database=> path to database that holds resolved hosts/classes =item B<--dbfirst> check if we have resolved entries in the database before sending out DNS queries =item B<--dbonly> don't send DNS queries, use only resolved data in the database =item B<--dumpdb> dumps a database to STDOUT =item B<--mergedb> merges resolved IP/classes from a file (or STDIN) with a database =item B<--expiredb=> expires entries in the database that are older than hours =item B<--unresolved> won't attempt to resolve IPs, only lists those that were not resolved =item B<> the log filename or '-' for STDIN =head1 EXAMPLES jdresolve access_log > resolved_log jdresolve -r -s 128 access_log > resolved_log jdresolve -r --database hosts.db access_log > res_log =head1 SEE ALSO rhost(1) =head1 AUTHOR B was written by John D. Rowell , and is licensed under the terms of the GNU General Public License. The original version of this man page was written by Craig Sanders , for the Debian GNU/Linux package of jdresolve, and is also licensed under the terms of the GNU GPL. =cut # Require variable declaration use strict; # Load the needed modules use Net::DNS; # installed separately use IO::Select; use Getopt::Long; use POSIX qw(strftime); use DB_File; #use GDBM_File; # Global constants my $APPNAME = 'jdresolve'; my $VERSION = '0.6.1'; my $AUTHOR = 'John D. Rowell'; my $YEAR = '1999-2000'; my $BUGS = 'bugs@jdrowell.com'; # Defaults for command line options my %opts = ( stdin => 0, help => 0, version => 0, nostats => 0, recursive => 0, debug => 0, mask => '%i.%c', linecache => 10000, timeout => 30, sockets => 64, database => '', anywhere => 0, dbfirst => 0, dbonly => 0, dumpdb => 0, unresolved => 0, mergedb => 0, expiredb => -1, progress => 0); # Recognized command line options my %optctl = ( '' => \$opts{stdin}, 'h' => \$opts{help}, 'help' => \$opts{help}, 'v' => \$opts{version}, 'version' => \$opts{version}, 'n' => \$opts{nostats}, 'nostats' => \$opts{nostats}, 'r' => \$opts{recursive}, 'recursive' => \$opts{recursive}, 'd' => \$opts{debug}, 'debug' => \$opts{debug}, 'm' => \$opts{mask}, 'mask' => \$opts{mask}, 'l' => \$opts{linecache}, 'linecache' => \$opts{linecache}, 't' => \$opts{timeout}, 'timeout' => \$opts{timeout}, 's' => \$opts{sockets}, 'sockets' => \$opts{sockets}, 'a' => \$opts{anywhere}, 'anywhere' => \$opts{anywhere}, 'p' => \$opts{progress}, 'progress' => \$opts{progress}, 'dbfirst' => \$opts{dbfirst}, 'dbonly' => \$opts{dbonly}, 'dumpdb' => \$opts{dumpdb}, 'unresolved' => \$opts{unresolved}, 'mergedb' => \$opts{mergedb}, 'expiredb' => \$opts{expiredb}, 'database' => \$opts{database} ); # When changing %optctl, @optlst should be updated also my @optlst = ('', 'h', 'help', 'v', 'version', 'n', 'nostats', 'r', 'recursive', 'p', 'progress', 'd=i', 'debug=i', 'm=s', 'mask=s', 'l=i', 'linecache=i', 't=i', 'timeout=i', 's=i', 'sockets=i', 'database=s', 'a', 'anywhere', 'dbfirst', 'dbonly', 'dumpdb', 'unresolved', 'mergedb', 'expiredb=i'); # Usage information my $usage =<] [--debug=] [-m ] [--mask=] [-l ] [--linecache=] [-t ] [--timeout=] [-s ] [--sockets=] [--progress] [--dbfirst] [--dbonly] [--dumpdb] [--unresolved] [--mergedb] [--expiredb=] [--database=] Report bugs to $BUGS EOF # Version information my $version =< or -d debug mode (no file output, just statistics during run). verbosity level range: 1-2 --timeout= or -t timeout in seconds (for each host resolution). default is 30 seconds --sockets= or -s maximum number of concurrent sockets to use. (use ulimit -a to check the max allowed for your operating system) default is 64 --mask= or -m accepts %i for IP and %c for class owner. ex: "somewhere.in.%c" or "%i.in.%c" default if "%i.%c" --linecache= or -l numbers of lines to cache in memory. default is 10000 --unresolved don't resolve anything, just dump the unresolved hosts to STDOUT --database= path to database that holds resolved hosts/classes --dbfirst check if we have a cached resolved host/class in the database before sending a DNS query --dbonly don't send DNS queries, use only cached data in the database --dumpdb dumps a database to STDOUT --mergedb merges input to a database --expiredb= expires database entries older than hours the log filename or '-' for STDIN EOF exit; } if ($opts{version}) { # Version requested, print and exit print < -1) and !$opts{database}) { print < 0, RECEIVED => 0, BOGUS => 0, RESOLVED => 0, HRESOLVED => 0, TIMEOUT => 0, STARTTIME => time(), MAXTIME => 0, TOTTIME => 0, TOTLINES => 0, TOTHOSTS => 0); # holds run time statistics unless ($opts{dumpdb} or $opts{expiredb} > -1) { # Check if the filename exists $filename ne '-' and !-f $filename and die "can't find log file '$filename'"; # Try to open the file open FILE, $filename or die "error trying to open log file '$filename'"; } # If a database is used, try to open it and tie it to %DB $opts{database} ne '' and (tie(%DB, 'DB_File', $opts{database}) or die "can't open database '$opts{database}'"); #$opts{database} ne '' and (tie(%DB, 'GDBM_File', $opts{database}, &GDBM_WRCREAT, 0644) or die "can't open database '$opts{database}'"); $opts{dumpdb} and dumpdb(), exit; $opts{mergedb} and mergedb(), exit; $opts{expiredb} > -1 and expiredb(), exit; $opts{unresolved} and unresolved(), exit; # MAIN LOOP while (1) { getlines(); # read lines from input log file $#lines == -1 and last; # no lines after read? we're done! makequeries(); # send async dns queries checkresponse(); # check for dns responses checktimeouts(); # check for dns timeouts printresults(); # print whatever we have resolved } printstats(); # print the session stats before we leave # MAIN EXIT exit; # SUBROUTINES sub debug { # debug(message, level) # Prints debug messages # message: any text message # level: the minimun debug level to print the message # RETURNS: 0 if no message printed # 1 if message was printed my ($message, $level) = @_; $opts{debug} < $level and return 0; print STDERR time(), "--> $message\n"; return 1; } sub dumpdb { # dumpdb() # Dumps a database to STDOUT # RETURNS: 1 (always) my $i = 1; for (%DB) { if ($i++ % 2) { print "$_ "; } else { print "$_\n"; } } return 1; } sub mergedb { # mergedb() # Merges a file containing IP/hostname pairs to a database # RETURNS: 1 (always) while () { my ($ipclass, $name) = split /\s+/; $DB{$ipclass} = join(' ', ($name, 'M', time())); } return 1; } sub expiredb { # expiredb() # Expires entries in the database # RETURNS: 1 (always) my $currtime = time(); my ($i, $t) = (0, 0); for (keys %DB) { my ($name, $type, $time) = dbread($_); if ($currtime - $time > $opts{expiredb} * 3600) { delete $DB{$_}; $i++; } else { $t++; } } print STDERR "Expired $i database entries, $t left in the database\n"; return 1; } sub unresolved { # unresolved() # Dumps the unresolved IPs from a file # RETURNS: 1 (always) my %ips; while () { !/$ipmask\s/ and next; my $ip = "$1.$2.$3.$4"; exists $ips{$ip} and next; $ips{$ip} = 1; print "$ip\n"; } return 1; } sub dbread { # dbread(key) # Reads data from the database # key: an IP address or class # RETURNS: (name, type, time) if lookup succeeds # (undef, undef, undef) if lookup failed my $key = shift; !$opts{database} and return (undef, undef, undef); !(exists $DB{$key}) and return (undef, undef, undef); my $fromdb = $DB{$key}; return split(/ /, $fromdb); } sub dbwrite { # dbwrite(key, name, type) # Writes data to the database # key: an IP address or class # name: the resolved name # type: N = nameserver, R = recursed, M = manual # RETURNS: 1 if using a DB # 0 if not using a DB my ($key, $name, $type) = @_; !$opts{database} and return 0; # Don't write back stuff that came from the db $type eq 'D' and return 1; $DB{$key} = join(' ', ($name, $type, time())); return 1; } sub addhost { # addhost(ip) # Adds a host to the cache/queue # ip: an IP address (x.y.z.k) # RETURNS: 1 (always) # Valid values for a {RESOLVED} field: # 'p' - pending # 'r' - pending recursion # 'F' - failed # 'D' - resolved from db # 'N' - resolved from nameserver # 'R' - resolved thru recursion my $ip = shift; debug("Adding host: $ip", 2); if (exists $hosts{$ip}) { # Host already queued, just increment the reference count $hosts{$ip}{COUNT}++; } else { # Add host to queue $hosts{$ip}{COUNT} = 1; $hosts{$ip}{SOCKET} = undef; $hosts{$ip}{RESOLVED} = 'p'; ($hosts{$ip}{DBNAME}, $hosts{$ip}{DBTYPE}, $hosts{$ip}{DBTIME}) = dbread($ip); $stats{TOTHOSTS}++; if ($opts{dbfirst} and defined $hosts{$ip}{DBNAME}) { $hosts{$ip}{NAME} = $hosts{$ip}{DBNAME}; $hosts{$ip}{RESOLVED} = 'D'; debug("host from db: $ip $hosts{$ip}{NAME}", 2); } else { if ($opts{dbonly}) { $hosts{$ip}{RESOLVED} = 'F'; } else { push @q, $ip; } } } return 1; } sub removehost { # removehost(ip) # Removes a host from the cache # ip: an IP address (x.y.z.k) # RETURNS: 1 (always) my $ip = shift; if ($opts{progress}) { if ($progresschars % 50 == 0) { printf STDERR "\n%10d: ", $progresschars; } $progresschars++; my $status = $hosts{$ip}{RESOLVED}; $status =~ tr/NRD/.rd/; print STDERR $status; } # Decrement reference count if (--$hosts{$ip}{COUNT} < 1) { # No more references, so remove host from cache # Check if host was resolved if (index('DNR', $hosts{$ip}{RESOLVED}) >= 0) { $stats{HRESOLVED}++; dbwrite($ip, $hosts{$ip}{NAME}, $hosts{$ip}{RESOLVED}); } freesocket($hosts{$ip}{SOCKET}); delete $hosts{$ip}; debug("Removed host: $ip", 2); } return 1; } sub addclass { # addclass(ip) # Adds the classes of a host to the cache/queue # ip: an IP address (x.y.z.k) # RETURNS: 1 (always) # Valid values for a {RESOLVED} field: # 'p' - pending # 'F' - failed # 'D' - resolved from db # 'N' - resolved from nameserver my $ip = shift; $ip =~ /$ipmask/; # Extract the classes this host belongs to and queue them for ("$1.$2.$3", "$1.$2", "$1") { debug("Adding class: $_", 2); if (exists $class{$_}) { # Class already queued, just increment the reference count $class{$_}{COUNT}++; } else { # Add class to queue $class{$_}{COUNT} = 1; $class{$_}{SOCKET} = undef; $class{$_}{RESOLVED} = 'p'; ($class{$_}{DBNAME}, $class{$_}{DBTYPE}, $class{$_}{DBTIME}) = dbread($_); if ($opts{dbfirst} and defined $class{$_}{DBNAME}) { $class{$_}{NAME} = $class{$_}{DBNAME}; $class{$_}{RESOLVED} = 'D'; debug("class from db: $_ $class{$_}{NAME}", 2); } else { if ($opts{dbonly}) { $class{$_}{RESOLVED} = 'F'; } else { # prioritize class in the queue unshift @q, $_; } } } } return 1; } sub removeclass { # removeclass(ip) # Removes all classes from an ip from the cache # ip: an IP address (x.y.z.k) # RETURNS: 1 (always) my $ip = shift; $ip =~ /$ipmask/; for ("$1.$2.$3", "$1.$2", "$1") { if (--$class{$_}{COUNT} < 1) { # Last reference, if resolved store to db $class{$_}{RESOLVED} eq 'N' and dbwrite($_, $class{$_}{NAME}, $class{$_}{RESOLVED}); freesocket($class{$_}{SOCKET}); delete $class{$_}; debug("Removed class: $_", 2); } } return 1; } sub checkrecurse { # checkrecurse(ip) # Checks for classes if normal resolve failed # ip: an IP address (x.y.z.k) # RETURNS: 1 (always) my $ip = shift; debug("Check recurse $ip", 2); $ip =~ /$ipmask/; for ("$1.$2.$3", "$1.$2", "$1") { # if still resolving class, return $class{$_}{RESOLVED} eq 'p' and return 1; # class was resolved, return class name if ($class{$_}{RESOLVED} ne 'F') { $hosts{$ip}{NAME} = maskthis($ip, $class{$_}{NAME}); $hosts{$ip}{RESOLVED} = 'R'; removeclass($ip); return 1; } # NOTE: The order of the classes is important. If we have a # class C resolved, no need to wait for the upper classes } # No luck, mark as failed $hosts{$ip}{RESOLVED} = 'F'; removeclass($ip); return 1; } sub maskthis { # maskthis(ip, class) # Masks a fake hostname based on an IP and a resolved class # ip: an IP address (x.y.z.k) # class: the class name (somewhere.com) # RETURNS: a masked representation of the IP (x.y.z.k.somewhere.com) my ($ip, $domain) = @_; my $masked = $opts{mask}; $masked =~ s/%i/$ip/; $masked =~ s/%c/$domain/; return $masked; } sub getlines { # getlines() # Fetches lines from the file into our line buffer # RETURNS: 1 if something was read, 0 if EOF eof(FILE) and return 0; my $line; while ($#lines < $opts{linecache} - 1 and $line = ) { my @hosts; while ($line =~ /$ipmask/g) { push @hosts, "$1.$2.$3.$4"; addhost("$1.$2.$3.$4"); } $stats{TOTLINES}++; push @lines, { TEXT => $line, HOSTS => \@hosts }; } return 1; } sub makequeries { # makequeries() # Takes IPs and classes from the queue and sends them to the query # function. This controls the number of sockets in use. # RETURNS: 1 (always) for (1..($opts{sockets} - $sel->count)) { my $query = $q[0]; !$query and last; my $ok = 0; if ($query =~ /$ipmask/) { $ok = query($query, 'H'); } elsif (exists $class{$query}) { $ok = query($query, 'C'); } else { debug("Out of context class $query was skipped", 3); $ok = 1; } $ok ? shift @q : last; } return 1; } sub freesocket { # freesocket(socket) # Frees a socket from our main select and the socket itself # RETURNS: 1 if freed # 0 if socket didn't exist my $socket = shift; !(defined $socket) and return 0; $sel->remove($socket); my $type = $socks{fileno($socket)}{TYPE}; my $query = $socks{fileno($socket)}{QUERY}; if ($type eq 'H') { !exists $hosts{$query} and die "no such host: $query"; undef $hosts{$query}{SOCKET}; } else { !exists $class{$query} and die "no such class: $query"; undef $class{$query}{SOCKET}; } delete $socks{fileno($socket)}; debug("Freed socket for query $query - socket count: " . (keys %socks) . " - " . $sel->count, 2); return 1; } sub nsfailed { # nsfailed(query, type) # Updates statuses when nameserver resolution fails # (bogus reply or timeout) # query: the DNS query # type: H for host or C for class # RETURNS: 1 (always) my ($query, $type) = @_; if ($type eq 'H') { if (defined $hosts{$query}{DBNAME}) { $hosts{$query}{NAME} = $hosts{$query}{DBNAME}; $hosts{$query}{RESOLVED} = 'D'; } elsif ($opts{recursive}) { $hosts{$query}{RESOLVED} = 'r'; addclass($query); } else { $hosts{$query}{RESOLVED} = 'F'; } } else { if (defined $class{$query}{DBNAME}) { $class{$query}{NAME} = $class{$query}{DBNAME}; $class{$query}{RESOLVED} = 'D'; } else { $class{$query}{RESOLVED} = 'F'; } } return 1; } sub checkresponse { # checkresponse() # Checks sockets for DNS replies and processes them # RETURNS: 1 (always) # Check pending replies, give it 5 seconds at most for ($sel->can_read(5)) { my $resolved = 0; my $fileno = fileno($_); my $query = $socks{$fileno}{QUERY}; my $type = $socks{$fileno}{TYPE}; my $timespan = time() - $socks{$fileno}{TIME}; $stats{TOTTIME} += $timespan; my $packet = $res->bgread($_); $stats{RECEIVED}++; debug("Response for query $query (" . $sel->count . ")", 2); # Got the reply and saved the results, so free the socket freesocket($_); if ($packet) { for ($packet->answer) { # For each DNS answer, check the data received if ($type eq 'H') { if (defined $_->{ptrdname}) { $hosts{$query}{NAME} = $_->{ptrdname}; $hosts{$query}{RESOLVED} = 'N'; $resolved = 1; debug("response HOST: $query is " . $hosts{$query}{NAME}, 2); } else { debug("undefined response for query $query", 2); } } else { my $fulldomain; # Check for the previously used SOA records and # the current NS records if ($_->type eq 'SOA') { $fulldomain = $_->{mname}; } elsif ($_->type eq 'NS') { $fulldomain = $_->{nsdname}; } else { next; } debug("Class: $fulldomain", 3); my ($ns, $domain) = $fulldomain =~ /([^\.]+)\.(.*)/; if (defined $domain) { # Avoid truncating records with no machine name $domain =~ /\./ or $domain = $fulldomain; $class{$query}{NAME} = lc $domain; $class{$query}{RESOLVED} = 'N'; $resolved = 1; } } } } if ($resolved) { $stats{RESOLVED}++; $timespan > $stats{MAXTIME} and $stats{MAXTIME} = $timespan; } else { $stats{BOGUS}++; nsfailed($query, $type); } } return 1; } sub checktimeouts { # checktimeouts() # Checks sockets for DNS reply timeouts # RETURNS: 1 (always) my $now = time(); for ($sel->handles) { # Iterate through all active sockets my $fileno = fileno($_); my $query = $socks{$fileno}{QUERY}; my $type = $socks{$fileno}{TYPE}; my $timespan = $now - $socks{$fileno}{TIME}; if ($timespan > $opts{timeout}) { # We have a timeout $stats{TIMEOUT}++; $stats{TOTTIME} += $timespan; # Mark query owner appropriately nsfailed($query, $type); freesocket($_); } } return 1; } sub printresults { # printresults() # Checks if the next lines in our buffer have their IPs resolved # and print the results to STDOUT # RETURNS: 1 (always) debug("Sent: $stats{SENT}, Received: $stats{RECEIVED}, Resolved: $stats{RESOLVED}, Bogus: $stats{BOGUS}, Timeout: $stats{TIMEOUT}", 1); while ($#lines != -1) { # We still have lines in the cache my %line = %{$lines[0]}; !@{$line{HOSTS}} and print($line{TEXT}), shift @lines, next; for (@{$line{HOSTS}}) { # Check all hosts for this line (pending, recursing) $hosts{$_}{RESOLVED} eq 'r' and checkrecurse($_); index('pr', $hosts{$_}{RESOLVED}) >= 0 and goto done; } # Nothing pending for this line if we got here for (@{$line{HOSTS}}) { # Update line with resolved hosts $hosts{$_}{RESOLVED} ne 'F' and $line{TEXT} =~ s/$_/$hosts{$_}{NAME}/; # We don't need this host anymore removehost($_); } print $line{TEXT}; shift @lines; } done: } sub printstats { # printstats() # Print the statistics gathered during program run # RETURNS: 1 (always) $opts{nostats} and return; $opts{progress} and print STDERR "\n\n"; my $timespan = time() - $stats{STARTTIME}; print STDERR " Total Lines: $stats{TOTLINES}\n", " Total Time : ", strftime("%H:%M:%S", gmtime($timespan)), " (", sprintf("%.2f", $timespan ? ($stats{TOTLINES} / $timespan) : 0), " lines/s)\n", " Total Hosts: $stats{TOTHOSTS}\n", " Resolved Hosts: $stats{HRESOLVED} (", sprintf("%.2f", $stats{TOTHOSTS} ? ($stats{HRESOLVED} / $stats{TOTHOSTS} * 100) : 0), "%)\n", "Unresolved Hosts: ", $stats{TOTHOSTS} - $stats{HRESOLVED}, " (", sprintf("%.2f", $stats{TOTHOSTS} ? (($stats{TOTHOSTS} - $stats{HRESOLVED}) / $stats{TOTHOSTS} * 100) : 0), "%)\n", "Average DNS time: ", sprintf("%.4f", $stats{SENT} ? ($stats{TOTTIME} / $stats{SENT}) : 0), "s per request\n", " Max DNS time: ", $stats{MAXTIME}, "s (consider this value for your timeout)\n"; debug("\n\nhosts: " . scalar(keys %hosts) . "\nclasses: " . scalar(keys %class) . "\nselect: " . $sel->count . "\n", 1); return 1; } sub query { # query() # Sends out an assynchronous DNS query # RETURNS: 1 if successful # 0 if failed (no free sockets) my ($find, $type) = @_; my $send = ($type eq 'H') ? $find : (join('.', reverse(split(/\./, $find))) . '.in-addr.arpa'); # Send a query of format PTR for hosts or NS for classes my $sock = $res->bgsend($send, ($type eq 'H') ? 'PTR' : 'NS'); if (!$sock) { # We're out of sockets. Warn the user and continue print STDERR "Error opening socket for bgsend. Are we out of sockets?\n"; return 0; } $stats{SENT}++; $sel->add($sock); # Make a socket record for cross referencing my $fileno = fileno($sock); $socks{$fileno}{TIME} = time(); $socks{$fileno}{QUERY} = $find; $socks{$fileno}{TYPE} = $type; debug("Sent query of type $type: $find", 2); # Update the owner of the socket also for easy referencing $type eq 'H' ? ($hosts{$find}{SOCKET} = $sock) : ($class{$find}{SOCKET} = $sock); return 1; } jdresolve-0.6.1.orig/jdresolve.10100600000175000001440000002142707172547274015572 0ustar mvelausers.rn '' }` ''' $RCSfile$$Revision$$Date$ ''' ''' $Log$ ''' .de Sh .br .if t .Sp .ne 5 .PP \fB\\$1\fR .PP .. .de Sp .if t .sp .5v .if n .sp .. .de Ip .br .ie \\n(.$>=3 .ne \\$3 .el .ne 3 .IP "\\$1" \\$2 .. .de Vb .ft CW .nf .ne \\$1 .. .de Ve .ft R .fi .. ''' ''' ''' Set up \*(-- to give an unbreakable dash; ''' string Tr holds user defined translation string. ''' Bell System Logo is used as a dummy character. ''' .tr \(*W-|\(bv\*(Tr .ie n \{\ .ds -- \(*W- .ds PI pi .if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch .if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch .ds L" "" .ds R" "" ''' \*(M", \*(S", \*(N" and \*(T" are the equivalent of ''' \*(L" and \*(R", except that they are used on ".xx" lines, ''' such as .IP and .SH, which do another additional levels of ''' double-quote interpretation .ds M" """ .ds S" """ .ds N" """"" .ds T" """"" .ds L' ' .ds R' ' .ds M' ' .ds S' ' .ds N' ' .ds T' ' 'br\} .el\{\ .ds -- \(em\| .tr \*(Tr .ds L" `` .ds R" '' .ds M" `` .ds S" '' .ds N" `` .ds T" '' .ds L' ` .ds R' ' .ds M' ` .ds S' ' .ds N' ` .ds T' ' .ds PI \(*p 'br\} .\" If the F register is turned on, we'll generate .\" index entries out stderr for the following things: .\" TH Title .\" SH Header .\" Sh Subsection .\" Ip Item .\" X<> Xref (embedded .\" Of course, you have to process the output yourself .\" in some meaninful fashion. .if \nF \{ .de IX .tm Index:\\$1\t\\n%\t"\\$2" .. .nr % 0 .rr F .\} .TH JDRESOLVE 1 "perl 5.005, patch 03" "16/Oct/2000" "User Contributed Perl Documentation" .UC .if n .hy 0 .if n .na .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .de CQ \" put $1 in typewriter font .ft CW 'if n "\c 'if t \\&\\$1\c 'if n \\&\\$1\c 'if n \&" \\&\\$2 \\$3 \\$4 \\$5 \\$6 \\$7 '.ft R .. .\" @(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2 . \" AM - accent mark definitions .bd B 3 . \" fudge factors for nroff and troff .if n \{\ . ds #H 0 . ds #V .8m . ds #F .3m . ds #[ \f1 . ds #] \fP .\} .if t \{\ . ds #H ((1u-(\\\\n(.fu%2u))*.13m) . ds #V .6m . ds #F 0 . ds #[ \& . ds #] \& .\} . \" simple accents for nroff and troff .if n \{\ . ds ' \& . ds ` \& . ds ^ \& . ds , \& . ds ~ ~ . ds ? ? . ds ! ! . ds / . ds q .\} .if t \{\ . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' . ds ? \s-2c\h'-\w'c'u*7/10'\u\h'\*(#H'\zi\d\s+2\h'\w'c'u*8/10' . ds ! \s-2\(or\s+2\h'-\w'\(or'u'\v'-.8m'.\v'.8m' . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' . ds q o\h'-\w'o'u*8/10'\s-4\v'.4m'\z\(*i\v'-.4m'\s+4\h'\w'o'u*8/10' .\} . \" troff and (daisy-wheel) nroff accents .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' .ds 8 \h'\*(#H'\(*b\h'-\*(#H' .ds v \\k:\h'-(\\n(.wu*9/10-\*(#H)'\v'-\*(#V'\*(#[\s-4v\s0\v'\*(#V'\h'|\\n:u'\*(#] .ds _ \\k:\h'-(\\n(.wu*9/10-\*(#H+(\*(#F*2/3))'\v'-.4m'\z\(hy\v'.4m'\h'|\\n:u' .ds . \\k:\h'-(\\n(.wu*8/10)'\v'\*(#V*4/10'\z.\v'-\*(#V*4/10'\h'|\\n:u' .ds 3 \*(#[\v'.2m'\s-2\&3\s0\v'-.2m'\*(#] .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] .ds ae a\h'-(\w'a'u*4/10)'e .ds Ae A\h'-(\w'A'u*4/10)'E .ds oe o\h'-(\w'o'u*4/10)'e .ds Oe O\h'-(\w'O'u*4/10)'E . \" corrections for vroff .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' . \" for low resolution devices (crt and lpr) .if \n(.H>23 .if \n(.V>19 \ \{\ . ds : e . ds 8 ss . ds v \h'-1'\o'\(aa\(ga' . ds _ \h'-1'^ . ds . \h'-1'. . ds 3 3 . ds o a . ds d- d\h'-1'\(ga . ds D- D\h'-1'\(hy . ds th \o'bp' . ds Th \o'LP' . ds ae ae . ds Ae AE . ds oe oe . ds Oe OE .\} .rm #[ #] #H #V #F C .SH "NAME" jdresolve \- resolves IP addresses into hostnames .SH "SYNOPSIS" \fBjdresolve\fR [\-h] [\-v] [\-n] [\-r] [\-a] [\-d ] [\-m ] [\-l ] [\-t ] [\-p] [\-s ] [--database=] <\fILOG FILE\fR> .PP \fBjdresolve\fR [--help] [--version] [--nostats] [--recursive] [--anywhere] [--debug=] [--mask=] [--linecache=] [--timeout=] [--sockets=] [--database=] [--dbfirst] [--dbonly] [--dumpdb] [--mergedb] [--expiredb=] [--unresolved] [--progress] <\fILOG FILE\fR> .SH "DESCRIPTION" \fBjdresolve\fR resolves IP addresses to hostnames. Any file format is supported, including those where the line does not begin with the IP address. One of the strongest features of the program is the support for recursion, which can drastically reduce the number of unresolved hosts by faking a hostname based on the network that the IP belongs to. DNS queries are sent in parallel, which means that you can decrease run time by increasing the number of simultaneous sockets used (given a fast enough machine and available bandwidth ). By using the database support, performance can be increased even further, by using cached data from previous runs. .SH "OPTIONS" .Ip "\fB\-h, --help\fR" 8 produces a short help message .Ip "\fB\-v, --version\fR" 8 display version information .Ip "\fB\-n, --no-stats\fR" 8 don't display stats after processing .Ip "\fB\-r, --recursive\fR" 8 recurse into C, B and A classes when there is no \s-1PTR\s0 (default is no recursion) .Ip "\fB\-d, --debug=" 8 debug mode \- no file output, just statistics during run (verbosity level range: 1-3) .Ip "\fB\-t, --timeout=" 8 timeout in seconds for each host resolution (default is 30 seconds) .Ip "\fB\-l, --line-cache=" 8 numbers of lines to cache in memory (default is 10000 .Ip "\fB\-s, --sockets=" 8 maximum number of concurrent sockets (use ulimit \-a to check the max allowed for your operating system \- defaults to 64) .Ip "\fB\-m, --mask=" 8 accepts \f(CW%i\fR for \s-1IP\s0 and \f(CW%c\fR for class owner, e.g. \*(L"somewhere.in.%c\*(R" or \*(L"%i.in.%c\*(R" (default is \*(L"%i.%c") .Ip "\fB\-a, --anywhere\fR" 8 resolves IPs found anywhere on a line (will resolve all IPs if there is more than one) .Ip "\fB\-p, --progress\fR" 8 prints a nice progress bar indicating the status of the resolve operations .Ip "\fB--database=" 8 path to database that holds resolved hosts/classes .Ip "\fB--dbfirst\fR" 8 check if we have resolved entries in the database before sending out \s-1DNS\s0 queries .Ip "\fB--dbonly\fR" 8 don't send \s-1DNS\s0 queries, use only resolved data in the database .Ip "\fB--dumpdb\fR" 8 dumps a database to \s-1STDOUT\s0 .Ip "\fB--mergedb\fR" 8 merges resolved \s-1IP/\s0classes from a file (or \s-1STDIN\s0) with a database .Ip "\fB--expiredb=" 8 expires entries in the database that are older than hours .Ip "\fB--unresolved\fR" 8 won't attempt to resolve IPs, only lists those that were not resolved .Ip "\fB<\s-1LOG\s0 \s-1FILE\s0\fR>" 8 the log filename or \*(L'\-\*(R' for \s-1STDIN\s0 .SH "EXAMPLES" .Sp .Vb 3 \& jdresolve access_log > resolved_log \& jdresolve -r -s 128 access_log > resolved_log \& jdresolve -r --database hosts.db access_log > res_log .Ve .SH "SEE ALSO" \fIrhost\fR\|(1) .SH "AUTHOR" \fBjdresolve\fR was written by John D. Rowell , and is licensed under the terms of the GNU General Public License. .Sp The original version of this man page was written by Craig Sanders , for the Debian GNU/Linux package of jdresolve, and is also licensed under the terms of the GNU GPL. .rn }` '' .IX Title "JDRESOLVE 1" .IX Name "jdresolve - resolves IP addresses into hostnames" .IX Header "NAME" .IX Header "SYNOPSIS" .IX Header "DESCRIPTION" .IX Header "OPTIONS" .IX Item "\fB\-h, --help\fR" .IX Item "\fB\-v, --version\fR" .IX Item "\fB\-n, --no-stats\fR" .IX Item "\fB\-r, --recursive\fR" .IX Item "\fB\-d, --debug=" .IX Item "\fB\-t, --timeout=" .IX Item "\fB\-l, --line-cache=" .IX Item "\fB\-s, --sockets=" .IX Item "\fB\-m, --mask=" .IX Item "\fB\-a, --anywhere\fR" .IX Item "\fB\-p, --progress\fR" .IX Item "\fB--database=" .IX Item "\fB--dbfirst\fR" .IX Item "\fB--dbonly\fR" .IX Item "\fB--dumpdb\fR" .IX Item "\fB--mergedb\fR" .IX Item "\fB--expiredb=" .IX Item "\fB--unresolved\fR" .IX Item "\fB<\s-1LOG\s0 \s-1FILE\s0\fR>" .IX Header "EXAMPLES" .IX Header "SEE ALSO" .IX Header "AUTHOR" jdresolve-0.6.1.orig/jdresolve.1.gz0100644000175000001440000000725707172547274016226 0ustar mvelausers99[[HWzHdY6  #N&1C[j]L3~eR[<ۆ,?wg 杜E&碔 ҩ9r&2I$X]wwUJC 1ZjG0}Fsi4Q.Ip."K̫gOf% '&h9? c*v4fd}r-".wq⪟JDrҁ"9QO+t*-% [˒|Kz*G5dܜ\`+[3i`Or/r2mkz^k(ÚXkb=,ވN0|9@Y ^"Ss/?{J4|UbX2!Hs&Q>RD3_b8,1xttq)"lcTM qa1TG'r-'7xiri3F, ePE4KIPE`NAV[ CR 7hq^Krx=A+Ah%btsd@&0~q+w^g(qdIUyU1ڛ;3){ j>m8svmNoE@r<$P.mr=_e<6ٲڀۧGwVu2<;pxavO4wgao L(G9KX|xM ʟbNO6 tSH[wM%YG9 8{fA_q|@٦AWݶrY r{qg%ޒ%8RqkRzSW5 ~R`W}>=#w?"jnŬevZΫUK]Rv-S~o7?EyCy u R`;ק?EGߑVx%t}Њ!ֶ1(4 D6n v(X-mS1?Ai?'1l̎f5]j=티XtgRFq9 hm鰚4|r8 ,@ ôaiքU9i%?a2^]2={$,`w@rηGũ+t@0'qw_)]R+qfG;.h|}"N+X6!}5;8@!e):¹ rߴ!V/gKmC4A_O l{`ZaRc ̸@}>?{NiwBPljH1{7M<^4, o/'R?" BQ]M=:w~WSGO5A ״Zc?kZ#KIٌyzuZH: Xy^ܙTrc:6pKh]hYjض]NǤx-DIJPȣ G-4۝o?>ߠNpnBG(>h  o&O^eKJvO5GI z4+]}ev(Dȟ 3ܲ`xu ^]'fLF=2{'hQ-+/D\@"V"19-4Jt+rsQ'hAV+Oji/ O:IQQ=$|Lb^L"&2BEذS%N*z*Q$'.ٜnZzB^!ӐDXТ:i&;-JwƉ#NT/%$0' NCO*FKT8K[Oj'8R"kI*rLSKꒇ(Ͼa 31i/-87d-KKb*xsHaEbzVP5bBIe0..IulȉD4 5gsa$~4NG(F::~Z ݎﰁ^\,c`[GlJ%8Q,kDG(YB +~%l&i @~^SĨp!4 #^2:kbBMT}gp#HY( 5K5:B%)biaÿC X|X4C|PDQsٯ/B*ĉmxK~ļMvOHiK:SG?)S'LeT>W/rӸfj.Ht1e%(?cP ڏab7'2𸩐aJ!#LMH8&6ǂSIS.tF}Y=e1k~PPťkW&UգhѵoRKqzk"T.X9ty[aH=Jdgv:/z2X+B4sOe-295u1yV]1P鰭# cqc#IkgNQ-#KchNwK- =RweuzT%愬Txy2uR:8 fH@Y3:"s!7ES6I:m.wvLTYp:~@%ɳgQj*?I-O@9०?86ҳ8uЩq0`\~^n愄pl;jnX&&_,s0c::K.e3LB9~&#.L;ක 8XW aێ闕&-#FN!v [5^9T~TMׯZ-Տ\沿¯,ܹVvꞕW鷱:׵ݧZf|%\vk sZVǟ@|-3{oekmQ%k@.Soe$:#jdresolve-0.6.1.orig/jdresolve.in0100755000175000001440000006372407172535020016043 0ustar mvelausers#!/usr/bin/perl -w # jdresolve - Resolves IP addresses into hostnames # # Copyright (c) 1999-2000 John D. Rowell # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. =head1 NAME jdresolve - resolves IP addresses into hostnames =head1 SYNOPSIS B [-h] [-v] [-n] [-r] [-a] [-d ] [-m ] [-l ] [-t ] [-p] [-s ] [--database=] > B [--help] [--version] [--nostats] [--recursive] [--anywhere] [--debug=] [--mask=] [--linecache=] [--timeout=] [--sockets=] [--database=] [--dbfirst] [--dbonly] [--dumpdb] [--mergedb] [--expiredb=] [--unresolved] [--progress] > =head1 DESCRIPTION B resolves IP addresses to hostnames. Any file format is supported, including those where the line does not begin with the IP address. One of the strongest features of the program is the support for recursion, which can drastically reduce the number of unresolved hosts by faking a hostname based on the network that the IP belongs to. DNS queries are sent in parallel, which means that you can decrease run time by increasing the number of simultaneous sockets used (given a fast enough machine and available bandwidth ). By using the database support, performance can be increased even further, by using cached data from previous runs. =head1 OPTIONS =over 8 =item B<-h, --help> produces a short help message =item B<-v, --version> display version information =item B<-n, --no-stats> don't display stats after processing =item B<-r, --recursive> recurse into C, B and A classes when there is no PTR (default is no recursion) =item B<-d, --debug=> debug mode - no file output, just statistics during run (verbosity level range: 1-3) =item B<-t, --timeout=> timeout in seconds for each host resolution (default is 30 seconds) =item B<-l, --line-cache=> numbers of lines to cache in memory (default is 10000 =item B<-s, --sockets=> maximum number of concurrent sockets (use ulimit -a to check the max allowed for your operating system - defaults to 64) =item B<-m, --mask=> accepts %i for IP and %c for class owner, e.g. "somewhere.in.%c" or "%i.in.%c" (default is "%i.%c") =item B<-a, --anywhere> resolves IPs found anywhere on a line (will resolve all IPs if there is more than one) =item B<-p, --progress> prints a nice progress bar indicating the status of the resolve operations =item B<--database=> path to database that holds resolved hosts/classes =item B<--dbfirst> check if we have resolved entries in the database before sending out DNS queries =item B<--dbonly> don't send DNS queries, use only resolved data in the database =item B<--dumpdb> dumps a database to STDOUT =item B<--mergedb> merges resolved IP/classes from a file (or STDIN) with a database =item B<--expiredb=> expires entries in the database that are older than hours =item B<--unresolved> won't attempt to resolve IPs, only lists those that were not resolved =item B<> the log filename or '-' for STDIN =head1 EXAMPLES jdresolve access_log > resolved_log jdresolve -r -s 128 access_log > resolved_log jdresolve -r --database hosts.db access_log > res_log =head1 SEE ALSO rhost(1) =head1 AUTHOR B was written by John D. Rowell , and is licensed under the terms of the GNU General Public License. The original version of this man page was written by Craig Sanders , for the Debian GNU/Linux package of jdresolve, and is also licensed under the terms of the GNU GPL. =cut # Require variable declaration use strict; # Load the needed modules use Net::DNS; # installed separately use IO::Select; use Getopt::Long; use POSIX qw(strftime); use DB_File; #use GDBM_File; # Global constants my $APPNAME = 'jdresolve'; my $VERSION = '0.6.1'; my $AUTHOR = 'John D. Rowell'; my $YEAR = '1999-2000'; my $BUGS = 'bugs@jdrowell.com'; # Defaults for command line options my %opts = ( stdin => 0, help => 0, version => 0, nostats => 0, recursive => 0, debug => 0, mask => '%i.%c', linecache => 10000, timeout => 30, sockets => 64, database => '', anywhere => 0, dbfirst => 0, dbonly => 0, dumpdb => 0, unresolved => 0, mergedb => 0, expiredb => -1, progress => 0); # Recognized command line options my %optctl = ( '' => \$opts{stdin}, 'h' => \$opts{help}, 'help' => \$opts{help}, 'v' => \$opts{version}, 'version' => \$opts{version}, 'n' => \$opts{nostats}, 'nostats' => \$opts{nostats}, 'r' => \$opts{recursive}, 'recursive' => \$opts{recursive}, 'd' => \$opts{debug}, 'debug' => \$opts{debug}, 'm' => \$opts{mask}, 'mask' => \$opts{mask}, 'l' => \$opts{linecache}, 'linecache' => \$opts{linecache}, 't' => \$opts{timeout}, 'timeout' => \$opts{timeout}, 's' => \$opts{sockets}, 'sockets' => \$opts{sockets}, 'a' => \$opts{anywhere}, 'anywhere' => \$opts{anywhere}, 'p' => \$opts{progress}, 'progress' => \$opts{progress}, 'dbfirst' => \$opts{dbfirst}, 'dbonly' => \$opts{dbonly}, 'dumpdb' => \$opts{dumpdb}, 'unresolved' => \$opts{unresolved}, 'mergedb' => \$opts{mergedb}, 'expiredb' => \$opts{expiredb}, 'database' => \$opts{database} ); # When changing %optctl, @optlst should be updated also my @optlst = ('', 'h', 'help', 'v', 'version', 'n', 'nostats', 'r', 'recursive', 'p', 'progress', 'd=i', 'debug=i', 'm=s', 'mask=s', 'l=i', 'linecache=i', 't=i', 'timeout=i', 's=i', 'sockets=i', 'database=s', 'a', 'anywhere', 'dbfirst', 'dbonly', 'dumpdb', 'unresolved', 'mergedb', 'expiredb=i'); # Usage information my $usage =<] [--debug=] [-m ] [--mask=] [-l ] [--linecache=] [-t ] [--timeout=] [-s ] [--sockets=] [--progress] [--dbfirst] [--dbonly] [--dumpdb] [--unresolved] [--mergedb] [--expiredb=] [--database=] Report bugs to $BUGS EOF # Version information my $version =< or -d debug mode (no file output, just statistics during run). verbosity level range: 1-2 --timeout= or -t timeout in seconds (for each host resolution). default is 30 seconds --sockets= or -s maximum number of concurrent sockets to use. (use ulimit -a to check the max allowed for your operating system) default is 64 --mask= or -m accepts %i for IP and %c for class owner. ex: "somewhere.in.%c" or "%i.in.%c" default if "%i.%c" --linecache= or -l numbers of lines to cache in memory. default is 10000 --unresolved don't resolve anything, just dump the unresolved hosts to STDOUT --database= path to database that holds resolved hosts/classes --dbfirst check if we have a cached resolved host/class in the database before sending a DNS query --dbonly don't send DNS queries, use only cached data in the database --dumpdb dumps a database to STDOUT --mergedb merges input to a database --expiredb= expires database entries older than hours the log filename or '-' for STDIN EOF exit; } if ($opts{version}) { # Version requested, print and exit print < -1) and !$opts{database}) { print < 0, RECEIVED => 0, BOGUS => 0, RESOLVED => 0, HRESOLVED => 0, TIMEOUT => 0, STARTTIME => time(), MAXTIME => 0, TOTTIME => 0, TOTLINES => 0, TOTHOSTS => 0); # holds run time statistics unless ($opts{dumpdb} or $opts{expiredb} > -1) { # Check if the filename exists $filename ne '-' and !-f $filename and die "can't find log file '$filename'"; # Try to open the file open FILE, $filename or die "error trying to open log file '$filename'"; } # If a database is used, try to open it and tie it to %DB $opts{database} ne '' and (tie(%DB, 'DB_File', $opts{database}) or die "can't open database '$opts{database}'"); #$opts{database} ne '' and (tie(%DB, 'GDBM_File', $opts{database}, &GDBM_WRCREAT, 0644) or die "can't open database '$opts{database}'"); $opts{dumpdb} and dumpdb(), exit; $opts{mergedb} and mergedb(), exit; $opts{expiredb} > -1 and expiredb(), exit; $opts{unresolved} and unresolved(), exit; # MAIN LOOP while (1) { getlines(); # read lines from input log file $#lines == -1 and last; # no lines after read? we're done! makequeries(); # send async dns queries checkresponse(); # check for dns responses checktimeouts(); # check for dns timeouts printresults(); # print whatever we have resolved } printstats(); # print the session stats before we leave # MAIN EXIT exit; # SUBROUTINES sub debug { # debug(message, level) # Prints debug messages # message: any text message # level: the minimun debug level to print the message # RETURNS: 0 if no message printed # 1 if message was printed my ($message, $level) = @_; $opts{debug} < $level and return 0; print STDERR time(), "--> $message\n"; return 1; } sub dumpdb { # dumpdb() # Dumps a database to STDOUT # RETURNS: 1 (always) my $i = 1; for (%DB) { if ($i++ % 2) { print "$_ "; } else { print "$_\n"; } } return 1; } sub mergedb { # mergedb() # Merges a file containing IP/hostname pairs to a database # RETURNS: 1 (always) while () { my ($ipclass, $name) = split /\s+/; $DB{$ipclass} = join(' ', ($name, 'M', time())); } return 1; } sub expiredb { # expiredb() # Expires entries in the database # RETURNS: 1 (always) my $currtime = time(); my ($i, $t) = (0, 0); for (keys %DB) { my ($name, $type, $time) = dbread($_); if ($currtime - $time > $opts{expiredb} * 3600) { delete $DB{$_}; $i++; } else { $t++; } } print STDERR "Expired $i database entries, $t left in the database\n"; return 1; } sub unresolved { # unresolved() # Dumps the unresolved IPs from a file # RETURNS: 1 (always) my %ips; while () { !/$ipmask\s/ and next; my $ip = "$1.$2.$3.$4"; exists $ips{$ip} and next; $ips{$ip} = 1; print "$ip\n"; } return 1; } sub dbread { # dbread(key) # Reads data from the database # key: an IP address or class # RETURNS: (name, type, time) if lookup succeeds # (undef, undef, undef) if lookup failed my $key = shift; !$opts{database} and return (undef, undef, undef); !(exists $DB{$key}) and return (undef, undef, undef); my $fromdb = $DB{$key}; return split(/ /, $fromdb); } sub dbwrite { # dbwrite(key, name, type) # Writes data to the database # key: an IP address or class # name: the resolved name # type: N = nameserver, R = recursed, M = manual # RETURNS: 1 if using a DB # 0 if not using a DB my ($key, $name, $type) = @_; !$opts{database} and return 0; # Don't write back stuff that came from the db $type eq 'D' and return 1; $DB{$key} = join(' ', ($name, $type, time())); return 1; } sub addhost { # addhost(ip) # Adds a host to the cache/queue # ip: an IP address (x.y.z.k) # RETURNS: 1 (always) # Valid values for a {RESOLVED} field: # 'p' - pending # 'r' - pending recursion # 'F' - failed # 'D' - resolved from db # 'N' - resolved from nameserver # 'R' - resolved thru recursion my $ip = shift; debug("Adding host: $ip", 2); if (exists $hosts{$ip}) { # Host already queued, just increment the reference count $hosts{$ip}{COUNT}++; } else { # Add host to queue $hosts{$ip}{COUNT} = 1; $hosts{$ip}{SOCKET} = undef; $hosts{$ip}{RESOLVED} = 'p'; ($hosts{$ip}{DBNAME}, $hosts{$ip}{DBTYPE}, $hosts{$ip}{DBTIME}) = dbread($ip); $stats{TOTHOSTS}++; if ($opts{dbfirst} and defined $hosts{$ip}{DBNAME}) { $hosts{$ip}{NAME} = $hosts{$ip}{DBNAME}; $hosts{$ip}{RESOLVED} = 'D'; debug("host from db: $ip $hosts{$ip}{NAME}", 2); } else { if ($opts{dbonly}) { $hosts{$ip}{RESOLVED} = 'F'; } else { push @q, $ip; } } } return 1; } sub removehost { # removehost(ip) # Removes a host from the cache # ip: an IP address (x.y.z.k) # RETURNS: 1 (always) my $ip = shift; if ($opts{progress}) { if ($progresschars % 50 == 0) { printf STDERR "\n%10d: ", $progresschars; } $progresschars++; my $status = $hosts{$ip}{RESOLVED}; $status =~ tr/NRD/.rd/; print STDERR $status; } # Decrement reference count if (--$hosts{$ip}{COUNT} < 1) { # No more references, so remove host from cache # Check if host was resolved if (index('DNR', $hosts{$ip}{RESOLVED}) >= 0) { $stats{HRESOLVED}++; dbwrite($ip, $hosts{$ip}{NAME}, $hosts{$ip}{RESOLVED}); } freesocket($hosts{$ip}{SOCKET}); delete $hosts{$ip}; debug("Removed host: $ip", 2); } return 1; } sub addclass { # addclass(ip) # Adds the classes of a host to the cache/queue # ip: an IP address (x.y.z.k) # RETURNS: 1 (always) # Valid values for a {RESOLVED} field: # 'p' - pending # 'F' - failed # 'D' - resolved from db # 'N' - resolved from nameserver my $ip = shift; $ip =~ /$ipmask/; # Extract the classes this host belongs to and queue them for ("$1.$2.$3", "$1.$2", "$1") { debug("Adding class: $_", 2); if (exists $class{$_}) { # Class already queued, just increment the reference count $class{$_}{COUNT}++; } else { # Add class to queue $class{$_}{COUNT} = 1; $class{$_}{SOCKET} = undef; $class{$_}{RESOLVED} = 'p'; ($class{$_}{DBNAME}, $class{$_}{DBTYPE}, $class{$_}{DBTIME}) = dbread($_); if ($opts{dbfirst} and defined $class{$_}{DBNAME}) { $class{$_}{NAME} = $class{$_}{DBNAME}; $class{$_}{RESOLVED} = 'D'; debug("class from db: $_ $class{$_}{NAME}", 2); } else { if ($opts{dbonly}) { $class{$_}{RESOLVED} = 'F'; } else { # prioritize class in the queue unshift @q, $_; } } } } return 1; } sub removeclass { # removeclass(ip) # Removes all classes from an ip from the cache # ip: an IP address (x.y.z.k) # RETURNS: 1 (always) my $ip = shift; $ip =~ /$ipmask/; for ("$1.$2.$3", "$1.$2", "$1") { if (--$class{$_}{COUNT} < 1) { # Last reference, if resolved store to db $class{$_}{RESOLVED} eq 'N' and dbwrite($_, $class{$_}{NAME}, $class{$_}{RESOLVED}); freesocket($class{$_}{SOCKET}); delete $class{$_}; debug("Removed class: $_", 2); } } return 1; } sub checkrecurse { # checkrecurse(ip) # Checks for classes if normal resolve failed # ip: an IP address (x.y.z.k) # RETURNS: 1 (always) my $ip = shift; debug("Check recurse $ip", 2); $ip =~ /$ipmask/; for ("$1.$2.$3", "$1.$2", "$1") { # if still resolving class, return $class{$_}{RESOLVED} eq 'p' and return 1; # class was resolved, return class name if ($class{$_}{RESOLVED} ne 'F') { $hosts{$ip}{NAME} = maskthis($ip, $class{$_}{NAME}); $hosts{$ip}{RESOLVED} = 'R'; removeclass($ip); return 1; } # NOTE: The order of the classes is important. If we have a # class C resolved, no need to wait for the upper classes } # No luck, mark as failed $hosts{$ip}{RESOLVED} = 'F'; removeclass($ip); return 1; } sub maskthis { # maskthis(ip, class) # Masks a fake hostname based on an IP and a resolved class # ip: an IP address (x.y.z.k) # class: the class name (somewhere.com) # RETURNS: a masked representation of the IP (x.y.z.k.somewhere.com) my ($ip, $domain) = @_; my $masked = $opts{mask}; $masked =~ s/%i/$ip/; $masked =~ s/%c/$domain/; return $masked; } sub getlines { # getlines() # Fetches lines from the file into our line buffer # RETURNS: 1 if something was read, 0 if EOF eof(FILE) and return 0; my $line; while ($#lines < $opts{linecache} - 1 and $line = ) { my @hosts; while ($line =~ /$ipmask/g) { push @hosts, "$1.$2.$3.$4"; addhost("$1.$2.$3.$4"); } $stats{TOTLINES}++; push @lines, { TEXT => $line, HOSTS => \@hosts }; } return 1; } sub makequeries { # makequeries() # Takes IPs and classes from the queue and sends them to the query # function. This controls the number of sockets in use. # RETURNS: 1 (always) for (1..($opts{sockets} - $sel->count)) { my $query = $q[0]; !$query and last; my $ok = 0; if ($query =~ /$ipmask/) { $ok = query($query, 'H'); } elsif (exists $class{$query}) { $ok = query($query, 'C'); } else { debug("Out of context class $query was skipped", 3); $ok = 1; } $ok ? shift @q : last; } return 1; } sub freesocket { # freesocket(socket) # Frees a socket from our main select and the socket itself # RETURNS: 1 if freed # 0 if socket didn't exist my $socket = shift; !(defined $socket) and return 0; $sel->remove($socket); my $type = $socks{fileno($socket)}{TYPE}; my $query = $socks{fileno($socket)}{QUERY}; if ($type eq 'H') { !exists $hosts{$query} and die "no such host: $query"; undef $hosts{$query}{SOCKET}; } else { !exists $class{$query} and die "no such class: $query"; undef $class{$query}{SOCKET}; } delete $socks{fileno($socket)}; debug("Freed socket for query $query - socket count: " . (keys %socks) . " - " . $sel->count, 2); return 1; } sub nsfailed { # nsfailed(query, type) # Updates statuses when nameserver resolution fails # (bogus reply or timeout) # query: the DNS query # type: H for host or C for class # RETURNS: 1 (always) my ($query, $type) = @_; if ($type eq 'H') { if (defined $hosts{$query}{DBNAME}) { $hosts{$query}{NAME} = $hosts{$query}{DBNAME}; $hosts{$query}{RESOLVED} = 'D'; } elsif ($opts{recursive}) { $hosts{$query}{RESOLVED} = 'r'; addclass($query); } else { $hosts{$query}{RESOLVED} = 'F'; } } else { if (defined $class{$query}{DBNAME}) { $class{$query}{NAME} = $class{$query}{DBNAME}; $class{$query}{RESOLVED} = 'D'; } else { $class{$query}{RESOLVED} = 'F'; } } return 1; } sub checkresponse { # checkresponse() # Checks sockets for DNS replies and processes them # RETURNS: 1 (always) # Check pending replies, give it 5 seconds at most for ($sel->can_read(5)) { my $resolved = 0; my $fileno = fileno($_); my $query = $socks{$fileno}{QUERY}; my $type = $socks{$fileno}{TYPE}; my $timespan = time() - $socks{$fileno}{TIME}; $stats{TOTTIME} += $timespan; my $packet = $res->bgread($_); $stats{RECEIVED}++; debug("Response for query $query (" . $sel->count . ")", 2); # Got the reply and saved the results, so free the socket freesocket($_); if ($packet) { for ($packet->answer) { # For each DNS answer, check the data received if ($type eq 'H') { if (defined $_->{ptrdname}) { $hosts{$query}{NAME} = $_->{ptrdname}; $hosts{$query}{RESOLVED} = 'N'; $resolved = 1; debug("response HOST: $query is " . $hosts{$query}{NAME}, 2); } else { debug("undefined response for query $query", 2); } } else { my $fulldomain; # Check for the previously used SOA records and # the current NS records if ($_->type eq 'SOA') { $fulldomain = $_->{mname}; } elsif ($_->type eq 'NS') { $fulldomain = $_->{nsdname}; } else { next; } debug("Class: $fulldomain", 3); my ($ns, $domain) = $fulldomain =~ /([^\.]+)\.(.*)/; if (defined $domain) { # Avoid truncating records with no machine name $domain =~ /\./ or $domain = $fulldomain; $class{$query}{NAME} = lc $domain; $class{$query}{RESOLVED} = 'N'; $resolved = 1; } } } } if ($resolved) { $stats{RESOLVED}++; $timespan > $stats{MAXTIME} and $stats{MAXTIME} = $timespan; } else { $stats{BOGUS}++; nsfailed($query, $type); } } return 1; } sub checktimeouts { # checktimeouts() # Checks sockets for DNS reply timeouts # RETURNS: 1 (always) my $now = time(); for ($sel->handles) { # Iterate through all active sockets my $fileno = fileno($_); my $query = $socks{$fileno}{QUERY}; my $type = $socks{$fileno}{TYPE}; my $timespan = $now - $socks{$fileno}{TIME}; if ($timespan > $opts{timeout}) { # We have a timeout $stats{TIMEOUT}++; $stats{TOTTIME} += $timespan; # Mark query owner appropriately nsfailed($query, $type); freesocket($_); } } return 1; } sub printresults { # printresults() # Checks if the next lines in our buffer have their IPs resolved # and print the results to STDOUT # RETURNS: 1 (always) debug("Sent: $stats{SENT}, Received: $stats{RECEIVED}, Resolved: $stats{RESOLVED}, Bogus: $stats{BOGUS}, Timeout: $stats{TIMEOUT}", 1); while ($#lines != -1) { # We still have lines in the cache my %line = %{$lines[0]}; !@{$line{HOSTS}} and print($line{TEXT}), shift @lines, next; for (@{$line{HOSTS}}) { # Check all hosts for this line (pending, recursing) $hosts{$_}{RESOLVED} eq 'r' and checkrecurse($_); index('pr', $hosts{$_}{RESOLVED}) >= 0 and goto done; } # Nothing pending for this line if we got here for (@{$line{HOSTS}}) { # Update line with resolved hosts $hosts{$_}{RESOLVED} ne 'F' and $line{TEXT} =~ s/$_/$hosts{$_}{NAME}/; # We don't need this host anymore removehost($_); } print $line{TEXT}; shift @lines; } done: } sub printstats { # printstats() # Print the statistics gathered during program run # RETURNS: 1 (always) $opts{nostats} and return; $opts{progress} and print STDERR "\n\n"; my $timespan = time() - $stats{STARTTIME}; print STDERR " Total Lines: $stats{TOTLINES}\n", " Total Time : ", strftime("%H:%M:%S", gmtime($timespan)), " (", sprintf("%.2f", $timespan ? ($stats{TOTLINES} / $timespan) : 0), " lines/s)\n", " Total Hosts: $stats{TOTHOSTS}\n", " Resolved Hosts: $stats{HRESOLVED} (", sprintf("%.2f", $stats{TOTHOSTS} ? ($stats{HRESOLVED} / $stats{TOTHOSTS} * 100) : 0), "%)\n", "Unresolved Hosts: ", $stats{TOTHOSTS} - $stats{HRESOLVED}, " (", sprintf("%.2f", $stats{TOTHOSTS} ? (($stats{TOTHOSTS} - $stats{HRESOLVED}) / $stats{TOTHOSTS} * 100) : 0), "%)\n", "Average DNS time: ", sprintf("%.4f", $stats{SENT} ? ($stats{TOTTIME} / $stats{SENT}) : 0), "s per request\n", " Max DNS time: ", $stats{MAXTIME}, "s (consider this value for your timeout)\n"; debug("\n\nhosts: " . scalar(keys %hosts) . "\nclasses: " . scalar(keys %class) . "\nselect: " . $sel->count . "\n", 1); return 1; } sub query { # query() # Sends out an assynchronous DNS query # RETURNS: 1 if successful # 0 if failed (no free sockets) my ($find, $type) = @_; my $send = ($type eq 'H') ? $find : (join('.', reverse(split(/\./, $find))) . '.in-addr.arpa'); # Send a query of format PTR for hosts or NS for classes my $sock = $res->bgsend($send, ($type eq 'H') ? 'PTR' : 'NS'); if (!$sock) { # We're out of sockets. Warn the user and continue print STDERR "Error opening socket for bgsend. Are we out of sockets?\n"; return 0; } $stats{SENT}++; $sel->add($sock); # Make a socket record for cross referencing my $fileno = fileno($sock); $socks{$fileno}{TIME} = time(); $socks{$fileno}{QUERY} = $find; $socks{$fileno}{TYPE} = $type; debug("Sent query of type $type: $find", 2); # Update the owner of the socket also for easy referencing $type eq 'H' ? ($hosts{$find}{SOCKET} = $sock) : ($class{$find}{SOCKET} = $sock); return 1; } jdresolve-0.6.1.orig/jdresolve.spec0100644000175000001440000000355007172551124016356 0ustar mvelausers%define name jdresolve %define version 0.6.1 %define release 1 %define prefix /usr Summary: jdresolve resolves IP addresses into hostnames Name: %{name} Version: %{version} Release: %{release} Copyright: GPL Group: Development/Languages Source: http://www.jdrowell.com/files/%{name}-%{version}.tar.gz Url: http://www.jdrowell.com/Linux/Projects/jdresolve Packager: John D. Rowell BuildRoot: /var/tmp/%{name}-%{version}-%{release}-buildroot Requires: perl >= 5.004, perl-Net-DNS >= 0.12 %description %changelog * Wed Jun 28 2000 John D. Rowell - version 0.6.1 - Fixed "oops" assertion bug - Improved performance - New "-p"/"--progress" option * Sat Jun 17 2000 John D. Rowell - version 0.6.0 - Improved performance (lines/s) - Better line caching algorithm - Reduced memory footprint - The code is now fully commented - A new ./configure script (locates Perl, Net::DNS, etc) ...more... (see CHANGELOG) * Thu Aug 26 1999 John D. Rowell - version 0.5.2 - fixed memory leak when the --database option was not in use - fixed warning messages when the --recursive option was not in use * Mon Aug 16 1999 John D. Rowell - version 0.5.1 - fixed warning messages on FreeBSD - added jdresolve-mergedb and jdresolve-unresolved utils * Wed Jul 27 1999 John D. Rowell - version 0.5 - Added database support (--database and jdresolve-dumpdb) * Wed Jul 14 1999 John D. Rowell - First build (v0.4). %ifarch noarch %prep %setup %build %install rm -rf $RPM_BUILD_ROOT mkdir -p $RPM_BUILD_ROOT%{prefix}/bin make prefix=$RPM_BUILD_ROOT%{prefix} install %clean rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root) %doc CHANGELOG COPYING CREDITS INSTALL README TODO /usr/bin/jdresolve /usr/bin/rhost /usr/man/man1/jdresolve.1.gz /usr/man/man1/rhost.1.gz %endif jdresolve-0.6.1.orig/rhost0100755000175000001440000000152307126574504014576 0ustar mvelausers#!/bin/sh # rhost - resolves a single IP address using jdresolve # # Copyright (c) 1999, 2000 John D. Rowell # # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. echo $1 | jdresolve -r -n $2 $3 $4 - jdresolve-0.6.1.orig/rhost.10100600000175000001440000000206307126534007014714 0ustar mvelausers.TH RHOST 1 .\" NAME should be all caps, SECTION should be 1-8, maybe w/ subsection .\" other parms are allowed: see man(7), man(1) .SH "NAME" rhost \- resolve a single ip address .SH "SYNOPSIS" .B rhost [ARGS...] .SH "DESCRIPTION" .PP .B rhost uses .B jdresolve to resolve a single IP address .SH "OPTIONS" .TP .B the address to resolve. .TP .B [ARGS...] up to 3 optional arguments to pass to .B jdresolve \. .SH "SEE ALSO" .BR jdresolve (1). .SH "AUTHOR" jdresolve was written by John Douglas Rowell , and is licensed under the terms of the GNU General Public License. This man page was written by Craig Sanders , for the Debian GNU/Linux package of jdresolve, and is also licensed under the terms of the GNU GPL. .SH "BUG REPORTS" If you find a bug in .B jdresolve, you should report it. But first, you should make sure that it really is a bug, and that it appears in the latest version of .B jdresolve that you have. Once you have determined that a bug actually exists, send a bug report to \fIbugs@jdrowell.com\fP. jdresolve-0.6.1.orig/rhost.1.gz0100644000175000001440000000112207172547274015351 0ustar mvelausers9mSo0_qij*21%a{px vۥ-{|,re|5L]SA Jњ!d<ona+wwK+ ;턁]'EZv4!U1i%*8UH}J~z +=,51И)c'2y ܕJci i}0jPJyOY3jdresolve-0.6.1.orig/AUTHORS0100644000175000001440000000015407172547274014565 0ustar mvelausers * [1]John D. Rowell + First versions of all files References 1. mailto:me@jdrowell.com jdresolve-0.6.1.orig/AUTHORS.html0100644000175000001440000000017207126574066015526 0ustar mvelausers