103914b0bSRick Macklem /*- 203914b0bSRick Macklem * Copyright (c) 2009 Rick Macklem, University of Guelph 303914b0bSRick Macklem * All rights reserved. 403914b0bSRick Macklem * 503914b0bSRick Macklem * Redistribution and use in source and binary forms, with or without 603914b0bSRick Macklem * modification, are permitted provided that the following conditions 703914b0bSRick Macklem * are met: 803914b0bSRick Macklem * 1. Redistributions of source code must retain the above copyright 903914b0bSRick Macklem * notice, this list of conditions and the following disclaimer. 1003914b0bSRick Macklem * 2. Redistributions in binary form must reproduce the above copyright 1103914b0bSRick Macklem * notice, this list of conditions and the following disclaimer in the 1203914b0bSRick Macklem * documentation and/or other materials provided with the distribution. 1303914b0bSRick Macklem * 1403914b0bSRick Macklem * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1503914b0bSRick Macklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1603914b0bSRick Macklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1703914b0bSRick Macklem * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1803914b0bSRick Macklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1903914b0bSRick Macklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2003914b0bSRick Macklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2103914b0bSRick Macklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2203914b0bSRick Macklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2303914b0bSRick Macklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2403914b0bSRick Macklem * SUCH DAMAGE. 2503914b0bSRick Macklem * 2603914b0bSRick Macklem */ 2703914b0bSRick Macklem 2803914b0bSRick Macklem #include <sys/cdefs.h> 2903914b0bSRick Macklem __FBSDID("$FreeBSD$"); 3003914b0bSRick Macklem 3103914b0bSRick Macklem #include <sys/param.h> 3203914b0bSRick Macklem #include <sys/linker.h> 3303914b0bSRick Macklem #include <sys/module.h> 3403914b0bSRick Macklem #include <sys/socket.h> 3503914b0bSRick Macklem 3603914b0bSRick Macklem #include <arpa/inet.h> 3703914b0bSRick Macklem 3803914b0bSRick Macklem #include <netinet/in.h> 3903914b0bSRick Macklem 4003914b0bSRick Macklem #include <nfs/nfssvc.h> 4103914b0bSRick Macklem 4203914b0bSRick Macklem #include <fs/nfs/rpcv2.h> 4303914b0bSRick Macklem #include <fs/nfs/nfsproto.h> 4403914b0bSRick Macklem #include <fs/nfs/nfskpiport.h> 4503914b0bSRick Macklem #include <fs/nfs/nfs.h> 4603914b0bSRick Macklem 4703914b0bSRick Macklem #include <ctype.h> 4803914b0bSRick Macklem #include <err.h> 4903914b0bSRick Macklem #include <errno.h> 5003914b0bSRick Macklem #include <stdio.h> 5103914b0bSRick Macklem #include <stdlib.h> 5203914b0bSRick Macklem #include <string.h> 5303914b0bSRick Macklem #include <unistd.h> 5403914b0bSRick Macklem 5503914b0bSRick Macklem #define DUMPSIZE 10000 5603914b0bSRick Macklem 5703914b0bSRick Macklem static void dump_lockstate(char *); 5803914b0bSRick Macklem static void dump_openstate(void); 5903914b0bSRick Macklem static void usage(void); 6003914b0bSRick Macklem static char *open_flags(uint32_t); 6103914b0bSRick Macklem static char *deleg_flags(uint32_t); 6203914b0bSRick Macklem static char *lock_flags(uint32_t); 6303914b0bSRick Macklem static char *client_flags(uint32_t); 6403914b0bSRick Macklem 6503914b0bSRick Macklem static struct nfsd_dumpclients dp[DUMPSIZE]; 6603914b0bSRick Macklem static struct nfsd_dumplocks lp[DUMPSIZE]; 6703914b0bSRick Macklem static char flag_string[20]; 6803914b0bSRick Macklem 6903914b0bSRick Macklem int 7003914b0bSRick Macklem main(int argc, char **argv) 7103914b0bSRick Macklem { 7203914b0bSRick Macklem int ch, openstate; 7303914b0bSRick Macklem char *lockfile; 7403914b0bSRick Macklem 7503914b0bSRick Macklem if (modfind("nfsd") < 0) 7603914b0bSRick Macklem errx(1, "nfsd not loaded - self terminating"); 7703914b0bSRick Macklem openstate = 0; 7803914b0bSRick Macklem lockfile = NULL; 791248463cSRick Macklem while ((ch = getopt(argc, argv, "ol:")) != -1) 8003914b0bSRick Macklem switch (ch) { 8103914b0bSRick Macklem case 'o': 8203914b0bSRick Macklem openstate = 1; 8303914b0bSRick Macklem break; 8403914b0bSRick Macklem case 'l': 8503914b0bSRick Macklem lockfile = optarg; 8603914b0bSRick Macklem break; 8703914b0bSRick Macklem default: 8803914b0bSRick Macklem usage(); 8903914b0bSRick Macklem } 9003914b0bSRick Macklem argc -= optind; 9103914b0bSRick Macklem argv += optind; 9203914b0bSRick Macklem 9303914b0bSRick Macklem if (openstate == 0 && lockfile == NULL) 9403914b0bSRick Macklem openstate = 1; 9503914b0bSRick Macklem else if (openstate != 0 && lockfile != NULL) 9603914b0bSRick Macklem errx(1, "-o and -l cannot both be specified"); 9703914b0bSRick Macklem 9803914b0bSRick Macklem /* 9903914b0bSRick Macklem * For -o, dump all open/lock state. 10003914b0bSRick Macklem * For -l, dump lock state for that file. 10103914b0bSRick Macklem */ 10203914b0bSRick Macklem if (openstate != 0) 10303914b0bSRick Macklem dump_openstate(); 10403914b0bSRick Macklem else 10503914b0bSRick Macklem dump_lockstate(lockfile); 10603914b0bSRick Macklem exit(0); 10703914b0bSRick Macklem } 10803914b0bSRick Macklem 10903914b0bSRick Macklem static void 11003914b0bSRick Macklem usage(void) 11103914b0bSRick Macklem { 11203914b0bSRick Macklem 11303914b0bSRick Macklem errx(1, "usage: nfsdumpstate [-o] [-l]"); 11403914b0bSRick Macklem } 11503914b0bSRick Macklem 11603914b0bSRick Macklem /* 11703914b0bSRick Macklem * Dump all open/lock state. 11803914b0bSRick Macklem */ 11903914b0bSRick Macklem static void 12003914b0bSRick Macklem dump_openstate(void) 12103914b0bSRick Macklem { 12203914b0bSRick Macklem struct nfsd_dumplist dumplist; 12303914b0bSRick Macklem int cnt, i; 12403914b0bSRick Macklem 12503914b0bSRick Macklem dumplist.ndl_size = DUMPSIZE; 12603914b0bSRick Macklem dumplist.ndl_list = (void *)dp; 12703914b0bSRick Macklem if (nfssvc(NFSSVC_DUMPCLIENTS, &dumplist) < 0) 12803914b0bSRick Macklem errx(1, "Can't perform dump clients syscall"); 12903914b0bSRick Macklem 13003914b0bSRick Macklem printf("%-13s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %-15s %s\n", 13103914b0bSRick Macklem "Flags", "OpenOwner", "Open", "LockOwner", 13203914b0bSRick Macklem "Lock", "Deleg", "OldDeleg", "Clientaddr", "ClientID"); 13303914b0bSRick Macklem /* 13403914b0bSRick Macklem * Loop through results, printing them out. 13503914b0bSRick Macklem */ 13603914b0bSRick Macklem cnt = 0; 13703914b0bSRick Macklem while (dp[cnt].ndcl_clid.nclid_idlen > 0 && cnt < DUMPSIZE) { 13803914b0bSRick Macklem printf("%-13s ", client_flags(dp[cnt].ndcl_flags)); 13903914b0bSRick Macklem printf("%9d %9d %9d %9d %9d %9d ", 14003914b0bSRick Macklem dp[cnt].ndcl_nopenowners, 14103914b0bSRick Macklem dp[cnt].ndcl_nopens, 14203914b0bSRick Macklem dp[cnt].ndcl_nlockowners, 14303914b0bSRick Macklem dp[cnt].ndcl_nlocks, 14403914b0bSRick Macklem dp[cnt].ndcl_ndelegs, 14503914b0bSRick Macklem dp[cnt].ndcl_nolddelegs); 14603914b0bSRick Macklem if (dp[cnt].ndcl_addrfam == AF_INET) 14703914b0bSRick Macklem printf("%-15s ", 14803914b0bSRick Macklem inet_ntoa(dp[cnt].ndcl_cbaddr.sin_addr)); 14903914b0bSRick Macklem for (i = 0; i < dp[cnt].ndcl_clid.nclid_idlen; i++) 15003914b0bSRick Macklem printf("%02x", dp[cnt].ndcl_clid.nclid_id[i]); 15103914b0bSRick Macklem printf("\n"); 15203914b0bSRick Macklem cnt++; 15303914b0bSRick Macklem } 15403914b0bSRick Macklem } 15503914b0bSRick Macklem 15603914b0bSRick Macklem /* 15703914b0bSRick Macklem * Dump the lock state for a file. 15803914b0bSRick Macklem */ 15903914b0bSRick Macklem static void 16003914b0bSRick Macklem dump_lockstate(char *fname) 16103914b0bSRick Macklem { 16203914b0bSRick Macklem struct nfsd_dumplocklist dumplocklist; 16303914b0bSRick Macklem int cnt, i; 16403914b0bSRick Macklem 16503914b0bSRick Macklem dumplocklist.ndllck_size = DUMPSIZE; 16603914b0bSRick Macklem dumplocklist.ndllck_list = (void *)lp; 16703914b0bSRick Macklem dumplocklist.ndllck_fname = fname; 16803914b0bSRick Macklem if (nfssvc(NFSSVC_DUMPLOCKS, &dumplocklist) < 0) 16903914b0bSRick Macklem errx(1, "Can't dump locks for %s\n", fname); 17003914b0bSRick Macklem 17103914b0bSRick Macklem printf("%-11s %-36s %-15s %s\n", 17203914b0bSRick Macklem "Open/Lock", 17303914b0bSRick Macklem " Stateid or Lock Range", 17403914b0bSRick Macklem "Clientaddr", 17503914b0bSRick Macklem "Owner and ClientID"); 17603914b0bSRick Macklem /* 17703914b0bSRick Macklem * Loop through results, printing them out. 17803914b0bSRick Macklem */ 17903914b0bSRick Macklem cnt = 0; 18003914b0bSRick Macklem while (lp[cnt].ndlck_clid.nclid_idlen > 0 && cnt < DUMPSIZE) { 18103914b0bSRick Macklem if (lp[cnt].ndlck_flags & NFSLCK_OPEN) 18203914b0bSRick Macklem printf("%-11s %9d %08x %08x %08x ", 18303914b0bSRick Macklem open_flags(lp[cnt].ndlck_flags), 18403914b0bSRick Macklem lp[cnt].ndlck_stateid.seqid, 18503914b0bSRick Macklem lp[cnt].ndlck_stateid.other[0], 18603914b0bSRick Macklem lp[cnt].ndlck_stateid.other[1], 18703914b0bSRick Macklem lp[cnt].ndlck_stateid.other[2]); 18803914b0bSRick Macklem else if (lp[cnt].ndlck_flags & (NFSLCK_DELEGREAD | 18903914b0bSRick Macklem NFSLCK_DELEGWRITE)) 19003914b0bSRick Macklem printf("%-11s %9d %08x %08x %08x ", 19103914b0bSRick Macklem deleg_flags(lp[cnt].ndlck_flags), 19203914b0bSRick Macklem lp[cnt].ndlck_stateid.seqid, 19303914b0bSRick Macklem lp[cnt].ndlck_stateid.other[0], 19403914b0bSRick Macklem lp[cnt].ndlck_stateid.other[1], 19503914b0bSRick Macklem lp[cnt].ndlck_stateid.other[2]); 19603914b0bSRick Macklem else 1979964058eSXin LI printf("%-11s %17jd %17jd ", 19803914b0bSRick Macklem lock_flags(lp[cnt].ndlck_flags), 19903914b0bSRick Macklem lp[cnt].ndlck_first, 20003914b0bSRick Macklem lp[cnt].ndlck_end); 20103914b0bSRick Macklem if (lp[cnt].ndlck_addrfam == AF_INET) 20203914b0bSRick Macklem printf("%-15s ", 20303914b0bSRick Macklem inet_ntoa(lp[cnt].ndlck_cbaddr.sin_addr)); 20403914b0bSRick Macklem else 20503914b0bSRick Macklem printf("%-15s ", " "); 20603914b0bSRick Macklem for (i = 0; i < lp[cnt].ndlck_owner.nclid_idlen; i++) 20703914b0bSRick Macklem printf("%02x", lp[cnt].ndlck_owner.nclid_id[i]); 20803914b0bSRick Macklem printf(" "); 20903914b0bSRick Macklem for (i = 0; i < lp[cnt].ndlck_clid.nclid_idlen; i++) 21003914b0bSRick Macklem printf("%02x", lp[cnt].ndlck_clid.nclid_id[i]); 21103914b0bSRick Macklem printf("\n"); 21203914b0bSRick Macklem cnt++; 21303914b0bSRick Macklem } 21403914b0bSRick Macklem } 21503914b0bSRick Macklem 21603914b0bSRick Macklem /* 21703914b0bSRick Macklem * Parse the Open/Lock flag bits and create a string to be printed. 21803914b0bSRick Macklem */ 21903914b0bSRick Macklem static char * 22003914b0bSRick Macklem open_flags(uint32_t flags) 22103914b0bSRick Macklem { 22203914b0bSRick Macklem int i, j; 22303914b0bSRick Macklem 22403914b0bSRick Macklem strlcpy(flag_string, "Open ", sizeof (flag_string)); 22503914b0bSRick Macklem i = 5; 22603914b0bSRick Macklem if (flags & NFSLCK_READACCESS) 22703914b0bSRick Macklem flag_string[i++] = 'R'; 22803914b0bSRick Macklem if (flags & NFSLCK_WRITEACCESS) 22903914b0bSRick Macklem flag_string[i++] = 'W'; 23003914b0bSRick Macklem flag_string[i++] = ' '; 23103914b0bSRick Macklem flag_string[i++] = 'D'; 23203914b0bSRick Macklem flag_string[i] = 'N'; 23303914b0bSRick Macklem j = i; 23403914b0bSRick Macklem if (flags & NFSLCK_READDENY) 23503914b0bSRick Macklem flag_string[i++] = 'R'; 23603914b0bSRick Macklem if (flags & NFSLCK_WRITEDENY) 23703914b0bSRick Macklem flag_string[i++] = 'W'; 23803914b0bSRick Macklem if (i == j) 23903914b0bSRick Macklem i++; 24003914b0bSRick Macklem flag_string[i] = '\0'; 24103914b0bSRick Macklem return (flag_string); 24203914b0bSRick Macklem } 24303914b0bSRick Macklem 24403914b0bSRick Macklem static char * 24503914b0bSRick Macklem deleg_flags(uint32_t flags) 24603914b0bSRick Macklem { 24703914b0bSRick Macklem 24803914b0bSRick Macklem if (flags & NFSLCK_DELEGREAD) 24903914b0bSRick Macklem strlcpy(flag_string, "Deleg R", sizeof (flag_string)); 25003914b0bSRick Macklem else 25103914b0bSRick Macklem strlcpy(flag_string, "Deleg W", sizeof (flag_string)); 25203914b0bSRick Macklem return (flag_string); 25303914b0bSRick Macklem } 25403914b0bSRick Macklem 25503914b0bSRick Macklem static char * 25603914b0bSRick Macklem lock_flags(uint32_t flags) 25703914b0bSRick Macklem { 25803914b0bSRick Macklem 25903914b0bSRick Macklem if (flags & NFSLCK_READ) 26003914b0bSRick Macklem strlcpy(flag_string, "Lock R", sizeof (flag_string)); 26103914b0bSRick Macklem else 26203914b0bSRick Macklem strlcpy(flag_string, "Lock W", sizeof (flag_string)); 26303914b0bSRick Macklem return (flag_string); 26403914b0bSRick Macklem } 26503914b0bSRick Macklem 26603914b0bSRick Macklem static char * 26703914b0bSRick Macklem client_flags(uint32_t flags) 26803914b0bSRick Macklem { 26903914b0bSRick Macklem 27003914b0bSRick Macklem flag_string[0] = '\0'; 27103914b0bSRick Macklem if (flags & LCL_NEEDSCONFIRM) 27203914b0bSRick Macklem strlcat(flag_string, "NC ", sizeof (flag_string)); 27303914b0bSRick Macklem if (flags & LCL_CALLBACKSON) 27403914b0bSRick Macklem strlcat(flag_string, "CB ", sizeof (flag_string)); 27503914b0bSRick Macklem if (flags & LCL_GSS) 27603914b0bSRick Macklem strlcat(flag_string, "GSS ", sizeof (flag_string)); 27703914b0bSRick Macklem if (flags & LCL_ADMINREVOKED) 27803914b0bSRick Macklem strlcat(flag_string, "REV", sizeof (flag_string)); 27903914b0bSRick Macklem return (flag_string); 28003914b0bSRick Macklem } 281