Add support for a virtual hostname to nfsd

Specifically, this allows (via "-V vhostname") telling nfsd what principal
to use, instead of the hostname.  This is used at iXsystems for fail-over in
HA systems.

Reviewed by:	macklem
Sponsored by:	iXsystems Inc.
Differential Revision:	https://reviews.freebsd.org/D19191
This commit is contained in:
sef 2019-02-16 00:15:54 +00:00
parent a8a1f42e71
commit 9fb40dda0a
3 changed files with 30 additions and 9 deletions

View File

@ -13,6 +13,7 @@ name="nfsd"
desc="Remote NFS server" desc="Remote NFS server"
rcvar="nfs_server_enable" rcvar="nfs_server_enable"
command="/usr/sbin/${name}" command="/usr/sbin/${name}"
nfs_server_vhost=""
load_rc_config $name load_rc_config $name
start_precmd="nfsd_precmd" start_precmd="nfsd_precmd"
@ -20,6 +21,7 @@ sig_stop="USR1"
nfsd_precmd() nfsd_precmd()
{ {
local _vhost
rc_flags="${nfs_server_flags}" rc_flags="${nfs_server_flags}"
# Load the modules now, so that the vfs.nfsd sysctl # Load the modules now, so that the vfs.nfsd sysctl
@ -46,6 +48,9 @@ nfsd_precmd()
force_depend rpcbind || return 1 force_depend rpcbind || return 1
force_depend mountd || return 1 force_depend mountd || return 1
if [ -n "${nfs_server_vhost}" ]; then
command_args="-V \"${nfs_server_vhost}\""
fi
} }
run_rc_command "$1" run_rc_command "$1"

View File

@ -28,7 +28,7 @@
.\" @(#)nfsd.8 8.4 (Berkeley) 3/29/95 .\" @(#)nfsd.8 8.4 (Berkeley) 3/29/95
.\" $FreeBSD$ .\" $FreeBSD$
.\" .\"
.Dd August 5, 2018 .Dd February 14, 2019
.Dt NFSD 8 .Dt NFSD 8
.Os .Os
.Sh NAME .Sh NAME
@ -43,6 +43,7 @@ server
.Op Fl h Ar bindip .Op Fl h Ar bindip
.Op Fl p Ar pnfs_setup .Op Fl p Ar pnfs_setup
.Op Fl m Ar mirror_level .Op Fl m Ar mirror_level
.Op Fl V Ar virtual_hostname
.Op Fl Fl maxthreads Ar max_threads .Op Fl Fl maxthreads Ar max_threads
.Op Fl Fl minthreads Ar min_threads .Op Fl Fl minthreads Ar min_threads
.Sh DESCRIPTION .Sh DESCRIPTION
@ -78,6 +79,9 @@ Unregister the
service with service with
.Xr rpcbind 8 .Xr rpcbind 8
without creating any servers. without creating any servers.
.It Fl V Ar virtual_hostname
Specifies a hostname to be used as a principal name, instead of
the default hostname.
.It Fl n Ar threads .It Fl n Ar threads
Specifies how many servers to create. This option is equivalent to specifying Specifies how many servers to create. This option is equivalent to specifying
.Fl Fl maxthreads .Fl Fl maxthreads

View File

