diff --git a/usr.sbin/pnfsdscopymr/pnfsdscopymr.c b/usr.sbin/pnfsdscopymr/pnfsdscopymr.c index 33dcd302ef73..7a6eb298fa8d 100644 --- a/usr.sbin/pnfsdscopymr/pnfsdscopymr.c +++ b/usr.sbin/pnfsdscopymr/pnfsdscopymr.c @@ -1,311 +1,311 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2017 Rick Macklem * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -static void usage(void); +static void usage(void) __dead2; static struct option longopts[] = { { "migrate", required_argument, NULL, 'm' }, { "mirror", required_argument, NULL, 'r' }, { NULL, 0, NULL, 0 } }; /* * This program creates a copy of the file's (first argument) data on the * new/recovering DS mirror. If the file is already on the new/recovering * DS, it will simply exit(0). */ int main(int argc, char *argv[]) { struct nfsd_pnfsd_args pnfsdarg; struct pnfsdsfile dsfile[NFSDEV_MAXMIRRORS]; struct stat sb; struct statfs sf; struct addrinfo hints, *res, *nres; struct sockaddr_in sin; struct sockaddr_in6 sin6; ssize_t xattrsize, xattrsize2; size_t mirlen; int ch, fnd, fndzero, i, migrateit, mirrorcnt, mirrorit, ret; int mirrorlevel; char host[MNAMELEN + NI_MAXHOST + 2], *cp; if (geteuid() != 0) errx(1, "Must be run as root/su"); mirrorit = migrateit = 0; pnfsdarg.dspath = pnfsdarg.curdspath = NULL; while ((ch = getopt_long(argc, argv, "m:r:", longopts, NULL)) != -1) { switch (ch) { case 'm': /* Migrate the file from the second DS to the first. */ if (mirrorit != 0) errx(1, "-r and -m are mutually exclusive"); migrateit = 1; pnfsdarg.curdspath = optarg; break; case 'r': /* Mirror the file on the specified DS. */ if (migrateit != 0) errx(1, "-r and -m are mutually exclusive"); mirrorit = 1; pnfsdarg.dspath = optarg; break; default: usage(); } } argc -= optind; argv += optind; if (migrateit != 0) { if (argc != 2) usage(); pnfsdarg.dspath = *argv++; } else if (argc != 1) usage(); /* Get the pNFS service's mirror level. */ mirlen = sizeof(mirrorlevel); ret = sysctlbyname("vfs.nfs.pnfsmirror", &mirrorlevel, &mirlen, NULL, 0); if (ret < 0) errx(1, "Can't get vfs.nfs.pnfsmirror"); if (pnfsdarg.dspath != NULL && pnfsdarg.curdspath != NULL && strcmp(pnfsdarg.dspath, pnfsdarg.curdspath) == 0) errx(1, "Can't migrate to same server"); /* * The host address and directory where the data storage file is * located is in the extended attribute "pnfsd.dsfile". */ xattrsize = extattr_get_file(*argv, EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsfile", dsfile, sizeof(dsfile)); mirrorcnt = xattrsize / sizeof(struct pnfsdsfile); xattrsize2 = mirrorcnt * sizeof(struct pnfsdsfile); if (mirrorcnt < 1 || xattrsize != xattrsize2) errx(1, "Can't get extattr pnfsd.dsfile for %s", *argv); /* See if there is a 0.0.0.0 entry. */ fndzero = 0; for (i = 0; i < mirrorcnt; i++) { if (dsfile[i].dsf_sin.sin_family == AF_INET && dsfile[i].dsf_sin.sin_addr.s_addr == 0) fndzero = 1; } /* If already mirrored for default case, just exit(0); */ if (mirrorit == 0 && migrateit == 0 && (mirrorlevel < 2 || (fndzero == 0 && mirrorcnt >= mirrorlevel) || (fndzero != 0 && mirrorcnt > mirrorlevel))) exit(0); /* For the "-r" case, there must be a 0.0.0.0 entry. */ if (mirrorit != 0 && (fndzero == 0 || mirrorlevel < 2 || mirrorcnt < 2 || mirrorcnt > mirrorlevel)) exit(0); /* For pnfsdarg.dspath set, if it is already in list, just exit(0); */ if (pnfsdarg.dspath != NULL) { /* Check the dspath to see that it's an NFS mount. */ if (stat(pnfsdarg.dspath, &sb) < 0) errx(1, "Can't stat %s", pnfsdarg.dspath); if (!S_ISDIR(sb.st_mode)) errx(1, "%s is not a directory", pnfsdarg.dspath); if (statfs(pnfsdarg.dspath, &sf) < 0) errx(1, "Can't fsstat %s", pnfsdarg.dspath); if (strcmp(sf.f_fstypename, "nfs") != 0) errx(1, "%s is not an NFS mount", pnfsdarg.dspath); if (strcmp(sf.f_mntonname, pnfsdarg.dspath) != 0) errx(1, "%s is not the mounted-on dir for the new DS", pnfsdarg.dspath); /* * Check the IP address of the NFS server against the entrie(s) * in the extended attribute. */ strlcpy(host, sf.f_mntfromname, sizeof(host)); cp = strchr(host, ':'); if (cp == NULL) errx(1, "No : in mount %s", host); *cp = '\0'; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if (getaddrinfo(host, NULL, &hints, &res) != 0) errx(1, "Can't get address for %s", host); for (i = 0; i < mirrorcnt; i++) { nres = res; while (nres != NULL) { if (dsfile[i].dsf_sin.sin_family == nres->ai_family) { /* * If there is already an entry for this * DS, just exit(0), since copying isn't * required. */ if (nres->ai_family == AF_INET && nres->ai_addrlen >= sizeof(sin)) { memcpy(&sin, nres->ai_addr, sizeof(sin)); if (sin.sin_addr.s_addr == dsfile[i].dsf_sin.sin_addr.s_addr) exit(0); } else if (nres->ai_family == AF_INET6 && nres->ai_addrlen >= sizeof(sin6)) { memcpy(&sin6, nres->ai_addr, sizeof(sin6)); if (IN6_ARE_ADDR_EQUAL(&sin6.sin6_addr, &dsfile[i].dsf_sin6.sin6_addr)) exit(0); } } nres = nres->ai_next; } } freeaddrinfo(res); } /* For "-m", the pnfsdarg.curdspath must be in the list. */ if (pnfsdarg.curdspath != NULL) { /* Check pnfsdarg.curdspath to see that it's an NFS mount. */ if (stat(pnfsdarg.curdspath, &sb) < 0) errx(1, "Can't stat %s", pnfsdarg.curdspath); if (!S_ISDIR(sb.st_mode)) errx(1, "%s is not a directory", pnfsdarg.curdspath); if (statfs(pnfsdarg.curdspath, &sf) < 0) errx(1, "Can't fsstat %s", pnfsdarg.curdspath); if (strcmp(sf.f_fstypename, "nfs") != 0) errx(1, "%s is not an NFS mount", pnfsdarg.curdspath); if (strcmp(sf.f_mntonname, pnfsdarg.curdspath) != 0) errx(1, "%s is not the mounted-on dir of the cur DS", pnfsdarg.curdspath); /* * Check the IP address of the NFS server against the entrie(s) * in the extended attribute. */ strlcpy(host, sf.f_mntfromname, sizeof(host)); cp = strchr(host, ':'); if (cp == NULL) errx(1, "No : in mount %s", host); *cp = '\0'; memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if (getaddrinfo(host, NULL, &hints, &res) != 0) errx(1, "Can't get address for %s", host); fnd = 0; for (i = 0; i < mirrorcnt && fnd == 0; i++) { nres = res; while (nres != NULL) { if (dsfile[i].dsf_sin.sin_family == nres->ai_family) { /* * Note if the entry is found. */ if (nres->ai_family == AF_INET && nres->ai_addrlen >= sizeof(sin)) { memcpy(&sin, nres->ai_addr, sizeof(sin)); if (sin.sin_addr.s_addr == dsfile[i].dsf_sin.sin_addr.s_addr) { fnd = 1; break; } } else if (nres->ai_family == AF_INET6 && nres->ai_addrlen >= sizeof(sin6)) { memcpy(&sin6, nres->ai_addr, sizeof(sin6)); if (IN6_ARE_ADDR_EQUAL(&sin6.sin6_addr, &dsfile[i].dsf_sin6.sin6_addr)) { fnd = 1; break; } } } nres = nres->ai_next; } } freeaddrinfo(res); /* * If not found just exit(0), since it is not on the * source DS. */ if (fnd == 0) exit(0); } /* Do the copy via the nfssvc() syscall. */ pnfsdarg.op = PNFSDOP_COPYMR; pnfsdarg.mdspath = *argv; ret = nfssvc(NFSSVC_PNFSDS, &pnfsdarg); if (ret < 0 && errno != EEXIST) err(1, "Copymr failed for file %s", *argv); exit(0); } static void usage(void) { fprintf(stderr, "pnfsdscopymr [-r recovered-DS-mounted-on-path] " "[-m soure-DS-mounted-on-path destination-DS-mounted-on-path] " "mds-filename"); exit(1); } diff --git a/usr.sbin/pnfsdsfile/pnfsdsfile.c b/usr.sbin/pnfsdsfile/pnfsdsfile.c index ca17586dd3bd..7669f1f29b93 100644 --- a/usr.sbin/pnfsdsfile/pnfsdsfile.c +++ b/usr.sbin/pnfsdsfile/pnfsdsfile.c @@ -1,362 +1,362 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2017 Rick Macklem * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include -static void usage(void); +static void usage(void) __dead2; static struct option longopts[] = { { "changeds", required_argument, NULL, 'c' }, { "mirror", required_argument, NULL, 'm' }, { "quiet", no_argument, NULL, 'q' }, { "zerods", required_argument, NULL, 'r' }, { "ds", required_argument, NULL, 's' }, { "zerofh", no_argument, NULL, 'z' }, { NULL, 0, NULL, 0 } }; /* * This program displays the location information of a data storage file * for a given file on a MetaData Server (MDS) in a pNFS service. This program * must be run on the MDS and the file argument must be a file in a local * file system that has been exported for the pNFS service. */ int main(int argc, char *argv[]) { struct addrinfo *res, *ad, *newres; struct sockaddr_in *sin, adsin; struct sockaddr_in6 *sin6, adsin6; char hostn[2 * NI_MAXHOST + 2], *cp; struct pnfsdsfile dsfile[NFSDEV_MAXMIRRORS]; int ch, dosetxattr, i, mirrorcnt, mirrorit, quiet, zerods, zerofh; in_port_t tport; ssize_t xattrsize, xattrsize2; zerods = 0; zerofh = 0; mirrorit = 0; quiet = 0; dosetxattr = 0; res = NULL; newres = NULL; cp = NULL; while ((ch = getopt_long(argc, argv, "c:m:qr:s:z", longopts, NULL)) != -1) { switch (ch) { case 'c': /* Replace the first DS server with the second one. */ if (zerofh != 0 || zerods != 0 || mirrorit != 0 || newres != NULL || res != NULL) errx(1, "-c, -m, -r, -s and -z are mutually " "exclusive and only can be used once"); strlcpy(hostn, optarg, 2 * NI_MAXHOST + 2); cp = strchr(hostn, ','); if (cp == NULL) errx(1, "Bad -c argument %s", hostn); *cp = '\0'; if (getaddrinfo(hostn, NULL, NULL, &res) != 0) errx(1, "Can't get IP# for %s", hostn); *cp++ = ','; if (getaddrinfo(cp, NULL, NULL, &newres) != 0) errx(1, "Can't get IP# for %s", cp); break; case 'm': /* Add 0.0.0.0 entries up to mirror level. */ if (zerofh != 0 || zerods != 0 || mirrorit != 0 || newres != NULL || res != NULL) errx(1, "-c, -m, -r, -s and -z are mutually " "exclusive and only can be used once"); mirrorit = atoi(optarg); if (mirrorit < 2 || mirrorit > NFSDEV_MAXMIRRORS) errx(1, "-m %d out of range", mirrorit); break; case 'q': quiet = 1; break; case 'r': /* Reset the DS server in a mirror with 0.0.0.0. */ if (zerofh != 0 || zerods != 0 || mirrorit != 0 || newres != NULL || res != NULL) errx(1, "-c, -m, -r, -s and -z are mutually " "exclusive and only can be used once"); zerods = 1; /* Translate the server name to an IP address. */ if (getaddrinfo(optarg, NULL, NULL, &res) != 0) errx(1, "Can't get IP# for %s", optarg); break; case 's': /* Translate the server name to an IP address. */ if (zerods != 0 || mirrorit != 0 || newres != NULL || res != NULL) errx(1, "-c, -m and -r are mutually exclusive " "from use with -s and -z"); if (getaddrinfo(optarg, NULL, NULL, &res) != 0) errx(1, "Can't get IP# for %s", optarg); break; case 'z': if (zerofh != 0 || zerods != 0 || mirrorit != 0 || newres != NULL) errx(1, "-c, -m and -r are mutually exclusive " "from use with -s and -z"); zerofh = 1; break; default: usage(); } } argc -= optind; if (argc != 1) usage(); argv += optind; /* * The host address and directory where the data storage file is * located is in the extended attribute "pnfsd.dsfile". */ xattrsize = extattr_get_file(*argv, EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsfile", dsfile, sizeof(dsfile)); mirrorcnt = xattrsize / sizeof(struct pnfsdsfile); xattrsize2 = mirrorcnt * sizeof(struct pnfsdsfile); if (mirrorcnt < 1 || xattrsize != xattrsize2) err(1, "Can't get extattr pnfsd.dsfile for %s", *argv); if (quiet == 0) printf("%s:\t", *argv); for (i = 0; i < mirrorcnt; i++) { if (i > 0 && quiet == 0) printf("\t"); /* Do the zerofh option. You must be root. */ if (zerofh != 0) { if (geteuid() != 0) errx(1, "Must be root/su to zerofh"); /* * Do it for the server specified by -s/--ds or all * servers, if -s/--ds was not specified. */ sin = &dsfile[i].dsf_sin; sin6 = &dsfile[i].dsf_sin6; ad = res; while (ad != NULL) { if (ad->ai_addr->sa_family == AF_INET && sin->sin_family == AF_INET && ad->ai_addrlen >= sizeof(adsin)) { memcpy(&adsin, ad->ai_addr, sizeof(adsin)); if (sin->sin_addr.s_addr == adsin.sin_addr.s_addr) break; } if (ad->ai_addr->sa_family == AF_INET6 && sin6->sin6_family == AF_INET6 && ad->ai_addrlen >= sizeof(adsin6)) { memcpy(&adsin6, ad->ai_addr, sizeof(adsin6)); if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &adsin6.sin6_addr)) break; } ad = ad->ai_next; } if (res == NULL || ad != NULL) { memset(&dsfile[i].dsf_fh, 0, sizeof(fhandle_t)); dosetxattr = 1; } } /* Do the zerods option. You must be root. */ if (zerods != 0 && mirrorcnt > 1) { if (geteuid() != 0) errx(1, "Must be root/su to zerods"); /* * Do it for the server specified. */ sin = &dsfile[i].dsf_sin; sin6 = &dsfile[i].dsf_sin6; ad = res; while (ad != NULL) { if (ad->ai_addr->sa_family == AF_INET && sin->sin_family == AF_INET && ad->ai_addrlen >= sizeof(adsin)) { memcpy(&adsin, ad->ai_addr, sizeof(adsin)); if (sin->sin_addr.s_addr == adsin.sin_addr.s_addr) break; } if (ad->ai_addr->sa_family == AF_INET6 && sin6->sin6_family == AF_INET6 && ad->ai_addrlen >= sizeof(adsin6)) { memcpy(&adsin6, ad->ai_addr, sizeof(adsin6)); if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &adsin6.sin6_addr)) break; } ad = ad->ai_next; } if (ad != NULL) { sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); sin->sin_port = 0; sin->sin_addr.s_addr = 0; dosetxattr = 1; } } /* Do the -c option to replace the DS host address. */ if (newres != NULL) { if (geteuid() != 0) errx(1, "Must be root/su to replace the host" " addr"); /* * Check that the old host address matches. */ sin = &dsfile[i].dsf_sin; sin6 = &dsfile[i].dsf_sin6; ad = res; while (ad != NULL) { if (ad->ai_addr->sa_family == AF_INET && sin->sin_family == AF_INET && ad->ai_addrlen >= sizeof(adsin)) { memcpy(&adsin, ad->ai_addr, sizeof(adsin)); if (sin->sin_addr.s_addr == adsin.sin_addr.s_addr) break; } if (ad->ai_addr->sa_family == AF_INET6 && sin6->sin6_family == AF_INET6 && ad->ai_addrlen >= sizeof(adsin6)) { memcpy(&adsin6, ad->ai_addr, sizeof(adsin6)); if (IN6_ARE_ADDR_EQUAL(&sin6->sin6_addr, &adsin6.sin6_addr)) break; } ad = ad->ai_next; } if (ad != NULL) { if (sin->sin_family == AF_INET) tport = sin->sin_port; else tport = sin6->sin6_port; /* * We have a match, so replace it with the first * AF_INET or AF_INET6 address in the newres * list. */ while (newres->ai_addr->sa_family != AF_INET && newres->ai_addr->sa_family != AF_INET6) { newres = newres->ai_next; if (newres == NULL) errx(1, "Hostname %s has no" " IP#", cp); } if (newres->ai_addr->sa_family == AF_INET) { memcpy(sin, newres->ai_addr, sizeof(*sin)); sin->sin_port = tport; } else if (newres->ai_addr->sa_family == AF_INET6) { memcpy(sin6, newres->ai_addr, sizeof(*sin6)); sin6->sin6_port = tport; } dosetxattr = 1; } } if (quiet == 0) { /* Translate the IP address to a hostname. */ if (getnameinfo((struct sockaddr *)&dsfile[i].dsf_sin, dsfile[i].dsf_sin.sin_len, hostn, sizeof(hostn), NULL, 0, 0) < 0) err(1, "Can't get hostname"); printf("%s\tds%d/%s", hostn, dsfile[i].dsf_dir, dsfile[i].dsf_filename); } } /* Add entrie(s) with IP address set to 0.0.0.0, as required. */ for (i = mirrorcnt; i < mirrorit; i++) { dsfile[i] = dsfile[0]; dsfile[i].dsf_sin.sin_family = AF_INET; dsfile[i].dsf_sin.sin_len = sizeof(struct sockaddr_in); dsfile[i].dsf_sin.sin_addr.s_addr = 0; dsfile[i].dsf_sin.sin_port = 0; if (quiet == 0) { /* Print out the 0.0.0.0 entry. */ printf("\t0.0.0.0\tds%d/%s", dsfile[i].dsf_dir, dsfile[i].dsf_filename); } } if (mirrorit > mirrorcnt) { xattrsize = mirrorit * sizeof(struct pnfsdsfile); dosetxattr = 1; } if (quiet == 0) printf("\n"); if (dosetxattr != 0 && extattr_set_file(*argv, EXTATTR_NAMESPACE_SYSTEM, "pnfsd.dsfile", dsfile, xattrsize) != xattrsize) err(1, "Can't set pnfsd.dsfile"); } static void usage(void) { fprintf(stderr, "pnfsdsfile [-q/--quiet] [-z/--zerofh] " "[-c/--changeds ] " "[-r/--zerods ] " "[-s/--ds ] " "\n"); exit(1); } diff --git a/usr.sbin/pnfsdskill/pnfsdskill.c b/usr.sbin/pnfsdskill/pnfsdskill.c index dcca4a17b626..878ca584d142 100644 --- a/usr.sbin/pnfsdskill/pnfsdskill.c +++ b/usr.sbin/pnfsdskill/pnfsdskill.c @@ -1,98 +1,98 @@ /*- * SPDX-License-Identifier: BSD-2-Clause * * Copyright (c) 2017 Rick Macklem * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include -static void usage(void); +static void usage(void) __dead2; static struct option longopts[] = { { "force", no_argument, NULL, 'f' }, { NULL, 0, NULL, 0 } }; /* * This program disables use of a DS mirror. The "dspath" command line * argument must be an exact match for the mounted-on path of the DS. * It should be done before any forced dismount is performed on the path * and should work even when the mount point is hung. */ int main(int argc, char *argv[]) { struct nfsd_pnfsd_args pnfsdarg; int ch, force; if (geteuid() != 0) errx(1, "Must be run as root/su"); force = 0; while ((ch = getopt_long(argc, argv, "f", longopts, NULL)) != -1) { switch (ch) { case 'f': force = 1; break; default: usage(); } } argc -= optind; argv += optind; if (argc != 1) usage(); if (force != 0) pnfsdarg.op = PNFSDOP_FORCEDELDS; else pnfsdarg.op = PNFSDOP_DELDSSERVER; pnfsdarg.dspath = *argv; if (nfssvc(NFSSVC_PNFSDS, &pnfsdarg) < 0) err(1, "Can't kill %s", *argv); } static void usage(void) { fprintf(stderr, "pnfsdsfile [-f] mounted-on-DS-dir\n"); exit(1); } diff --git a/usr.sbin/quotaon/quotaon.c b/usr.sbin/quotaon/quotaon.c index f5340c6b44c5..224da3b2032c 100644 --- a/usr.sbin/quotaon/quotaon.c +++ b/usr.sbin/quotaon/quotaon.c @@ -1,194 +1,194 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Robert Elz at The University of Melbourne. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1990, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)quotaon.c 8.1 (Berkeley) 6/6/93"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); /* * Turn quota on/off for a filesystem. */ #include #include #include #include #include #include #include #include #include #include #include static const char *qfextension[] = INITQFNAMES; static int aflag; /* all filesystems */ static int gflag; /* operate on group quotas */ static int uflag; /* operate on user quotas */ static int vflag; /* verbose */ static int oneof(char *, char *[], int); static int quotaonoff(struct fstab *fs, int, int); -static void usage(void); +static void usage(void) __dead2; int main(int argc, char **argv) { struct fstab *fs; const char *whoami; long argnum, done = 0; int ch, i, offmode = 0, errs = 0; whoami = getprogname(); if (strcmp(whoami, "quotaoff") == 0) offmode++; else if (strcmp(whoami, "quotaon") != 0) errx(1, "name must be quotaon or quotaoff"); while ((ch = getopt(argc, argv, "avug")) != -1) { switch(ch) { case 'a': aflag++; break; case 'g': gflag++; break; case 'u': uflag++; break; case 'v': vflag++; break; default: usage(); } } argc -= optind; argv += optind; if (argc <= 0 && !aflag) usage(); if (!gflag && !uflag) { gflag++; uflag++; } setfsent(); while ((fs = getfsent()) != NULL) { if (strcmp(fs->fs_vfstype, "ufs") || strcmp(fs->fs_type, FSTAB_RW)) continue; if (aflag) { if (gflag) errs += quotaonoff(fs, offmode, GRPQUOTA); if (uflag) errs += quotaonoff(fs, offmode, USRQUOTA); continue; } if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 || (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) { done |= 1 << argnum; if (gflag) errs += quotaonoff(fs, offmode, GRPQUOTA); if (uflag) errs += quotaonoff(fs, offmode, USRQUOTA); } } endfsent(); for (i = 0; i < argc; i++) if ((done & (1 << i)) == 0) warnx("%s not found in fstab", argv[i]); exit(errs); } static void usage(void) { fprintf(stderr, "%s\n%s\n%s\n%s\n", "usage: quotaon [-g] [-u] [-v] -a", " quotaon [-g] [-u] [-v] filesystem ...", " quotaoff [-g] [-u] [-v] -a", " quotaoff [-g] [-u] [-v] filesystem ..."); exit(1); } static int quotaonoff(struct fstab *fs, int offmode, int type) { struct quotafile *qf; if ((qf = quota_open(fs, type, O_RDONLY)) == NULL) return (0); if (offmode) { if (quota_off(qf) != 0) { warn("%s", quota_fsname(qf)); return (1); } if (vflag) printf("%s: quotas turned off\n", quota_fsname(qf)); quota_close(qf); return(0); } if (quota_on(qf) != 0) { warn("using %s on %s", quota_qfname(qf), quota_fsname(qf)); return (1); } if (vflag) printf("%s: %s quotas turned on with data file %s\n", quota_fsname(qf), qfextension[type], quota_qfname(qf)); quota_close(qf); return(0); } /* * Check to see if target appears in list of size cnt. */ static int oneof(char *target, char *list[], int cnt) { int i; for (i = 0; i < cnt; i++) if (strcmp(target, list[i]) == 0) return (i); return (-1); } diff --git a/usr.sbin/repquota/repquota.c b/usr.sbin/repquota/repquota.c index 23abcca93752..9fc8829ad1b6 100644 --- a/usr.sbin/repquota/repquota.c +++ b/usr.sbin/repquota/repquota.c @@ -1,373 +1,373 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1990, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Robert Elz at The University of Melbourne. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if 0 #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1990, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint static char sccsid[] = "@(#)repquota.c 8.1 (Berkeley) 6/6/93"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); /* * Quota report */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* Let's be paranoid about block size */ #if 10 > DEV_BSHIFT #define dbtokb(db) \ ((off_t)(db) >> (10-DEV_BSHIFT)) #elif 10 < DEV_BSHIFT #define dbtokb(db) \ ((off_t)(db) << (DEV_BSHIFT-10)) #else #define dbtokb(db) (db) #endif #define max(a,b) ((a) >= (b) ? (a) : (b)) static const char *qfextension[] = INITQFNAMES; struct fileusage { struct fileusage *fu_next; u_long fu_id; char fu_name[1]; /* actually bigger */ }; #define FUHASH 1024 /* must be power of two */ static struct fileusage *fuhead[MAXQUOTAS][FUHASH]; static struct fileusage *lookup(u_long, int); static struct fileusage *addid(u_long, int, char *); static u_long highid[MAXQUOTAS]; /* highest addid()'ed identifier per type */ static int vflag; /* verbose */ static int aflag; /* all filesystems */ static int nflag; /* display user/group by id */ static int hflag; /* display in human readable format */ int oneof(char *, char *[], int); int repquota(struct fstab *, int); char *timeprt(time_t); static void prthumanval(int64_t bytes); -static void usage(void); +static void usage(void) __dead2; int main(int argc, char *argv[]) { struct fstab *fs; struct passwd *pw; struct group *gr; int ch, gflag = 0, uflag = 0, errs = 0; long i, argnum, done = 0; while ((ch = getopt(argc, argv, "aghnuv")) != -1) { switch(ch) { case 'a': aflag++; break; case 'g': gflag++; break; case 'h': hflag++; break; case 'n': nflag++; break; case 'u': uflag++; break; case 'v': vflag++; break; default: usage(); } } argc -= optind; argv += optind; if (argc == 0 && !aflag) usage(); if (!gflag && !uflag) { if (aflag) gflag++; uflag++; } if (gflag && !nflag) { setgrent(); while ((gr = getgrent()) != 0) (void) addid((u_long)gr->gr_gid, GRPQUOTA, gr->gr_name); endgrent(); } if (uflag && !nflag) { setpwent(); while ((pw = getpwent()) != 0) (void) addid((u_long)pw->pw_uid, USRQUOTA, pw->pw_name); endpwent(); } setfsent(); while ((fs = getfsent()) != NULL) { if (strcmp(fs->fs_vfstype, "ufs")) continue; if (aflag) { if (gflag) errs += repquota(fs, GRPQUOTA); if (uflag) errs += repquota(fs, USRQUOTA); continue; } if ((argnum = oneof(fs->fs_file, argv, argc)) >= 0 || (argnum = oneof(fs->fs_spec, argv, argc)) >= 0) { done |= 1 << argnum; if (gflag) errs += repquota(fs, GRPQUOTA); if (uflag) errs += repquota(fs, USRQUOTA); } } endfsent(); for (i = 0; i < argc; i++) if ((done & (1 << i)) == 0) warnx("%s not found in fstab", argv[i]); exit(errs); } static void usage(void) { fprintf(stderr, "%s\n%s\n", "usage: repquota [-h] [-v] [-g] [-n] [-u] -a", " repquota [-h] [-v] [-g] [-n] [-u] filesystem ..."); exit(1); } int repquota(struct fstab *fs, int type) { struct fileusage *fup; struct quotafile *qf; u_long id, maxid; struct dqblk dqbuf; static int multiple = 0; if ((qf = quota_open(fs, type, O_RDONLY)) == NULL) { if (vflag && !aflag) { if (multiple++) printf("\n"); fprintf(stdout, "*** No %s quotas on %s (%s)\n", qfextension[type], fs->fs_file, fs->fs_spec); return(1); } return(0); } if (multiple++) printf("\n"); if (vflag) fprintf(stdout, "*** Report for %s quotas on %s (%s)\n", qfextension[type], fs->fs_file, fs->fs_spec); printf("%*s Block limits File limits\n", max(MAXLOGNAME - 1, 10), " "); printf("User%*s used soft hard grace used soft hard grace\n", max(MAXLOGNAME - 1, 10), " "); maxid = quota_maxid(qf); for (id = 0; id <= maxid; id++) { if (quota_read(qf, &dqbuf, id) != 0) break; if (dqbuf.dqb_curinodes == 0 && dqbuf.dqb_curblocks == 0) continue; if ((fup = lookup(id, type)) == 0) fup = addid(id, type, (char *)0); printf("%-*s ", max(MAXLOGNAME - 1, 10), fup->fu_name); printf("%c%c", dqbuf.dqb_bsoftlimit && dqbuf.dqb_curblocks >= dqbuf.dqb_bsoftlimit ? '+' : '-', dqbuf.dqb_isoftlimit && dqbuf.dqb_curinodes >= dqbuf.dqb_isoftlimit ? '+' : '-'); prthumanval(dqbuf.dqb_curblocks); prthumanval(dqbuf.dqb_bsoftlimit); prthumanval(dqbuf.dqb_bhardlimit); printf(" %6s", dqbuf.dqb_bsoftlimit && dqbuf.dqb_curblocks >= dqbuf.dqb_bsoftlimit ? timeprt(dqbuf.dqb_btime) : "-"); printf(" %7ju %7ju %7ju %6s\n", (uintmax_t)dqbuf.dqb_curinodes, (uintmax_t)dqbuf.dqb_isoftlimit, (uintmax_t)dqbuf.dqb_ihardlimit, dqbuf.dqb_isoftlimit && dqbuf.dqb_curinodes >= dqbuf.dqb_isoftlimit ? timeprt(dqbuf.dqb_itime) : "-"); } quota_close(qf); return (0); } static void prthumanval(int64_t blocks) { char buf[7]; int flags; if (!hflag) { printf(" %6ju", (uintmax_t)dbtokb(blocks)); return; } flags = HN_NOSPACE | HN_DECIMAL; if (blocks != 0) flags |= HN_B; humanize_number(buf, sizeof(buf) - (blocks < 0 ? 0 : 1), dbtob(blocks), "", HN_AUTOSCALE, flags); (void)printf("%7s", buf); } /* * Check to see if target appears in list of size cnt. */ int oneof(char *target, char *list[], int cnt) { int i; for (i = 0; i < cnt; i++) if (strcmp(target, list[i]) == 0) return (i); return (-1); } /* * Routines to manage the file usage table. * * Lookup an id of a specific type. */ struct fileusage * lookup(u_long id, int type) { struct fileusage *fup; for (fup = fuhead[type][id & (FUHASH-1)]; fup != 0; fup = fup->fu_next) if (fup->fu_id == id) return (fup); return ((struct fileusage *)0); } /* * Add a new file usage id if it does not already exist. */ struct fileusage * addid(u_long id, int type, char *name) { struct fileusage *fup, **fhp; int len; if ((fup = lookup(id, type))) return (fup); if (name) len = strlen(name); else len = 10; if ((fup = (struct fileusage *)calloc(1, sizeof(*fup) + len)) == NULL) errx(1, "out of memory for fileusage structures"); fhp = &fuhead[type][id & (FUHASH - 1)]; fup->fu_next = *fhp; *fhp = fup; fup->fu_id = id; if (id > highid[type]) highid[type] = id; if (name) { bcopy(name, fup->fu_name, len + 1); } else { sprintf(fup->fu_name, "%lu", id); } return (fup); } /* * Calculate the grace period and return a printable string for it. */ char * timeprt(time_t seconds) { time_t hours, minutes; static char buf[20]; static time_t now; if (now == 0) time(&now); if (now > seconds) { strlcpy(buf, "none", sizeof (buf)); return (buf); } seconds -= now; minutes = (seconds + 30) / 60; hours = (minutes + 30) / 60; if (hours >= 36) { sprintf(buf, "%lddays", (long)(hours + 12) / 24); return (buf); } if (minutes >= 60) { sprintf(buf, "%2ld:%ld", (long)minutes / 60, (long)minutes % 60); return (buf); } sprintf(buf, "%2ld", (long)minutes); return (buf); } diff --git a/usr.sbin/rip6query/rip6query.c b/usr.sbin/rip6query/rip6query.c index b3d745965965..549e05c4bae6 100644 --- a/usr.sbin/rip6query/rip6query.c +++ b/usr.sbin/rip6query/rip6query.c @@ -1,199 +1,198 @@ /* $KAME: rip6query.c,v 1.11 2001/05/08 04:36:37 itojun Exp $ */ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the project nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "route6d.h" static int s; static struct sockaddr_in6 sin6; static struct rip6 *ripbuf; #define RIPSIZE(n) (sizeof(struct rip6) + (n-1) * sizeof(struct netinfo6)) int main(int, char **); -static void usage(void); +static void usage(void) __dead2; static const char *sa_n2a(struct sockaddr *); static const char *inet6_n2a(struct in6_addr *); int main(int argc, char *argv[]) { struct netinfo6 *np; struct sockaddr_in6 fsock; int i, n, len; int c; int ifidx = -1; int error; socklen_t flen; char pbuf[10]; struct addrinfo hints, *res; while ((c = getopt(argc, argv, "I:")) != -1) { switch (c) { case 'I': ifidx = if_nametoindex(optarg); if (ifidx == 0) { errx(1, "invalid interface %s", optarg); /*NOTREACHED*/ } break; default: usage(); - exit(1); /*NOTREACHED*/ } } argv += optind; argc -= optind; if (argc != 1) { usage(); - exit(1); } if ((s = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { err(1, "socket"); /*NOTREACHED*/ } /* getaddrinfo is preferred for addr@ifname syntax */ snprintf(pbuf, sizeof(pbuf), "%d", RIP6_PORT); memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_INET6; hints.ai_socktype = SOCK_DGRAM; error = getaddrinfo(argv[0], pbuf, &hints, &res); if (error) { errx(1, "%s: %s", argv[0], gai_strerror(error)); /*NOTREACHED*/ } if (res->ai_next) { errx(1, "%s: %s", argv[0], "resolved to multiple addrs"); /*NOTREACHED*/ } if (sizeof(sin6) != res->ai_addrlen) { errx(1, "%s: %s", argv[0], "invalid addrlen"); /*NOTREACHED*/ } memcpy(&sin6, res->ai_addr, res->ai_addrlen); if (ifidx >= 0) sin6.sin6_scope_id = ifidx; if ((ripbuf = (struct rip6 *)malloc(BUFSIZ)) == NULL) { err(1, "malloc"); /*NOTREACHED*/ } ripbuf->rip6_cmd = RIP6_REQUEST; ripbuf->rip6_vers = RIP6_VERSION; ripbuf->rip6_res1[0] = 0; ripbuf->rip6_res1[1] = 0; np = ripbuf->rip6_nets; bzero(&np->rip6_dest, sizeof(struct in6_addr)); np->rip6_tag = 0; np->rip6_plen = 0; np->rip6_metric = HOPCNT_INFINITY6; if (sendto(s, ripbuf, RIPSIZE(1), 0, (struct sockaddr *)&sin6, sizeof(struct sockaddr_in6)) < 0) { err(1, "send"); /*NOTREACHED*/ } do { flen = sizeof(fsock); if ((len = recvfrom(s, ripbuf, BUFSIZ, 0, (struct sockaddr *)&fsock, &flen)) < 0) { err(1, "recvfrom"); /*NOTREACHED*/ } printf("Response from %s len %d\n", sa_n2a((struct sockaddr *)&fsock), len); n = (len - sizeof(struct rip6) + sizeof(struct netinfo6)) / sizeof(struct netinfo6); np = ripbuf->rip6_nets; for (i = 0; i < n; i++, np++) { printf("\t%s/%d [%d]", inet6_n2a(&np->rip6_dest), np->rip6_plen, np->rip6_metric); if (np->rip6_tag) printf(" tag=0x%x", ntohs(np->rip6_tag)); printf("\n"); } } while (len == RIPSIZE(24)); - exit(0); + return 0; } static void usage(void) { fprintf(stderr, "usage: rip6query [-I iface] address\n"); + exit(1); } /* getnameinfo() is preferred as we may be able to show ifindex as ifname */ static const char * sa_n2a(struct sockaddr *sa) { static char buf[NI_MAXHOST]; if (getnameinfo(sa, sa->sa_len, buf, sizeof(buf), NULL, 0, NI_NUMERICHOST) != 0) { snprintf(buf, sizeof(buf), "%s", "(invalid)"); } return buf; } static const char * inet6_n2a(struct in6_addr *addr) { static char buf[NI_MAXHOST]; return inet_ntop(AF_INET6, addr, buf, sizeof(buf)); } diff --git a/usr.sbin/rtprio/rtprio.c b/usr.sbin/rtprio/rtprio.c index 9ce74b5547ad..f8da2cc96290 100644 --- a/usr.sbin/rtprio/rtprio.c +++ b/usr.sbin/rtprio/rtprio.c @@ -1,155 +1,155 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 1994 David Greenman * Copyright (c) 1994 Henrik Vestergaard Draboel (hvd@terry.ping.dk) * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Henrik Vestergaard Draboel. * This product includes software developed by David Greenman. * 4. Neither the names of the authors nor the names of contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include static int parseint(const char *, const char *); -static void usage(void); +static void usage(void) __dead2; int main(int argc, char *argv[]) { struct rtprio rtp; const char *progname; pid_t proc = 0; progname = getprogname(); if (strcmp(progname, "rtprio") == 0) rtp.type = RTP_PRIO_REALTIME; else if (strcmp(progname, "idprio") == 0) rtp.type = RTP_PRIO_IDLE; else errx(1, "invalid progname"); switch (argc) { case 2: proc = parseint(argv[1], "pid"); proc = abs(proc); /* FALLTHROUGH */ case 1: if (rtprio(RTP_LOOKUP, proc, &rtp) != 0) err(1, "RTP_LOOKUP"); switch (rtp.type) { case RTP_PRIO_REALTIME: case RTP_PRIO_FIFO: warnx("realtime priority %d", rtp.prio); break; case RTP_PRIO_NORMAL: warnx("normal priority"); break; case RTP_PRIO_IDLE: warnx("idle priority %d", rtp.prio); break; default: errx(1, "invalid priority type %d", rtp.type); break; } exit(0); default: if (argv[1][0] == '-' || isdigit(argv[1][0])) { if (argv[1][0] == '-') { if (strcmp(argv[1], "-t") == 0) { rtp.type = RTP_PRIO_NORMAL; rtp.prio = 0; } else { usage(); break; } } else rtp.prio = parseint(argv[1], "priority"); } else { usage(); break; } if (argv[2][0] == '-') { proc = parseint(argv[2], "pid"); proc = abs(proc); } if (rtprio(RTP_SET, proc, &rtp) != 0) err(1, "RTP_SET"); if (proc == 0) { execvp(argv[2], &argv[2]); err(1, "execvp: %s", argv[2]); } exit(0); } /* NOTREACHED */ } static int parseint(const char *str, const char *errname) { char *endp; long res; errno = 0; res = strtol(str, &endp, 10); if (errno != 0 || endp == str || *endp != '\0') errx(1, "%s must be a number", errname); if (res >= INT_MAX) errx(1, "Integer overflow parsing %s", errname); return (res); } static void usage(void) { (void) fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n", "usage: [id|rt]prio", " [id|rt]prio [-]pid", " [id|rt]prio priority command [args]", " [id|rt]prio priority -pid", " [id|rt]prio -t command [args]", " [id|rt]prio -t -pid"); exit(1); } diff --git a/usr.sbin/rwhod/rwhod.c b/usr.sbin/rwhod/rwhod.c index 23c307e33829..1b2b2b153a0f 100644 --- a/usr.sbin/rwhod/rwhod.c +++ b/usr.sbin/rwhod/rwhod.c @@ -1,784 +1,784 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1993 The Regents of the University of California. * Copyright (c) 2013 Mariusz Zaborski * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #if 0 #ifndef lint static char sccsid[] = "@(#)rwhod.c 8.1 (Berkeley) 6/6/93"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define UNPRIV_USER "daemon" #define UNPRIV_GROUP "daemon" #define NO_MULTICAST 0 /* multicast modes */ #define PER_INTERFACE_MULTICAST 1 #define SCOPED_MULTICAST 2 #define MAX_MULTICAST_SCOPE 32 /* "site-wide", by convention */ #define INADDR_WHOD_GROUP (u_long)0xe0000103 /* 224.0.1.3 */ /* (belongs in protocols/rwhod.h) */ int insecure_mode; int quiet_mode; int iff_flag = IFF_POINTOPOINT; int multicast_mode = NO_MULTICAST; int multicast_scope; struct sockaddr_in multicast_addr = { sizeof(multicast_addr), AF_INET, 0, { 0 }, { 0 } }; /* * Sleep interval. Don't forget to change the down time check in ruptime * if this is changed. */ #define SL_INTERVAL (3 * 60) char myname[MAXHOSTNAMELEN]; /* * We communicate with each neighbor in a list constructed at the time we're * started up. Neighbors are currently directly connected via a hardware * interface. */ struct neighbor { struct neighbor *n_next; char *n_name; /* interface name */ struct sockaddr *n_addr; /* who to send to */ int n_addrlen; /* size of address */ int n_flags; /* should forward?, interface flags */ }; struct neighbor *neighbors; struct whod mywd; struct servent *sp; int s; int fdp; pid_t pid_child_receiver; #define WHDRSIZE (int)(sizeof(mywd) - sizeof(mywd.wd_we)) int configure(int so); void getboottime(int signo __unused); void receiver_process(void); void rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo); void run_as(uid_t *uid, gid_t *gid); void quit(const char *msg); void sender_process(void); int verify(char *name, int maxlen); -static void usage(void); +static void usage(void) __dead2; #ifdef DEBUG char *interval(int time, char *updown); void Sendto(int s, const void *buf, size_t cc, int flags, const struct sockaddr *to, int tolen); #define sendto Sendto #endif /* * This version of Berkeley's rwhod has been modified to use IP multicast * datagrams, under control of a new command-line option: * * rwhod -m causes rwhod to use IP multicast (instead of * broadcast or unicast) on all interfaces that have * the IFF_MULTICAST flag set in their "ifnet" structs * (excluding the loopback interface). The multicast * reports are sent with a time-to-live of 1, to prevent * forwarding beyond the directly-connected subnet(s). * * rwhod -m causes rwhod to send IP multicast datagrams with a * time-to-live of , via a SINGLE interface rather * than all interfaces. must be between 0 and * MAX_MULTICAST_SCOPE, defined below. Note that "-m 1" * is different than "-m", in that "-m 1" specifies * transmission on one interface only. * * When "-m" is used without a argument, the program accepts multicast * rwhod reports from all multicast-capable interfaces. If a argument * is given, it accepts multicast reports from only one interface, the one * on which reports are sent (which may be controlled via the host's routing * table). Regardless of the "-m" option, the program accepts broadcast or * unicast reports from all interfaces. Thus, this program will hear the * reports of old, non-multicasting rwhods, but, if multicasting is used, * those old rwhods won't hear the reports generated by this program. * * -- Steve Deering, Stanford University, February 1989 */ int main(int argc, char *argv[]) { int on; char *cp; struct sockaddr_in soin; uid_t unpriv_uid; gid_t unpriv_gid; on = 1; if (getuid()) errx(1, "not super user"); run_as(&unpriv_uid, &unpriv_gid); argv++; argc--; while (argc > 0 && *argv[0] == '-') { if (strcmp(*argv, "-m") == 0) { if (argc > 1 && isdigit(*(argv + 1)[0])) { argv++; argc--; multicast_mode = SCOPED_MULTICAST; multicast_scope = atoi(*argv); if (multicast_scope > MAX_MULTICAST_SCOPE) { errx(1, "ttl must not exceed %u", MAX_MULTICAST_SCOPE); } } else { multicast_mode = PER_INTERFACE_MULTICAST; } } else if (strcmp(*argv, "-i") == 0) { insecure_mode = 1; } else if (strcmp(*argv, "-l") == 0) { quiet_mode = 1; } else if (strcmp(*argv, "-p") == 0) { iff_flag = 0; } else { usage(); } argv++; argc--; } if (argc > 0) usage(); #ifndef DEBUG daemon(1, 0); #endif (void) signal(SIGHUP, getboottime); openlog("rwhod", LOG_PID | LOG_NDELAY, LOG_DAEMON); sp = getservbyname("who", "udp"); if (sp == NULL) { syslog(LOG_ERR, "who/udp: unknown service"); exit(1); } if (chdir(_PATH_RWHODIR) < 0) { syslog(LOG_ERR, "%s: %m", _PATH_RWHODIR); exit(1); } /* * Establish host name as returned by system. */ if (gethostname(myname, sizeof(myname) - 1) < 0) { syslog(LOG_ERR, "gethostname: %m"); exit(1); } if ((cp = strchr(myname, '.')) != NULL) *cp = '\0'; strlcpy(mywd.wd_hostname, myname, sizeof(mywd.wd_hostname)); getboottime(0); if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { syslog(LOG_ERR, "socket: %m"); exit(1); } if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) { syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m"); exit(1); } memset(&soin, 0, sizeof(soin)); soin.sin_len = sizeof(soin); soin.sin_family = AF_INET; soin.sin_port = sp->s_port; if (bind(s, (struct sockaddr *)&soin, sizeof(soin)) < 0) { syslog(LOG_ERR, "bind: %m"); exit(1); } if (setgid(unpriv_gid) != 0) { syslog(LOG_ERR, "setgid: %m"); exit(1); } if (setgroups(1, &unpriv_gid) != 0) { /* XXX BOGUS groups[0] = egid */ syslog(LOG_ERR, "setgroups: %m"); exit(1); } if (setuid(unpriv_uid) != 0) { syslog(LOG_ERR, "setuid: %m"); exit(1); } if (!configure(s)) exit(1); if (!quiet_mode) { pid_child_receiver = pdfork(&fdp, 0); if (pid_child_receiver == 0) { receiver_process(); } else if (pid_child_receiver > 0) { sender_process(); } else if (pid_child_receiver == -1) { if (errno == ENOSYS) { syslog(LOG_ERR, "The pdfork(2) system call is not available - kernel too old."); } else { syslog(LOG_ERR, "pdfork: %m"); } exit(1); } } else { receiver_process(); } } static void usage(void) { fprintf(stderr, "usage: rwhod [-i] [-p] [-l] [-m [ttl]]\n"); exit(1); } void run_as(uid_t *uid, gid_t *gid) { struct passwd *pw; struct group *gr; pw = getpwnam(UNPRIV_USER); if (pw == NULL) { syslog(LOG_ERR, "getpwnam(%s): %m", UNPRIV_USER); exit(1); } *uid = pw->pw_uid; gr = getgrnam(UNPRIV_GROUP); if (gr == NULL) { syslog(LOG_ERR, "getgrnam(%s): %m", UNPRIV_GROUP); exit(1); } *gid = gr->gr_gid; } /* * Check out host name for unprintables * and other funnies before allowing a file * to be created. Sorry, but blanks aren't allowed. */ int verify(char *name, int maxlen) { int size; size = 0; while (*name != '\0' && size < maxlen - 1) { if (!isascii((unsigned char)*name) || !(isalnum((unsigned char)*name) || ispunct((unsigned char)*name))) { return (0); } name++; size++; } *name = '\0'; return (size > 0); } void receiver_process(void) { struct sockaddr_in from; struct stat st; cap_rights_t rights; char path[64]; int dirfd; struct whod wd; socklen_t len; int cc, whod; time_t t; len = sizeof(from); dirfd = open(".", O_RDONLY | O_DIRECTORY); if (dirfd < 0) { syslog(LOG_WARNING, "%s: %m", _PATH_RWHODIR); exit(1); } cap_rights_init(&rights, CAP_CREATE, CAP_FSTAT, CAP_FTRUNCATE, CAP_LOOKUP, CAP_SEEK, CAP_WRITE); if (caph_rights_limit(dirfd, &rights) < 0) { syslog(LOG_WARNING, "cap_rights_limit: %m"); exit(1); } if (caph_enter() < 0) { syslog(LOG_ERR, "cap_enter: %m"); exit(1); } for (;;) { cc = recvfrom(s, &wd, sizeof(wd), 0, (struct sockaddr *)&from, &len); if (cc <= 0) { if (cc < 0 && errno != EINTR) syslog(LOG_WARNING, "recv: %m"); continue; } if (from.sin_port != sp->s_port && !insecure_mode) { syslog(LOG_WARNING, "%d: bad source port from %s", ntohs(from.sin_port), inet_ntoa(from.sin_addr)); continue; } if (cc < WHDRSIZE) { syslog(LOG_WARNING, "short packet from %s", inet_ntoa(from.sin_addr)); continue; } if (wd.wd_vers != WHODVERSION) continue; if (wd.wd_type != WHODTYPE_STATUS) continue; if (!verify(wd.wd_hostname, sizeof(wd.wd_hostname))) { syslog(LOG_WARNING, "malformed host name from %s", inet_ntoa(from.sin_addr)); continue; } (void) snprintf(path, sizeof(path), "whod.%s", wd.wd_hostname); /* * Rather than truncating and growing the file each time, * use ftruncate if size is less than previous size. */ whod = openat(dirfd, path, O_WRONLY | O_CREAT, 0644); if (whod < 0) { syslog(LOG_WARNING, "%s: %m", path); continue; } cap_rights_init(&rights, CAP_FSTAT, CAP_FTRUNCATE, CAP_WRITE); if (caph_rights_limit(whod, &rights) < 0) { syslog(LOG_WARNING, "cap_rights_limit: %m"); exit(1); } #if ENDIAN != BIG_ENDIAN { struct whoent *we; int i, n; n = (cc - WHDRSIZE) / sizeof(struct whoent); /* undo header byte swapping before writing to file */ wd.wd_sendtime = ntohl(wd.wd_sendtime); for (i = 0; i < 3; i++) wd.wd_loadav[i] = ntohl(wd.wd_loadav[i]); wd.wd_boottime = ntohl(wd.wd_boottime); we = wd.wd_we; for (i = 0; i < n; i++) { we->we_idle = ntohl(we->we_idle); we->we_utmp.out_time = ntohl(we->we_utmp.out_time); we++; } } #endif (void) time(&t); wd.wd_recvtime = _time_to_int(t); (void) write(whod, (char *)&wd, cc); if (fstat(whod, &st) < 0 || st.st_size > cc) ftruncate(whod, cc); (void) close(whod); } (void) close(dirfd); } void sender_process(void) { int sendcount; double avenrun[3]; time_t now; int i, cc, status; struct utmpx *ut; struct stat stb; struct neighbor *np; struct whoent *we, *wend; sendcount = 0; for (;;) { we = mywd.wd_we; now = time(NULL); if (sendcount % 10 == 0) getboottime(0); sendcount++; wend = &mywd.wd_we[1024 / sizeof(struct whoent)]; setutxent(); while ((ut = getutxent()) != NULL && we < wend) { if (ut->ut_type != USER_PROCESS) continue; strncpy(we->we_utmp.out_line, ut->ut_line, sizeof(we->we_utmp.out_line)); strncpy(we->we_utmp.out_name, ut->ut_user, sizeof(we->we_utmp.out_name)); we->we_utmp.out_time = htonl(_time_to_time32(ut->ut_tv.tv_sec)); we++; } endutxent(); if (chdir(_PATH_DEV) < 0) { syslog(LOG_ERR, "chdir(%s): %m", _PATH_DEV); exit(1); } wend = we; for (we = mywd.wd_we; we < wend; we++) { if (stat(we->we_utmp.out_line, &stb) >= 0) we->we_idle = htonl(now - stb.st_atime); } (void) getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])); for (i = 0; i < 3; i++) mywd.wd_loadav[i] = htonl((u_long)(avenrun[i] * 100)); cc = (char *)wend - (char *)&mywd; mywd.wd_sendtime = htonl(_time_to_time32(time(NULL))); mywd.wd_vers = WHODVERSION; mywd.wd_type = WHODTYPE_STATUS; if (multicast_mode == SCOPED_MULTICAST) { (void) sendto(s, (char *)&mywd, cc, 0, (struct sockaddr *)&multicast_addr, sizeof(multicast_addr)); } else { for (np = neighbors; np != NULL; np = np->n_next) { if (multicast_mode == PER_INTERFACE_MULTICAST && (np->n_flags & IFF_MULTICAST) != 0) { /* * Select the outgoing interface for the * multicast. */ if (setsockopt(s, IPPROTO_IP, IP_MULTICAST_IF, &(((struct sockaddr_in *)np->n_addr)->sin_addr), sizeof(struct in_addr)) < 0) { syslog(LOG_ERR, "setsockopt IP_MULTICAST_IF: %m"); exit(1); } (void) sendto(s, (char *)&mywd, cc, 0, (struct sockaddr *)&multicast_addr, sizeof(multicast_addr)); } else { (void) sendto(s, (char *)&mywd, cc, 0, np->n_addr, np->n_addrlen); } } } if (chdir(_PATH_RWHODIR) < 0) { syslog(LOG_ERR, "chdir(%s): %m", _PATH_RWHODIR); exit(1); } if (waitpid(pid_child_receiver, &status, WNOHANG) == pid_child_receiver) { break; } sleep(SL_INTERVAL); } } void getboottime(int signo __unused) { int mib[2]; size_t size; struct timeval tm; mib[0] = CTL_KERN; mib[1] = KERN_BOOTTIME; size = sizeof(tm); if (sysctl(mib, nitems(mib), &tm, &size, NULL, 0) == -1) { syslog(LOG_ERR, "cannot get boottime: %m"); exit(1); } mywd.wd_boottime = htonl(_time_to_time32(tm.tv_sec)); } void quit(const char *msg) { syslog(LOG_ERR, "%s", msg); exit(1); } void rt_xaddrs(caddr_t cp, caddr_t cplim, struct rt_addrinfo *rtinfo) { struct sockaddr *sa; int i; memset(rtinfo->rti_info, 0, sizeof(rtinfo->rti_info)); for (i = 0; i < RTAX_MAX && cp < cplim; i++) { if ((rtinfo->rti_addrs & (1 << i)) == 0) continue; sa = (struct sockaddr *)cp; rtinfo->rti_info[i] = sa; cp += SA_SIZE(sa); } } /* * Figure out device configuration and select * networks which deserve status information. */ int configure(int so) { struct neighbor *np; struct if_msghdr *ifm; struct ifa_msghdr *ifam; struct sockaddr_dl *sdl; size_t needed; int mib[6], flags, lflags, len; char *buf, *lim, *next; struct rt_addrinfo info; flags = 0; if (multicast_mode != NO_MULTICAST) { multicast_addr.sin_addr.s_addr = htonl(INADDR_WHOD_GROUP); multicast_addr.sin_port = sp->s_port; } if (multicast_mode == SCOPED_MULTICAST) { struct ip_mreq mreq; unsigned char ttl; mreq.imr_multiaddr.s_addr = htonl(INADDR_WHOD_GROUP); mreq.imr_interface.s_addr = htonl(INADDR_ANY); if (setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { syslog(LOG_ERR, "setsockopt IP_ADD_MEMBERSHIP: %m"); return (0); } ttl = multicast_scope; if (setsockopt(so, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) { syslog(LOG_ERR, "setsockopt IP_MULTICAST_TTL: %m"); return (0); } return (1); } mib[0] = CTL_NET; mib[1] = PF_ROUTE; mib[2] = 0; mib[3] = AF_INET; mib[4] = NET_RT_IFLIST; mib[5] = 0; if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0) quit("route-sysctl-estimate"); if ((buf = malloc(needed)) == NULL) quit("malloc"); if (sysctl(mib, nitems(mib), buf, &needed, NULL, 0) < 0) quit("actual retrieval of interface table"); lim = buf + needed; sdl = NULL; /* XXX just to keep gcc -Wall happy */ for (next = buf; next < lim; next += ifm->ifm_msglen) { ifm = (struct if_msghdr *)next; if (ifm->ifm_type == RTM_IFINFO) { sdl = (struct sockaddr_dl *)(ifm + 1); flags = ifm->ifm_flags; continue; } if ((flags & IFF_UP) == 0) continue; lflags = IFF_BROADCAST | iff_flag; if (multicast_mode == PER_INTERFACE_MULTICAST) lflags |= IFF_MULTICAST; if ((flags & lflags) == 0) continue; if (ifm->ifm_type != RTM_NEWADDR) quit("out of sync parsing NET_RT_IFLIST"); ifam = (struct ifa_msghdr *)ifm; info.rti_addrs = ifam->ifam_addrs; rt_xaddrs((char *)(ifam + 1), ifam->ifam_msglen + (char *)ifam, &info); /* gag, wish we could get rid of Internet dependencies */ #define dstaddr info.rti_info[RTAX_BRD] #define ifaddr info.rti_info[RTAX_IFA] #define IPADDR_SA(x) ((struct sockaddr_in *)(x))->sin_addr.s_addr #define PORT_SA(x) ((struct sockaddr_in *)(x))->sin_port if (dstaddr == 0 || dstaddr->sa_family != AF_INET) continue; PORT_SA(dstaddr) = sp->s_port; for (np = neighbors; np != NULL; np = np->n_next) { if (memcmp(sdl->sdl_data, np->n_name, sdl->sdl_nlen) == 0 && IPADDR_SA(np->n_addr) == IPADDR_SA(dstaddr)) { break; } } if (np != NULL) continue; len = sizeof(*np) + dstaddr->sa_len + sdl->sdl_nlen + 1; np = malloc(len); if (np == NULL) quit("malloc of neighbor structure"); memset(np, 0, len); np->n_flags = flags; np->n_addr = (struct sockaddr *)(np + 1); np->n_addrlen = dstaddr->sa_len; np->n_name = np->n_addrlen + (char *)np->n_addr; memcpy((char *)np->n_addr, (char *)dstaddr, np->n_addrlen); memcpy(np->n_name, sdl->sdl_data, sdl->sdl_nlen); if (multicast_mode == PER_INTERFACE_MULTICAST && (flags & IFF_MULTICAST) != 0 && (flags & IFF_LOOPBACK) == 0) { struct ip_mreq mreq; memcpy((char *)np->n_addr, (char *)ifaddr, np->n_addrlen); mreq.imr_multiaddr.s_addr = htonl(INADDR_WHOD_GROUP); mreq.imr_interface.s_addr = ((struct sockaddr_in *)np->n_addr)->sin_addr.s_addr; if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { syslog(LOG_ERR, "setsockopt IP_ADD_MEMBERSHIP: %m"); #if 0 /* Fall back to broadcast on this if. */ np->n_flags &= ~IFF_MULTICAST; #else free(np); continue; #endif } } np->n_next = neighbors; neighbors = np; } free(buf); return (1); } #ifdef DEBUG void Sendto(int s, const void *buf, size_t cc, int flags, const struct sockaddr *to, int tolen) { struct whod *w; struct whoent *we; struct sockaddr_in *sin; w = (struct whod *)buf; sin = (struct sockaddr_in *)to; printf("sendto %x.%d\n", ntohl(sin->sin_addr.s_addr), ntohs(sin->sin_port)); printf("hostname %s %s\n", w->wd_hostname, interval(ntohl(w->wd_sendtime) - ntohl(w->wd_boottime), " up")); printf("load %4.2f, %4.2f, %4.2f\n", ntohl(w->wd_loadav[0]) / 100.0, ntohl(w->wd_loadav[1]) / 100.0, ntohl(w->wd_loadav[2]) / 100.0); cc -= WHDRSIZE; for (we = w->wd_we, cc /= sizeof(struct whoent); cc > 0; cc--, we++) { time_t t = _time32_to_time(ntohl(we->we_utmp.out_time)); printf("%-8.8s %s:%s %.12s", we->we_utmp.out_name, w->wd_hostname, we->we_utmp.out_line, ctime(&t) + 4); we->we_idle = ntohl(we->we_idle) / 60; if (we->we_idle != 0) { if (we->we_idle >= 100 * 60) we->we_idle = 100 * 60 - 1; if (we->we_idle >= 60) printf(" %2d", we->we_idle / 60); else printf(" "); printf(":%02d", we->we_idle % 60); } printf("\n"); } } char * interval(int time, char *updown) { static char resbuf[32]; int days, hours, minutes; if (time < 0 || time > 3 * 30 * 24 * 60 * 60) { (void) sprintf(resbuf, " %s ??:??", updown); return (resbuf); } minutes = (time + 59) / 60; /* round to minutes */ hours = minutes / 60; minutes %= 60; days = hours / 24; hours %= 24; if (days > 0) { (void) sprintf(resbuf, "%s %2d+%02d:%02d", updown, days, hours, minutes); } else { (void) sprintf(resbuf, "%s %2d:%02d", updown, hours, minutes); } return (resbuf); } #endif diff --git a/usr.sbin/setfib/setfib.c b/usr.sbin/setfib/setfib.c index 0783a07f4597..1c8adbc988da 100644 --- a/usr.sbin/setfib/setfib.c +++ b/usr.sbin/setfib/setfib.c @@ -1,107 +1,107 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1989, 1993, 1994 * The Regents of the University of California. All rights reserved. * Copyright (c) 2008 Cisco Systems, All rights reserved * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * setfib file skelaton taken from nice.c */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include -static void usage(void); +static void usage(void) __dead2; int main(int argc, char *argv[]) { long fib = 0; int ch; char *ep; int numfibs; size_t intsize = sizeof(int); if (sysctlbyname("net.fibs", &numfibs, &intsize, NULL, 0) == -1) errx(1, "Multiple FIBS not supported"); if (argc < 2) usage(); ep = argv[1]; /* * convert -N or N to -FN. (N is a number) */ if (ep[0]== '-' && isdigit((unsigned char)ep[1])) ep++; if (isdigit((unsigned char)*ep)) if (asprintf(&argv[1], "-F%s", ep) < 0) err(1, "asprintf"); while ((ch = getopt(argc, argv, "F:")) != -1) { switch (ch) { case 'F': errno = 0; fib = strtol(optarg, &ep, 10); if (ep == optarg || *ep != '\0' || errno || fib < 0 || fib >= numfibs) errx(1, "%s: invalid FIB (max %d)", optarg, numfibs - 1); break; default: usage(); } } argc -= optind; argv += optind; if (argc == 0) usage(); errno = 0; if (setfib((int)fib)) warn("setfib"); execvp(*argv, argv); err(errno == ENOENT ? 127 : 126, "%s", *argv); } static void usage(void) { (void)fprintf(stderr, "usage: setfib [-[F]]value command\n"); exit(1); } diff --git a/usr.sbin/spray/spray.c b/usr.sbin/spray/spray.c index d8d25ef8a33c..18caf3ff3bd9 100644 --- a/usr.sbin/spray/spray.c +++ b/usr.sbin/spray/spray.c @@ -1,222 +1,222 @@ /*- * SPDX-License-Identifier: BSD-4-Clause * * Copyright (c) 1993 Winning Strategies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Winning Strategies, Inc. * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef lint static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ #include #include #include #include #include #include #ifndef SPRAYOVERHEAD #define SPRAYOVERHEAD 86 #endif -static void usage(void); +static void usage(void) __dead2; static void print_xferstats(unsigned int, int, double); /* spray buffer */ static char spray_buffer[SPRAYMAX]; /* RPC timeouts */ static struct timeval NO_DEFAULT = { -1, -1 }; static struct timeval ONE_WAY = { 0, 0 }; static struct timeval TIMEOUT = { 25, 0 }; int main(int argc, char *argv[]) { spraycumul host_stats; sprayarr host_array; CLIENT *cl; int c; u_int i; u_int count = 0; int delay = 0; int length = 0; double xmit_time; /* time to receive data */ while ((c = getopt(argc, argv, "c:d:l:")) != -1) { switch (c) { case 'c': count = atoi(optarg); break; case 'd': delay = atoi(optarg); break; case 'l': length = atoi(optarg); break; default: usage(); /* NOTREACHED */ } } argc -= optind; argv += optind; if (argc != 1) { usage(); /* NOTREACHED */ } /* Correct packet length. */ if (length > SPRAYMAX) { length = SPRAYMAX; } else if (length < SPRAYOVERHEAD) { length = SPRAYOVERHEAD; } else { /* The RPC portion of the packet is a multiple of 32 bits. */ length -= SPRAYOVERHEAD - 3; length &= ~3; length += SPRAYOVERHEAD; } /* * The default value of count is the number of packets required * to make the total stream size 100000 bytes. */ if (!count) { count = 100000 / length; } /* Initialize spray argument */ host_array.sprayarr_len = length - SPRAYOVERHEAD; host_array.sprayarr_val = spray_buffer; /* create connection with server */ cl = clnt_create(*argv, SPRAYPROG, SPRAYVERS, "udp"); if (cl == NULL) errx(1, "%s", clnt_spcreateerror("")); /* * For some strange reason, RPC 4.0 sets the default timeout, * thus timeouts specified in clnt_call() are always ignored. * * The following (undocumented) hack resets the internal state * of the client handle. */ clnt_control(cl, CLSET_TIMEOUT, &NO_DEFAULT); /* Clear server statistics */ if (clnt_call(cl, SPRAYPROC_CLEAR, (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) errx(1, "%s", clnt_sperror(cl, "")); /* Spray server with packets */ printf ("sending %u packets of length %d to %s ...", count, length, *argv); fflush (stdout); for (i = 0; i < count; i++) { clnt_call(cl, SPRAYPROC_SPRAY, (xdrproc_t)xdr_sprayarr, &host_array, (xdrproc_t)xdr_void, NULL, ONE_WAY); if (delay) { usleep(delay); } } /* Collect statistics from server */ if (clnt_call(cl, SPRAYPROC_GET, (xdrproc_t)xdr_void, NULL, (xdrproc_t)xdr_spraycumul, &host_stats, TIMEOUT) != RPC_SUCCESS) errx(1, "%s", clnt_sperror(cl, "")); xmit_time = host_stats.clock.sec + (host_stats.clock.usec / 1000000.0); printf ("\n\tin %.2f seconds elapsed time\n", xmit_time); /* report dropped packets */ if (host_stats.counter != count) { int packets_dropped = count - host_stats.counter; printf("\t%d packets (%.2f%%) dropped\n", packets_dropped, 100.0 * packets_dropped / count ); } else { printf("\tno packets dropped\n"); } printf("Sent:"); print_xferstats(count, length, xmit_time); printf("Rcvd:"); print_xferstats(host_stats.counter, length, xmit_time); exit (0); } static void print_xferstats(u_int packets, int packetlen, double xfertime) { int datalen; double pps; /* packets per second */ double bps; /* bytes per second */ datalen = packets * packetlen; pps = packets / xfertime; bps = datalen / xfertime; printf("\t%.0f packets/sec, ", pps); if (bps >= 1024) printf ("%.1fK ", bps / 1024); else printf ("%.0f ", bps); printf("bytes/sec\n"); } static void usage(void) { fprintf(stderr, "usage: spray [-c count] [-l length] [-d delay] host\n"); exit(1); } diff --git a/usr.sbin/tcpdrop/tcpdrop.c b/usr.sbin/tcpdrop/tcpdrop.c index 135f1b52c403..018ef8456e6a 100644 --- a/usr.sbin/tcpdrop/tcpdrop.c +++ b/usr.sbin/tcpdrop/tcpdrop.c @@ -1,401 +1,401 @@ /* $OpenBSD: tcpdrop.c,v 1.4 2004/05/22 23:55:22 deraadt Exp $ */ /*- * Copyright (c) 2009 Juli Mallett * Copyright (c) 2004 Markus Friedl * * 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. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #define TCPSTATES #include #include #include #include #include #include #include #include #include #define TCPDROP_FOREIGN 0 #define TCPDROP_LOCAL 1 struct host_service { char hs_host[NI_MAXHOST]; char hs_service[NI_MAXSERV]; }; static bool tcpdrop_list_commands = false; static char *findport(const char *); static struct xinpgen *getxpcblist(const char *); static void sockinfo(const struct sockaddr *, struct host_service *); static bool tcpdrop(const struct sockaddr *, const struct sockaddr *); static bool tcpdropall(const char *, const char *, int); static bool tcpdropbyname(const char *, const char *, const char *, const char *); static bool tcpdropconn(const struct in_conninfo *); -static void usage(void); +static void usage(void) __dead2; /* * Drop a tcp connection. */ int main(int argc, char *argv[]) { char stack[TCP_FUNCTION_NAME_LEN_MAX]; char ca_name[TCP_CA_NAME_MAX]; char *lport, *fport; bool dropall, dropspecific; int ch, state; dropall = false; dropspecific = false; ca_name[0] = '\0'; stack[0] = '\0'; state = -1; while ((ch = getopt(argc, argv, "aC:lS:s:")) != -1) { switch (ch) { case 'a': dropall = true; break; case 'C': dropspecific = true; strlcpy(ca_name, optarg, sizeof(ca_name)); break; case 'l': tcpdrop_list_commands = true; break; case 'S': dropspecific = true; strlcpy(stack, optarg, sizeof(stack)); break; case 's': dropspecific = true; for (state = 0; state < TCP_NSTATES; state++) { if (strcmp(tcpstates[state], optarg) == 0) break; } break; default: usage(); } } argc -= optind; argv += optind; if (state == TCP_NSTATES || state == TCPS_CLOSED || state == TCPS_LISTEN) usage(); if (dropall && dropspecific) usage(); if (dropall || dropspecific) { if (argc != 0) usage(); if (!tcpdropall(ca_name, stack, state)) exit(1); exit(0); } if ((argc != 2 && argc != 4) || tcpdrop_list_commands) usage(); if (argc == 2) { lport = findport(argv[0]); fport = findport(argv[1]); if (lport == NULL || lport[1] == '\0' || fport == NULL || fport[1] == '\0') usage(); *lport++ = '\0'; *fport++ = '\0'; if (!tcpdropbyname(argv[0], lport, argv[1], fport)) exit(1); } else if (!tcpdropbyname(argv[0], argv[1], argv[2], argv[3])) exit(1); exit(0); } static char * findport(const char *arg) { char *dot, *colon; /* A strrspn() or strrpbrk() would be nice. */ dot = strrchr(arg, '.'); colon = strrchr(arg, ':'); if (dot == NULL) return (colon); if (colon == NULL) return (dot); if (dot < colon) return (colon); else return (dot); } static struct xinpgen * getxpcblist(const char *name) { struct xinpgen *xinp; size_t len; int rv; len = 0; rv = sysctlbyname(name, NULL, &len, NULL, 0); if (rv == -1) err(1, "sysctlbyname %s", name); if (len == 0) errx(1, "%s is empty", name); xinp = malloc(len); if (xinp == NULL) errx(1, "malloc failed"); rv = sysctlbyname(name, xinp, &len, NULL, 0); if (rv == -1) err(1, "sysctlbyname %s", name); return (xinp); } static void sockinfo(const struct sockaddr *sa, struct host_service *hs) { static const int flags = NI_NUMERICHOST | NI_NUMERICSERV; int rv; rv = getnameinfo(sa, sa->sa_len, hs->hs_host, sizeof hs->hs_host, hs->hs_service, sizeof hs->hs_service, flags); if (rv == -1) err(1, "getnameinfo"); } static bool tcpdrop(const struct sockaddr *lsa, const struct sockaddr *fsa) { struct host_service local, foreign; struct sockaddr_storage addrs[2]; int rv; memcpy(&addrs[TCPDROP_FOREIGN], fsa, fsa->sa_len); memcpy(&addrs[TCPDROP_LOCAL], lsa, lsa->sa_len); sockinfo(lsa, &local); sockinfo(fsa, &foreign); if (tcpdrop_list_commands) { printf("tcpdrop %s %s %s %s\n", local.hs_host, local.hs_service, foreign.hs_host, foreign.hs_service); return (true); } rv = sysctlbyname("net.inet.tcp.drop", NULL, NULL, &addrs, sizeof addrs); if (rv == -1) { warn("%s %s %s %s", local.hs_host, local.hs_service, foreign.hs_host, foreign.hs_service); return (false); } printf("%s %s %s %s: dropped\n", local.hs_host, local.hs_service, foreign.hs_host, foreign.hs_service); return (true); } static bool tcpdropall(const char *ca_name, const char *stack, int state) { struct xinpgen *head, *xinp; struct xtcpcb *xtp; struct xinpcb *xip; bool ok; ok = true; head = getxpcblist("net.inet.tcp.pcblist"); #define XINP_NEXT(xinp) \ ((struct xinpgen *)(uintptr_t)((uintptr_t)(xinp) + (xinp)->xig_len)) for (xinp = XINP_NEXT(head); xinp->xig_len > sizeof *xinp; xinp = XINP_NEXT(xinp)) { xtp = (struct xtcpcb *)xinp; xip = &xtp->xt_inp; /* * XXX * Check protocol, support just v4 or v6, etc. */ /* Ignore PCBs which were freed during copyout. */ if (xip->inp_gencnt > head->xig_gen) continue; /* Skip listening sockets. */ if (xtp->t_state == TCPS_LISTEN) continue; /* If requested, skip sockets not having the requested state. */ if ((state != -1) && (xtp->t_state != state)) continue; /* * If requested, skip sockets not having the requested * congestion control algorithm. */ if (ca_name[0] != '\0' && strncmp(xtp->xt_cc, ca_name, TCP_CA_NAME_MAX)) continue; /* If requested, skip sockets not having the requested stack. */ if (stack[0] != '\0' && strncmp(xtp->xt_stack, stack, TCP_FUNCTION_NAME_LEN_MAX)) continue; if (!tcpdropconn(&xip->inp_inc)) ok = false; } free(head); return (ok); } static bool tcpdropbyname(const char *lhost, const char *lport, const char *fhost, const char *fport) { static const struct addrinfo hints = { /* * Look for TCP streams in all domains. */ .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_protocol = IPPROTO_TCP, }; struct addrinfo *ail, *local, *aif, *foreign; int error; bool ok, infamily; error = getaddrinfo(lhost, lport, &hints, &local); if (error != 0) errx(1, "getaddrinfo: %s port %s: %s", lhost, lport, gai_strerror(error)); error = getaddrinfo(fhost, fport, &hints, &foreign); if (error != 0) { freeaddrinfo(local); /* XXX gratuitous */ errx(1, "getaddrinfo: %s port %s: %s", fhost, fport, gai_strerror(error)); } ok = true; infamily = false; /* * Try every combination of local and foreign address pairs. */ for (ail = local; ail != NULL; ail = ail->ai_next) { for (aif = foreign; aif != NULL; aif = aif->ai_next) { if (ail->ai_family != aif->ai_family) continue; infamily = true; if (!tcpdrop(ail->ai_addr, aif->ai_addr)) ok = false; } } if (!infamily) { warnx("%s %s %s %s: different address families", lhost, lport, fhost, fport); ok = false; } freeaddrinfo(local); freeaddrinfo(foreign); return (ok); } static bool tcpdropconn(const struct in_conninfo *inc) { struct sockaddr *local, *foreign; struct sockaddr_in6 sin6[2]; struct sockaddr_in sin4[2]; if ((inc->inc_flags & INC_ISIPV6) != 0) { memset(sin6, 0, sizeof sin6); sin6[TCPDROP_LOCAL].sin6_len = sizeof sin6[TCPDROP_LOCAL]; sin6[TCPDROP_LOCAL].sin6_family = AF_INET6; sin6[TCPDROP_LOCAL].sin6_port = inc->inc_lport; memcpy(&sin6[TCPDROP_LOCAL].sin6_addr, &inc->inc6_laddr, sizeof inc->inc6_laddr); local = (struct sockaddr *)&sin6[TCPDROP_LOCAL]; sin6[TCPDROP_FOREIGN].sin6_len = sizeof sin6[TCPDROP_FOREIGN]; sin6[TCPDROP_FOREIGN].sin6_family = AF_INET6; sin6[TCPDROP_FOREIGN].sin6_port = inc->inc_fport; memcpy(&sin6[TCPDROP_FOREIGN].sin6_addr, &inc->inc6_faddr, sizeof inc->inc6_faddr); foreign = (struct sockaddr *)&sin6[TCPDROP_FOREIGN]; } else { memset(sin4, 0, sizeof sin4); sin4[TCPDROP_LOCAL].sin_len = sizeof sin4[TCPDROP_LOCAL]; sin4[TCPDROP_LOCAL].sin_family = AF_INET; sin4[TCPDROP_LOCAL].sin_port = inc->inc_lport; memcpy(&sin4[TCPDROP_LOCAL].sin_addr, &inc->inc_laddr, sizeof inc->inc_laddr); local = (struct sockaddr *)&sin4[TCPDROP_LOCAL]; sin4[TCPDROP_FOREIGN].sin_len = sizeof sin4[TCPDROP_FOREIGN]; sin4[TCPDROP_FOREIGN].sin_family = AF_INET; sin4[TCPDROP_FOREIGN].sin_port = inc->inc_fport; memcpy(&sin4[TCPDROP_FOREIGN].sin_addr, &inc->inc_faddr, sizeof inc->inc_faddr); foreign = (struct sockaddr *)&sin4[TCPDROP_FOREIGN]; } return (tcpdrop(local, foreign)); } static void usage(void) { fprintf(stderr, "usage: tcpdrop local-address local-port foreign-address foreign-port\n" " tcpdrop local-address:local-port foreign-address:foreign-port\n" " tcpdrop local-address.local-port foreign-address.foreign-port\n" " tcpdrop [-l] -a\n" " tcpdrop [-l] -C cc-algo [-S stack] [-s state]\n" " tcpdrop [-l] [-C cc-algo] -S stack [-s state]\n" " tcpdrop [-l] [-C cc-algo] [-S stack] -s state\n"); exit(1); }