udyfi

Small client for dy.fi (and possibly other services) DNS renewals
git clone https://git.inz.fi/udyfi/
Log | Files | Refs

commit 912e1d583ea18ed2c3ca1d1fd884ed1cce1825d8
parent 02621f745a3a9f8c2a809a8bceededa935c6f6d6
Author: Santtu Lakkala <inz@inz.fi>
Date:   Thu,  6 Jul 2023 12:56:57 +0300

Add error handling and man page

Some error handling for configuration file parsing and shiny new manual
page.

Diffstat:
MMakefile | 7+++++--
Audyfi.8 | 118+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mudyfi.c | 30++++++++++++++++++++++--------
3 files changed, 145 insertions(+), 10 deletions(-)

diff --git a/Makefile b/Makefile @@ -2,6 +2,7 @@ CFLAGS ?= -Os CFLAGS += -W -Wall -std=c99 -pedantic -D_POSIX_C_SOURCE=200809L PREFIX ?= /usr/local BINDIR := $(PREFIX)/bin +MANDIR := $(PREFIX)/share/man/man8 IFADDRS_CFLAGS ?= -DUSE_IFADDRS HEADERS = arg.h config.h VERSION=0.1.0 @@ -16,8 +17,8 @@ LIBS := -L/usr/local/lib -ltls all: udyfi config.h: config.def.h - if test -f "$@"; then echo "Refusing to overwrite old config.h"; false; fi - cp $< $@ + if test -f "$@"; then echo "Refusing to overwrite old config.h; please remove or update manually"; false; fi + cp config.def.h $@ udyfi: udyfi.c $(HEADERS) $(CROSS)$(CC) -DVERSION='"$(VERSION)"' $(CFLAGS) $(LIBTLS_CFLAGS) $(OPENSSL_CFLAGS) $(IFADDRS_CFLAGS) $< -o $@ $(LIBS) @@ -28,3 +29,5 @@ clean: install: udyfi install -d $(DESTDIR)$(BINDIR) install udyfi $(DESTDIR)$(BINDIR) + install -d $(DESTDIR)$(MANDIR) + install udyfi.8 $(DESTDIR)$(MANDIR) diff --git a/udyfi.8 b/udyfi.8 @@ -0,0 +1,118 @@ +.Dd Jul 6, 2023 +.Dt UDYFI 8 +.Os +. +.Sh NAME +.Nm udyfi +.Nd dynamic dns updater daemon +. +.Sh SYNOPSIS +.Nm +.Bk -words +.Op Fl 4 +.Op Fl 6 +.Op Fl a Ar user-agent string +.Op Fl d Ar dyndns server +.Op Fl i Ar interface to bind to +.Op Fl u Ar dyndns username +.Op Fl p Ar dyndns password +.Op Fl F Ar configuration file +.Op Fl f Ar password file +.Op Fl c Ar checkip server +.Op Fl D Ar dyndns port +.Op Fl C Ar checkip port +.Op Fl b +.Op Fl l Ar logfile +.Op Fl P Ar pidfile +.Op Fl U Ar run as user +.Op Fl s +.Op Fl S +.Op Fl z +.Op Fl Z +.Ar domain names +.Ek +. +.Sh DESCRIPTION +.Bd -filled +.Nm +is a dynamic DNS updater daemon +.Ed +. +.Sh OPTIONS +udyfi options and default settings +.Bl -tag -width Ds +. +.It Fl 4 +Operate over IPv4 only. (Default: any) +. +.It Fl 6 +Operate over IPv6 only. (Default: any) +. +.It Fl b +Fork into background. (Default: don't fork) +. +.It Fl l Ar logfile +Location for a log file (no default). +. +.It Fl a Ar user-agent string +User-agent string used in requests (Default: udyfi/version) +. +.It Fl d Ar dyndns server +Dynamic DNS server to connect to (Default: dy.fi) +. +.It Fl i Ar interface to bind to +Interface or address to connect from (Default: any) +. +.It Fl u Ar dyndns username +Username for the dynamic DNS service +. +.It Fl p Ar dyndns password +Password for the dynamic DNS service +. +.It Fl F Ar configuration file +Read configuration from file +. +.It Fl f Ar password file +Read password from file +. +.It Fl c Ar checkip server +Checkip service to check public IP from (Default: checkip.dy.fi) +. +.It Fl D Ar dyndns port +Dynamic DNS server port (Default: 80 for HTTP, 443 for HTTPS) +. +.It Fl C Ar checkip port +Checkip server port (Default: 80 for HTTP, 443 for HTTPS) +. +.It Fl P Ar pidfile +Write daemon pid to pidfile (Default: none) +. +.It Fl U Ar run as user +Change to user after startup (Default: none) +. +.It Fl s +Connect to dynamic DNS server over HTTPS (Default: yes) +. +.It Fl S +Connect to checkip server over HTTPS (Default: no) +. +.It Fl z +Connect to dynamic DNS server over HTTP (Default: no) +. +.It Fl Z +Connect to checkip server over HTTP (Default: yes) +. +.It Ar domain names +Comma-separated list of domain names to update +. +.It +At minimum, username, password and at least one domain name needs to be +specified, either on command line, or in a configuration file. +. +.Sh CONFIGURATION FILE +.Bd -filled +The configuration file is a single-line file consisting of command line +arguments. The arguments are processed in-place, overriding arguments +specified before, and overridden by arguments after. Multiple files may +be read sequentially, but cannot be nested. Basic quotation is supported. +. diff --git a/udyfi.c b/udyfi.c @@ -75,7 +75,7 @@ static char **strsplit(char *s, int *c) char *r = s; char *w = s; char **rv = malloc((n + 1) * sizeof(*rv)); - enum { NONE, SQUOT = '\'', DQUOT = '"' } state = NONE; + enum { NONE, ERR, SQUOT = '\'', DQUOT = '"' } state = NONE; rv[0] = s; @@ -108,12 +108,21 @@ static char **strsplit(char *s, int *c) continue; case '\\': - if (state != SQUOT) - r++; + if (state != SQUOT) { + if (!*++r) { + state = ERR; + continue; + } + } break; } *w++ = *r++; } + + if (state != NONE) { + free(rv); + return NULL; + } *w = '\0'; rv[n] = NULL; *c = n; @@ -701,11 +710,11 @@ cfgtoggle: dropuser = EARGF(usage()); break; case 'p': { - char *pass = EARGF(usage()); - snprintf(password, sizeof(password), - "%s", pass); - memset(pass, 0, strlen(pass)); - break; + char *pass = EARGF(usage()); + snprintf(password, sizeof(password), + "%s", pass); + memset(pass, 0, strlen(pass)); + break; } case 'F': { FILE *f; @@ -744,6 +753,11 @@ cfgtoggle: cfgfile.arg = arg; argv = strsplit(data, &argc); + if (!argv) { + fprintf(stderr, "Failed to parse configuration file\n"); + free(data); + return EXIT_FAILURE; + } arg = argv[0]; if (*arg != '-') continue;