2 * Copyright (c) 1987, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 #include <pcap.h> // for PCAP_ERRBUF_SIZE
43 #include "portability.h"
45 #include "config_params.h" // configuration file parameters
47 #include "rpcap-protocol.h"
53 #define PARAM_ACTIVECLIENT "ActiveClient"
54 #define PARAM_PASSIVECLIENT "PassiveClient"
55 #define PARAM_NULLAUTHPERMIT "NullAuthPermit"
57 static char *skipws(char *ptr
);
60 * Locale-independent version checks for alphabetical and alphanumerical
61 * characters that also can handle being handed a char value that might
64 #define FILECONF_ISALPHA(c) \
65 (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
66 #define FILECONF_ISALNUM(c) \
67 (FILECONF_ISALPHA(c) || ((c) >= '0' && (c) <= '9'))
69 void fileconf_read(void)
72 unsigned int num_active_clients
;
74 if ((fp
= fopen(loadfile
, "r")) != NULL
)
76 char line
[MAX_LINE
+ 1];
80 num_active_clients
= 0;
83 while (fgets(line
, MAX_LINE
, fp
) != NULL
)
93 linelen
= strlen(line
);
94 if (line
[linelen
- 1] != '\n')
99 // Either the line doesn't fit in
100 // the buffer, or we got an EOF
101 // before the EOL. Assume it's the
104 rpcapd_log(LOGPRIO_ERROR
,
105 "%s, line %u is longer than %u characters",
106 loadfile
, lineno
, MAX_LINE
);
109 // Eat characters until we get an NL.
111 while ((c
= getc(fp
)) != '\n')
118 // Try the next line.
125 // Skip leading white space, if any.
135 // Is the next character a "#"? If so, this
136 // line is a comment; skip to the next line.
142 // Is the next character alphabetic? If not,
143 // this isn't a valid parameter name.
145 if (FILECONF_ISALPHA(*ptr
))
147 rpcapd_log(LOGPRIO_ERROR
,
148 "%s, line %u doesn't have a valid parameter name",
154 // Grab the first token, which is made of
155 // alphanumerics, underscores, and hyphens.
156 // That's the name of the parameter being set.
159 while (FILECONF_ISALNUM(*ptr
) || *ptr
== '-' || *ptr
== '_')
163 // Skip over white space, if any.
166 if (ptr
== NULL
|| *ptr
!= '=')
169 // We hit the end of the line before
170 // finding a non-white space character,
171 // or we found one but it's not an "=".
172 // That means there's no "=", so this
173 // line is invalid. Complain and skip
176 rpcapd_log(LOGPRIO_ERROR
,
177 "%s, line %u has a parameter but no =",
183 // We found the '='; set it to '\0', and skip
189 // Skip past any white space after the "=".
195 // The value is empty.
197 rpcapd_log(LOGPRIO_ERROR
,
198 "%s, line %u has a parameter but no value",
204 // OK, what parameter is this?
206 if (strcmp(param
, PARAM_ACTIVECLIENT
) == 0) {
208 // Add this to the list of active clients.
210 char *address
, *port
;
213 // We can't have more than MAX_ACTIVE_LIST
216 if (num_active_clients
>= MAX_ACTIVE_LIST
)
219 // Too many entries for the active
220 // client list. Complain and
223 rpcapd_log(LOGPRIO_ERROR
,
224 "%s, line %u has an %s parameter, but we already have %u active clients",
225 loadfile
, lineno
, PARAM_ACTIVECLIENT
,
232 // It's terminated by a host list separator
233 // *or* a #; there *shouldn't* be a #, as
234 // that starts a comment, and that would
235 // mean that we have no port.
238 toklen
= strcspn(ptr
, RPCAP_HOSTLIST_SEP
"#");
239 ptr
+= toklen
; // skip to the terminator
242 if (*ptr
== ' ' || *ptr
== '\t' ||
243 *ptr
== '\r' || *ptr
== '\n' ||
244 *ptr
== '#' || *ptr
== '\0')
247 // The first character it saw
248 // was a whitespace character
249 // or a comment character,
250 // or we ran out of characters.
251 // This means that there's
254 rpcapd_log(LOGPRIO_ERROR
,
255 "%s, line %u has a parameter but no value",
261 // This means that the first
262 // character it saw was a
263 // separator. This means that
264 // there's no address in the
265 // value, just a port.
267 rpcapd_log(LOGPRIO_ERROR
,
268 "%s, line %u has an %s parameter with a value containing no address",
269 loadfile
, lineno
, PARAM_ACTIVECLIENT
);
275 // Null-terminate the address, and skip past
281 // Skip any white space following the
282 // separating character.
288 // The value is empty, so there's
289 // no port in the value.
291 rpcapd_log(LOGPRIO_ERROR
,
292 "%s, line %u has an %s parameter with a value containing no port",
293 loadfile
, lineno
, PARAM_ACTIVECLIENT
);
299 // We look for a white space character
300 // or a # as a terminator; the # introduces
301 // a comment that runs to the end of the
305 toklen
= strcspn(ptr
, " \t#\r\n");
310 // The value is empty, so there's
311 // no port in the value.
313 rpcapd_log(LOGPRIO_ERROR
,
314 "%s, line %u has an %s parameter with a value containing no port",
315 loadfile
, lineno
, PARAM_ACTIVECLIENT
);
320 // Null-terminate the port, and skip past
324 result
= pcapint_strlcpy(activelist
[num_active_clients
].address
, address
, sizeof(activelist
[num_active_clients
].address
));
325 if (result
>= sizeof(activelist
[num_active_clients
].address
))
330 rpcapd_log(LOGPRIO_ERROR
,
331 "%s, line %u has an %s parameter with an address with more than %u characters",
332 loadfile
, lineno
, PARAM_ACTIVECLIENT
,
333 (unsigned int)(sizeof(activelist
[num_active_clients
].address
) - 1));
336 if (strcmp(port
, "DEFAULT") == 0) // the user choose a custom port
337 result
= pcapint_strlcpy(activelist
[num_active_clients
].port
, RPCAP_DEFAULT_NETPORT_ACTIVE
, sizeof(activelist
[num_active_clients
].port
));
339 result
= pcapint_strlcpy(activelist
[num_active_clients
].port
, port
, sizeof(activelist
[num_active_clients
].port
));
340 if (result
>= sizeof(activelist
[num_active_clients
].address
))
345 rpcapd_log(LOGPRIO_ERROR
,
346 "%s, line %u has an %s parameter with an port with more than %u characters",
347 loadfile
, lineno
, PARAM_ACTIVECLIENT
,
348 (unsigned int)(sizeof(activelist
[num_active_clients
].port
) - 1));
352 num_active_clients
++;
354 else if (strcmp(param
, PARAM_PASSIVECLIENT
) == 0)
361 // We look for a white space character
362 // or a # as a terminator; the # introduces
363 // a comment that runs to the end of the
367 toklen
= strcspn(ptr
, " \t#\r\n");
371 // The first character it saw
372 // was a whitespace character
373 // or a comment character.
374 // This means that there's
377 rpcapd_log(LOGPRIO_ERROR
,
378 "%s, line %u has a parameter but no value",
386 // Append this to the host list.
387 // Save the current end-of-string for the
388 // host list, in case the new host doesn't
389 // fit, so that we can discard the partially-
392 eos
= hostlist
+ strlen(hostlist
);
396 // The list is not empty, so prepend
397 // a comma before adding this host.
399 result
= pcapint_strlcat(hostlist
, ",", sizeof(hostlist
));
400 if (result
>= sizeof(hostlist
))
403 // It didn't fit. Discard
404 // the comma (which wasn't
405 // added, but...), complain,
406 // and ignore this line.
409 rpcapd_log(LOGPRIO_ERROR
,
410 "%s, line %u has a %s parameter with a host name that doesn't fit",
411 loadfile
, lineno
, PARAM_PASSIVECLIENT
);
415 result
= pcapint_strlcat(hostlist
, host
, sizeof(hostlist
));
416 if (result
>= sizeof(hostlist
))
419 // It didn't fit. Discard the comma,
420 // complain, and ignore this line.
423 rpcapd_log(LOGPRIO_ERROR
,
424 "%s, line %u has a %s parameter with a host name that doesn't fit",
425 loadfile
, lineno
, PARAM_PASSIVECLIENT
);
429 else if (strcmp(param
, PARAM_NULLAUTHPERMIT
) == 0)
435 // We look for a white space character
436 // or a # as a terminator; the # introduces
437 // a comment that runs to the end of the
441 toklen
= strcspn(ptr
, " \t#\r\n");
446 // The first character it saw
447 // was a whitespace character
448 // or a comment character.
449 // This means that there's
452 rpcapd_log(LOGPRIO_ERROR
,
453 "%s, line %u has a parameter but no value",
460 // XXX - should we complain if it's
461 // neither "yes" nor "no"?
463 if (strcmp(setting
, "YES") == 0)
470 rpcapd_log(LOGPRIO_ERROR
,
471 "%s, line %u has an unknown parameter %s",
472 loadfile
, lineno
, param
);
478 // clear the remaining fields of the active list
479 for (int i
= num_active_clients
; i
< MAX_ACTIVE_LIST
; i
++)
481 activelist
[i
].address
[0] = 0;
482 activelist
[i
].port
[0] = 0;
483 num_active_clients
++;
486 rpcapd_log(LOGPRIO_DEBUG
, "New passive host list: %s", hostlist
);
491 int fileconf_save(const char *savefile
)
495 if ((fp
= fopen(savefile
, "w")) != NULL
)
497 char *token
; /*, *port;*/ // temp, needed to separate items into the hostlist
498 char temphostlist
[MAX_HOST_LIST
+ 1];
502 fprintf(fp
, "# Configuration file help.\n\n");
504 // Save list of clients which are allowed to connect to us in passive mode
505 fprintf(fp
, "# Hosts which are allowed to connect to this server (passive mode)\n");
506 fprintf(fp
, "# Format: PassiveClient = <name or address>\n\n");
508 pcapint_strlcpy(temphostlist
, hostlist
, sizeof (temphostlist
));
510 token
= pcapint_strtok_r(temphostlist
, RPCAP_HOSTLIST_SEP
, &lasts
);
513 fprintf(fp
, "%s = %s\n", PARAM_PASSIVECLIENT
, token
);
514 token
= pcapint_strtok_r(NULL
, RPCAP_HOSTLIST_SEP
, &lasts
);
518 // Save list of clients which are allowed to connect to us in active mode
520 fprintf(fp
, "# Hosts to which this server is trying to connect to (active mode)\n");
521 fprintf(fp
, "# Format: ActiveClient = <name or address>, <port | DEFAULT>\n\n");
524 while ((i
< MAX_ACTIVE_LIST
) && (activelist
[i
].address
[0] != 0))
526 fprintf(fp
, "%s = %s, %s\n", PARAM_ACTIVECLIENT
,
527 activelist
[i
].address
, activelist
[i
].port
);
531 // Save if we want to permit NULL authentication
533 fprintf(fp
, "# Permit NULL authentication: YES or NO\n\n");
535 fprintf(fp
, "%s = %s\n", PARAM_NULLAUTHPERMIT
,
536 nullAuthAllowed
? "YES" : "NO");
549 // Skip over white space.
550 // If we hit a CR or LF, return NULL, otherwise return a pointer to
551 // the first non-white space character. Replace white space characters
552 // other than CR or LF with '\0', so that, if we're skipping white space
553 // after a token, the token is null-terminated.
555 static char *skipws(char *ptr
)
557 while (*ptr
== ' ' || *ptr
== '\t' || *ptr
== '\r' || *ptr
== '\n') {
558 if (*ptr
== '\r' || *ptr
== '\n')