@ -122,7 +122,7 @@ static void nonfs(int);
static void reapchild(int); static void reapchild(int);
static int setbindhost(struct addrinfo **ia, const char *bindhost, static int setbindhost(struct addrinfo **ia, const char *bindhost,
struct addrinfo hints); struct addrinfo hints);
static void start_server(int, struct nfsd_nfsd_args *); static void start_server(int, struct nfsd_nfsd_args *, const char *vhost);
static void unregistration(void); static void unregistration(void);
static void usage(void); static void usage(void);
static void open_stable(int *, int *); static void open_stable(int *, int *);
@ -176,6 +176,7 @@ main(int argc, char **argv)
char **bindhost = NULL; char **bindhost = NULL;
pid_t pid; pid_t pid;
struct nfsd_nfsd_args nfsdargs; struct nfsd_nfsd_args nfsdargs;
const char *vhostname = NULL;
nfsdargs.mirrorcnt = 1; nfsdargs.mirrorcnt = 1;
nfsdargs.addr = NULL; nfsdargs.addr = NULL;
@ -183,16 +184,24 @@ main(int argc, char **argv)
nfsdcnt = DEFNFSDCNT; nfsdcnt = DEFNFSDCNT;
unregister = reregister = tcpflag = maxsock = 0; unregister = reregister = tcpflag = maxsock = 0;
bindanyflag = udpflag = connect_type_cnt = bindhostc = 0; bindanyflag = udpflag = connect_type_cnt = bindhostc = 0;
getopt_shortopts = "ah:n:rdtuep:m:"; getopt_shortopts = "ah:n:rdtuep:m:V:";
getopt_usage = getopt_usage =
"usage:\n" "usage:\n"
" nfsd [-ardtue] [-h bindip]\n" " nfsd [-ardtue] [-h bindip]\n"
" [-n numservers] [--minthreads #] [--maxthreads #]\n" " [-n numservers] [--minthreads #] [--maxthreads #]\n"
" [-p/--pnfs dsserver0:/dsserver0-mounted-on-dir,...," " [-p/--pnfs dsserver0:/dsserver0-mounted-on-dir,...,\n"
"dsserverN:/dsserverN-mounted-on-dir] [-m mirrorlevel]\n"; " [-V virtual_hostname]\n"
" dsserverN:/dsserverN-mounted-on-dir] [-m mirrorlevel]\n";
while ((ch = getopt_long(argc, argv, getopt_shortopts, longopts, while ((ch = getopt_long(argc, argv, getopt_shortopts, longopts,
&longindex)) != -1) &longindex)) != -1)
switch (ch) { switch (ch) {
case 'V':
if (strlen(optarg) <= MAXHOSTNAMELEN)
vhostname = optarg;
else
warnx("Virtual host name (%s) is too long",
optarg);
break;
case 'a': case 'a':
bindanyflag = 1; bindanyflag = 1;
break; break;
@ -473,7 +482,7 @@ main(int argc, char **argv)
} else { } else {
(void)signal(SIGUSR1, child_cleanup); (void)signal(SIGUSR1, child_cleanup);
setproctitle("server"); setproctitle("server");
start_server(0, &nfsdargs); start_server(0, &nfsdargs, vhostname);
} }
} }
@ -790,7 +799,7 @@ main(int argc, char **argv)
* a "server" too. start_server will not return. * a "server" too. start_server will not return.
*/ */
if (!tcpflag) if (!tcpflag)
start_server(1, &nfsdargs); start_server(1, &nfsdargs, vhostname);
/* /*
* Loop forever accepting connections and passing the sockets * Loop forever accepting connections and passing the sockets
@ -987,7 +996,7 @@ get_tuned_nfsdcount(void)
} }
static void static void
start_server(int master, struct nfsd_nfsd_args *nfsdargp) start_server(int master, struct nfsd_nfsd_args *nfsdargp, const char *vhost)
{ {
char principal[MAXHOSTNAMELEN + 5]; char principal[MAXHOSTNAMELEN + 5];
int status, error; int status, error;
@ -995,7 +1004,10 @@ start_server(int master, struct nfsd_nfsd_args *nfsdargp)
struct addrinfo *aip, hints; struct addrinfo *aip, hints;
status = 0; status = 0;
gethostname(hostname, sizeof (hostname)); if (vhost == NULL)
gethostname(hostname, sizeof (hostname));
else
strlcpy(hostname, vhost, sizeof (hostname));
snprintf(principal, sizeof (principal), "nfs@%s", hostname); snprintf(principal, sizeof (principal), "nfs@%s", hostname);
if ((cp = strchr(hostname, '.')) == NULL || if ((cp = strchr(hostname, '.')) == NULL ||
*(cp + 1) == '\0') { *(cp + 1) == '\0') {