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
43 #include <pcap.h> // for PCAP_ERRBUF_SIZE
45 #include "portability.h"
47 #include "config_params.h" // configuration file parameters
49 #include "rpcap-protocol.h"
55 #define PARAM_ACTIVECLIENT "ActiveClient"
56 #define PARAM_PASSIVECLIENT "PassiveClient"
57 #define PARAM_NULLAUTHPERMIT "NullAuthPermit"
59 static char *skipws(char *ptr
);
62 * Locale-independent version checks for alphabetical and alphanumerical
63 * characters that also can handle being handed a char value that might
66 #define FILECONF_ISALPHA(c) \
67 (((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
68 #define FILECONF_ISALNUM(c) \
69 (FILECONF_ISALPHA(c) || ((c) >= '0' && (c) <= '9'))
71 void fileconf_read(void)
74 unsigned int num_active_clients
;
76 if ((fp
= fopen(loadfile
, "r")) != NULL
)
78 char line
[MAX_LINE
+ 1];
82 num_active_clients
= 0;
85 while (fgets(line
, MAX_LINE
, fp
) != NULL
)
95 linelen
= strlen(line
);
96 if (line
[linelen
- 1] != '\n')
101 // Either the line doesn't fit in
102 // the buffer, or we got an EOF
103 // before the EOL. Assume it's the
106 rpcapd_log(LOGPRIO_ERROR
,
107 "%s, line %u is longer than %u characters",
108 loadfile
, lineno
, MAX_LINE
);
111 // Eat characters until we get an NL.
113 while ((c
= getc(fp
)) != '\n')
120 // Try the next line.
127 // Skip leading white space, if any.
137 // Is the next character a "#"? If so, this
138 // line is a comment; skip to the next line.
144 // Is the next character alphabetic? If not,
145 // this isn't a valid parameter name.
147 if (FILECONF_ISALPHA(*ptr
))
149 rpcapd_log(LOGPRIO_ERROR
,
150 "%s, line %u doesn't have a valid parameter name",
156 // Grab the first token, which is made of
157 // alphanumerics, underscores, and hyphens.
158 // That's the name of the parameter being set.
161 while (FILECONF_ISALNUM(*ptr
) || *ptr
== '-' || *ptr
== '_')
165 // Skip over white space, if any.
168 if (ptr
== NULL
|| *ptr
!= '=')
171 // We hit the end of the line before
172 // finding a non-white space character,
173 // or we found one but it's not an "=".
174 // That means there's no "=", so this
175 // line is invalid. Complain and skip
178 rpcapd_log(LOGPRIO_ERROR
,
179 "%s, line %u has a parameter but no =",
185 // We found the '='; set it to '\0', and skip
191 // Skip past any white space after the "=".
197 // The value is empty.
199 rpcapd_log(LOGPRIO_ERROR
,
200 "%s, line %u has a parameter but no value",
206 // OK, what parameter is this?
208 if (strcmp(param
, PARAM_ACTIVECLIENT
) == 0) {
210 // Add this to the list of active clients.
212 char *address
, *port
;
215 // We can't have more than MAX_ACTIVE_LIST
218 if (num_active_clients
>= MAX_ACTIVE_LIST
)
221 // Too many entries for the active
222 // client list. Complain and
225 rpcapd_log(LOGPRIO_ERROR
,
226 "%s, line %u has an %s parameter, but we already have %u active clients",
227 loadfile
, lineno
, PARAM_ACTIVECLIENT
,
234 // It's terminated by a host list separator
235 // *or* a #; there *shouldn't* be a #, as
236 // that starts a comment, and that would
237 // mean that we have no port.
240 toklen
= strcspn(ptr
, RPCAP_HOSTLIST_SEP
"#");
241 ptr
+= toklen
; // skip to the terminator
244 if (*ptr
== ' ' || *ptr
== '\t' ||
245 *ptr
== '\r' || *ptr
== '\n' ||
246 *ptr
== '#' || *ptr
== '\0')
249 // The first character it saw
250 // was a whitespace character
251 // or a comment character,
252 // or we ran out of characters.
253 // This means that there's
256 rpcapd_log(LOGPRIO_ERROR
,
257 "%s, line %u has a parameter but no value",
263 // This means that the first
264 // character it saw was a
265 // separator. This means that
266 // there's no address in the
267 // value, just a port.
269 rpcapd_log(LOGPRIO_ERROR
,
270 "%s, line %u has an %s parameter with a value containing no address",
271 loadfile
, lineno
, PARAM_ACTIVECLIENT
);
277 // Null-terminate the address, and skip past
283 // Skip any white space following the
284 // separating character.
290 // The value is empty, so there's
291 // no port in the value.
293 rpcapd_log(LOGPRIO_ERROR
,
294 "%s, line %u has an %s parameter with a value containing no port",
295 loadfile
, lineno
, PARAM_ACTIVECLIENT
);
301 // We look for a white space character
302 // or a # as a terminator; the # introduces
303 // a comment that runs to the end of the
307 toklen
= strcspn(ptr
, " \t#\r\n");
312 // The value is empty, so there's
313 // no port in the value.
315 rpcapd_log(LOGPRIO_ERROR
,
316 "%s, line %u has an %s parameter with a value containing no port",
317 loadfile
, lineno
, PARAM_ACTIVECLIENT
);
322 // Null-terminate the port, and skip past
326 result
= pcapint_strlcpy(activelist
[num_active_clients
].address
, address
, sizeof(activelist
[num_active_clients
].address
));
327 if (result
>= sizeof(activelist
[num_active_clients
].address
))
332 rpcapd_log(LOGPRIO_ERROR
,
333 "%s, line %u has an %s parameter with an address with more than %u characters",
334 loadfile
, lineno
, PARAM_ACTIVECLIENT
,
335 (unsigned int)(sizeof(activelist
[num_active_clients
].address
) - 1));
338 if (strcmp(port
, "DEFAULT") == 0) // the user choose a custom port
339 result
= pcapint_strlcpy(activelist
[num_active_clients
].port
, RPCAP_DEFAULT_NETPORT_ACTIVE
, sizeof(activelist
[num_active_clients
].port
));
341 result
= pcapint_strlcpy(activelist
[num_active_clients
].port
, port
, sizeof(activelist
[num_active_clients
].port
));
342 if (result
>= sizeof(activelist
[num_active_clients
].address
))
347 rpcapd_log(LOGPRIO_ERROR
,
348 "%s, line %u has an %s parameter with an port with more than %u characters",
349 loadfile
, lineno
, PARAM_ACTIVECLIENT
,
350 (unsigned int)(sizeof(activelist
[num_active_clients
].port
) - 1));
354 num_active_clients
++;
356 else if (strcmp(param
, PARAM_PASSIVECLIENT
) == 0)
363 // We look for a white space character
364 // or a # as a terminator; the # introduces
365 // a comment that runs to the end of the
369 toklen
= strcspn(ptr
, " \t#\r\n");
373 // The first character it saw
374 // was a whitespace character
375 // or a comment character.
376 // This means that there's
379 rpcapd_log(LOGPRIO_ERROR
,
380 "%s, line %u has a parameter but no value",
388 // Append this to the host list.
389 // Save the current end-of-string for the
390 // host list, in case the new host doesn't
391 // fit, so that we can discard the partially-
394 eos
= hostlist
+ strlen(hostlist
);
398 // The list is not empty, so prepend
399 // a comma before adding this host.
401 result
= pcapint_strlcat(hostlist
, ",", sizeof(hostlist
));
402 if (result
>= sizeof(hostlist
))
405 // It didn't fit. Discard
406 // the comma (which wasn't
407 // added, but...), complain,
408 // and ignore this line.
411 rpcapd_log(LOGPRIO_ERROR
,
412 "%s, line %u has a %s parameter with a host name that doesn't fit",
413 loadfile
, lineno
, PARAM_PASSIVECLIENT
);
417 result
= pcapint_strlcat(hostlist
, host
, sizeof(hostlist
));
418 if (result
>= sizeof(hostlist
))
421 // It didn't fit. Discard the comma,
422 // complain, and ignore this line.
425 rpcapd_log(LOGPRIO_ERROR
,
426 "%s, line %u has a %s parameter with a host name that doesn't fit",
427 loadfile
, lineno
, PARAM_PASSIVECLIENT
);
431 else if (strcmp(param
, PARAM_NULLAUTHPERMIT
) == 0)
437 // We look for a white space character
438 // or a # as a terminator; the # introduces
439 // a comment that runs to the end of the
443 toklen
= strcspn(ptr
, " \t#\r\n");
448 // The first character it saw
449 // was a whitespace character
450 // or a comment character.
451 // This means that there's
454 rpcapd_log(LOGPRIO_ERROR
,
455 "%s, line %u has a parameter but no value",
462 // XXX - should we complain if it's
463 // neither "yes" nor "no"?
465 if (strcmp(setting
, "YES") == 0)
472 rpcapd_log(LOGPRIO_ERROR
,
473 "%s, line %u has an unknown parameter %s",
474 loadfile
, lineno
, param
);
480 // clear the remaining fields of the active list
481 for (int i
= num_active_clients
; i
< MAX_ACTIVE_LIST
; i
++)
483 activelist
[i
].address
[0] = 0;
484 activelist
[i
].port
[0] = 0;
485 num_active_clients
++;
488 rpcapd_log(LOGPRIO_DEBUG
, "New passive host list: %s", hostlist
);
493 int fileconf_save(const char *savefile
)
497 if ((fp
= fopen(savefile
, "w")) != NULL
)
499 char *token
; /*, *port;*/ // temp, needed to separate items into the hostlist
500 char temphostlist
[MAX_HOST_LIST
+ 1];
504 fprintf(fp
, "# Configuration file help.\n\n");
506 // Save list of clients which are allowed to connect to us in passive mode
507 fprintf(fp
, "# Hosts which are allowed to connect to this server (passive mode)\n");
508 fprintf(fp
, "# Format: PassiveClient = <name or address>\n\n");
510 pcapint_strlcpy(temphostlist
, hostlist
, sizeof (temphostlist
));
512 token
= pcapint_strtok_r(temphostlist
, RPCAP_HOSTLIST_SEP
, &lasts
);
515 fprintf(fp
, "%s = %s\n", PARAM_PASSIVECLIENT
, token
);
516 token
= pcapint_strtok_r(NULL
, RPCAP_HOSTLIST_SEP
, &lasts
);
520 // Save list of clients which are allowed to connect to us in active mode
522 fprintf(fp
, "# Hosts to which this server is trying to connect to (active mode)\n");
523 fprintf(fp
, "# Format: ActiveClient = <name or address>, <port | DEFAULT>\n\n");
526 while ((i
< MAX_ACTIVE_LIST
) && (activelist
[i
].address
[0] != 0))
528 fprintf(fp
, "%s = %s, %s\n", PARAM_ACTIVECLIENT
,
529 activelist
[i
].address
, activelist
[i
].port
);
533 // Save if we want to permit NULL authentication
535 fprintf(fp
, "# Permit NULL authentication: YES or NO\n\n");
537 fprintf(fp
, "%s = %s\n", PARAM_NULLAUTHPERMIT
,
538 nullAuthAllowed
? "YES" : "NO");
551 // Skip over white space.
552 // If we hit a CR or LF, return NULL, otherwise return a pointer to
553 // the first non-white space character. Replace white space characters
554 // other than CR or LF with '\0', so that, if we're skipping white space
555 // after a token, the token is null-terminated.
557 static char *skipws(char *ptr
)
559 while (*ptr
== ' ' || *ptr
== '\t' || *ptr
== '\r' || *ptr
== '\n') {
560 if (*ptr
== '\r' || *ptr
== '\n')