1192811Srmacklem/*- 2192811Srmacklem * Copyright (c) 2009 Rick Macklem, University of Guelph 3192811Srmacklem * All rights reserved. 4192811Srmacklem * 5192811Srmacklem * Redistribution and use in source and binary forms, with or without 6192811Srmacklem * modification, are permitted provided that the following conditions 7192811Srmacklem * are met: 8192811Srmacklem * 1. Redistributions of source code must retain the above copyright 9192811Srmacklem * notice, this list of conditions and the following disclaimer. 10192811Srmacklem * 2. Redistributions in binary form must reproduce the above copyright 11192811Srmacklem * notice, this list of conditions and the following disclaimer in the 12192811Srmacklem * documentation and/or other materials provided with the distribution. 13192811Srmacklem * 14192811Srmacklem * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15192811Srmacklem * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16192811Srmacklem * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17192811Srmacklem * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18192811Srmacklem * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19192811Srmacklem * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20192811Srmacklem * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21192811Srmacklem * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22192811Srmacklem * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23192811Srmacklem * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24192811Srmacklem * SUCH DAMAGE. 25192811Srmacklem * 26192811Srmacklem */ 27192811Srmacklem 28192811Srmacklem#include <sys/cdefs.h> 29192811Srmacklem__FBSDID("$FreeBSD: stable/10/usr.sbin/nfsdumpstate/nfsdumpstate.c 347174 2019-05-06 03:20:02Z rmacklem $"); 30192811Srmacklem 31192811Srmacklem#include <sys/param.h> 32192811Srmacklem#include <sys/linker.h> 33192811Srmacklem#include <sys/module.h> 34192811Srmacklem#include <sys/socket.h> 35192811Srmacklem 36192811Srmacklem#include <arpa/inet.h> 37192811Srmacklem 38192811Srmacklem#include <netinet/in.h> 39192811Srmacklem 40192811Srmacklem#include <nfs/nfssvc.h> 41192811Srmacklem 42192811Srmacklem#include <fs/nfs/rpcv2.h> 43192811Srmacklem#include <fs/nfs/nfsproto.h> 44192811Srmacklem#include <fs/nfs/nfskpiport.h> 45192811Srmacklem#include <fs/nfs/nfs.h> 46192811Srmacklem 47192811Srmacklem#include <ctype.h> 48192811Srmacklem#include <err.h> 49192811Srmacklem#include <errno.h> 50192811Srmacklem#include <stdio.h> 51192811Srmacklem#include <stdlib.h> 52192811Srmacklem#include <string.h> 53192811Srmacklem#include <unistd.h> 54192811Srmacklem 55192811Srmacklem#define DUMPSIZE 10000 56192811Srmacklem 57192811Srmacklemstatic void dump_lockstate(char *); 58192811Srmacklemstatic void dump_openstate(void); 59192811Srmacklemstatic void usage(void); 60192811Srmacklemstatic char *open_flags(uint32_t); 61192811Srmacklemstatic char *deleg_flags(uint32_t); 62192811Srmacklemstatic char *lock_flags(uint32_t); 63192811Srmacklemstatic char *client_flags(uint32_t); 64192811Srmacklem 65192811Srmacklemstatic struct nfsd_dumpclients dp[DUMPSIZE]; 66192811Srmacklemstatic struct nfsd_dumplocks lp[DUMPSIZE]; 67192811Srmacklemstatic char flag_string[20]; 68192811Srmacklem 69192811Srmacklemint 70192811Srmacklemmain(int argc, char **argv) 71192811Srmacklem{ 72192811Srmacklem int ch, openstate; 73192811Srmacklem char *lockfile; 74192811Srmacklem 75192811Srmacklem if (modfind("nfsd") < 0) 76192811Srmacklem errx(1, "nfsd not loaded - self terminating"); 77192811Srmacklem openstate = 0; 78192811Srmacklem lockfile = NULL; 79210272Srmacklem while ((ch = getopt(argc, argv, "ol:")) != -1) 80192811Srmacklem switch (ch) { 81192811Srmacklem case 'o': 82192811Srmacklem openstate = 1; 83192811Srmacklem break; 84192811Srmacklem case 'l': 85192811Srmacklem lockfile = optarg; 86192811Srmacklem break; 87192811Srmacklem default: 88192811Srmacklem usage(); 89192811Srmacklem } 90192811Srmacklem argc -= optind; 91192811Srmacklem argv += optind; 92192811Srmacklem 93192811Srmacklem if (openstate == 0 && lockfile == NULL) 94192811Srmacklem openstate = 1; 95192811Srmacklem else if (openstate != 0 && lockfile != NULL) 96192811Srmacklem errx(1, "-o and -l cannot both be specified"); 97192811Srmacklem 98192811Srmacklem /* 99192811Srmacklem * For -o, dump all open/lock state. 100192811Srmacklem * For -l, dump lock state for that file. 101192811Srmacklem */ 102192811Srmacklem if (openstate != 0) 103192811Srmacklem dump_openstate(); 104192811Srmacklem else 105192811Srmacklem dump_lockstate(lockfile); 106192811Srmacklem exit(0); 107192811Srmacklem} 108192811Srmacklem 109192811Srmacklemstatic void 110192811Srmacklemusage(void) 111192811Srmacklem{ 112192811Srmacklem 113192811Srmacklem errx(1, "usage: nfsdumpstate [-o] [-l]"); 114192811Srmacklem} 115192811Srmacklem 116192811Srmacklem/* 117192811Srmacklem * Dump all open/lock state. 118192811Srmacklem */ 119192811Srmacklemstatic void 120192811Srmacklemdump_openstate(void) 121192811Srmacklem{ 122192811Srmacklem struct nfsd_dumplist dumplist; 123192811Srmacklem int cnt, i; 124347174Srmacklem#ifdef INET6 125346778Srmacklem char nbuf[INET6_ADDRSTRLEN]; 126347174Srmacklem#endif 127192811Srmacklem 128192811Srmacklem dumplist.ndl_size = DUMPSIZE; 129192811Srmacklem dumplist.ndl_list = (void *)dp; 130192811Srmacklem if (nfssvc(NFSSVC_DUMPCLIENTS, &dumplist) < 0) 131192811Srmacklem errx(1, "Can't perform dump clients syscall"); 132192811Srmacklem 133346778Srmacklem printf("%-13s %9.9s %9.9s %9.9s %9.9s %9.9s %9.9s %-45s %s\n", 134192811Srmacklem "Flags", "OpenOwner", "Open", "LockOwner", 135192811Srmacklem "Lock", "Deleg", "OldDeleg", "Clientaddr", "ClientID"); 136192811Srmacklem /* 137192811Srmacklem * Loop through results, printing them out. 138192811Srmacklem */ 139192811Srmacklem cnt = 0; 140192811Srmacklem while (dp[cnt].ndcl_clid.nclid_idlen > 0 && cnt < DUMPSIZE) { 141192811Srmacklem printf("%-13s ", client_flags(dp[cnt].ndcl_flags)); 142192811Srmacklem printf("%9d %9d %9d %9d %9d %9d ", 143192811Srmacklem dp[cnt].ndcl_nopenowners, 144192811Srmacklem dp[cnt].ndcl_nopens, 145192811Srmacklem dp[cnt].ndcl_nlockowners, 146192811Srmacklem dp[cnt].ndcl_nlocks, 147192811Srmacklem dp[cnt].ndcl_ndelegs, 148192811Srmacklem dp[cnt].ndcl_nolddelegs); 149346778Srmacklem switch (dp[cnt].ndcl_addrfam) { 150346778Srmacklem#ifdef INET 151346778Srmacklem case AF_INET: 152346778Srmacklem printf("%-45s ", 153192811Srmacklem inet_ntoa(dp[cnt].ndcl_cbaddr.sin_addr)); 154346778Srmacklem break; 155346778Srmacklem#endif 156346778Srmacklem#ifdef INET6 157346778Srmacklem case AF_INET6: 158346778Srmacklem if (inet_ntop(AF_INET6, &dp[cnt].ndcl_cbaddr.sin6_addr, 159346778Srmacklem nbuf, sizeof(nbuf)) != NULL) 160346778Srmacklem printf("%-45s ", nbuf); 161346778Srmacklem else 162346778Srmacklem printf("%-45s ", " "); 163346778Srmacklem break; 164346778Srmacklem#endif 165346778Srmacklem } 166192811Srmacklem for (i = 0; i < dp[cnt].ndcl_clid.nclid_idlen; i++) 167192811Srmacklem printf("%02x", dp[cnt].ndcl_clid.nclid_id[i]); 168192811Srmacklem printf("\n"); 169192811Srmacklem cnt++; 170192811Srmacklem } 171192811Srmacklem} 172192811Srmacklem 173192811Srmacklem/* 174192811Srmacklem * Dump the lock state for a file. 175192811Srmacklem */ 176192811Srmacklemstatic void 177192811Srmacklemdump_lockstate(char *fname) 178192811Srmacklem{ 179192811Srmacklem struct nfsd_dumplocklist dumplocklist; 180192811Srmacklem int cnt, i; 181347174Srmacklem#ifdef INET6 182347010Srmacklem char nbuf[INET6_ADDRSTRLEN]; 183347174Srmacklem#endif 184192811Srmacklem 185192811Srmacklem dumplocklist.ndllck_size = DUMPSIZE; 186192811Srmacklem dumplocklist.ndllck_list = (void *)lp; 187192811Srmacklem dumplocklist.ndllck_fname = fname; 188192811Srmacklem if (nfssvc(NFSSVC_DUMPLOCKS, &dumplocklist) < 0) 189192811Srmacklem errx(1, "Can't dump locks for %s\n", fname); 190192811Srmacklem 191347010Srmacklem printf("%-11s %-36s %-45s %s\n", 192192811Srmacklem "Open/Lock", 193192811Srmacklem " Stateid or Lock Range", 194192811Srmacklem "Clientaddr", 195192811Srmacklem "Owner and ClientID"); 196192811Srmacklem /* 197192811Srmacklem * Loop through results, printing them out. 198192811Srmacklem */ 199192811Srmacklem cnt = 0; 200192811Srmacklem while (lp[cnt].ndlck_clid.nclid_idlen > 0 && cnt < DUMPSIZE) { 201192811Srmacklem if (lp[cnt].ndlck_flags & NFSLCK_OPEN) 202192811Srmacklem printf("%-11s %9d %08x %08x %08x ", 203192811Srmacklem open_flags(lp[cnt].ndlck_flags), 204192811Srmacklem lp[cnt].ndlck_stateid.seqid, 205192811Srmacklem lp[cnt].ndlck_stateid.other[0], 206192811Srmacklem lp[cnt].ndlck_stateid.other[1], 207192811Srmacklem lp[cnt].ndlck_stateid.other[2]); 208192811Srmacklem else if (lp[cnt].ndlck_flags & (NFSLCK_DELEGREAD | 209192811Srmacklem NFSLCK_DELEGWRITE)) 210192811Srmacklem printf("%-11s %9d %08x %08x %08x ", 211192811Srmacklem deleg_flags(lp[cnt].ndlck_flags), 212192811Srmacklem lp[cnt].ndlck_stateid.seqid, 213192811Srmacklem lp[cnt].ndlck_stateid.other[0], 214192811Srmacklem lp[cnt].ndlck_stateid.other[1], 215192811Srmacklem lp[cnt].ndlck_stateid.other[2]); 216192811Srmacklem else 217193070Sdelphij printf("%-11s %17jd %17jd ", 218192811Srmacklem lock_flags(lp[cnt].ndlck_flags), 219192811Srmacklem lp[cnt].ndlck_first, 220192811Srmacklem lp[cnt].ndlck_end); 221347010Srmacklem switch (lp[cnt].ndlck_addrfam) { 222347010Srmacklem#ifdef INET 223347010Srmacklem case AF_INET: 224347010Srmacklem printf("%-45s ", 225192811Srmacklem inet_ntoa(lp[cnt].ndlck_cbaddr.sin_addr)); 226347010Srmacklem break; 227347010Srmacklem#endif 228347010Srmacklem#ifdef INET6 229347010Srmacklem case AF_INET6: 230347010Srmacklem if (inet_ntop(AF_INET6, &lp[cnt].ndlck_cbaddr.sin6_addr, 231347010Srmacklem nbuf, sizeof(nbuf)) != NULL) 232347010Srmacklem printf("%-45s ", nbuf); 233347010Srmacklem else 234347010Srmacklem printf("%-45s ", " "); 235347010Srmacklem break; 236347010Srmacklem#endif 237347010Srmacklem default: 238347010Srmacklem printf("%-45s ", " "); 239347010Srmacklem break; 240347010Srmacklem } 241192811Srmacklem for (i = 0; i < lp[cnt].ndlck_owner.nclid_idlen; i++) 242192811Srmacklem printf("%02x", lp[cnt].ndlck_owner.nclid_id[i]); 243192811Srmacklem printf(" "); 244192811Srmacklem for (i = 0; i < lp[cnt].ndlck_clid.nclid_idlen; i++) 245192811Srmacklem printf("%02x", lp[cnt].ndlck_clid.nclid_id[i]); 246192811Srmacklem printf("\n"); 247192811Srmacklem cnt++; 248192811Srmacklem } 249192811Srmacklem} 250192811Srmacklem 251192811Srmacklem/* 252192811Srmacklem * Parse the Open/Lock flag bits and create a string to be printed. 253192811Srmacklem */ 254192811Srmacklemstatic char * 255192811Srmacklemopen_flags(uint32_t flags) 256192811Srmacklem{ 257192811Srmacklem int i, j; 258192811Srmacklem 259192811Srmacklem strlcpy(flag_string, "Open ", sizeof (flag_string)); 260192811Srmacklem i = 5; 261192811Srmacklem if (flags & NFSLCK_READACCESS) 262192811Srmacklem flag_string[i++] = 'R'; 263192811Srmacklem if (flags & NFSLCK_WRITEACCESS) 264192811Srmacklem flag_string[i++] = 'W'; 265192811Srmacklem flag_string[i++] = ' '; 266192811Srmacklem flag_string[i++] = 'D'; 267192811Srmacklem flag_string[i] = 'N'; 268192811Srmacklem j = i; 269192811Srmacklem if (flags & NFSLCK_READDENY) 270192811Srmacklem flag_string[i++] = 'R'; 271192811Srmacklem if (flags & NFSLCK_WRITEDENY) 272192811Srmacklem flag_string[i++] = 'W'; 273192811Srmacklem if (i == j) 274192811Srmacklem i++; 275192811Srmacklem flag_string[i] = '\0'; 276192811Srmacklem return (flag_string); 277192811Srmacklem} 278192811Srmacklem 279192811Srmacklemstatic char * 280192811Srmacklemdeleg_flags(uint32_t flags) 281192811Srmacklem{ 282192811Srmacklem 283192811Srmacklem if (flags & NFSLCK_DELEGREAD) 284192811Srmacklem strlcpy(flag_string, "Deleg R", sizeof (flag_string)); 285192811Srmacklem else 286192811Srmacklem strlcpy(flag_string, "Deleg W", sizeof (flag_string)); 287192811Srmacklem return (flag_string); 288192811Srmacklem} 289192811Srmacklem 290192811Srmacklemstatic char * 291192811Srmacklemlock_flags(uint32_t flags) 292192811Srmacklem{ 293192811Srmacklem 294192811Srmacklem if (flags & NFSLCK_READ) 295192811Srmacklem strlcpy(flag_string, "Lock R", sizeof (flag_string)); 296192811Srmacklem else 297192811Srmacklem strlcpy(flag_string, "Lock W", sizeof (flag_string)); 298192811Srmacklem return (flag_string); 299192811Srmacklem} 300192811Srmacklem 301192811Srmacklemstatic char * 302192811Srmacklemclient_flags(uint32_t flags) 303192811Srmacklem{ 304192811Srmacklem 305192811Srmacklem flag_string[0] = '\0'; 306192811Srmacklem if (flags & LCL_NEEDSCONFIRM) 307192811Srmacklem strlcat(flag_string, "NC ", sizeof (flag_string)); 308192811Srmacklem if (flags & LCL_CALLBACKSON) 309192811Srmacklem strlcat(flag_string, "CB ", sizeof (flag_string)); 310192811Srmacklem if (flags & LCL_GSS) 311192811Srmacklem strlcat(flag_string, "GSS ", sizeof (flag_string)); 312192811Srmacklem if (flags & LCL_ADMINREVOKED) 313192811Srmacklem strlcat(flag_string, "REV", sizeof (flag_string)); 314192811Srmacklem return (flag_string); 315192811Srmacklem} 316