2 * nbtscanner -- a tool for scanning large networks for SMB servers.
4 * configfile.c: Functions for parsing the configuration file.
5 * Copyright (C) 2000 Steinar H. Gunderson
7 * Large amounts of code adapted from Samba (http://www.samba.org/)
8 * Copyright (C) Andrew Tridgell 1994-1998, and others.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include "configfile.h"
26 #include "nbtscanner.h"
27 #include "mysql_interface.h"
32 #include <sys/socket.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
44 struct in_addr scanrange[NUM_RANGES];
45 int scanrangesize[NUM_RANGES];
50 char mysql_username[32];
51 char mysql_password[32];
53 void parse_configfile()
55 FILE *configfile = fopen("nbtscanner.conf", "r");
58 if (configfile == NULL) {
59 perror("nbtscanner.conf");
72 strcpy(mysql_host, "no_host_given");
73 strcpy(mysql_username, "no_username_given");
74 strcpy(mysql_password, "no_password_given");
76 while (!feof(configfile)) {
81 fgets(buf, 1024, configfile);
82 while (buf[strlen(buf) - 1] == '\n' || buf[strlen(buf) - 1] == '\r') {
83 buf[strlen(buf) - 1] = '\0';
86 if (buf[0] == '#' || buf[0] == '\0') {
87 /* comment or blank line */
90 if (strspn(buf, " \t") == strlen(buf)) {
95 parse_line(buf, lineno);
101 void parse_line(char *buf, int lineno)
103 char *ptr = strchr(buf, '=');
105 if (ptr == NULL || strchr(ptr + 1, '=') != NULL) {
106 line_error(lineno, "Malformed line (must be exactly one `=' sign)");
109 /* split the line into a keyword and a value */
114 * trim any trailing spaces, make sure there are no spaces in
118 char *ptr2 = strchr(ptr, ' ');
120 /* must only be spaces from here */
121 if (strspn(ptr2 + 1, " ") != strlen(ptr2 + 1)) {
122 line_error(lineno, "Malformed value (can't have any spaces)");
129 /* make sure both the parameter and the value is non-empty */
130 if (buf[0] == '\0') {
131 line_error(lineno, "Malformed keyword (can't be empty)");
133 if (ptr[0] == '\0') {
134 line_error(lineno, "Malformed value (can't be empty)");
137 /* finally pass it on to the keyword checker */
138 parse_keyword(buf, ptr, lineno);
141 void parse_keyword(char *keyword, char *value, int lineno)
143 if (strcasecmp(keyword, "num_retries") == 0) {
144 parse_int(value, &num_retries, lineno);
145 } else if (strcasecmp(keyword, "retry_time") == 0) {
146 parse_int(value, &retry_time, lineno);
147 } else if (strcasecmp(keyword, "delay_time") == 0) {
148 parse_int(value, &delay_time, lineno);
149 } else if (strcasecmp(keyword, "verbosity") == 0) {
150 parse_int(value, &verbosity, lineno);
151 } else if (strcasecmp(keyword, "scan_interval") == 0) {
152 parse_int(value, &scan_interval, lineno);
153 } else if (strcasecmp(keyword, "scan_wait") == 0) {
154 parse_int(value, &scan_wait, lineno);
155 } else if (strcasecmp(keyword, "use_mysql") == 0) {
156 parse_int(value, &use_mysql, lineno);
157 } else if (strcasecmp(keyword, "mysql_host") == 0) {
158 strcpy(mysql_host, value);
159 } else if (strcasecmp(keyword, "mysql_username") == 0) {
160 strcpy(mysql_username, value);
161 } else if (strcasecmp(keyword, "mysql_password") == 0) {
162 strcpy(mysql_password, value);
163 } else if (strcasecmp(keyword, "range") == 0) {
164 parse_range(value, lineno);
167 sprintf(buf, "Unknown keyword `%s'", keyword);
168 line_error(lineno, buf);
172 void parse_int(char *string, int *retval, int lineno)
174 if (strspn(string, "0123456789") != strlen(string)) {
176 sprintf(buf, "`%s' isn't a positive integer", string);
177 line_error(lineno, buf);
180 *retval = atoi(string);
183 void parse_range(char *string, int lineno)
185 /* exactly one / is allowed */
186 char *ptr = strchr(string, '/');
190 if (ptr != NULL && strchr(ptr + 1, '/') != NULL) {
191 line_error(lineno, "Malformed range (only one `/' allowed)");
194 /* lots and lots of code :-) */
195 if (ptr == NULL) { /* single IP */
201 /* find out whether this is a pure integer or not */
202 if (strspn(ptr, "0123456789") == strlen(ptr)) {
203 rangesize = atoi(ptr);
204 if (rangesize < 0 || rangesize > 32) {
205 line_error(lineno, "Malformed range (significant bits must be between 0 and 32, inclusive)");
207 } else if (strspn(ptr, "0123456789.") == strlen(ptr)) {
209 struct in_addr netmask;
212 if (inet_aton(ptr, &netmask) == 0) {
213 line_error(lineno, "Malformed range (malformed netmask)");
216 /* find the rightmost 1-bit (by finding the leftmost 0-bit) */
218 for (i = 31; i >= 0; i--) {
219 if ((netmask.s_addr & (1 << i)) == 0) {
225 rangesize = 32; /* 255.255.255.255 */
227 unsigned int clean_mask = htonl(~((1 << (31-i)) - 1));
231 /* verify that this is a `clean' netmask */
232 if (netmask.s_addr != clean_mask) {
233 line_error(lineno, "Malformed range (netmask must be `clean')");
237 line_error(lineno, "Malformed range (malformed netmask)");
238 rangesize = 32; /* will never reach this, but for gcc */
242 /* try to scan the IP part */
243 if (inet_aton(string, &in) == 0) {
244 line_error(lineno, "Malformed range (malformed IP address)");
247 /* check that the IP address and the netmask match */
248 if (rangesize != 32) {
249 /* not really the netmask, actually it's the inverted netmask */
250 unsigned int netmask = htonl((1 << (31-rangesize)) - 1);
252 if ((in.s_addr & netmask) != 0) {
253 line_error(lineno, "Malformed range (IP address doesn't match netmask)");
257 memcpy((char *)(&(scanrange[ranges])), (char *)(&in), sizeof(in));
258 scanrangesize[ranges++] = rangesize;
261 void line_error(int lineno, char *err_str)
263 fprintf(stderr, "nbtscanner.conf:%d: %s\n", lineno, err_str);