--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, 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.
+\f
+ 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.)
+\f
+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.
+\f
+ 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.
+\f
+ 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
+\f
+ 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.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ 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., 675 Mass Ave, Cambridge, MA 02139, 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.
+
+ <signature of Ty Coon>, 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.
--- /dev/null
+# change for your CPU and compiler
+
+# note that mysql_config is braindamaged ;-)
+CC=gcc
+CFLAGS=-g -Wall "`mysql_config --cflags | tr -d \'`"
+
+LIBS=`mysql_config --libs | tr -d \'` # '`
+LDFLAGS=-lefence
+
+#
+# *** end of configuration ***
+#
+
+# due to some icky programming, we will have to add all the .o files everywhere.
+
+OBJSN=nbtscanner.o mysql_interface.o configfile.o nmb.o stats.o socket.o util.o id_list.o
+OBJSO=outputfile.o mysql_interface.o configfile.o nmb.o stats.o socket.o util.o id_list.o
+
+all: nbtscanner outputfile
+nbtscanner: $(OBJSN)
+ $(CC) -o nbtscanner $(OBJSN) $(LIBS)
+outputfile: $(OBJSO)
+ $(CC) -o outputfile $(OBJSO) $(LIBS)
+
+nbtscanner.o: nbtscanner.c nbtscanner.h configfile.h mysql_interface.h nmb.h socket.h stats.h \
+ packet.h byteorder.h util.h id_list.h
+ $(CC) $(CFLAGS) -c nbtscanner.c
+outputfile.o: outputfile.c configfile.h mysql_interface.h
+ $(CC) $(CFLAGS) -c outputfile.c
+
+mysql_interface.o: mysql_interface.c mysql_interface.h
+ $(CC) $(CFLAGS) -c mysql_interface.c
+
+configfile.o: configfile.c configfile.h nbtscanner.h
+ $(CC) $(CFLAGS) -c configfile.c
+
+nmb.o: nmb.c nmb.h packet.h byteorder.h util.h
+ $(CC) $(CFLAGS) -c nmb.c
+
+stats.o: stats.c stats.h configfile.h util.h
+ $(CC) $(CFLAGS) -c stats.c
+
+socket.o: socket.c socket.h nmb.h packet.h
+ $(CC) $(CFLAGS) -c socket.c
+
+util.o: util.c util.h
+ $(CC) $(CFLAGS) -c util.c
+
+id_list.o: id_list.c id_list.h configfile.h util.h
+ $(CC) $(CFLAGS) -c id_list.c
+
+.PHONY: clean
+clean:
+ rm -f $(OBJSO) $(OBJSN) nbtscanner outputfile
--- /dev/null
+This program is GPLed, v2. No documentation exists yet -- use common
+sense and read the source :-)
+
+This program borrows considerable amount of code from Samba, and would
+not be possible at all without it. Big thanks to the Samba team :-)
+
+- Steinar H. Gunderson <sgunderson@bigfoot.com>
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * byteorder.h: structure access functions (i386 only!).
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _BYTEORDER_H
+#define _BYTEORDER_H 1
+
+#define IVAL(buf,pos) (SVAL(buf,pos)|SVAL(buf,(pos)+2)<<16)
+#define SREV(x) ((((x)&0xFF)<<8) | (((x)>>8)&0xFF))
+#define SVAL(buf,pos) (*(unsigned short *)((char *)(buf) + (pos)))
+#define SSVAL(buf,pos,val) SVAL(buf,pos)=((unsigned short)(val))
+#define RSSVAL(buf,pos,val) SSVAL(buf,pos,SREV(val))
+#define RSVAL(buf,pos) SREV(SVAL(buf,pos))
+#define CVAL(buf,pos) (((unsigned char *)(buf))[pos])
+#define RIVAL(buf,pos) IREV(IVAL(buf,pos))
+#define IREV(x) ((SREV(x)<<16) | (SREV((x)>>16)))
+
+#define PTR_DIFF(p1,p2) ((ptrdiff_t)(((const char *)(p1)) - (const char *)(p2)))
+
+#endif /* _BYTEORDER_H */
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * configfile.c: Functions for parsing the configuration file.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "configfile.h"
+#include "nbtscanner.h"
+#include "mysql_interface.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+int num_retries;
+int retry_time;
+int delay_time;
+int verbosity;
+
+int use_mysql;
+char mysql_host[64];
+char mysql_username[32];
+char mysql_password[32];
+
+void parse_configfile(int do_scan)
+{
+ FILE *configfile = fopen("nbtscanner.conf", "r");
+ int lineno = 0;
+
+ if (configfile == NULL) {
+ perror("nbtscanner.conf");
+ exit(1);
+ }
+
+ /* defaults */
+ num_retries = 3;
+ retry_time = 5000;
+ delay_time = 100;
+ verbosity = 2;
+
+ use_mysql = 0;
+ strcpy(mysql_host, "no_host_given");
+ strcpy(mysql_username, "no_username_given");
+ strcpy(mysql_password, "no_password_given");
+
+ while (!feof(configfile)) {
+ char buf[1024];
+
+ lineno++;
+
+ fgets(buf, 1024, configfile);
+ while (buf[strlen(buf) - 1] == '\n' || buf[strlen(buf) - 1] == '\r') {
+ buf[strlen(buf) - 1] = '\0';
+ }
+
+ if (buf[0] == '#' || buf[0] == '\0') {
+ /* comment or blank line */
+ continue;
+ }
+ if (strspn(buf, " \t") == strlen(buf)) {
+ /* blank line */
+ continue;
+ }
+
+ parse_line(buf, lineno, do_scan);
+ }
+
+ fclose(configfile);
+}
+
+void parse_line(char *buf, int lineno, int do_scan)
+{
+ char *ptr = strchr(buf, '=');
+
+ if (ptr == NULL || strchr(ptr + 1, '=') != NULL) {
+ line_error(lineno, "Malformed line (must be exactly one `=' sign)");
+ }
+
+ /* split the line into a keyword and a value */
+ ptr[0] = 0;
+ ptr++;
+
+ /*
+ * trim any trailing spaces, make sure there are no spaces in
+ * the value
+ */
+ {
+ char *ptr2 = strchr(ptr, ' ');
+ if (ptr2 != NULL) {
+ /* must only be spaces from here */
+ if (strspn(ptr2 + 1, " ") != strlen(ptr2 + 1)) {
+ line_error(lineno, "Malformed value (can't have any spaces)");
+ }
+
+ ptr2[0] = 0;
+ }
+ }
+
+ /* make sure both the parameter and the value is non-empty */
+ if (buf[0] == '\0') {
+ line_error(lineno, "Malformed keyword (can't be empty)");
+ }
+ if (ptr[0] == '\0') {
+ line_error(lineno, "Malformed value (can't be empty)");
+ }
+
+ /* finally pass it on to the keyword checker */
+ parse_keyword(buf, ptr, lineno, do_scan);
+}
+
+void parse_keyword(char *keyword, char *value, int lineno, int do_scan)
+{
+ if (strcasecmp(keyword, "num_retries") == 0) {
+ parse_int(value, &num_retries, lineno);
+ } else if (strcasecmp(keyword, "retry_time") == 0) {
+ parse_int(value, &retry_time, lineno);
+ } else if (strcasecmp(keyword, "delay_time") == 0) {
+ parse_int(value, &delay_time, lineno);
+ } else if (strcasecmp(keyword, "verbosity") == 0) {
+ parse_int(value, &verbosity, lineno);
+ } else if (strcasecmp(keyword, "use_mysql") == 0) {
+ parse_int(value, &use_mysql, lineno);
+ } else if (strcasecmp(keyword, "mysql_host") == 0) {
+ strcpy(mysql_host, value);
+ } else if (strcasecmp(keyword, "mysql_username") == 0) {
+ strcpy(mysql_username, value);
+ } else if (strcasecmp(keyword, "mysql_password") == 0) {
+ strcpy(mysql_password, value);
+ } else if (strcasecmp(keyword, "range") == 0) {
+ /* really ugly to have here */
+ if (use_mysql) {
+ init_mysql(mysql_host, mysql_username, mysql_password);
+ }
+ if (do_scan) parse_range(value, lineno);
+ } else {
+ char buf[1024];
+ sprintf(buf, "Unknown keyword `%s'", keyword);
+ line_error(lineno, buf);
+ }
+}
+
+void parse_int(char *string, int *retval, int lineno)
+{
+ if (strspn(string, "0123456789") != strlen(string)) {
+ char buf[1024];
+ sprintf(buf, "`%s' isn't a positive integer", string);
+ line_error(lineno, buf);
+ }
+
+ *retval = atoi(string);
+}
+
+void parse_range(char *string, int lineno)
+{
+ /* exactly one / is allowed */
+ char *ptr = strchr(string, '/');
+ struct in_addr in;
+ int rangesize;
+
+ if (ptr != NULL && strchr(ptr + 1, '/') != NULL) {
+ line_error(lineno, "Malformed range (only one `/' allowed)");
+ }
+
+ /* lots and lots of code :-) */
+ if (ptr == NULL) { /* single IP */
+ rangesize = 32;
+ } else { /* range */
+ ptr[0] = 0;
+ ptr++;
+
+ /* find out whether this is a pure integer or not */
+ if (strspn(ptr, "0123456789") == strlen(ptr)) {
+ rangesize = atoi(ptr);
+ if (rangesize < 0 || rangesize > 32) {
+ line_error(lineno, "Malformed range (significant bits must be between 0 and 32, inclusive)");
+ }
+ } else if (strspn(ptr, "0123456789.") == strlen(ptr)) {
+ /* IP address... */
+ struct in_addr netmask;
+ int found, i;
+
+ if (inet_aton(ptr, &netmask) == 0) {
+ line_error(lineno, "Malformed range (malformed netmask)");
+ }
+
+ /* find the rightmost 1-bit (by finding the leftmost 0-bit) */
+ found = 0;
+ for (i = 31; i >= 0; i--) {
+ if ((netmask.s_addr & (1 << i)) == 0) {
+ found = 1;
+ break;
+ }
+ }
+ if (found == 0) {
+ rangesize = 32; /* 255.255.255.255 */
+ } else {
+ unsigned int clean_mask = htonl(~((1 << (31-i)) - 1));
+
+ rangesize = i + 1;
+
+ /* verify that this is a `clean' netmask */
+ if (netmask.s_addr != clean_mask) {
+ line_error(lineno, "Malformed range (netmask must be `clean')");
+ }
+ }
+ } else {
+ line_error(lineno, "Malformed range (malformed netmask)");
+ rangesize = 32; /* will never reach this, but for gcc */
+ }
+ }
+
+ /* try to scan the IP part */
+ if (inet_aton(string, &in) == 0) {
+ line_error(lineno, "Malformed range (malformed IP address)");
+ }
+
+ /* check that the IP address and the netmask match */
+ if (rangesize != 32) {
+ /* not really the netmask, actually it's the inverted netmask */
+ unsigned int netmask = htonl((1 << (31-rangesize)) - 1);
+
+ if ((in.s_addr & netmask) != 0) {
+ line_error(lineno, "Malformed range (IP address doesn't match netmask)");
+ }
+ }
+
+ scan_range(in, rangesize);
+}
+
+void line_error(int lineno, char *err_str)
+{
+ fprintf(stderr, "nbtscanner.conf:%d: %s\n", lineno, err_str);
+ exit(1);
+}
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * configfile.h: Prototypes for configfile.c.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _CONFIGFILE_H
+#define _CONFIGFILE_H 1
+
+extern int num_retries;
+extern int retry_time;
+extern int delay_time;
+extern int verbosity;
+
+extern int use_mysql;
+extern char mysql_host[64];
+extern char mysql_username[32];
+extern char mysql_password[32];
+
+void parse_configfile(int do_scan);
+void parse_line(char *buf, int lineno, int do_scan);
+void parse_keyword(char *keyword, char *value, int lineno, int do_scan);
+void parse_int(char *string, int *retval, int lineno);
+void parse_range(char *string, int lineno);
+
+void line_error(int lineno, char *err_str);
+
+#endif
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * id_list.c: a singly linked list for keeping track of the packet IDs.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "id_list.h"
+#include "configfile.h"
+#include "util.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/time.h>
+
+struct id_entry ids[65536];
+struct id_list_entry *head_free_id;
+int num_free_ids;
+
+void id_list_init()
+{
+ int i, start_num;
+
+ num_free_ids = 0;
+ head_free_id = NULL;
+
+ /* we want to start at some halfway random number instead of 0 */
+ start_num = (time(NULL) + getpid()) & 0xffff;
+
+ for (i = 65535; i >= 0; i--) {
+ int ii = (i + start_num) & 0xffff;
+
+ ids[ii].id = ii;
+ ids[ii].in_use = 0;
+
+ id_free(&ids[ii]);
+ }
+}
+
+void id_free(struct id_entry *i)
+{
+ struct id_list_entry *ie = (struct id_list_entry *)malloc(sizeof(struct id_list_entry));
+
+ if (ie == NULL) {
+ perror("malloc()");
+ exit(1);
+ }
+
+ i->in_use = 0;
+ ie->id = i;
+
+ /* insert at the beginning of the linked list */
+ ie->next = head_free_id;
+ head_free_id = ie;
+
+ num_free_ids++;
+}
+
+/* mark as free, but don't delete until desperation cleanup */
+void id_mark_free(struct id_entry *i)
+{
+ i->in_use = 2;
+ num_free_ids++;
+}
+
+struct id_entry *id_get_free_id()
+{
+ struct id_list_entry *ie = head_free_id;
+ struct id_entry *i;
+
+ if (ie == NULL) {
+ return NULL;
+ } else {
+ i = ie->id;
+ head_free_id = ie->next;
+ free(ie);
+
+ i->in_use = 1;
+ num_free_ids--;
+
+ return i;
+ }
+}
+
+/* desperation time :-) */
+int id_cleanup(int timeout_ms)
+{
+ int i;
+ int num_freed = 0;
+ struct timeval now;
+ gettimeofday(&now, NULL);
+
+ for (i = 0; i < 65536; i++) {
+ if (ids[i].in_use == 2) {
+ id_free(&ids[i]);
+ num_freed++;
+ num_free_ids--; /* was already counted */
+
+ continue;
+ }
+ if (mydifftime(ids[i].timestamp, now) > timeout_ms &&
+ ids[i].retries == num_retries) {
+ id_free(&ids[i]);
+ num_freed++;
+
+ continue;
+ }
+ }
+
+ return num_freed;
+}
+
+int get_num_free_ids()
+{
+ return num_free_ids;
+}
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * id_list.h: Prototypes and structures for keeping track of the packet IDs.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _ID_LIST_H
+#define _ID_LIST_H 1
+
+#include <sys/time.h>
+#include <netinet/in.h>
+
+/*
+ * There's quite some data duplication here, in the interest of speed and code
+ * simplicity.
+ */
+
+struct id_entry {
+ unsigned short id; /* ID number from NBT packet */
+ int in_use; /* Are we awaiting a reply on this ID? */
+
+ struct in_addr sin; /* IP address we've sent it to */
+ struct timeval timestamp; /* When we sent the packet */
+ int retries; /* Number of retries tried */
+
+ /* we list on index entry instead of using pointers */
+ int prev_index;
+ int next_index;
+};
+
+struct id_list_entry {
+ struct id_list_entry *next;
+ struct id_entry *id;
+};
+
+/*
+ * a list of all the available ID numbers (sin is unused, in_use = 0)
+ *
+ * We could have a used_id list as well, but it would require a doubly
+ * linked list, and perhaps doesn't help all that much anyways
+ */
+extern struct id_list_entry *head_free_id;
+
+/* an array with a one-to-one mapping of the array index vs. the id field */
+extern struct id_entry ids[];
+
+void id_list_init();
+void id_free(struct id_entry *i);
+void id_mark_free(struct id_entry *i);
+struct id_entry *id_get_free_id();
+int id_cleanup(int timeout_ms);
+int get_num_free_ids();
+
+#endif /* _ID_LIST_H */
+
--- /dev/null
+USE mysql;
+INSERT INTO mysql.user (Host, User, Password) VALUES('%', 'nbtscanner', PASSWORD('tg01'));
+INSERT INTO mysql.user (Host, User, Password) VALUES('localhost', 'nbtscanner', PASSWORD('tg01'));
+FLUSH PRIVILEGES;
+
+CREATE DATABASE nbtscanner;
+USE nbtscanner;
+CREATE TABLE nbtscanner (
+ ip CHAR(16) NOT NULL,
+ hostname CHAR(32),
+ fileservername CHAR(32),
+ groupname CHAR(32),
+ PRIMARY KEY (
+ ip
+ )
+);
+GRANT INSERT, UPDATE, DELETE ON nbtscanner.nbtscanner TO nbtscanner@"%" IDENTIFIED BY 'tg01';
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * mysql_interface.c: Interface routines for the MySQL table.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <mysql.h>
+
+#include "mysql_interface.h"
+#include "configfile.h"
+
+MYSQL *mysql = NULL;
+
+/* veeeery detailed error reporting here ;-) */
+void init_mysql(char *host, char *username, char *password)
+{
+ if (mysql != NULL) return; /* hack */
+
+ mysql = mysql_init(NULL);
+ if (mysql == NULL) {
+ if (verbosity >= 1) {
+ fprintf(stderr, "mysql_init() failed\n");
+ }
+ exit(1);
+ }
+
+ if (mysql_real_connect(mysql, mysql_host, username, password, "nbtscanner",
+ 0, NULL, 0) == 0) {
+ if (verbosity >= 1) {
+ fprintf(stderr, "mysql_real_connect() failed\n");
+ }
+ exit(1);
+ }
+}
+
+void add_record_mysql(char *ip, char *hostname, char *fileservername, char *groupname)
+{
+ char query[256];
+ snprintf(query, 256,
+ "REPLACE INTO nbtscanner.nbtscanner SET ip='%s', hostname='%s', fileservername='%s', groupname='%s';",
+ ip, hostname, fileservername, groupname);
+
+ if (mysql_query(mysql, query) != 0) {
+ if (verbosity >= 1) {
+ fprintf(stderr, "mysql_query(`%s') failed\n", query);
+ }
+ exit(1);
+ }
+}
+
+void delete_record_mysql(char *ip)
+{
+ char query[256];
+ snprintf(query, 256,
+ "DELETE FROM nbtscanner.nbtscanner WHERE ip='%s';",
+ ip);
+
+ if (mysql_query(mysql, query) != 0) {
+ if (verbosity >= 1) {
+ fprintf(stderr, "mysql_query(`%s') failed\n", query);
+ }
+ exit(1);
+ }
+}
+
+void print_all_records_mysql()
+{
+ MYSQL_RES *result;
+ unsigned long *lengths;
+ unsigned int num_fields;
+ int i;
+
+ if (mysql_query(mysql, "SELECT ip,fileservername,groupname,(fileservername <> '-unknown-nbtscanner-') FROM nbtscanner.nbtscanner;") != 0) {
+ if (verbosity >= 1) {
+ fprintf(stderr, "mysql_query('SELECT ip'...) failed\n");
+ }
+ exit(1);
+ }
+
+ result = mysql_store_result(mysql);
+ if (result == NULL) {
+ if (verbosity >= 1) {
+ fprintf(stderr, "mysql_store_result() failed\n");
+ }
+ exit(1);
+ }
+
+ num_fields = mysql_num_fields(result);
+ while (1) {
+ MYSQL_ROW row = mysql_fetch_row(result);
+ if (row == NULL) return;
+
+ lengths = mysql_fetch_lengths(result);
+
+ for (i = 0; i < num_fields; i++) {
+ int j;
+
+ /* strip away CR/LFs */
+ for (j = 0; j < lengths[i]; j++) {
+ if (row[i][j] == 0 || row[i][j] == 10 || row[i][j] == 13) {
+ row[i][j] = '?';
+ }
+ }
+ printf("%.*s", (int) lengths[i], row[i] ? row[i] : "NULL");
+ if (i != num_fields - 1) putchar(0);
+ }
+ printf("\r\n");
+ }
+}
+
+void finish_mysql()
+{
+ /* don't care if this fails */
+ mysql_query(mysql, "OPTIMIZE TABLE nbtscanner.nbtscanner;");
+
+ mysql_close(mysql);
+}
+
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * mysql_interface.c: Interface routines for the MySQL table.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _MYSQL_INTERFACE_H
+#define _MYSQL_INTERFACE_H 1
+
+void init_mysql(char *host, char *username, char *password);
+void add_record_mysql(char *ip, char *hostname, char *fileservername, char *groupname);
+void delete_record_mysql(char *ip);
+void print_all_records_mysql();
+void finish_mysql();
+
+#endif /* _MYSQL_INTERFACE_H */
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * nbtscanner.c: nbtscanner main body.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+
+#include "nbtscanner.h"
+#include "mysql_interface.h"
+#include "configfile.h"
+#include "nmb.h"
+#include "socket.h"
+#include "stats.h"
+#include "packet.h"
+#include "byteorder.h"
+#include "util.h"
+#include "id_list.h"
+
+/* one global variable -- the UDP socket */
+int server_fd;
+
+void interpret_node_status(char *p, struct in_addr in)
+{
+ int numnames = CVAL(p,0);
+ char hostname[32], fileservername[32], group[32];
+
+ /*
+ * hopefully this will be enough to identify the host as unknown
+ * (note that this is longer than the 16 char maximum NetBIOS
+ * name length)
+ */
+ strcpy(hostname, "-unknown-nbtscanner-");
+ strcpy(fileservername, "-unknown-nbtscanner-");
+ strcpy(group, "-unknown-nbtscanner-");
+
+ p += 1;
+ while (numnames--) {
+ char qname[17];
+ int type;
+ int i;
+
+ strncpy(qname,p,15);
+ qname[15] = 0;
+ type = CVAL(p,15);
+ p += 16;
+
+ for (i = strlen(qname); --i >= 0; ) {
+ if (!isprint((int)qname[i])) qname[i] = '.';
+ }
+
+ /*
+ * this is code duplication (see parse_nmb_name in nmb.c)
+ * but it obviously isn't done in our case :-)
+ */
+ for (i = strlen(qname); --i >= 0; ) {
+ if (qname[i] == ' ') {
+ qname[i] = 0;
+ } else {
+ break;
+ }
+ }
+
+ /* <ACTIVE>, non-<GROUP> server hostname (type 0x00) */
+ if ((p[0] & 0x80) == 0x00 && ((p[0] & 0x1f) == 0x04) && type == 0x00) {
+ strcpy(hostname, qname);
+ }
+ /* <ACTIVE>, non-<GROUP> server hostname (type 0x20) */
+ if ((p[0] & 0x80) == 0x00 && ((p[0] & 0x1f) == 0x04) && type == 0x20) {
+ strcpy(fileservername, qname);
+ }
+ /* <ACTIVE>, <GROUP> group (type 0x00) */
+ if ((p[0] & 0x80) == 0x80 && ((p[0] & 0x1f) == 0x04) && type == 0x00) {
+ strcpy(group, qname);
+ }
+
+ p += 2;
+ }
+
+ if (use_mysql) {
+ add_record_mysql(inet_ntoa(in), hostname, fileservername, group);
+ } else {
+ printf("%s,%s,%s,%s\n", inet_ntoa(in), hostname, fileservername, group);
+ }
+}
+
+void resend_timed_out_packets(int fd)
+{
+ int i;
+ struct timeval now;
+ struct nmb_packet nmb;
+
+ gettimeofday(&now, NULL);
+
+ for (i = 0; i < 65536; i++) {
+ if (ids[i].in_use == 1 &&
+ mydifftime(ids[i].timestamp, now) > retry_time) {
+ if (ids[i].retries >= num_retries) {
+ id_mark_free(&ids[i]);
+
+ num_failed++;
+ if (use_mysql) {
+ delete_record_mysql(inet_ntoa(ids[i].sin));
+ }
+ print_stats(0);
+ } else {
+ gettimeofday(&(ids[i].timestamp), NULL);
+ ids[i].retries++;
+ num_sent_total++;
+
+ build_nbt_packet(&nmb, i);
+ send_packet(&nmb, ids[i].sin, 137, fd);
+ recv_nbt_packets(fd); /* delay and empty buffer */
+ print_stats(0);
+ }
+ }
+ }
+}
+
+void send_nbt_packet(int fd, struct in_addr to_ip)
+{
+ struct nmb_packet nmb;
+ static int name_trn_id = 0;
+ struct id_entry *i = id_get_free_id();
+
+ if (i == NULL) {
+ /* uh-oh... try to remove timed-out IDs */
+ if (id_cleanup(retry_time + 1000) == 0 ||
+ (i=id_get_free_id()) == NULL) {
+ if (verbosity >= 1) {
+ fprintf(stderr, "No free NBT IDs! Reduce "
+ "the number of hosts, the "
+ "number\n");
+ fprintf(stderr, "of retries, or the scanning "
+ "speed. nbtscanner is now "
+ "exiting.\n");
+ }
+ exit(1);
+ }
+ }
+ name_trn_id = i->id;
+ i->sin = to_ip;
+ gettimeofday(&(i->timestamp), NULL);
+ i->retries = 0;
+
+ build_nbt_packet(&nmb, name_trn_id);
+
+ /* FIXME: what to do with sending errors? */
+ send_packet(&nmb, to_ip, 137, fd);
+
+ num_sent++;
+ num_sent_total++;
+ print_stats(0);
+}
+
+/*
+ * This function not only receives and handles any NBT replies, but
+ * also guarantees a delay of minimum delay_time.
+ */
+void recv_nbt_packets(int fd)
+{
+ struct nmb_packet *nmb;
+ struct in_addr in;
+ struct timeval start;
+ int dt = delay_time;
+
+ gettimeofday(&start, NULL);
+
+ while (dt > 0) {
+ struct timeval now;
+
+ print_stats(0);
+
+ gettimeofday(&now, NULL);
+ dt = delay_time - mydifftime(start, now);
+
+ if (dt < 0) break;
+
+ nmb = receive_packet(fd, dt, &in);
+ if (nmb) {
+ struct id_entry *i = &ids[nmb->header.name_trn_id];
+
+ if (!nmb->header.response) {
+ /* It's not for us */
+ free_nmb_packet(nmb);
+ continue;
+ }
+ if (i->in_use == 0) {
+ if (verbosity < 2) continue;
+
+ fprintf(stderr, "Warning: received NBT "
+ "response for unused "
+ "id %04x!\n",
+ i->id);
+ continue;
+ }
+ if (i->in_use == 2) {
+ if (verbosity < 2) continue;
+
+ fprintf(stderr, "Warning: received "
+ "duplicate NBT response "
+ "for id %04x!\n",
+ i->id);
+ continue;
+ }
+ if (in.s_addr != i->sin.s_addr) {
+ char got_addr[32], want_addr[32];
+
+ if (verbosity < 2) continue;
+
+ strcpy(got_addr, inet_ntoa(in));
+ strcpy(want_addr, inet_ntoa(i->sin));
+
+ fprintf(stderr, "Warning: received NBT "
+ "response for id %04x "
+ "from %s instead of %s!\n",
+ i->id, got_addr, want_addr);
+ continue;
+ }
+
+ if (nmb->header.opcode != 0 ||
+ nmb->header.nm_flags.bcast ||
+ nmb->header.rcode ||
+ !nmb->header.ancount ||
+ nmb->answers->rr_type != 0x21) {
+ /* XXXX what do we do with this? could be a redirect, but
+ we'll discard it for the moment */
+ free_nmb_packet(nmb);
+ continue;
+ }
+
+ num_recv++;
+ num_recv_retries = i->retries;
+
+ interpret_node_status(&nmb->answers->rdata[0], in);
+ free_nmb_packet(nmb);
+
+ id_mark_free(i);
+ }
+ }
+}
+
+void scan_range(struct in_addr ip, int rangesize)
+{
+ if (rangesize == 32) {
+ /* scan a single IP */
+ send_nbt_packet(server_fd, ip);
+ recv_nbt_packets(server_fd);
+ } else if (rangesize == 31) {
+ /* scan two IPs */
+ send_nbt_packet(server_fd, ip);
+ recv_nbt_packets(server_fd);
+
+ ip.s_addr = htonl(ntohl(ip.s_addr) + 1);
+ send_nbt_packet(server_fd, ip);
+ recv_nbt_packets(server_fd);
+ } else {
+ /* scan a range of IPs, minus the top and bottom one */
+ int i;
+
+ ip.s_addr = htonl(ntohl(ip.s_addr) + 1); /* skip bottom */
+
+ for (i = 0; i < (1 << (32-rangesize)) - 2; i++) {
+ send_nbt_packet(server_fd, ip);
+ recv_nbt_packets(server_fd);
+
+ ip.s_addr = htonl(ntohl(ip.s_addr) + 1);
+ }
+ }
+}
+
+int main(int argc, char *argv[])
+{
+ int fd = open_sockets();
+
+ id_list_init();
+ init_stats();
+
+ /* note that parse_configfile() will call scan_range()! */
+ server_fd = fd;
+ parse_configfile(1);
+
+/* for (i=1;i<argc;i++) {
+ struct in_addr ip;
+
+ ip.s_addr = inet_addr(argv[i]); //interpret_addr2(argv[i]);
+ send_nbt_packet(fd, ip);
+ recv_nbt_packets(fd);
+ } */
+
+ /*
+ * receive answers and resend packets until all answers have
+ * been received, or all packets have been timed out
+ */
+ status = RETRYING;
+ while (get_num_free_ids() != 65536) {
+ recv_nbt_packets(fd);
+ resend_timed_out_packets(fd);
+ }
+
+ if (use_mysql) {
+ finish_mysql();
+ }
+
+ if (verbosity >= 3) {
+ print_stats(1);
+ fprintf(stderr, "\n");
+ }
+
+ return 0;
+}
--- /dev/null
+#
+# nbtscanner.conf example
+#
+# Note that the config file scanner is not very smart, so you'd
+# better be a bit restrictive here :-) (In particular, don't forget
+# a newline at the end, and the ranges MUST come after the settings,
+# otherwise you'll get slightly weird results :-) )
+#
+# This file is case-insensitive.
+#
+
+# The number of retries each host should be allowed to have.
+num_retries=3
+
+# The amount of time between each retry, in milliseconds.
+retry_time=5000
+
+# How long nbtscanner will delay between each sent packet, in ms.
+delay_time=100
+
+# Verbosity level:
+# 0: Absolutely no warnings or error messages will be printed (not
+# recommended, it's kinda nice to know why the program failed).
+# 1: Fatal error messages will be printed on standard error.
+# 2: Warnings (like suspicious NBT responses coming in, etc.) are
+# also printed.
+# 3: Errors, warnings and progress indicators.
+#
+# Config file errors are printed regardless of this setting. It's
+# recommended that you redirect standard output to a file (or a
+# pipe) if using verbosity >= 1.
+#
+verbosity=3
+
+#
+# MySQL setup
+#
+# If this is 1, a MySQL connection is used instead of outputting
+# all the IPs to standard output. This is highly recommended, but
+# needs some table setup before use.
+#
+use_mysql=1
+
+#
+# Your MySQL server information. mysql_host is the IP address (or
+# host name) of your MySQL server, often localhost. mysql_username
+# and password_username have obvious meanings. The password is in
+# cleartext, so make sure the permissions on this file are set to
+# 0600 or similiar.
+#
+mysql_host=127.0.0.1
+mysql_username=nbtscanner
+mysql_password=tg01
+
+#
+# Each IP address range is specified with a range= parameter.
+# There are three different ways to specify these:
+#
+# range=10.0.0.1 -- scan one IP address only.
+# range=10.0.0.0/24 -- scan an entire C-net.
+# range=10.0.0.0/255.255.255.0 -- the same, using netmask notation.
+#
+# If you specify networks, the top and bottom address will not be
+# scanned. Netmasks must be filled from the left (if you don't have
+# a VERY weird network layout, this will come naturally).
+#
+# Duplicate IP address _will_ be scanned twice. :-)
+#
+range=10.0.7.80/28
+# range=10.0.0.0/24
+range=10.0.19.0/24
+
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * nbtscanner.c: Prototypes for nbtscanner.c.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _NBTSCANNER_H
+#define _NBTSCANNER_H 1
+
+#include <netinet/in.h>
+
+void interpret_node_status(char *p, struct in_addr in);
+void resend_timed_out_packets(int fd);
+void send_nbt_packet(int fd, struct in_addr to_ip);
+void recv_nbt_packets(int fd);
+
+void scan_range(struct in_addr ip, int rangesize);
+int main(int argc, char *argv[]);
+
+#endif /* _NBTSCANNER_H */
+
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * nmb.c: Most functions directly related to the NMB protocol.
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "nmb.h"
+#include "packet.h"
+#include "byteorder.h"
+#include "util.h"
+
+void build_nbt_packet(struct nmb_packet *nmb, int name_trn_id)
+{
+ nmb->header.name_trn_id = name_trn_id;
+ nmb->header.opcode = 0;
+ nmb->header.response = 0;
+ nmb->header.nm_flags.bcast = 0;
+ nmb->header.nm_flags.recursion_available = 0;
+ nmb->header.nm_flags.recursion_desired = 0;
+ nmb->header.nm_flags.trunc = 0;
+ nmb->header.nm_flags.authoritative = 0;
+ nmb->header.rcode = 0;
+ nmb->header.qdcount = 1;
+ nmb->header.ancount = 0;
+ nmb->header.nscount = 0;
+ nmb->header.arcount = 0;
+
+ make_nmb_name(&(nmb->question.question_name), "*", 0x0, "");
+
+ nmb->question.question_type = 0x21;
+ nmb->question.question_class = 0x1;
+}
+
+int build_nmb(char *buf, struct nmb_packet *nmb)
+{
+ unsigned char *ubuf = (unsigned char *)buf;
+ int offset=0;
+
+ /* put in the header */
+ RSSVAL(ubuf,offset, nmb->header.name_trn_id);
+ ubuf[offset+2] = (nmb->header.opcode & 0xF) << 3;
+ if (nmb->header.response) ubuf[offset+2] |= (1<<7);
+ if (nmb->header.nm_flags.authoritative &&
+ nmb->header.response) ubuf[offset+2] |= 0x4;
+ if (nmb->header.nm_flags.trunc) ubuf[offset+2] |= 0x2;
+ if (nmb->header.nm_flags.recursion_desired) ubuf[offset+2] |= 0x1;
+ if (nmb->header.nm_flags.recursion_available &&
+ nmb->header.response) ubuf[offset+3] |= 0x80;
+ if (nmb->header.nm_flags.bcast) ubuf[offset+3] |= 0x10;
+ ubuf[offset+3] |= (nmb->header.rcode & 0xF);
+
+ RSSVAL(ubuf, offset+4, nmb->header.qdcount);
+ RSSVAL(ubuf, offset+6, nmb->header.ancount);
+ RSSVAL(ubuf, offset+8, nmb->header.nscount);
+ RSSVAL(ubuf, offset+10, nmb->header.arcount);
+
+ offset += 12;
+ if (nmb->header.qdcount) {
+ /* XXXX this doesn't handle a qdcount of > 1 */
+ offset += put_nmb_name((char *)ubuf, offset, &nmb->question.question_name);
+ RSSVAL(ubuf,offset, nmb->question.question_type);
+ RSSVAL(ubuf,offset+2, nmb->question.question_class);
+ offset += 4;
+ }
+ return offset;
+}
+
+int parse_nmb(char *inbuf, int length, struct nmb_packet *nmb)
+{
+ int nm_flags, offset;
+
+ memset((char *)nmb, 0, sizeof(*nmb));
+
+ if (length < 12) return(0);
+
+ /* parse the header */
+ nmb->header.name_trn_id = RSVAL(inbuf, 0);
+
+ nmb->header.opcode = (CVAL(inbuf, 2) >> 3) & 0xF;
+ nmb->header.response = ((CVAL(inbuf, 2) >> 7) & 1) ? 1 : 0;
+ nm_flags = ((CVAL(inbuf, 2) & 0x7) << 4) + (CVAL(inbuf, 3) >> 4);
+ nmb->header.nm_flags.bcast = (nm_flags & 1) ? 1 : 0;
+ nmb->header.nm_flags.recursion_available = (nm_flags & 8) ? 1 : 0;
+ nmb->header.nm_flags.recursion_desired = (nm_flags & 0x10) ? 1 : 0;
+ nmb->header.nm_flags.trunc = (nm_flags & 0x20) ? 1 : 0;
+ nmb->header.nm_flags.authoritative = (nm_flags & 0x40) ? 1 : 0;
+ nmb->header.rcode = CVAL(inbuf, 3) & 0xF;
+ nmb->header.qdcount = RSVAL(inbuf, 4);
+ nmb->header.ancount = RSVAL(inbuf, 6);
+ nmb->header.nscount = RSVAL(inbuf, 8);
+ nmb->header.arcount = RSVAL(inbuf, 10);
+
+ if (nmb->header.qdcount) {
+ offset = parse_nmb_name(inbuf, 12, length, &nmb->question.question_name);
+ if (!offset) return 0;
+
+ if (length - (12+offset) < 4) return 0;
+ nmb->question.question_type = RSVAL(inbuf, 12+offset);
+ nmb->question.question_class = RSVAL(inbuf, 12+offset+2);
+
+ offset += 12+4;
+ } else {
+ offset = 12;
+ }
+
+ /* and any resource records */
+ if (nmb->header.ancount &&
+ !parse_alloc_res_rec(inbuf, &offset, length, &nmb->answers,
+ nmb->header.ancount)) {
+ return 0;
+ }
+
+ if (nmb->header.nscount &&
+ !parse_alloc_res_rec(inbuf, &offset, length, &nmb->nsrecs,
+ nmb->header.nscount)) {
+ return 0;
+ }
+
+ if (nmb->header.arcount &&
+ !parse_alloc_res_rec(inbuf, &offset, length, &nmb->additional,
+ nmb->header.arcount)) {
+ return 0;
+ }
+
+ return 1;
+}
+
+void make_nmb_name(struct nmb_name *n, const char *name, int type, const char *this_scope)
+{
+ memset((char *)n, 0, sizeof(struct nmb_name));
+ strncpy(n->name, name, 15);
+ strupper(n->name);
+ n->name_type = (unsigned int)type & 0xFF;
+ strncpy(n->scope, this_scope, 63);
+ strupper(n->scope);
+}
+
+int parse_nmb_name(char *inbuf, int offset, int length, struct nmb_name *name)
+{
+ int m, n = 0;
+ unsigned char *ubuf = (unsigned char *)inbuf;
+ int ret = 0;
+ int got_pointer = 0;
+ int loop_count = 0;
+
+ if (length - offset < 2)
+ return 0;
+
+ /* handle initial name pointers */
+ if (!handle_name_ptrs(ubuf, &offset, length, &got_pointer, &ret))
+ return 0;
+
+ m = ubuf[offset];
+
+ if (!m)
+ return 0;
+ if ((m & 0xC0) || offset+m+2 > length)
+ return 0;
+
+ memset((char *)name, 0, sizeof(*name));
+
+ /* the "compressed" part */
+ if (!got_pointer)
+ ret += m + 2;
+ offset++;
+
+ while (m > 0) {
+ unsigned char c1,c2;
+ c1 = ubuf[offset++]-'A';
+ c2 = ubuf[offset++]-'A';
+ if ((c1 & 0xF0) || (c2 & 0xF0) || (n > sizeof(name->name)-1))
+ return 0;
+ name->name[n++] = (c1<<4) | c2;
+ m -= 2;
+ }
+ name->name[n] = 0;
+
+ if (n==16) {
+ /* parse out the name type,
+ its always in the 16th byte of the name */
+ name->name_type = ((unsigned char)name->name[15]) & 0xff;
+
+ /* remove trailing spaces */
+ name->name[15] = 0;
+ n = 14;
+ while (n && name->name[n]==' ')
+ name->name[n--] = 0;
+ }
+
+ /* now the domain parts (if any) */
+ n = 0;
+ while (ubuf[offset]) {
+ /* we can have pointers within the domain part as well */
+ if (!handle_name_ptrs(ubuf,&offset,length,&got_pointer,&ret))
+ return 0;
+
+ m = ubuf[offset];
+ /*
+ * Don't allow null domain parts.
+ */
+ if (!m)
+ return 0;
+ if (!got_pointer)
+ ret += m+1;
+ if (n)
+ name->scope[n++] = '.';
+ if (m + 2 + offset > length || n + m + 1 > sizeof(name->scope))
+ return 0;
+ offset++;
+ while (m--)
+ name->scope[n++] = (char)ubuf[offset++];
+
+ /*
+ * Watch for malicious loops.
+ */
+ if (loop_count++ == 10)
+ return 0;
+ }
+ name->scope[n++] = 0;
+
+ return ret;
+}
+
+int put_nmb_name(char *buf, int offset, struct nmb_name *name)
+{
+ int ret,m;
+ char buf1[128];
+ char *p;
+
+ if (strcmp(name->name,"*") == 0) {
+ /* special case for wildcard name */
+ memset(buf1,'\0',20);
+ buf1[0] = '*';
+ buf1[15] = name->name_type;
+ } else {
+ snprintf(buf1, sizeof(buf1) - 1,"%-15.15s%c",name->name,name->name_type);
+ }
+
+ buf[offset] = 0x20;
+ ret = 34;
+
+ for (m=0; m<16; m++) {
+ buf[offset + 1 + 2*m] = 'A' + ((buf1[m] >> 4) & 0xF);
+ buf[offset + 2 + 2*m] = 'A' + ( buf1[m] & 0xF);
+ }
+ offset += 33;
+
+ buf[offset] = 0;
+
+ if (name->scope[0]) {
+ /* XXXX this scope handling needs testing */
+ ret += strlen(name->scope) + 1;
+ strcpy(&buf[offset + 1], name->scope);
+
+ p = &buf[offset + 1];
+ while ((p = strchr(p, '.'))) {
+ buf[offset] = PTR_DIFF(p, &buf[offset]);
+ offset += buf[offset];
+ p = &buf[offset+1];
+ }
+ buf[offset] = strlen(&buf[offset+1]);
+ }
+
+ return ret;
+}
+
+int handle_name_ptrs(unsigned char *ubuf, int *offset, int length,
+ int *got_pointer, int *ret)
+{
+ int loop_count=0;
+
+ while ((ubuf[*offset] & 0xC0) == 0xC0) {
+ if (!*got_pointer) (*ret) += 2;
+ (*got_pointer) = 1;
+ (*offset) = ((ubuf[*offset] & ~0xC0) << 8) | ubuf[(*offset)+1];
+ if (loop_count++ == 10 || (*offset) < 0 || (*offset) > (length-2)) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+int parse_alloc_res_rec(char *inbuf, int *offset, int length,
+ struct res_rec **recs, int count)
+{
+ int i;
+ *recs = (struct res_rec *)malloc(sizeof(**recs) * count);
+ if (!*recs) return 0;
+
+ memset((char *)*recs, 0, sizeof(**recs) * count);
+
+ for (i=0; i<count; i++) {
+ int l = parse_nmb_name(inbuf, *offset, length, &(*recs)[i].rr_name);
+ (*offset) += l;
+ if (!l || (*offset)+10 > length) {
+ free(*recs);
+ *recs = NULL;
+ return 0;
+ }
+ (*recs)[i].rr_type = RSVAL(inbuf, (*offset));
+ (*recs)[i].rr_class = RSVAL(inbuf, (*offset)+2);
+ (*recs)[i].ttl = RIVAL(inbuf, (*offset)+4);
+ (*recs)[i].rdlength = RSVAL(inbuf, (*offset)+8);
+ (*offset) += 10;
+ if ((*recs)[i].rdlength > sizeof((*recs)[i].rdata) ||
+ (*offset)+(*recs)[i].rdlength > length) {
+ free(*recs);
+ *recs = NULL;
+ return 0;
+ }
+ memcpy((*recs)[i].rdata, inbuf+(*offset), (*recs)[i].rdlength);
+ (*offset) += (*recs)[i].rdlength;
+ }
+ return 0;
+}
+
+void free_nmb_packet(struct nmb_packet *nmb)
+{
+ if (nmb->answers) {
+ free(nmb->answers);
+ nmb->answers = NULL;
+ }
+ if (nmb->nsrecs) {
+ free(nmb->nsrecs);
+ nmb->nsrecs = NULL;
+ }
+ if (nmb->additional) {
+ free(nmb->additional);
+ nmb->additional = NULL;
+ }
+ free(nmb);
+}
+
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * nmb.h: Prototypes for nmb.c.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _NMB_H
+#define _NMB_H 1
+
+#include "packet.h"
+
+void build_nbt_packet(struct nmb_packet *nmb, int name_trn_id);
+int put_nmb_name(char *buf, int offset, struct nmb_name *name);
+int build_nmb(char *buf, struct nmb_packet *nmb);
+int parse_nmb(char *inbuf, int length, struct nmb_packet *nmb);
+void make_nmb_name(struct nmb_name *n, const char *name, int type, const char *this_scope);
+int parse_nmb_name(char *inbuf,int offset,int length, struct nmb_name *name);
+int handle_name_ptrs(unsigned char *ubuf, int *offset, int length,
+ int *got_pointer, int *ret);
+int parse_alloc_res_rec(char *inbuf, int *offset, int length,
+ struct res_rec **recs, int count);
+void free_nmb_packet(struct nmb_packet *nmb);
+
+#endif /* _NMB_H */
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * outputfile.c: nbtscanner text file output.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+
+#include "mysql_interface.h"
+#include "configfile.h"
+
+int main(int argc, char *argv[])
+{
+ parse_configfile(0);
+
+ if (!use_mysql) {
+ if (verbosity >= 1) {
+ fprintf(stderr, "Eeeeh, you have disabled MySQL! :-)\n");
+ }
+ exit(1);
+ }
+
+ print_all_records_mysql();
+ finish_mysql();
+
+ return 0;
+}
+
+/* will never be called */
+void scan_range(struct in_addr ip, int rangesize) {}
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * packet.h: NMB/NBT packet structure definitions.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _PACKET_H
+#define _PACKET_H 1
+
+#define MAX_DGRAM_SIZE 576
+#define MIN_DGRAM_SIZE 12
+
+struct nmb_name {
+ char name[17];
+ char scope[64];
+ unsigned int name_type;
+};
+
+struct res_rec {
+ struct nmb_name rr_name;
+ int rr_type;
+ int rr_class;
+ int ttl;
+ int rdlength;
+ char rdata[MAX_DGRAM_SIZE];
+};
+
+struct nmb_packet {
+ struct {
+ int name_trn_id;
+ int opcode;
+ int response;
+ struct {
+ int bcast;
+ int recursion_available;
+ int recursion_desired;
+ int trunc;
+ int authoritative;
+ } nm_flags;
+ int rcode;
+ int qdcount;
+ int ancount;
+ int nscount;
+ int arcount;
+ } header;
+
+ struct {
+ struct nmb_name question_name;
+ int question_type;
+ int question_class;
+ } question;
+
+ struct res_rec *answers;
+ struct res_rec *nsrecs;
+ struct res_rec *additional;
+};
+
+#endif /* _PACKET_H */
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * socket.c: Most functions that are related to TCP/IP (socket) use.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * This file is probably the most platform-dependent one, and would most
+ * likely be needed to undergo some changes if ported to another OS than
+ * the ones using BSD-style sockets (Winsock is a variant of these,
+ * by the way -- you may only want to change some header files and add some
+ * extra initialization calls).
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "socket.h"
+#include "nmb.h"
+#include "packet.h"
+
+int open_sockets(void)
+{
+ unsigned int one = 1;
+ struct sockaddr_in sin;
+ int sock;
+
+ memset((char *)&sin, 0, sizeof(sin));
+ sin.sin_port = htons(0);
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = INADDR_ANY;
+
+ sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sock == -1) {
+ perror("socket()");
+ exit(0);
+ }
+
+ setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
+
+ /* bind the socket */
+ if (bind(sock, (struct sockaddr *) &sin,sizeof(sin)) < 0) {
+ perror("bind()");
+ exit(1);
+ }
+
+ return sock;
+}
+
+int send_packet(struct nmb_packet *nmb, struct in_addr ip, int port, int fd)
+{
+ char buf[1024];
+ int len = 0;
+
+ memset(buf, 0, sizeof(buf));
+
+ len = build_nmb(buf,nmb);
+ if (!len) return(0);
+
+ return(send_udp(fd,buf,len,ip,port));
+}
+
+struct nmb_packet *receive_packet(int fd, int t, struct in_addr *in)
+{
+ fd_set fds;
+ struct timeval timeout;
+
+ FD_ZERO(&fds);
+ FD_SET(fd,&fds);
+ timeout.tv_sec = t / 1000;
+ timeout.tv_usec = 1000 * (t % 1000);
+
+ select(fd+1,&fds,NULL,NULL,&timeout);
+
+ if (FD_ISSET(fd,&fds))
+ return read_packet(fd, in);
+
+ return(NULL);
+}
+
+struct nmb_packet *read_packet(int fd, struct in_addr *in)
+{
+ /* extern struct in_addr lastip;
+ extern int lastport; */
+ char buf[MAX_DGRAM_SIZE];
+ int length;
+ int ok = 0;
+ struct nmb_packet *nmb;
+
+ length = read_udp_socket(fd, buf, sizeof(buf), in);
+ if (length < MIN_DGRAM_SIZE) return(NULL);
+
+ nmb = (struct nmb_packet *)malloc(sizeof(struct nmb_packet)); /* ?? */
+ ok = parse_nmb(buf, length, nmb);
+
+ return(nmb);
+}
+
+int send_udp(int fd,char *buf,int len,struct in_addr ip,int port)
+{
+ int ret;
+ struct sockaddr_in sock_out;
+
+ /* set the address and port */
+ memset((char *)&sock_out, 0, sizeof(sock_out));
+ memcpy((char *)&sock_out.sin_addr, (char *)&ip, 4);
+ sock_out.sin_port = htons(port);
+ sock_out.sin_family = AF_INET;
+
+ ret = (sendto(fd,buf,len,0,(struct sockaddr *)&sock_out,
+ sizeof(sock_out)) >= 0);
+
+ return ret;
+}
+
+ssize_t read_udp_socket(int fd, char *buf, size_t len, struct in_addr *in)
+{
+ ssize_t ret;
+ struct sockaddr_in sin;
+ int sin_len;
+
+ sin_len = sizeof(sin);
+ memset((char *)&sin, 0, sin_len);
+ ret = (ssize_t)recvfrom(fd, buf, len, 0, (struct sockaddr *)&sin, &sin_len);
+ if (ret <= 0) {
+ perror("recvfrom()");
+ return(0);
+ }
+
+ *in = sin.sin_addr;
+
+ return ret;
+}
+
+
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * socket.h: Prototypes for socket.c.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _SOCKET_H
+#define _SOCKET_H 1
+
+#include "packet.h"
+
+#include <netinet/in.h>
+
+int open_sockets(void);
+int send_packet(struct nmb_packet *nmb, struct in_addr ip, int port, int fd);
+struct nmb_packet *receive_packet(int fd, int t, struct in_addr *in);
+struct nmb_packet *read_packet(int fd, struct in_addr *in);
+int send_udp(int fd, char *buf, int len, struct in_addr ip, int port);
+ssize_t read_udp_socket(int fd, char *buf, size_t len, struct in_addr *in);
+
+#endif /* _SOCKET_H */
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * stats.c: Running statistics.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "stats.h"
+#include "configfile.h"
+#include "util.h"
+
+#include <stdio.h>
+#include <sys/time.h>
+
+int num_recv;
+int num_recv_retries;
+int num_failed;
+int num_sent;
+int num_sent_total;
+enum statuses status;
+
+struct timeval last_stats;
+
+void init_stats()
+{
+ num_recv = 0;
+ num_recv_retries = 0;
+ num_failed = 0;
+ num_sent = 0;
+ num_sent_total = 0;
+ status = SCANNING;
+
+ gettimeofday(&last_stats, NULL);
+}
+
+void print_stats(int force)
+{
+ struct timeval now;
+
+ gettimeofday(&now, NULL);
+ if (verbosity >= 3 && (mydifftime(last_stats, now) > 1000 || force == 1)) {
+ fprintf(stderr, "%s: Received %5u/%5u/%5u (%5u failed) (avg. "
+ "retries/succ.: %3.2f)\r",
+ (status == SCANNING) ? "Scanning" : "Retrying",
+ num_recv, num_sent, num_sent_total, num_failed,
+ (float)num_recv_retries / (float)num_recv);
+
+ gettimeofday(&last_stats, NULL);
+ }
+}
+
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * stats.h: Definitions and prototypes for stats.c.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _STATS_H
+#define _STATS_H 1
+
+extern int num_recv;
+extern int num_recv_retries;
+extern int num_failed;
+extern int num_sent;
+extern int num_sent_total;
+
+enum statuses {
+ SCANNING,
+ RETRYING
+};
+
+extern enum statuses status;
+
+void init_stats();
+void print_stats(int force);
+
+#endif /* _STATS_H */
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * util.c: Useful small functions.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <ctype.h>
+#include <sys/time.h>
+
+void strupper(char *s)
+{
+ while (*s) { *s = toupper(*s); s++; }
+}
+
+int mydifftime(struct timeval t1, struct timeval t2)
+{
+ return (t2.tv_sec - t1.tv_sec) * 1000 +
+ (t2.tv_usec - t1.tv_usec) / 1000;
+}
+
--- /dev/null
+/*
+ * nbtscanner -- a tool for scanning large networks for SMB servers.
+ *
+ * string_util.h: Function prototypes for string_util.c.
+ * Copyright (C) 2000 Steinar H. Gunderson
+ *
+ * Large amounts of code adapted from Samba (http://www.samba.org/)
+ * Copyright (C) Andrew Tridgell 1994-1998, and others.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _STRING_UTIL_H
+#define _STRING_UTIL_H 1
+
+#include <sys/time.h>
+
+void strupper(char *s);
+int mydifftime(struct timeval t1, struct timeval t2);
+
+#endif /* STRING_UTIL_H */