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>
43 char mysql_username[32];
44 char mysql_password[32];
46 void parse_configfile(int do_scan)
48 FILE *configfile = fopen("nbtscanner.conf", "r");
51 if (configfile == NULL) {
52 perror("nbtscanner.conf");
63 strcpy(mysql_host, "no_host_given");
64 strcpy(mysql_username, "no_username_given");
65 strcpy(mysql_password, "no_password_given");
67 while (!feof(configfile)) {
72 fgets(buf, 1024, configfile);
73 while (buf[strlen(buf) - 1] == '\n' || buf[strlen(buf) - 1] == '\r') {
74 buf[strlen(buf) - 1] = '\0';
77 if (buf[0] == '#' || buf[0] == '\0') {
78 /* comment or blank line */
81 if (strspn(buf, " \t") == strlen(buf)) {
86 parse_line(buf, lineno, do_scan);
92 void parse_line(char *buf, int lineno, int do_scan)
94 char *ptr = strchr(buf, '=');
96 if (ptr == NULL || strchr(ptr + 1, '=') != NULL) {
97 line_error(lineno, "Malformed line (must be exactly one `=' sign)");
100 /* split the line into a keyword and a value */
105 * trim any trailing spaces, make sure there are no spaces in
109 char *ptr2 = strchr(ptr, ' ');
111 /* must only be spaces from here */
112 if (strspn(ptr2 + 1, " ") != strlen(ptr2 + 1)) {
113 line_error(lineno, "Malformed value (can't have any spaces)");
120 /* make sure both the parameter and the value is non-empty */
121 if (buf[0] == '\0') {
122 line_error(lineno, "Malformed keyword (can't be empty)");
124 if (ptr[0] == '\0') {
125 line_error(lineno, "Malformed value (can't be empty)");
128 /* finally pass it on to the keyword checker */
129 parse_keyword(buf, ptr, lineno, do_scan);
132 void parse_keyword(char *keyword, char *value, int lineno, int do_scan)
134 if (strcasecmp(keyword, "num_retries") == 0) {
135 parse_int(value, &num_retries, lineno);
136 } else if (strcasecmp(keyword, "retry_time") == 0) {
137 parse_int(value, &retry_time, lineno);
138 } else if (strcasecmp(keyword, "delay_time") == 0) {
139 parse_int(value, &delay_time, lineno);
140 } else if (strcasecmp(keyword, "verbosity") == 0) {
141 parse_int(value, &verbosity, lineno);
142 } else if (strcasecmp(keyword, "use_mysql") == 0) {
143 parse_int(value, &use_mysql, lineno);
144 } else if (strcasecmp(keyword, "mysql_host") == 0) {
145 strcpy(mysql_host, value);
146 } else if (strcasecmp(keyword, "mysql_username") == 0) {
147 strcpy(mysql_username, value);
148 } else if (strcasecmp(keyword, "mysql_password") == 0) {
149 strcpy(mysql_password, value);
150 } else if (strcasecmp(keyword, "range") == 0) {
151 /* really ugly to have here */
153 init_mysql(mysql_host, mysql_username, mysql_password);
155 if (do_scan) parse_range(value, lineno);
158 sprintf(buf, "Unknown keyword `%s'", keyword);
159 line_error(lineno, buf);
163 void parse_int(char *string, int *retval, int lineno)
165 if (strspn(string, "0123456789") != strlen(string)) {
167 sprintf(buf, "`%s' isn't a positive integer", string);
168 line_error(lineno, buf);
171 *retval = atoi(string);
174 void parse_range(char *string, int lineno)
176 /* exactly one / is allowed */
177 char *ptr = strchr(string, '/');
181 if (ptr != NULL && strchr(ptr + 1, '/') != NULL) {
182 line_error(lineno, "Malformed range (only one `/' allowed)");
185 /* lots and lots of code :-) */
186 if (ptr == NULL) { /* single IP */
192 /* find out whether this is a pure integer or not */
193 if (strspn(ptr, "0123456789") == strlen(ptr)) {
194 rangesize = atoi(ptr);
195 if (rangesize < 0 || rangesize > 32) {
196 line_error(lineno, "Malformed range (significant bits must be between 0 and 32, inclusive)");
198 } else if (strspn(ptr, "0123456789.") == strlen(ptr)) {
200 struct in_addr netmask;
203 if (inet_aton(ptr, &netmask) == 0) {
204 line_error(lineno, "Malformed range (malformed netmask)");
207 /* find the rightmost 1-bit (by finding the leftmost 0-bit) */
209 for (i = 31; i >= 0; i--) {
210 if ((netmask.s_addr & (1 << i)) == 0) {
216 rangesize = 32; /* 255.255.255.255 */
218 unsigned int clean_mask = htonl(~((1 << (31-i)) - 1));
222 /* verify that this is a `clean' netmask */
223 if (netmask.s_addr != clean_mask) {
224 line_error(lineno, "Malformed range (netmask must be `clean')");
228 line_error(lineno, "Malformed range (malformed netmask)");
229 rangesize = 32; /* will never reach this, but for gcc */
233 /* try to scan the IP part */
234 if (inet_aton(string, &in) == 0) {
235 line_error(lineno, "Malformed range (malformed IP address)");
238 /* check that the IP address and the netmask match */
239 if (rangesize != 32) {
240 /* not really the netmask, actually it's the inverted netmask */
241 unsigned int netmask = htonl((1 << (31-rangesize)) - 1);
243 if ((in.s_addr & netmask) != 0) {
244 line_error(lineno, "Malformed range (IP address doesn't match netmask)");
248 scan_range(in, rangesize);
251 void line_error(int lineno, char *err_str)
253 fprintf(stderr, "nbtscanner.conf:%d: %s\n", lineno, err_str);