> On Feb 8, 2022, at 11:04 AM, Steve Dickson <steved@xxxxxxxxxx> wrote: > > Hello, > > On 2/4/22 7:56 AM, Benjamin Coddington wrote: >> The nfs4id program will either create a new UUID from a random source or >> derive it from /etc/machine-id, else it returns a UUID that has already >> been written to /etc/nfs4-id. This small, lightweight tool is suitable for >> execution by systemd-udev in rules to populate the nfs4 client uniquifier. >> Signed-off-by: Benjamin Coddington <bcodding@xxxxxxxxxx> >> --- >> .gitignore | 1 + >> configure.ac | 4 + >> tools/Makefile.am | 1 + >> tools/nfs4id/Makefile.am | 8 ++ >> tools/nfs4id/nfs4id.c | 184 +++++++++++++++++++++++++++++++++++++++ >> tools/nfs4id/nfs4id.man | 29 ++++++ >> 6 files changed, 227 insertions(+) >> create mode 100644 tools/nfs4id/Makefile.am >> create mode 100644 tools/nfs4id/nfs4id.c >> create mode 100644 tools/nfs4id/nfs4id.man > Just a nit... naming convention... In the past > we never put the protocol version in the name. > Do a ls tools and utils directory and you > see what I mean.... > > Would it be a problem to change the name from > nfs4id to nfsid? nfs4id is pretty generic, too. Can we go with nfs-client-id ? > steved. > >> diff --git a/.gitignore b/.gitignore >> index c89d1cd2583d..a37964148dd8 100644 >> --- a/.gitignore >> +++ b/.gitignore >> @@ -61,6 +61,7 @@ utils/statd/statd >> tools/locktest/testlk >> tools/getiversion/getiversion >> tools/nfsconf/nfsconf >> +tools/nfs4id/nfs4id >> support/export/mount.h >> support/export/mount_clnt.c >> support/export/mount_xdr.c >> diff --git a/configure.ac b/configure.ac >> index 50e9b321dcf3..93d0a902cfd8 100644 >> --- a/configure.ac >> +++ b/configure.ac >> @@ -355,6 +355,9 @@ if test "$enable_nfsv4" = yes; then >> dnl check for the keyutils libraries and headers >> AC_KEYUTILS >> + dnl check for the libuuid library and headers >> + AC_LIBUUID >> + >> dnl Check for sqlite3 >> AC_SQLITE3_VERS >> @@ -740,6 +743,7 @@ AC_CONFIG_FILES([ >> tools/nfsdclnts/Makefile >> tools/nfsconf/Makefile >> tools/nfsdclddb/Makefile >> + tools/nfs4id/Makefile >> utils/Makefile >> utils/blkmapd/Makefile >> utils/nfsdcld/Makefile >> diff --git a/tools/Makefile.am b/tools/Makefile.am >> index 9b4b0803db39..cc658f69bb32 100644 >> --- a/tools/Makefile.am >> +++ b/tools/Makefile.am >> @@ -7,6 +7,7 @@ OPTDIRS += rpcgen >> endif >> OPTDIRS += nfsconf >> +OPTDIRS += nfs4id >> if CONFIG_NFSDCLD >> OPTDIRS += nfsdclddb >> diff --git a/tools/nfs4id/Makefile.am b/tools/nfs4id/Makefile.am >> new file mode 100644 >> index 000000000000..d1e60a35a510 >> --- /dev/null >> +++ b/tools/nfs4id/Makefile.am >> @@ -0,0 +1,8 @@ >> +## Process this file with automake to produce Makefile.in >> + >> +man8_MANS = nfs4id.man >> + >> +bin_PROGRAMS = nfs4id >> + >> +nfs4id_SOURCES = nfs4id.c >> +nfs4id_LDADD = $(LIBUUID) >> diff --git a/tools/nfs4id/nfs4id.c b/tools/nfs4id/nfs4id.c >> new file mode 100644 >> index 000000000000..dbb807ae21f3 >> --- /dev/null >> +++ b/tools/nfs4id/nfs4id.c >> @@ -0,0 +1,184 @@ >> +/* >> + * nfs4id.c -- create and persist uniquifiers for nfs4 clients >> + * >> + * Copyright (C) 2022 Red Hat, Benjamin Coddington <bcodding@xxxxxxxxxx> >> + * >> + * This program is free software; you can redistribute it and/or >> + * modify it under the terms of the GNU General Public License >> + * as published by the Free Software Foundation; either version 2 >> + * of the License, or (at your option) any later version. >> + * >> + * This program is distributed in the hope that it will be useful, >> + * but WITHOUT ANY WARRANTY; without even the implied warranty of >> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the >> + * GNU General Public License for more details. >> + * >> + * You should have received a copy of the GNU General Public License >> + * along with this program; if not, write to the Free Software >> + * Foundation, Inc., 51 Franklin Street, Fifth Floor, >> + * Boston, MA 02110-1301, USA. >> + */ >> + >> +#include <stdio.h> >> +#include <stdarg.h> >> +#include <getopt.h> >> +#include <string.h> >> +#include <errno.h> >> +#include <stdlib.h> >> +#include <fcntl.h> >> +#include <unistd.h> >> +#include <uuid/uuid.h> >> + >> +#define NFS4IDFILE "/etc/nfs4-id" >> + >> +UUID_DEFINE(nfs4_clientid_uuid_template, >> + 0xa2, 0x25, 0x68, 0xb2, 0x7a, 0x5f, 0x49, 0x90, >> + 0x8f, 0x98, 0xc5, 0xf0, 0x67, 0x78, 0xcc, 0xf1); >> + >> +static char *prog; >> +static char *source = NULL; >> +static char nfs4_id[64]; >> +static int force = 0; >> + >> +static void usage(void) >> +{ >> + fprintf(stderr, "usage: %s [-f|--force] [machine]\n", prog); >> +} >> + >> +static void fatal(const char *fmt, ...) >> +{ >> + int err = errno; >> + va_list args; >> + char fatal_msg[256] = "fatal: "; >> + >> + va_start(args, fmt); >> + vsnprintf(&fatal_msg[7], 255, fmt, args); >> + if (err) >> + fprintf(stderr, "%s: %s\n", fatal_msg, strerror(err)); >> + else >> + fprintf(stderr, "%s\n", fatal_msg); >> + exit(-1); >> +} >> + >> +static int read_nfs4_id(void) >> +{ >> + int fd; >> + >> + fd = open(NFS4IDFILE, O_RDONLY); >> + if (fd < 0) >> + return fd; >> + read(fd, nfs4_id, 64); >> + close(fd); >> + return 0; >> +} >> + >> +static void write_nfs4_id(void) >> +{ >> + int fd; >> + >> + fd = open(NFS4IDFILE, O_RDWR|O_TRUNC|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); >> + if (fd < 0) >> + fatal("could not write id to " NFS4IDFILE); >> + write(fd, nfs4_id, 37); >> +} >> + >> +static void print_nfs4_id(void) >> +{ >> + fprintf(stdout, "%s", nfs4_id); >> +} >> + >> +static void check_or_make_id(void) >> +{ >> + int ret; >> + uuid_t nfs4id_uuid; >> + >> + ret = read_nfs4_id(); >> + if (ret != 0) { >> + if (errno != ENOENT ) >> + fatal("reading file " NFS4IDFILE); >> + uuid_generate_random(nfs4id_uuid); >> + uuid_unparse(nfs4id_uuid, nfs4_id); >> + nfs4_id[36] = '\n'; >> + nfs4_id[37] = '\0'; >> + write_nfs4_id(); >> + } >> + print_nfs4_id(); >> +} >> + >> +static void check_or_make_id_from_machine(void) >> +{ >> + int fd, ret; >> + char machineid[32]; >> + uuid_t nfs4id_uuid; >> + >> + ret = read_nfs4_id(); >> + if (ret != 0) { >> + if (errno != ENOENT ) >> + fatal("reading file " NFS4IDFILE); >> + >> + fd = open("/etc/machine-id", O_RDONLY); >> + if (fd < 0) >> + fatal("unable to read /etc/machine-id"); >> + >> + read(fd, machineid, 32); >> + close(fd); >> + >> + uuid_generate_sha1(nfs4id_uuid, nfs4_clientid_uuid_template, machineid, 32); >> + uuid_unparse(nfs4id_uuid, nfs4_id); >> + nfs4_id[36] = '\n'; >> + nfs4_id[37] = '\0'; >> + write_nfs4_id(); >> + } >> + print_nfs4_id(); >> +} >> + >> +int main(int argc, char **argv) >> +{ >> + prog = argv[0]; >> + >> + while (1) { >> + int opt; >> + int option_index = 0; >> + static struct option long_options[] = { >> + {"force", no_argument, 0, 'f' }, >> + {0, 0, 0, 0 } >> + }; >> + >> + errno = 0; >> + opt = getopt_long(argc, argv, ":f", long_options, &option_index); >> + if (opt == -1) >> + break; >> + >> + switch (opt) { >> + case 'f': >> + force = 1; >> + break; >> + case '?': >> + usage(); >> + fatal("unexpected arg \"%s\"", argv[optind - 1]); >> + break; >> + } >> + } >> + >> + argc -= optind; >> + >> + if (argc > 1) { >> + usage(); >> + fatal("Too many arguments"); >> + } >> + >> + if (argc) >> + source = argv[optind++]; >> + >> + if (force) >> + unlink(NFS4IDFILE); >> + >> + if (!source) >> + check_or_make_id(); >> + else if (strcmp(source, "machine") == 0) >> + check_or_make_id_from_machine(); >> + else { >> + usage(); >> + fatal("unrecognized source %s\n", source); >> + } >> +} >> diff --git a/tools/nfs4id/nfs4id.man b/tools/nfs4id/nfs4id.man >> new file mode 100644 >> index 000000000000..358f836468a2 >> --- /dev/null >> +++ b/tools/nfs4id/nfs4id.man >> @@ -0,0 +1,29 @@ >> +.\" >> +.\" nfs4id(8) >> +.\" >> +.TH nfs4id 8 "3 Feb 2022" >> +.SH NAME >> +nfs4id \- Generate or return nfs4 client id uniqueifiers >> +.SH SYNOPSIS >> +.B nfs4id [ -f | --force ] [<source>] >> + >> +.SH DESCRIPTION >> +The >> +.B nfs4id >> +command provides a simple utility to help NFS Version 4 clients use unique >> +and persistent client id values. The command checks for the existence of a >> +file /etc/nfs4-id and returns the first 64 chars read from that file. If >> +the file is not found, a UUID is generated from the specified source and >> +written to the file and returned. >> +.SH OPTIONS >> +.TP >> +.BR \-f, \-\-force >> +Overwrite the existing /etc/nfs4-id with a UUID generated from <source>. >> +.SH Sources >> +If <source> is not specified, nfs4id will generate a new random UUID. >> + >> +If <source> is "machine", nfs4id will generate a deterministic UUID value >> +derived from a sha1 hash of the contents of /etc/machine-id and a static >> +key. >> +.SH SEE ALSO >> +.BR machine-id (5) -- Chuck Lever