aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2020-02-28 10:07:54 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2020-02-28 10:07:54 +0200
commit73bfc3bdfac590266ad67c48de5e866bb5d5fa4d (patch)
tree2488c3b3b009c0c49f56a63f10df7340432588c4
parent7e8ff0ed908913de7467daa28feb25164abc7ad9 (diff)
downloadping903-73bfc3bdfac590266ad67c48de5e866bb5d5fa4d.tar.gz
ping903-73bfc3bdfac590266ad67c48de5e866bb5d5fa4d.tar.bz2
Implement here-document syntax in configuration file.
Here-document is supported for ip-list and trusted-ip statements. * doc/ping903.conf.5: Document the here-document syntax. * NEWS: Likewise. * examples/inspect: Mention that the created output is a valid configuration file. * src/config.c: Support for here-document. * src/defs.h: Mark printf-like functions as such. * src/ping903.h (CF_HEREDOC_OPCODE): New data type. (cf_callback_arg): Add heredoc member. (STMT_T_HEREDOC): New statement type. * src/remoteip.c (cf_trusted_ip_heredoc): New function. * src/ping903.c: Fix format strings and unused variables. * src/ping903q.c: Likewise. * src/pinger.c: Likewise.
-rw-r--r--NEWS13
-rw-r--r--doc/ping903.conf.525
-rwxr-xr-xexamples/inspect3
-rw-r--r--src/config.c109
-rw-r--r--src/defs.h9
-rw-r--r--src/ping903.c7
-rw-r--r--src/ping903.h16
-rw-r--r--src/ping903q.c8
-rw-r--r--src/pinger.c27
-rw-r--r--src/remoteip.c21
10 files changed, 195 insertions, 43 deletions
diff --git a/NEWS b/NEWS
index 920702f..d661fe6 100644
--- a/NEWS
+++ b/NEWS
@@ -1,4 +1,4 @@
-Ping903 -- history of user-visible changes. 2020-02-27
+Ping903 -- history of user-visible changes. 2020-02-28
See the end of file for copying conditions.
Please send Ping903 bug reports to <gray@gnu.org>
@@ -7,6 +7,17 @@ Version 0.4.90 (Git)
* Support for HTTP basic authorization.
+* Support for "here-document" syntax in config file.
+
+Two statements allow the use of here-document: ip-list and
+trusted-ip. Example:
+
+ ip-list <<EOF
+ 98.51.100.10
+ 203.0.113.1
+ 192.0.2.15
+ EOF
+
Version 0.4, 2020-92-27
diff --git a/doc/ping903.conf.5 b/doc/ping903.conf.5
index c6835f3..befe082 100644
--- a/doc/ping903.conf.5
+++ b/doc/ping903.conf.5
@@ -13,7 +13,7 @@
.\"
.\" You should have received a copy of the GNU General Public License
.\" along with Ping903. If not, see <http://www.gnu.org/licenses/>.
-.TH PING903.CONF 5 "February 27, 2020" "PING903.CONF" "File Formats Manual"
+.TH PING903.CONF 5 "February 28, 2020" "PING903.CONF" "File Formats Manual"
.SH NAME
ping903.conf \- configuration file for high-performance ICMP monitoring daemon
.SH DESCRIPTION
@@ -29,6 +29,10 @@ Leading and trailing whitespace characters are ignored.
The pound sign (\fB#\fR) appearing as the first non-whitespace
character on a line introduces a comment. Such lines are ignored.
Empty lines are ignored as well.
+.PP
+Maximum length of a statement line is limited to 1022 characters.
+Lines longer than that cause syntax error to be reported and are
+ignored otherwise.
.SH STATEMENTS
.SS Server configuration
.TP
@@ -65,9 +69,17 @@ Name of the file supplying a list of IP addresses (or hostnames) to
monitor. Each IP must be listed on a separate line. Empty lines,
leading and trailing whitespace is ignored. Comments are introduced
by a hash sign as the first non-whitespace character on the line.
+.TP
+\fBip\-list <<\fIWORD\fR
+A \fIhere-document\fR version of the above statement. \fIWORD\fR is
+an arbitrary word. The material following this statement is scanned
+up to the line consisting only of \fIWORD\fR (surrounding whitespace
+allowed). Each line in the collected material must contain a single IP
+address or host name to be incorporated into IP list.
-Multiple \fBip\-list\fR statements accumulate. At least
-one must be present.
+Empty lines and comments are allowed within \fIhere-document\fR.
+.PP
+Multiple \fBip\-list\fR statements of any form accumulate.
.TP
\fBprobe\-interval \fIN\fR
Sets interval between subsequent probes, in seconds. Default is 60
@@ -149,7 +161,12 @@ first IP in the list is encountered, whichever occurs first.
\fICIDR\fR is either an IPv4 address, or an address followed by slash
and the network mask in dotted quad, or the length of the network mask
in decimal.
-
+.TP
+\fBtrusted\-ip <<\fIWORD\fR
+A \fIhere-document\fR version of the above statement. See the
+description of \fBip\-list\fR above for the description of
+\fIhere-document\fR syntax. The collected material must contain a
+single CIDR per line.
.SS HTTP Authorization configuration
It is suggested that HTTP entry points be protected by the HTTP
authorization. This is especially critical for \fB/config\fR and
diff --git a/examples/inspect b/examples/inspect
index 8af9b25..f9e21f2 100755
--- a/examples/inspect
+++ b/examples/inspect
@@ -31,7 +31,8 @@ B<inspect>
=head1 DESCRIPTION
Queries the running B<ping903> instance and displays its configuration on
-standard output.
+standard output. The output is formatted as a valid B<ping903> configuration
+file.
=head1 OPTIONS
diff --git a/src/config.c b/src/config.c
index a04423f..58841c9 100644
--- a/src/config.c
+++ b/src/config.c
@@ -118,7 +118,7 @@ file_read_ip_list(FILE *fp, char const *fname)
rc = pinger_host_add(p, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);
if (rc) {
- error("%s:%d: out of memory");
+ error("%s:%d: out of memory", fname, ln);
ret = CF_RET_FAIL;
break;
}
@@ -143,7 +143,45 @@ cf_ip_list(int mode, union cf_callback_arg *arg, void *data)
case CF_SERIALIZE:
return cf_ip_list_serialize(arg, data);
}
+ abort();
}
+
+static int
+cf_ip_list_heredoc(int mode, union cf_callback_arg *arg, void *data)
+{
+ struct addrinfo hints, *res;
+ int rc;
+
+ if (mode == CF_SERIALIZE)
+ return CF_RET_IGNORE;
+
+ switch (arg->heredoc.op) {
+ case CF_HEREDOC_START:
+ case CF_HEREDOC_STOP:
+ break;
+
+ case CF_HEREDOC_NEXT:
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET;
+ hints.ai_protocol = IPPROTO_TCP;
+ rc = getaddrinfo(arg->heredoc.val, NULL, &hints, &res);
+ if (rc) {
+ error("%s:%d: invalid IP address",
+ arg->heredoc.file, arg->heredoc.line);
+ return CF_RET_FAIL;
+ }
+ rc = pinger_host_add(arg->heredoc.val, res->ai_addr,
+ res->ai_addrlen);
+ freeaddrinfo(res);
+ if (rc) {
+ error("%s:%d: out of memory", arg->heredoc.file,
+ arg->heredoc.line);
+ return CF_RET_FAIL;
+ }
+ }
+ return CF_RET_OK;
+}
+
struct cf_stmt {
char const *kw;
@@ -156,11 +194,13 @@ struct cf_stmt statements[] = {
{ "listen", STMT_T_STRING, &httpd_addr },
{ "pidfile", STMT_T_STRING, &pidfile },
{ "trusted-ip", STMT_T_CALLBACK, NULL, cf_trusted_ip },
+ { "trusted-ip", STMT_T_HEREDOC, NULL, cf_trusted_ip_heredoc },
{ "probe-interval", STMT_T_ULONG, &probe_interval },
{ "ping-interval", STMT_T_ULONG, &ping_interval },
{ "ping-count", STMT_T_ULONG, &ping_count },
{ "tolerance", STMT_T_ULONG, &ping_tolerance },
{ "ip-list", STMT_T_CALLBACK, NULL, cf_ip_list },
+ { "ip-list", STMT_T_HEREDOC, NULL, cf_ip_list_heredoc },
{ "data-length", STMT_T_ULONG, &data_length },
{ "syslog-facility", STMT_T_CALLBACK, NULL, cf_syslog_facility },
{ "access-log", STMT_T_BOOL, &httpd_access_log },
@@ -171,11 +211,13 @@ struct cf_stmt statements[] = {
};
static struct cf_stmt *
-find_stmt(char const *kw)
+find_stmt(char const *kw, int heredoc)
{
struct cf_stmt *cf;
for (cf = statements; cf->kw; cf++) {
- if (strcmp(cf->kw, kw) == 0)
+ if (((heredoc && cf->type == STMT_T_HEREDOC)
+ || (!heredoc && cf->type != STMT_T_HEREDOC))
+ && strcmp(cf->kw, kw) == 0)
return cf;
}
return NULL;
@@ -184,7 +226,7 @@ find_stmt(char const *kw)
static int
stmt_parse(char const *kw, char const *val, char const *file, unsigned line)
{
- struct cf_stmt *cf = find_stmt(kw);
+ struct cf_stmt *cf = find_stmt(kw, 0);
union cf_callback_arg arg;
if (!cf) {
@@ -240,6 +282,12 @@ readconfig(char const *file)
unsigned ln = 0;
int skip_to_eol = 0;
int ec = 0;
+ struct {
+ char *eot;
+ CF_CALLBACK callback;
+ void *data;
+ unsigned line;
+ } heredoc = { .eot = NULL };
fp = fopen(file, "r");
if (!fp) {
@@ -281,6 +329,29 @@ readconfig(char const *file)
;
if (*p == 0 || *p == '#')
continue;
+
+ if (heredoc.eot) {
+ union cf_callback_arg arg;
+ arg.heredoc.file = file;
+ arg.heredoc.line = ln;
+
+ if (strcmp(heredoc.eot, p) == 0) {
+ arg.heredoc.op = CF_HEREDOC_STOP;
+ if (heredoc.callback(CF_PARSE, &arg,
+ heredoc.data))
+ ec = 1;
+ free(heredoc.eot);
+ heredoc.eot = NULL;
+ } else {
+ arg.heredoc.op = CF_HEREDOC_NEXT;
+ arg.heredoc.val = p;
+ if (heredoc.callback(CF_PARSE, &arg,
+ heredoc.data))
+ ec = 1;
+ }
+ continue;
+ }
+
kw = p;
while (*p && isascii(*p) && (isalnum(*p) || *p == '_' || *p == '-'))
@@ -296,12 +367,41 @@ readconfig(char const *file)
continue;
}
+ if (p[0] == '<' && p[1] == '<') {
+ p += 2;
+ struct cf_stmt *cf = find_stmt(kw, 1);
+ if (cf) {
+ union cf_callback_arg arg;
+
+ arg.heredoc.op = CF_HEREDOC_START;
+ arg.heredoc.file = file;
+ arg.heredoc.line = ln;
+
+ heredoc.callback = cf->callback;
+ heredoc.data = cf->data;
+ heredoc.line = ln;
+ heredoc.eot = estrdup(p);
+ if (heredoc.callback(CF_PARSE, &arg,
+ heredoc.data))
+ ec = 1;
+ } else {
+ error("%s:%d: unknown heredoc statement",
+ file, ln);
+ ec = 1;
+ }
+ continue;
+ }
+
if (stmt_parse(kw, p, file, ln)) {
ec = 1;
}
}
fclose(fp);
+ if (heredoc.eot) {
+ error("%s:%d: heredoc not closed", file, heredoc.line);
+ ec = 1;
+ }
if ((double) ping_count * ping_interval >= probe_interval) {
error("configuration error: ping_count * ping_interval >= probe_interval");
ec = 1;
@@ -339,6 +439,7 @@ config_to_json(void)
break;
case STMT_T_CALLBACK:
+ case STMT_T_HEREDOC:
arg.output = NULL;
switch (cf->callback(CF_SERIALIZE, &arg, cf->data)) {
case CF_RET_OK:
diff --git a/src/defs.h b/src/defs.h
index 85918ef..1f7c7f3 100644
--- a/src/defs.h
+++ b/src/defs.h
@@ -51,10 +51,13 @@ void *e2nrealloc(void *p, size_t *pn, size_t s);
extern char *progname;
+#define ATTR_PRINTFLIKE(fmt,narg) \
+ __attribute__ ((__format__ (__printf__, fmt, narg)))
+
void vlogger(int prio, char const *fmt, va_list ap);
-void fatal(char const *fmt, ...);
-void error(char const *fmt, ...);
-void info(char const *fmt, ...);
+void fatal(char const *fmt, ...) ATTR_PRINTFLIKE(1,2);
+void error(char const *fmt, ...) ATTR_PRINTFLIKE(1,2);
+void info(char const *fmt, ...) ATTR_PRINTFLIKE(1,2);
void syslog_enable(void);
void set_progname(char const *arg);
int set_log_facility(char const *arg);
diff --git a/src/ping903.c b/src/ping903.c
index 3e5aadd..7bc0f1c 100644
--- a/src/ping903.c
+++ b/src/ping903.c
@@ -369,8 +369,6 @@ ept_ip_put(struct MHD_Connection *conn,
const char *url, const char *method, const char *suffix,
struct json_value *unused)
{
- int ret;
-
while (*suffix == '/')
suffix++;
if (!*suffix)
@@ -886,8 +884,9 @@ p903_httpd_handler(void *cls,
}
rc = json_parse_string(pb->base, &jv, &endp);
if (rc != JSON_E_NOERR) {
- error("%s: %s near #%d", url,
- json_strerror(rc), endp - pb->base);
+ error("%s: %s near #%ld", url,
+ json_strerror(rc),
+ endp - pb->base);
return http_response(conn, method, url,
MHD_HTTP_BAD_REQUEST);
}
diff --git a/src/ping903.h b/src/ping903.h
index 26851ad..1390152 100644
--- a/src/ping903.h
+++ b/src/ping903.h
@@ -30,6 +30,12 @@ enum {
CF_SERIALIZE /* serialize configuration setting */
};
+typedef enum {
+ CF_HEREDOC_START,
+ CF_HEREDOC_NEXT,
+ CF_HEREDOC_STOP
+} CF_HEREDOC_OPCODE;
+
union cf_callback_arg {
struct json_value *output; /* Output value */
struct cf_line {
@@ -37,6 +43,12 @@ union cf_callback_arg {
char const *file; /* Statement location: file name */
unsigned line; /* ... and input line number */
} input;
+ struct cf_heredoc {
+ CF_HEREDOC_OPCODE op;
+ char const *val; /* Statement value (after keyword) */
+ char const *file; /* Statement location: file name */
+ unsigned line; /* ... and input line number */
+ } heredoc;
};
enum {
@@ -53,11 +65,13 @@ enum {
STMT_T_STRING,
STMT_T_ULONG,
STMT_T_BOOL,
- STMT_T_CALLBACK
+ STMT_T_CALLBACK,
+ STMT_T_HEREDOC
};
int readconfig(char const *file);
int cf_trusted_ip(int mode, union cf_callback_arg *arg, void *data);
+int cf_trusted_ip_heredoc(int mode, union cf_callback_arg *arg, void *data);
int cf_syslog_facility(int mode, union cf_callback_arg *arg, void *data);
int cf_auth(int mode, union cf_callback_arg *arg, void *data);
diff --git a/src/ping903q.c b/src/ping903q.c
index e9070ab..8323f44 100644
--- a/src/ping903q.c
+++ b/src/ping903q.c
@@ -469,8 +469,6 @@ nodecmp(char const *a, char const *b)
static int
machinecmp(char const *pat)
{
- size_t slen;
-
if (strcmp(pat, "*") == 0)
return 0;
if (pat[0] == '*' && pat[1] == ':') {
@@ -505,7 +503,6 @@ machinecmp(char const *pat)
static int
get_realm_creds(char const *realm, char **retval)
{
- char *p;
size_t len;
char const *cfname;
FILE *fp;
@@ -592,7 +589,8 @@ get_realm_creds(char const *realm, char **retval)
strcat(plaintext, av[3]);
/* Encode it to base64 */
- if (base64_encode(plaintext, len, &b64, &b64_len))
+ if (base64_encode((unsigned char const *)plaintext,
+ len, &b64, &b64_len))
emalloc_die();
free(plaintext);
@@ -602,7 +600,7 @@ get_realm_creds(char const *realm, char **retval)
+ b64_len
+ 1);
strcpy(hdr, HTTP_AUTHORIZATION);
- strcat(hdr, b64);
+ strcat(hdr, (char*) b64);
free(b64);
/* Return it */
diff --git a/src/pinger.c b/src/pinger.c
index 96a55ae..825c814 100644
--- a/src/pinger.c
+++ b/src/pinger.c
@@ -211,17 +211,6 @@ hostlist_concat(HOSTLIST *a, HOSTLIST *b)
b->head = b->tail = NULL;
b->count = 0;
}
-
-static HOSTPING *
-hostlist_locate(HOSTLIST *list, char const *name)
-{
- HOSTPING *hp;
- for (hp = list->head; hp; hp++) {
- if (strcmp(hp->name, name) == 0)
- break;
- }
- return hp;
-}
static HOSTLIST *hostlist;
static HOSTPING *conf_hostping_tail;
@@ -604,7 +593,6 @@ err:
int
pinger_host_delete_by_name(char const *name)
{
- HOSTPING *hp;
int rc;
pthread_mutex_lock(&update_mutex);
@@ -1101,7 +1089,7 @@ send_echo(HOSTPING *host, unsigned char *ping_buffer)
}
if (verbose > 2)
- info("sending %d bytes to %s, icmp_seq=%d", buflen, host->name,
+ info("sending %zu bytes to %s, icmp_seq=%d", buflen, host->name,
seqno);
icmp_generic_encode(ping_buffer, buflen, ICMP_ECHO, ping_ident, seqno);
@@ -1117,7 +1105,7 @@ send_echo(HOSTPING *host, unsigned char *ping_buffer)
hostping_unlock(host);
xmit_total++;
if (n != buflen)
- error("ping: wrote %s %d chars, ret=%d\n",
+ error("ping: wrote %s %zu chars, ret=%ld\n",
host->name, buflen, n);
}
}
@@ -1127,7 +1115,6 @@ static void hostping_commit(HOSTPING *host);
void *
p903_sender(void *p)
{
- size_t i;
unsigned char *ping_buffer;
struct pollfd pfd;
int n;
@@ -1166,10 +1153,11 @@ p903_sender(void *p)
fatal("poll: %s", strerror(errno));
exit(1);
}
- if (i < hostlist->count - 1)
+ if (hp->next)
clock_nanosleep(CLOCK_MONOTONIC,
TIMER_ABSTIME, &nts,
NULL);
+
}
send_count++;
if (send_count == ping_count)
@@ -1197,7 +1185,7 @@ log_echo(struct sockaddr *addr, socklen_t addrlen,
strcpy(hbuf, "UNKNOWN");
}
- info("%d bytes from %s: icmp_seq=%u ttl=%d time=%.3f ms", datalen,
+ info("%zu bytes from %s: icmp_seq=%u ttl=%d time=%.3f ms", datalen,
hbuf, icmp->icmp_seq, ip->ip_ttl, rtt);
}
@@ -1232,9 +1220,9 @@ p903_receiver(void *p)
addrlen,
hbuf, sizeof(hbuf),
NULL, 0, NI_NUMERICHOST)) {
- error("packet too short (%d bytes)", n);
+ error("packet too short (%zu bytes)", n);
} else {
- error("packet too short (%d bytes), from %s",
+ error("packet too short (%zu bytes), from %s",
n, hbuf);
}
continue;
@@ -1351,7 +1339,6 @@ save_local_ip_list(void)
{
FILE *fp;
HOSTPING *hp;
- size_t i;
info("saving mutable IP address list");
fp = fopen(LOCAL_IP_LIST_FILE, "w");
diff --git a/src/remoteip.c b/src/remoteip.c
index 5146efb..573b69d 100644
--- a/src/remoteip.c
+++ b/src/remoteip.c
@@ -289,6 +289,27 @@ cf_trusted_ip(int mode, union cf_callback_arg *arg, void *data)
return CF_RET_OK;
}
+int
+cf_trusted_ip_heredoc(int mode, union cf_callback_arg *arg, void *data)
+{
+ struct cidr *cidr;
+
+ if (mode == CF_SERIALIZE)
+ return CF_RET_IGNORE;
+
+ cidr = emalloc(sizeof(cidr[0]));
+
+ if (str_to_cidr(arg->heredoc.val, cidr,
+ arg->heredoc.file, arg->heredoc.line)) {
+ free(cidr);
+ return CF_RET_FAIL;
+ }
+ cidr->next = trusted_ip_list;
+ trusted_ip_list = cidr;
+
+ return CF_RET_OK;
+}
+
static int
is_trusted_ip(char const *ipstr)
{

Return to:

Send suggestions and report system problems to the System administrator.