Add dnsconfig(8).

This commit is contained in:
Juhani Krekelä 2021-08-22 13:08:44 +03:00
parent d605911ddc
commit d4528e9401
5 changed files with 248 additions and 0 deletions

View File

@ -13,6 +13,7 @@ bench \
carray \
checksum \
disked \
dnsconfig \
editor \
ext \
games \

1
dnsconfig/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
dnsconfig

30
dnsconfig/Makefile Normal file
View File

@ -0,0 +1,30 @@
SOFTWARE_MEANT_FOR_SORTIX=1
include ../build-aux/platform.mak
include ../build-aux/compiler.mak
include ../build-aux/version.mak
include ../build-aux/dirs.mak
OPTLEVEL?=$(DEFAULT_OPTLEVEL)
CFLAGS?=$(OPTLEVEL)
CFLAGS += -Wall -Wextra
BINARIES = dnsconfig
MANPAGES8 = dnsconfig.8
all: $(BINARIES)
.PHONY: all install clean
install: all
mkdir -p $(DESTDIR)$(SBINDIR)
install $(BINARIES) $(DESTDIR)$(SBINDIR)
mkdir -p $(DESTDIR)$(MANDIR)/man8
cp $(MANPAGES8) $(DESTDIR)$(MANDIR)/man8
%: %.c
$(CC) -std=gnu11 $(CFLAGS) $(CPPFLAGS) $< -o $@
clean:
rm -f $(BINARIES)

86
dnsconfig/dnsconfig.8 Normal file
View File

@ -0,0 +1,86 @@
.Dd October 7, 2021
.Dt DNSCONFIG 8
.Os
.Sh NAME
.Nm dnsconfig
.Nd configure kernel DNS resolver list
.Sh SYNOPSIS
.Nm
.Nm
.Ar resolver ...
.Nm
.Fl s
.Op Ar resolver ...
.Nm
.Fl a
.Op Ar resolver ...
.Nm
.Fl d
.Op Ar resolver ...
.Sh DESCRIPTION
.Nm
writes the current kernel DNS resolver list, or modifies it if any resolvers are
specified.
.Pp
The options are as follows:
.Bl -tag -width "12345678"
.It Fl a
Append resolvers to the list.
.It Fl d
Delete resolvers from the list.
.It Fl s
Set the resolver list.
This option is the default if
.Nm
is invoked with any resolvers.
.El
.Sh EXIT STATUS
.Nm
will exit 0 on success and non-zero otherwise.
.Sh EXAMPLES
Get the resolvers:
.Bd -literal
$ dnsconfig
192.0.2.1
.Ed
.Pp
Set two resolvers:
.Bd -literal
# dnsconfig 192.0.2.15 192.0.2.100
# dnsconfig
192.0.2.15
192.0.2.100
.Ed
.Pp
Set the resolvers to the empty list:
.Bd -literal
# dnsconfig -s
# dnsconfig
.Ed
.Pp
Append a resolver:
.Bd -literal
# dnsconfig 192.0.2.128
# dnsconfig -a 192.0.2.40
# dnsconfig
192.0.2.128
192.0.2.40
.Ed
.Pp
Delete a resolver:
.Bd -literal
# dnsconfig -d 192.0.2.128
# dnsconfig
192.0.2.40
.Ed
.Sh SEE ALSO
.Xr getdnsconfig 2 ,
.Xr setdnsconfig 2
.Sh HISTORY
.Nm
originally appeared in Sortix 1.1.
.Sh CAVEATS
The kernel DNS resolver list is global state.
Changes made with
.Nm
may be overwritten by other programs.

130
dnsconfig/dnsconfig.c Normal file
View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2021 Juhani 'nortti' Krekelä.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*
* dnsconfig.c
* Configure kernel DNS resolver list.
*/
#include <sys/dnsconfig.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <err.h>
#include <getopt.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
bool append = false;
bool delete = false;
bool set = false;
int opt;
while ( (opt = getopt(argc, argv, "ads")) != -1 )
{
switch ( opt )
{
case 'a': append = true; break;
case 'd': delete = true; break;
case 's': set = true; break;
}
}
if ( append + delete + set > 1 )
errx(1, "-a, -d, -s are mutually exclusive");
// If no mode is provided but there are arguments, default to set.
if ( !append && !delete && !set && optind < argc )
set = true;
struct dnsconfig dnsconfig = {0};
if ( !set && getdnsconfig(&dnsconfig) < 0 )
err(1, "getdnsconfig");
if ( append || delete || set )
{
for ( int i = optind; i < argc; i++ )
{
struct dnsconfig_server server = {0};
if ( inet_pton(AF_INET, argv[i], &server.addr.in) )
{
server.family = AF_INET;
server.addrsize = sizeof(server.addr.in);
}
else if ( inet_pton(AF_INET6, argv[i], &server.addr.in6) )
{
server.family = AF_INET6;
server.addrsize = sizeof(server.addr.in6);
}
else
errx(1, "Invalid address: %s", argv[i]);
if ( !delete )
{
size_t index = dnsconfig.servers_count++;
if ( dnsconfig.servers_count > DNSCONFIG_MAX_SERVERS )
errx(1, "Too many DNS resolvers (%zu max)",
(size_t) DNSCONFIG_MAX_SERVERS);
dnsconfig.servers[index] = server;
}
else
{
// Search for a matching entry.
bool found = false;
for ( size_t j = 0; j < dnsconfig.servers_count; j++ )
{
if ( dnsconfig.servers[j].family != server.family ||
memcmp(&dnsconfig.servers[j].addr, &server.addr,
server.addrsize) )
continue;
for ( size_t k = j + 1; k < dnsconfig.servers_count; k++ )
dnsconfig.servers[k - 1] = dnsconfig.servers[k];
dnsconfig.servers_count--;
memset(&dnsconfig.servers[dnsconfig.servers_count], 0,
sizeof(struct dnsconfig_server));
found = true;
break;
}
if ( !found )
errx(1, "Resolver not in the list: %s", argv[i]);
}
}
if ( setdnsconfig(&dnsconfig) < 0 )
err(1, "setdnsconfig");
}
else
{
for ( size_t i = 0; i < dnsconfig.servers_count; i++ )
{
char address[INET6_ADDRSTRLEN];
if ( !inet_ntop(dnsconfig.servers[i].family,
&dnsconfig.servers[i].addr,
address, sizeof(address)) )
err(1, "inet_ntop");
if ( printf("%s\n", address) < 0 )
err(1, "stdout");
}
if ( fflush(stdout) )
err(1, "stdout");
}
return 0;
}