xref: /freebsd/usr.sbin/pnfsdsfile/pnfsdsfile.c (revision 1d386b48a555f61cb7325543adbbb5c3f3407a66)
16cb9ec3cSRick Macklem /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
36cb9ec3cSRick Macklem  *
46cb9ec3cSRick Macklem  * Copyright (c) 2017 Rick Macklem
56cb9ec3cSRick Macklem  *
66cb9ec3cSRick Macklem  * Redistribution and use in source and binary forms, with or without
76cb9ec3cSRick Macklem  * modification, are permitted provided that the following conditions
86cb9ec3cSRick Macklem  * are met:
96cb9ec3cSRick Macklem  * 1. Redistributions of source code must retain the above copyright
106cb9ec3cSRick Macklem  *    notice, this list of conditions and the following disclaimer.
116cb9ec3cSRick Macklem  * 2. Redistributions in binary form must reproduce the above copyright
126cb9ec3cSRick Macklem  *    notice, this list of conditions and the following disclaimer in the
136cb9ec3cSRick Macklem  *    documentation and/or other materials provided with the distribution.
146cb9ec3cSRick Macklem  *
156cb9ec3cSRick Macklem  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
166cb9ec3cSRick Macklem  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
176cb9ec3cSRick Macklem  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
186cb9ec3cSRick Macklem  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
196cb9ec3cSRick Macklem  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
206cb9ec3cSRick Macklem  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
216cb9ec3cSRick Macklem  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
226cb9ec3cSRick Macklem  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
236cb9ec3cSRick Macklem  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
246cb9ec3cSRick Macklem  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
256cb9ec3cSRick Macklem  * SUCH DAMAGE.
266cb9ec3cSRick Macklem  *
276cb9ec3cSRick Macklem  */
286cb9ec3cSRick Macklem 
296cb9ec3cSRick Macklem #include <sys/cdefs.h>
306cb9ec3cSRick Macklem #include <err.h>
316cb9ec3cSRick Macklem #include <getopt.h>
326cb9ec3cSRick Macklem #include <netdb.h>
336cb9ec3cSRick Macklem #include <stdio.h>
346cb9ec3cSRick Macklem #include <stdlib.h>
356cb9ec3cSRick Macklem #include <string.h>
366cb9ec3cSRick Macklem #include <unistd.h>
376cb9ec3cSRick Macklem #include <sys/param.h>
386cb9ec3cSRick Macklem #include <sys/extattr.h>
396cb9ec3cSRick Macklem #include <sys/mount.h>
406cb9ec3cSRick Macklem #include <sys/socket.h>
416cb9ec3cSRick Macklem #include <netinet/in.h>
426cb9ec3cSRick Macklem #include <fs/nfs/nfskpiport.h>
436cb9ec3cSRick Macklem #include <fs/nfs/nfsproto.h>
446cb9ec3cSRick Macklem #include <fs/nfs/nfs.h>
456cb9ec3cSRick Macklem #include <fs/nfs/nfsrvstate.h>
466cb9ec3cSRick Macklem 
47*a2cc93ecSAlfonso Gregory static void usage(void) __dead2;
486cb9ec3cSRick Macklem 
496cb9ec3cSRick Macklem static struct option longopts[] = {
506cb9ec3cSRick Macklem 	{ "changeds",	required_argument,	NULL,	'c'	},
517c126cfaSRick Macklem 	{ "mirror",	required_argument,	NULL,	'm'	},
526cb9ec3cSRick Macklem 	{ "quiet",	no_argument,		NULL,	'q'	},
536cb9ec3cSRick Macklem 	{ "zerods",	required_argument,	NULL,	'r'	},
546cb9ec3cSRick Macklem 	{ "ds",		required_argument,	NULL,	's'	},
556cb9ec3cSRick Macklem 	{ "zerofh",	no_argument,		NULL,	'z'	},
566cb9ec3cSRick Macklem 	{ NULL,		0,			NULL,	0	}
576cb9ec3cSRick Macklem };
586cb9ec3cSRick Macklem 
596cb9ec3cSRick Macklem /*
606cb9ec3cSRick Macklem  * This program displays the location information of a data storage file
616cb9ec3cSRick Macklem  * for a given file on a MetaData Server (MDS) in a pNFS service.  This program
626cb9ec3cSRick Macklem  * must be run on the MDS and the file argument must be a file in a local
636cb9ec3cSRick Macklem  * file system that has been exported for the pNFS service.
646cb9ec3cSRick Macklem  */
656cb9ec3cSRick Macklem int
main(int argc,char * argv[])666cb9ec3cSRick Macklem main(int argc, char *argv[])
676cb9ec3cSRick Macklem {
686cb9ec3cSRick Macklem 	struct addrinfo *res, *ad, *newres;
696cb9ec3cSRick Macklem 	struct sockaddr_in *sin, adsin;
706cb9ec3cSRick Macklem 	struct sockaddr_in6 *sin6, adsin6;
716cb9ec3cSRick Macklem 	char hostn[2 * NI_MAXHOST + 2], *cp;
726cb9ec3cSRick Macklem 	struct pnfsdsfile dsfile[NFSDEV_MAXMIRRORS];
737c126cfaSRick Macklem 	int ch, dosetxattr, i, mirrorcnt, mirrorit, quiet, zerods, zerofh;
746cb9ec3cSRick Macklem 	in_port_t tport;
756cb9ec3cSRick Macklem 	ssize_t xattrsize, xattrsize2;
766cb9ec3cSRick Macklem 
776cb9ec3cSRick Macklem 	zerods = 0;
786cb9ec3cSRick Macklem 	zerofh = 0;
797c126cfaSRick Macklem 	mirrorit = 0;
806cb9ec3cSRick Macklem 	quiet = 0;
816cb9ec3cSRick Macklem 	dosetxattr = 0;
826cb9ec3cSRick Macklem 	res = NULL;
836cb9ec3cSRick Macklem 	newres = NULL;
846cb9ec3cSRick Macklem 	cp = NULL;
857c126cfaSRick Macklem 	while ((ch = getopt_long(argc, argv, "c:m:qr:s:z", longopts, NULL)) !=
867c126cfaSRick Macklem 	    -1) {
876cb9ec3cSRick Macklem 		switch (ch) {
886cb9ec3cSRick Macklem 		case 'c':
896cb9ec3cSRick Macklem 			/* Replace the first DS server with the second one. */
907c126cfaSRick Macklem 			if (zerofh != 0 || zerods != 0 || mirrorit != 0 ||
917c126cfaSRick Macklem 			    newres != NULL || res != NULL)
927c126cfaSRick Macklem 				errx(1, "-c, -m, -r, -s and -z are mutually "
937c126cfaSRick Macklem 				    "exclusive and only can be used once");
946cb9ec3cSRick Macklem 			strlcpy(hostn, optarg, 2 * NI_MAXHOST + 2);
956cb9ec3cSRick Macklem 			cp = strchr(hostn, ',');
966cb9ec3cSRick Macklem 			if (cp == NULL)
976cb9ec3cSRick Macklem 				errx(1, "Bad -c argument %s", hostn);
986cb9ec3cSRick Macklem 			*cp = '\0';
996cb9ec3cSRick Macklem 			if (getaddrinfo(hostn, NULL, NULL, &res) != 0)
1006cb9ec3cSRick Macklem 				errx(1, "Can't get IP# for %s", hostn);
1016cb9ec3cSRick Macklem 			*cp++ = ',';
1026cb9ec3cSRick Macklem 			if (getaddrinfo(cp, NULL, NULL, &newres) != 0)
1036cb9ec3cSRick Macklem 				errx(1, "Can't get IP# for %s", cp);
1046cb9ec3cSRick Macklem 			break;
1057c126cfaSRick Macklem 		case 'm':
1067c126cfaSRick Macklem 			/* Add 0.0.0.0 entries up to mirror level. */
1077c126cfaSRick Macklem 			if (zerofh != 0 || zerods != 0 || mirrorit != 0 ||
1087c126cfaSRick Macklem 			    newres != NULL || res != NULL)
1097c126cfaSRick Macklem 				errx(1, "-c, -m, -r, -s and -z are mutually "
1107c126cfaSRick Macklem 				    "exclusive and only can be used once");
1117c126cfaSRick Macklem 			mirrorit = atoi(optarg);
1127c126cfaSRick Macklem 			if (mirrorit < 2 || mirrorit > NFSDEV_MAXMIRRORS)
1137c126cfaSRick Macklem 				errx(1, "-m %d out of range", mirrorit);
1147c126cfaSRick Macklem 			break;
1156cb9ec3cSRick Macklem 		case 'q':
1166cb9ec3cSRick Macklem 			quiet = 1;
1176cb9ec3cSRick Macklem 			break;
1186cb9ec3cSRick Macklem 		case 'r':
1196cb9ec3cSRick Macklem 			/* Reset the DS server in a mirror with 0.0.0.0. */
1207c126cfaSRick Macklem 			if (zerofh != 0 || zerods != 0 || mirrorit != 0 ||
1217c126cfaSRick Macklem 			    newres != NULL || res != NULL)
1227c126cfaSRick Macklem 				errx(1, "-c, -m, -r, -s and -z are mutually "
1237c126cfaSRick Macklem 				    "exclusive and only can be used once");
1246cb9ec3cSRick Macklem 			zerods = 1;
1256cb9ec3cSRick Macklem 			/* Translate the server name to an IP address. */
1266cb9ec3cSRick Macklem 			if (getaddrinfo(optarg, NULL, NULL, &res) != 0)
1276cb9ec3cSRick Macklem 				errx(1, "Can't get IP# for %s", optarg);
1286cb9ec3cSRick Macklem 			break;
1296cb9ec3cSRick Macklem 		case 's':
1306cb9ec3cSRick Macklem 			/* Translate the server name to an IP address. */
1317c126cfaSRick Macklem 			if (zerods != 0 || mirrorit != 0 || newres != NULL ||
1327c126cfaSRick Macklem 			    res != NULL)
1337c126cfaSRick Macklem 				errx(1, "-c, -m and -r are mutually exclusive "
1347c126cfaSRick Macklem 				    "from use with -s and -z");
1356cb9ec3cSRick Macklem 			if (getaddrinfo(optarg, NULL, NULL, &res) != 0)
1366cb9ec3cSRick Macklem 				errx(1, "Can't get IP# for %s", optarg);
1376cb9ec3cSRick Macklem 			break;
1386cb9ec3cSRick Macklem 		case 'z':
1397c126cfaSRick Macklem 			if (zerofh != 0 || zerods != 0 || mirrorit != 0 ||
1407c126cfaSRick Macklem 			    newres != NULL)
1417c126cfaSRick Macklem 				errx(1, "-c, -m and -r are mutually exclusive "
1427c126cfaSRick Macklem 				    "from use with -s and -z");
1436cb9ec3cSRick Macklem 			zerofh = 1;
1446cb9ec3cSRick Macklem 			break;
1456cb9ec3cSRick Macklem 		default:
1466cb9ec3cSRick Macklem 			usage();
1476cb9ec3cSRick Macklem 		}
1486cb9ec3cSRick Macklem 	}
1496cb9ec3cSRick Macklem 	argc -= optind;
1506cb9ec3cSRick Macklem 	if (argc != 1)
1516cb9ec3cSRick Macklem 		usage();
1526cb9ec3cSRick Macklem 	argv += optind;
1536cb9ec3cSRick Macklem 
1546cb9ec3cSRick Macklem 	/*
1556cb9ec3cSRick Macklem 	 * The host address and directory where the data storage file is
1566cb9ec3cSRick Macklem 	 * located is in the extended attribute "pnfsd.dsfile".
1576cb9ec3cSRick Macklem 	 */
1586cb9ec3cSRick Macklem 	xattrsize = extattr_get_file(*argv, EXTATTR_NAMESPACE_SYSTEM,
1596cb9ec3cSRick Macklem 	    "pnfsd.dsfile", dsfile, sizeof(dsfile));
1606cb9ec3cSRick Macklem 	mirrorcnt = xattrsize / sizeof(struct pnfsdsfile);
1616cb9ec3cSRick Macklem 	xattrsize2 = mirrorcnt * sizeof(struct pnfsdsfile);
1626cb9ec3cSRick Macklem 	if (mirrorcnt < 1 || xattrsize != xattrsize2)
1636cb9ec3cSRick Macklem 		err(1, "Can't get extattr pnfsd.dsfile for %s", *argv);
1646cb9ec3cSRick Macklem 
1656cb9ec3cSRick Macklem 	if (quiet == 0)
1666cb9ec3cSRick Macklem 		printf("%s:\t", *argv);
1676cb9ec3cSRick Macklem 	for (i = 0; i < mirrorcnt; i++) {
1686cb9ec3cSRick Macklem 		if (i > 0 && quiet == 0)
1696cb9ec3cSRick Macklem 			printf("\t");
1706cb9ec3cSRick Macklem 		/* Do the zerofh option. You must be root. */
1716cb9ec3cSRick Macklem 		if (zerofh != 0) {
1726cb9ec3cSRick Macklem 			if (geteuid() != 0)
1736cb9ec3cSRick Macklem 				errx(1, "Must be root/su to zerofh");
1746cb9ec3cSRick Macklem 
1756cb9ec3cSRick Macklem 			/*
1766cb9ec3cSRick Macklem 			 * Do it for the server specified by -s/--ds or all
1776cb9ec3cSRick Macklem 			 * servers, if -s/--ds was not specified.
1786cb9ec3cSRick Macklem 			 */
1796cb9ec3cSRick Macklem 			sin = &dsfile[i].dsf_sin;
1806cb9ec3cSRick Macklem 			sin6 = &dsfile[i].dsf_sin6;
1816cb9ec3cSRick Macklem 			ad = res;
1826cb9ec3cSRick Macklem 			while (ad != NULL) {
1836cb9ec3cSRick Macklem 				if (ad->ai_addr->sa_family == AF_INET &&
1846cb9ec3cSRick Macklem 				    sin->sin_family == AF_INET &&
1856cb9ec3cSRick Macklem 				    ad->ai_addrlen >= sizeof(adsin)) {
1866cb9ec3cSRick Macklem 					memcpy(&adsin, ad->ai_addr,
1876cb9ec3cSRick Macklem 					    sizeof(adsin));
1886cb9ec3cSRick Macklem 					if (sin->sin_addr.s_addr ==
1896cb9ec3cSRick Macklem 					    adsin.sin_addr.s_addr)
1906cb9ec3cSRick Macklem 						break;
1916cb9ec3cSRick Macklem 				}
1926cb9ec3cSRick Macklem 				if (ad->ai_addr->sa_family == AF_INET6 &&
1936cb9ec3cSRick Macklem 				    sin6->sin6_family == AF_INET6 &&
1946cb9ec3cSRick Macklem 				    ad->ai_addrlen >= sizeof(adsin6)) {
1956cb9ec3cSRick Macklem 					memcpy(&adsin6, ad->ai_addr,
1966cb9ec3cSRick Macklem 					    sizeof(adsin6));
1976cb9ec3cSRick Macklem 					if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
1986cb9ec3cSRick Macklem 					    &adsin6.sin6_addr))
1996cb9ec3cSRick Macklem 						break;
2006cb9ec3cSRick Macklem 				}
2016cb9ec3cSRick Macklem 				ad = ad->ai_next;
2026cb9ec3cSRick Macklem 			}
2036cb9ec3cSRick Macklem 			if (res == NULL || ad != NULL) {
2046cb9ec3cSRick Macklem 				memset(&dsfile[i].dsf_fh, 0, sizeof(fhandle_t));
2056cb9ec3cSRick Macklem 				dosetxattr = 1;
2066cb9ec3cSRick Macklem 			}
2076cb9ec3cSRick Macklem 		}
2086cb9ec3cSRick Macklem 
2096cb9ec3cSRick Macklem 		/* Do the zerods option. You must be root. */
2106cb9ec3cSRick Macklem 		if (zerods != 0 && mirrorcnt > 1) {
2116cb9ec3cSRick Macklem 			if (geteuid() != 0)
2126cb9ec3cSRick Macklem 				errx(1, "Must be root/su to zerods");
2136cb9ec3cSRick Macklem 
2146cb9ec3cSRick Macklem 			/*
2156cb9ec3cSRick Macklem 			 * Do it for the server specified.
2166cb9ec3cSRick Macklem 			 */
2176cb9ec3cSRick Macklem 			sin = &dsfile[i].dsf_sin;
2186cb9ec3cSRick Macklem 			sin6 = &dsfile[i].dsf_sin6;
2196cb9ec3cSRick Macklem 			ad = res;
2206cb9ec3cSRick Macklem 			while (ad != NULL) {
2216cb9ec3cSRick Macklem 				if (ad->ai_addr->sa_family == AF_INET &&
2226cb9ec3cSRick Macklem 				    sin->sin_family == AF_INET &&
2236cb9ec3cSRick Macklem 				    ad->ai_addrlen >= sizeof(adsin)) {
2246cb9ec3cSRick Macklem 					memcpy(&adsin, ad->ai_addr,
2256cb9ec3cSRick Macklem 					    sizeof(adsin));
2266cb9ec3cSRick Macklem 					if (sin->sin_addr.s_addr ==
2276cb9ec3cSRick Macklem 					    adsin.sin_addr.s_addr)
2286cb9ec3cSRick Macklem 						break;
2296cb9ec3cSRick Macklem 				}
2306cb9ec3cSRick Macklem 				if (ad->ai_addr->sa_family == AF_INET6 &&
2316cb9ec3cSRick Macklem 				    sin6->sin6_family == AF_INET6 &&
2326cb9ec3cSRick Macklem 				    ad->ai_addrlen >= sizeof(adsin6)) {
2336cb9ec3cSRick Macklem 					memcpy(&adsin6, ad->ai_addr,
2346cb9ec3cSRick Macklem 					    sizeof(adsin6));
2356cb9ec3cSRick Macklem 					if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
2366cb9ec3cSRick Macklem 					    &adsin6.sin6_addr))
2376cb9ec3cSRick Macklem 						break;
2386cb9ec3cSRick Macklem 				}
2396cb9ec3cSRick Macklem 				ad = ad->ai_next;
2406cb9ec3cSRick Macklem 			}
2416cb9ec3cSRick Macklem 			if (ad != NULL) {
2426cb9ec3cSRick Macklem 				sin->sin_family = AF_INET;
2436cb9ec3cSRick Macklem 				sin->sin_len = sizeof(*sin);
2446cb9ec3cSRick Macklem 				sin->sin_port = 0;
2456cb9ec3cSRick Macklem 				sin->sin_addr.s_addr = 0;
2466cb9ec3cSRick Macklem 				dosetxattr = 1;
2476cb9ec3cSRick Macklem 			}
2486cb9ec3cSRick Macklem 		}
2496cb9ec3cSRick Macklem 
2506cb9ec3cSRick Macklem 		/* Do the -c option to replace the DS host address. */
2516cb9ec3cSRick Macklem 		if (newres != NULL) {
2526cb9ec3cSRick Macklem 			if (geteuid() != 0)
2536cb9ec3cSRick Macklem 				errx(1, "Must be root/su to replace the host"
2546cb9ec3cSRick Macklem 				    " addr");
2556cb9ec3cSRick Macklem 
2566cb9ec3cSRick Macklem 			/*
2576cb9ec3cSRick Macklem 			 * Check that the old host address matches.
2586cb9ec3cSRick Macklem 			 */
2596cb9ec3cSRick Macklem 			sin = &dsfile[i].dsf_sin;
2606cb9ec3cSRick Macklem 			sin6 = &dsfile[i].dsf_sin6;
2616cb9ec3cSRick Macklem 			ad = res;
2626cb9ec3cSRick Macklem 			while (ad != NULL) {
2636cb9ec3cSRick Macklem 				if (ad->ai_addr->sa_family == AF_INET &&
2646cb9ec3cSRick Macklem 				    sin->sin_family == AF_INET &&
2656cb9ec3cSRick Macklem 				    ad->ai_addrlen >= sizeof(adsin)) {
2666cb9ec3cSRick Macklem 					memcpy(&adsin, ad->ai_addr,
2676cb9ec3cSRick Macklem 					    sizeof(adsin));
2686cb9ec3cSRick Macklem 					if (sin->sin_addr.s_addr ==
2696cb9ec3cSRick Macklem 					    adsin.sin_addr.s_addr)
2706cb9ec3cSRick Macklem 						break;
2716cb9ec3cSRick Macklem 				}
2726cb9ec3cSRick Macklem 				if (ad->ai_addr->sa_family == AF_INET6 &&
2736cb9ec3cSRick Macklem 				    sin6->sin6_family == AF_INET6 &&
2746cb9ec3cSRick Macklem 				    ad->ai_addrlen >= sizeof(adsin6)) {
2756cb9ec3cSRick Macklem 					memcpy(&adsin6, ad->ai_addr,
2766cb9ec3cSRick Macklem 					    sizeof(adsin6));
2776cb9ec3cSRick Macklem 					if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr,
2786cb9ec3cSRick Macklem 					    &adsin6.sin6_addr))
2796cb9ec3cSRick Macklem 						break;
2806cb9ec3cSRick Macklem 				}
2816cb9ec3cSRick Macklem 				ad = ad->ai_next;
2826cb9ec3cSRick Macklem 			}
2836cb9ec3cSRick Macklem 			if (ad != NULL) {
2846cb9ec3cSRick Macklem 				if (sin->sin_family == AF_INET)
2856cb9ec3cSRick Macklem 					tport = sin->sin_port;
2866cb9ec3cSRick Macklem 				else
2876cb9ec3cSRick Macklem 					tport = sin6->sin6_port;
2886cb9ec3cSRick Macklem 				/*
2896cb9ec3cSRick Macklem 				 * We have a match, so replace it with the first
2906cb9ec3cSRick Macklem 				 * AF_INET or AF_INET6 address in the newres
2916cb9ec3cSRick Macklem 				 * list.
2926cb9ec3cSRick Macklem 				 */
2936cb9ec3cSRick Macklem 				while (newres->ai_addr->sa_family != AF_INET &&
2946cb9ec3cSRick Macklem 				    newres->ai_addr->sa_family != AF_INET6) {
2956cb9ec3cSRick Macklem 					newres = newres->ai_next;
2966cb9ec3cSRick Macklem 					if (newres == NULL)
2976cb9ec3cSRick Macklem 						errx(1, "Hostname %s has no"
2986cb9ec3cSRick Macklem 						    " IP#", cp);
2996cb9ec3cSRick Macklem 				}
3006cb9ec3cSRick Macklem 				if (newres->ai_addr->sa_family == AF_INET) {
3016cb9ec3cSRick Macklem 					memcpy(sin, newres->ai_addr,
3026cb9ec3cSRick Macklem 					    sizeof(*sin));
3036cb9ec3cSRick Macklem 					sin->sin_port = tport;
3046cb9ec3cSRick Macklem 				} else if (newres->ai_addr->sa_family ==
3056cb9ec3cSRick Macklem 				    AF_INET6) {
3066cb9ec3cSRick Macklem 					memcpy(sin6, newres->ai_addr,
3076cb9ec3cSRick Macklem 					    sizeof(*sin6));
3086cb9ec3cSRick Macklem 					sin6->sin6_port = tport;
3096cb9ec3cSRick Macklem 				}
3106cb9ec3cSRick Macklem 				dosetxattr = 1;
3116cb9ec3cSRick Macklem 			}
3126cb9ec3cSRick Macklem 		}
3136cb9ec3cSRick Macklem 
3146cb9ec3cSRick Macklem 		if (quiet == 0) {
3156cb9ec3cSRick Macklem 			/* Translate the IP address to a hostname. */
3166cb9ec3cSRick Macklem 			if (getnameinfo((struct sockaddr *)&dsfile[i].dsf_sin,
3176cb9ec3cSRick Macklem 			    dsfile[i].dsf_sin.sin_len, hostn, sizeof(hostn),
3186cb9ec3cSRick Macklem 			    NULL, 0, 0) < 0)
3196cb9ec3cSRick Macklem 				err(1, "Can't get hostname");
3206cb9ec3cSRick Macklem 			printf("%s\tds%d/%s", hostn, dsfile[i].dsf_dir,
3216cb9ec3cSRick Macklem 			    dsfile[i].dsf_filename);
3226cb9ec3cSRick Macklem 		}
3236cb9ec3cSRick Macklem 	}
3247c126cfaSRick Macklem 	/* Add entrie(s) with IP address set to 0.0.0.0, as required. */
3257c126cfaSRick Macklem 	for (i = mirrorcnt; i < mirrorit; i++) {
3267c126cfaSRick Macklem 		dsfile[i] = dsfile[0];
3277c126cfaSRick Macklem 		dsfile[i].dsf_sin.sin_family = AF_INET;
3287c126cfaSRick Macklem 		dsfile[i].dsf_sin.sin_len = sizeof(struct sockaddr_in);
3297c126cfaSRick Macklem 		dsfile[i].dsf_sin.sin_addr.s_addr = 0;
3307c126cfaSRick Macklem 		dsfile[i].dsf_sin.sin_port = 0;
3317c126cfaSRick Macklem 		if (quiet == 0) {
3327c126cfaSRick Macklem 			/* Print out the 0.0.0.0 entry. */
3337c126cfaSRick Macklem 			printf("\t0.0.0.0\tds%d/%s", dsfile[i].dsf_dir,
3347c126cfaSRick Macklem 			    dsfile[i].dsf_filename);
3357c126cfaSRick Macklem 		}
3367c126cfaSRick Macklem 	}
3377c126cfaSRick Macklem 	if (mirrorit > mirrorcnt) {
3387c126cfaSRick Macklem 		xattrsize = mirrorit * sizeof(struct pnfsdsfile);
3397c126cfaSRick Macklem 		dosetxattr = 1;
3407c126cfaSRick Macklem 	}
3416cb9ec3cSRick Macklem 	if (quiet == 0)
3426cb9ec3cSRick Macklem 		printf("\n");
3437c126cfaSRick Macklem 
3446cb9ec3cSRick Macklem 	if (dosetxattr != 0 && extattr_set_file(*argv, EXTATTR_NAMESPACE_SYSTEM,
3456cb9ec3cSRick Macklem 	    "pnfsd.dsfile", dsfile, xattrsize) != xattrsize)
3466cb9ec3cSRick Macklem 		err(1, "Can't set pnfsd.dsfile");
3476cb9ec3cSRick Macklem }
3486cb9ec3cSRick Macklem 
3496cb9ec3cSRick Macklem static void
usage(void)3506cb9ec3cSRick Macklem usage(void)
3516cb9ec3cSRick Macklem {
3526cb9ec3cSRick Macklem 
3536cb9ec3cSRick Macklem 	fprintf(stderr, "pnfsdsfile [-q/--quiet] [-z/--zerofh] "
3546cb9ec3cSRick Macklem 	    "[-c/--changeds <old dshostname> <new dshostname>] "
3556cb9ec3cSRick Macklem 	    "[-r/--zerods <dshostname>] "
3566cb9ec3cSRick Macklem 	    "[-s/--ds <dshostname>] "
3576cb9ec3cSRick Macklem 	    "<filename>\n");
3586cb9ec3cSRick Macklem 	exit(1);
3596cb9ec3cSRick Macklem }
3606cb9ec3cSRick Macklem 
361