diff --git a/support/include/conffile.h b/support/include/conffile.h index ce7aa21..05ea5d2 100644 --- a/support/include/conffile.h +++ b/support/include/conffile.h @@ -54,7 +54,7 @@ extern int conf_end(int, int); extern void conf_free_list(struct conf_list *); extern struct sockaddr *conf_get_address(char *, char *); extern struct conf_list *conf_get_list(char *, char *); -extern struct conf_list *conf_get_tag_list(char *); +extern struct conf_list *conf_get_tag_list(char *, char *); extern int conf_get_num(char *, char *, int); extern char *conf_get_str(char *, char *); extern char *conf_get_section(char *, char *, char *); diff --git a/support/include/nfs/nfs.h b/support/include/nfs/nfs.h index 174c2dd..38db5b5 100644 --- a/support/include/nfs/nfs.h +++ b/support/include/nfs/nfs.h @@ -15,6 +15,10 @@ #define NFSD_MINVERS 2 #define NFSD_MAXVERS 4 +#define NFS4_MINMINOR 1 +#define NFS4_MAXMINOR 2 +#define NFS4_VERDEFAULT 0x1 /* minor verion 1 */ + struct nfs_fh_len { int fh_size; u_int8_t fh_handle[NFS3_FHSIZE]; @@ -52,6 +56,7 @@ struct nfs_fh_old { #define NFSCTL_UDPISSET(_cltbits) ((_cltbits) & NFSCTL_UDPBIT) #define NFSCTL_TCPISSET(_cltbits) ((_cltbits) & NFSCTL_TCPBIT) +#define NFSCTL_VERDEFAULT (0xc) /* versions 3 and 4 */ #define NFSCTL_VERSET(_cltbits, _v) ((_cltbits) |= (1 << ((_v) - 1))) #define NFSCTL_UDPSET(_cltbits) ((_cltbits) |= NFSCTL_UDPBIT) #define NFSCTL_TCPSET(_cltbits) ((_cltbits) |= NFSCTL_TCPBIT) diff --git a/support/include/nfsrpc.h b/support/include/nfsrpc.h index a0b80e1..1bfae7a 100644 --- a/support/include/nfsrpc.h +++ b/support/include/nfsrpc.h @@ -156,6 +156,11 @@ extern unsigned long nfs_pmap_getport(const struct sockaddr_in *, const struct timeval *); /* + * Use nfs_pmap_getport to see if statd is running locally + */ +extern int nfs_probe_statd(void); + +/* * Contact a remote RPC service to discover whether it is responding * to requests. */ diff --git a/support/nfs/conffile.c b/support/nfs/conffile.c index 5015e94..c3434d5 100644 --- a/support/nfs/conffile.c +++ b/support/nfs/conffile.c @@ -565,7 +565,7 @@ cleanup: } struct conf_list * -conf_get_tag_list(char *section) +conf_get_tag_list(char *section, char *arg) { struct conf_list *list = 0; struct conf_list_node *node; @@ -579,6 +579,8 @@ conf_get_tag_list(char *section) cb = LIST_FIRST(&conf_bindings[conf_hash (section)]); for (; cb; cb = LIST_NEXT(cb, link)) { if (strcasecmp (section, cb->section) == 0) { + if (arg != NULL && strcasecmp(arg, cb->arg) != 0) + continue; list->cnt++; node = calloc(1, sizeof *node); if (!node) diff --git a/support/nfs/exports.c b/support/nfs/exports.c index dea040f..05178f7 100644 --- a/support/nfs/exports.c +++ b/support/nfs/exports.c @@ -196,10 +196,35 @@ getexportent(int fromkernel, int fromexports) return ⅇ } +static const struct secinfo_flag_displaymap { + unsigned int flag; + const char *set; + const char *unset; +} secinfo_flag_displaymap[] = { + { NFSEXP_READONLY, "ro", "rw" }, + { NFSEXP_INSECURE_PORT, "insecure", "secure" }, + { NFSEXP_ROOTSQUASH, "root_squash", "no_root_squash" }, + { NFSEXP_ALLSQUASH, "all_squash", "no_all_squash" }, + { 0, NULL, NULL } +}; + +static void secinfo_flags_show(FILE *fp, unsigned int flags, unsigned int mask) +{ + const struct secinfo_flag_displaymap *p; + + for (p = &secinfo_flag_displaymap[0]; p->flag != 0; p++) { + if (!(mask & p->flag)) + continue; + fprintf(fp, ",%s", (flags & p->flag) ? p->set : p->unset); + } +} + void secinfo_show(FILE *fp, struct exportent *ep) { + const struct export_features *ef; struct sec_entry *p1, *p2; - int flags; + + ef = get_export_features(); for (p1=ep->e_secinfo; p1->flav; p1=p2) { @@ -208,12 +233,7 @@ void secinfo_show(FILE *fp, struct exportent *ep) p2++) { fprintf(fp, ":%s", p2->flav->flavour); } - flags = p1->flags; - fprintf(fp, ",%s", (flags & NFSEXP_READONLY) ? "ro" : "rw"); - fprintf(fp, ",%sroot_squash", (flags & NFSEXP_ROOTSQUASH)? - "" : "no_"); - fprintf(fp, ",%sall_squash", (flags & NFSEXP_ALLSQUASH)? - "" : "no_"); + secinfo_flags_show(fp, p1->flags, ef->secinfo_flags); } } diff --git a/support/nfs/getport.c b/support/nfs/getport.c index 3331ad4..081594c 100644 --- a/support/nfs/getport.c +++ b/support/nfs/getport.c @@ -1102,3 +1102,25 @@ unsigned long nfs_pmap_getport(const struct sockaddr_in *sin, return port; } + +static const char *nfs_ns_pgmtbl[] = { + "status", + NULL, +}; + +/* + * nfs_probe_statd - use nfs_pmap_getport to see if statd is running locally + * + * Returns non-zero if statd is running locally. + */ +int nfs_probe_statd(void) +{ + struct sockaddr_in addr = { + .sin_family = AF_INET, + .sin_addr.s_addr = htonl(INADDR_LOOPBACK), + }; + rpcprog_t program = nfs_getrpcbyname(NSMPROG, nfs_ns_pgmtbl); + + return nfs_getport_ping((struct sockaddr *)(char *)&addr, sizeof(addr), + program, (rpcvers_t)1, IPPROTO_UDP); +} diff --git a/tools/mountstats/mountstats.py b/tools/mountstats/mountstats.py index b95b71d..3f5fea5 100644 --- a/tools/mountstats/mountstats.py +++ b/tools/mountstats/mountstats.py @@ -53,7 +53,7 @@ class DeviceData: if words[6].find('nfs') != -1: self.__nfs_data['statvers'] = words[7] elif words[0] == 'age:': - self.__nfs_data['age'] = long(words[1]) + self.__nfs_data['age'] = int(words[1]) elif words[0] == 'opts:': self.__nfs_data['mountoptions'] = ''.join(words[1:]).split(',') elif words[0] == 'caps:': @@ -91,12 +91,12 @@ class DeviceData: self.__nfs_data['shortwrites'] = int(words[22]) self.__nfs_data['delay'] = int(words[23]) elif words[0] == 'bytes:': - self.__nfs_data['normalreadbytes'] = long(words[1]) - self.__nfs_data['normalwritebytes'] = long(words[2]) - self.__nfs_data['directreadbytes'] = long(words[3]) - self.__nfs_data['directwritebytes'] = long(words[4]) - self.__nfs_data['serverreadbytes'] = long(words[5]) - self.__nfs_data['serverwritebytes'] = long(words[6]) + self.__nfs_data['normalreadbytes'] = int(words[1]) + self.__nfs_data['normalwritebytes'] = int(words[2]) + self.__nfs_data['directreadbytes'] = int(words[3]) + self.__nfs_data['directwritebytes'] = int(words[4]) + self.__nfs_data['serverreadbytes'] = int(words[5]) + self.__nfs_data['serverwritebytes'] = int(words[6]) def __parse_rpc_line(self, words): if words[0] == 'RPC': @@ -110,8 +110,8 @@ class DeviceData: self.__rpc_data['rpcsends'] = int(words[4]) self.__rpc_data['rpcreceives'] = int(words[5]) self.__rpc_data['badxids'] = int(words[6]) - self.__rpc_data['inflightsends'] = long(words[7]) - self.__rpc_data['backlogutil'] = long(words[8]) + self.__rpc_data['inflightsends'] = int(words[7]) + self.__rpc_data['backlogutil'] = int(words[8]) elif words[1] == 'tcp': self.__rpc_data['port'] = words[2] self.__rpc_data['bind_count'] = int(words[3]) @@ -121,7 +121,7 @@ class DeviceData: self.__rpc_data['rpcsends'] = int(words[7]) self.__rpc_data['rpcreceives'] = int(words[8]) self.__rpc_data['badxids'] = int(words[9]) - self.__rpc_data['inflightsends'] = long(words[10]) + self.__rpc_data['inflightsends'] = int(words[10]) self.__rpc_data['backlogutil'] = int(words[11]) elif words[1] == 'rdma': self.__rpc_data['port'] = words[2] @@ -148,7 +148,7 @@ class DeviceData: else: op = words[0][:-1] self.__rpc_data['ops'] += [op] - self.__rpc_data[op] = [long(word) for word in words[1:]] + self.__rpc_data[op] = [int(word) for word in words[1:]] def parse_stats(self, lines): """Turn a list of lines from a mount stat file into a @@ -179,81 +179,81 @@ class DeviceData: def display_nfs_options(self): """Pretty-print the NFS options """ - print 'Stats for %s mounted on %s:' % \ - (self.__nfs_data['export'], self.__nfs_data['mountpoint']) - - print ' NFS mount options: %s' % ','.join(self.__nfs_data['mountoptions']) - print ' NFS server capabilities: %s' % ','.join(self.__nfs_data['servercapabilities']) - if self.__nfs_data.has_key('nfsv4flags'): - print ' NFSv4 capability flags: %s' % ','.join(self.__nfs_data['nfsv4flags']) - if self.__nfs_data.has_key('pseudoflavor'): - print ' NFS security flavor: %d pseudoflavor: %d' % \ - (self.__nfs_data['flavor'], self.__nfs_data['pseudoflavor']) + print('Stats for %s mounted on %s:' % \ + (self.__nfs_data['export'], self.__nfs_data['mountpoint'])) + + print(' NFS mount options: %s' % ','.join(self.__nfs_data['mountoptions'])) + print(' NFS server capabilities: %s' % ','.join(self.__nfs_data['servercapabilities'])) + if 'nfsv4flags' in self.__nfs_data: + print(' NFSv4 capability flags: %s' % ','.join(self.__nfs_data['nfsv4flags'])) + if 'pseudoflavor' in self.__nfs_data: + print(' NFS security flavor: %d pseudoflavor: %d' % \ + (self.__nfs_data['flavor'], self.__nfs_data['pseudoflavor'])) else: - print ' NFS security flavor: %d' % self.__nfs_data['flavor'] + print(' NFS security flavor: %d' % self.__nfs_data['flavor']) def display_nfs_events(self): """Pretty-print the NFS event counters """ - print - print 'Cache events:' - print ' data cache invalidated %d times' % self.__nfs_data['datainvalidates'] - print ' attribute cache invalidated %d times' % self.__nfs_data['attrinvalidates'] - print ' inodes synced %d times' % self.__nfs_data['syncinodes'] - print - print 'VFS calls:' - print ' VFS requested %d inode revalidations' % self.__nfs_data['inoderevalidates'] - print ' VFS requested %d dentry revalidations' % self.__nfs_data['dentryrevalidates'] - print - print ' VFS called nfs_readdir() %d times' % self.__nfs_data['vfsreaddir'] - print ' VFS called nfs_lookup() %d times' % self.__nfs_data['vfslookup'] - print ' VFS called nfs_permission() %d times' % self.__nfs_data['vfspermission'] - print ' VFS called nfs_file_open() %d times' % self.__nfs_data['vfsopen'] - print ' VFS called nfs_file_flush() %d times' % self.__nfs_data['vfsflush'] - print ' VFS called nfs_lock() %d times' % self.__nfs_data['vfslock'] - print ' VFS called nfs_fsync() %d times' % self.__nfs_data['vfsfsync'] - print ' VFS called nfs_file_release() %d times' % self.__nfs_data['vfsrelease'] - print - print 'VM calls:' - print ' VFS called nfs_readpage() %d times' % self.__nfs_data['vfsreadpage'] - print ' VFS called nfs_readpages() %d times' % self.__nfs_data['vfsreadpages'] - print ' VFS called nfs_writepage() %d times' % self.__nfs_data['vfswritepage'] - print ' VFS called nfs_writepages() %d times' % self.__nfs_data['vfswritepages'] - print - print 'Generic NFS counters:' - print ' File size changing operations:' - print ' truncating SETATTRs: %d extending WRITEs: %d' % \ - (self.__nfs_data['setattrtrunc'], self.__nfs_data['extendwrite']) - print ' %d silly renames' % self.__nfs_data['sillyrenames'] - print ' short reads: %d short writes: %d' % \ - (self.__nfs_data['shortreads'], self.__nfs_data['shortwrites']) - print ' NFSERR_DELAYs from server: %d' % self.__nfs_data['delay'] + print() + print('Cache events:') + print(' data cache invalidated %d times' % self.__nfs_data['datainvalidates']) + print(' attribute cache invalidated %d times' % self.__nfs_data['attrinvalidates']) + print(' inodes synced %d times' % self.__nfs_data['syncinodes']) + print() + print('VFS calls:') + print(' VFS requested %d inode revalidations' % self.__nfs_data['inoderevalidates']) + print(' VFS requested %d dentry revalidations' % self.__nfs_data['dentryrevalidates']) + print() + print(' VFS called nfs_readdir() %d times' % self.__nfs_data['vfsreaddir']) + print(' VFS called nfs_lookup() %d times' % self.__nfs_data['vfslookup']) + print(' VFS called nfs_permission() %d times' % self.__nfs_data['vfspermission']) + print(' VFS called nfs_file_open() %d times' % self.__nfs_data['vfsopen']) + print(' VFS called nfs_file_flush() %d times' % self.__nfs_data['vfsflush']) + print(' VFS called nfs_lock() %d times' % self.__nfs_data['vfslock']) + print(' VFS called nfs_fsync() %d times' % self.__nfs_data['vfsfsync']) + print(' VFS called nfs_file_release() %d times' % self.__nfs_data['vfsrelease']) + print() + print('VM calls:') + print(' VFS called nfs_readpage() %d times' % self.__nfs_data['vfsreadpage']) + print(' VFS called nfs_readpages() %d times' % self.__nfs_data['vfsreadpages']) + print(' VFS called nfs_writepage() %d times' % self.__nfs_data['vfswritepage']) + print(' VFS called nfs_writepages() %d times' % self.__nfs_data['vfswritepages']) + print() + print('Generic NFS counters:') + print(' File size changing operations:') + print(' truncating SETATTRs: %d extending WRITEs: %d' % \ + (self.__nfs_data['setattrtrunc'], self.__nfs_data['extendwrite'])) + print(' %d silly renames' % self.__nfs_data['sillyrenames']) + print(' short reads: %d short writes: %d' % \ + (self.__nfs_data['shortreads'], self.__nfs_data['shortwrites'])) + print(' NFSERR_DELAYs from server: %d' % self.__nfs_data['delay']) def display_nfs_bytes(self): """Pretty-print the NFS event counters """ - print - print 'NFS byte counts:' - print ' applications read %d bytes via read(2)' % self.__nfs_data['normalreadbytes'] - print ' applications wrote %d bytes via write(2)' % self.__nfs_data['normalwritebytes'] - print ' applications read %d bytes via O_DIRECT read(2)' % self.__nfs_data['directreadbytes'] - print ' applications wrote %d bytes via O_DIRECT write(2)' % self.__nfs_data['directwritebytes'] - print ' client read %d bytes via NFS READ' % self.__nfs_data['serverreadbytes'] - print ' client wrote %d bytes via NFS WRITE' % self.__nfs_data['serverwritebytes'] + print() + print('NFS byte counts:') + print(' applications read %d bytes via read(2)' % self.__nfs_data['normalreadbytes']) + print(' applications wrote %d bytes via write(2)' % self.__nfs_data['normalwritebytes']) + print(' applications read %d bytes via O_DIRECT read(2)' % self.__nfs_data['directreadbytes']) + print(' applications wrote %d bytes via O_DIRECT write(2)' % self.__nfs_data['directwritebytes']) + print(' client read %d bytes via NFS READ' % self.__nfs_data['serverreadbytes']) + print(' client wrote %d bytes via NFS WRITE' % self.__nfs_data['serverwritebytes']) def display_rpc_generic_stats(self): """Pretty-print the generic RPC stats """ sends = self.__rpc_data['rpcsends'] - print - print 'RPC statistics:' + print() + print('RPC statistics:') - print ' %d RPC requests sent, %d RPC replies received (%d XIDs not found)' % \ - (sends, self.__rpc_data['rpcreceives'], self.__rpc_data['badxids']) + print(' %d RPC requests sent, %d RPC replies received (%d XIDs not found)' % \ + (sends, self.__rpc_data['rpcreceives'], self.__rpc_data['badxids'])) if sends != 0: - print ' average backlog queue length: %d' % \ - (float(self.__rpc_data['backlogutil']) / sends) + print(' average backlog queue length: %d' % \ + (float(self.__rpc_data['backlogutil']) / sends)) def display_rpc_op_stats(self): """Pretty-print the per-op stats @@ -261,23 +261,23 @@ class DeviceData: sends = self.__rpc_data['rpcsends'] # XXX: these should be sorted by 'count' - print + print() for op in self.__rpc_data['ops']: stats = self.__rpc_data[op] count = stats[0] retrans = stats[1] - count if count != 0: - print '%s:' % op - print '\t%d ops (%d%%)' % \ - (count, ((count * 100) / sends)), - print '\t%d retrans (%d%%)' % (retrans, ((retrans * 100) / count)), - print '\t%d major timeouts' % stats[2] - print '\tavg bytes sent per op: %d\tavg bytes received per op: %d' % \ - (stats[3] / count, stats[4] / count) - print '\tbacklog wait: %f' % (float(stats[5]) / count), - print '\tRTT: %f' % (float(stats[6]) / count), - print '\ttotal execute time: %f (milliseconds)' % \ - (float(stats[7]) / count) + print('%s:' % op) + print('\t%d ops (%d%%)' % \ + (count, ((count * 100) / sends)), end=' ') + print('\t%d retrans (%d%%)' % (retrans, ((retrans * 100) / count)), end=' ') + print('\t%d major timeouts' % stats[2]) + print('\tavg bytes sent per op: %d\tavg bytes received per op: %d' % \ + (stats[3] / count, stats[4] / count)) + print('\tbacklog wait: %f' % (float(stats[5]) / count), end=' ') + print('\tRTT: %f' % (float(stats[6]) / count), end=' ') + print('\ttotal execute time: %f (milliseconds)' % \ + (float(stats[7]) / count)) def compare_iostats(self, old_stats): """Return the difference between two sets of stats @@ -285,9 +285,9 @@ class DeviceData: result = DeviceData() # copy self into result - for key, value in self.__nfs_data.iteritems(): + for key, value in self.__nfs_data.items(): result.__nfs_data[key] = value - for key, value in self.__rpc_data.iteritems(): + for key, value in self.__rpc_data.items(): result.__rpc_data[key] = value # compute the difference of each item in the list @@ -295,7 +295,7 @@ class DeviceData: # the reference to them. so we build new lists here # for the result object. for op in result.__rpc_data['ops']: - result.__rpc_data[op] = map(difference, self.__rpc_data[op], old_stats.__rpc_data[op]) + result.__rpc_data[op] = list(map(difference, self.__rpc_data[op], old_stats.__rpc_data[op])) # update the remaining keys we care about result.__rpc_data['rpcsends'] -= old_stats.__rpc_data['rpcsends'] @@ -312,17 +312,17 @@ class DeviceData: if sample_time == 0: sample_time = float(self.__nfs_data['age']) - print - print '%s mounted on %s:' % \ - (self.__nfs_data['export'], self.__nfs_data['mountpoint']) + print() + print('%s mounted on %s:' % \ + (self.__nfs_data['export'], self.__nfs_data['mountpoint'])) - print '\top/s\trpc bklog' - print '\t%.2f' % (sends / sample_time), + print('\top/s\trpc bklog') + print('\t%.2f' % (sends / sample_time), end=' ') if sends != 0: - print '\t%.2f' % \ - ((float(self.__rpc_data['backlogutil']) / sends) / sample_time) + print('\t%.2f' % \ + ((float(self.__rpc_data['backlogutil']) / sends) / sample_time)) else: - print '\t0.00' + print('\t0.00') # reads: ops/s, kB/s, avg rtt, and avg exe # XXX: include avg xfer size and retransmits? @@ -332,15 +332,15 @@ class DeviceData: rtt = float(read_rpc_stats[6]) exe = float(read_rpc_stats[7]) - print '\treads:\tops/s\t\tkB/s\t\tavg RTT (ms)\tavg exe (ms)' - print '\t\t%.2f' % (ops / sample_time), - print '\t\t%.2f' % (kilobytes / sample_time), + print('\treads:\tops/s\t\tkB/s\t\tavg RTT (ms)\tavg exe (ms)') + print('\t\t%.2f' % (ops / sample_time), end=' ') + print('\t\t%.2f' % (kilobytes / sample_time), end=' ') if ops != 0: - print '\t\t%.2f' % (rtt / ops), - print '\t\t%.2f' % (exe / ops) + print('\t\t%.2f' % (rtt / ops), end=' ') + print('\t\t%.2f' % (exe / ops)) else: - print '\t\t0.00', - print '\t\t0.00' + print('\t\t0.00', end=' ') + print('\t\t0.00') # writes: ops/s, kB/s, avg rtt, and avg exe # XXX: include avg xfer size and retransmits? @@ -350,15 +350,15 @@ class DeviceData: rtt = float(write_rpc_stats[6]) exe = float(write_rpc_stats[7]) - print '\twrites:\tops/s\t\tkB/s\t\tavg RTT (ms)\tavg exe (ms)' - print '\t\t%.2f' % (ops / sample_time), - print '\t\t%.2f' % (kilobytes / sample_time), + print('\twrites:\tops/s\t\tkB/s\t\tavg RTT (ms)\tavg exe (ms)') + print('\t\t%.2f' % (ops / sample_time), end=' ') + print('\t\t%.2f' % (kilobytes / sample_time), end=' ') if ops != 0: - print '\t\t%.2f' % (rtt / ops), - print '\t\t%.2f' % (exe / ops) + print('\t\t%.2f' % (rtt / ops), end=' ') + print('\t\t%.2f' % (exe / ops)) else: - print '\t\t0.00', - print '\t\t0.00' + print('\t\t0.00', end=' ') + print('\t\t0.00') def parse_stats_file(filename): """pop the contents of a mountstats file into a dictionary, @@ -388,18 +388,18 @@ def parse_stats_file(filename): return ms_dict def print_mountstats_help(name): - print 'usage: %s [ options ] ' % name - print - print ' Version %s' % Mountstats_version - print - print ' Display NFS client per-mount statistics.' - print - print ' --version display the version of this command' - print ' --nfs display only the NFS statistics' - print ' --rpc display only the RPC statistics' - print ' --start sample and save statistics' - print ' --end resample statistics and compare them with saved' - print + print('usage: %s [ options ] ' % name) + print() + print(' Version %s' % Mountstats_version) + print() + print(' Display NFS client per-mount statistics.') + print() + print(' --version display the version of this command') + print(' --nfs display only the NFS statistics') + print(' --rpc display only the RPC statistics') + print(' --start sample and save statistics') + print(' --end resample statistics and compare them with saved') + print() def mountstats_command(): """Mountstats command @@ -414,7 +414,7 @@ def mountstats_command(): return if arg in ['-v', '--version', 'version']: - print '%s version %s' % (sys.argv[0], Mountstats_version) + print('%s version %s' % (sys.argv[0], Mountstats_version)) sys.exit(0) if arg in ['-n', '--nfs']: @@ -426,10 +426,10 @@ def mountstats_command(): continue if arg in ['-s', '--start']: - raise Exception, 'Sampling is not yet implemented' + raise Exception('Sampling is not yet implemented') if arg in ['-e', '--end']: - raise Exception, 'Sampling is not yet implemented' + raise Exception('Sampling is not yet implemented') if arg == sys.argv[0]: continue @@ -448,14 +448,14 @@ def mountstats_command(): for mp in mountpoints: if mp not in mountstats: - print 'Statistics for mount point %s not found' % mp + print('Statistics for mount point %s not found' % mp) continue stats = DeviceData() stats.parse_stats(mountstats[mp]) if not stats.is_nfs_mountpoint(): - print 'Mount point %s exists but is not an NFS mount' % mp + print('Mount point %s exists but is not an NFS mount' % mp) continue if nfs_only: @@ -472,37 +472,37 @@ def mountstats_command(): stats.display_rpc_op_stats() def print_nfsstat_help(name): - print 'usage: %s [ options ]' % name - print - print ' Version %s' % Mountstats_version - print - print ' nfsstat-like program that uses NFS client per-mount statistics.' - print + print('usage: %s [ options ]' % name) + print() + print(' Version %s' % Mountstats_version) + print() + print(' nfsstat-like program that uses NFS client per-mount statistics.') + print() def nfsstat_command(): print_nfsstat_help(prog) def print_iostat_help(name): - print 'usage: %s [ [ ] ] [ ] ' % name - print - print ' Version %s' % Mountstats_version - print - print ' iostat-like program to display NFS client per-mount statistics.' - print - print ' The parameter specifies the amount of time in seconds between' - print ' each report. The first report contains statistics for the time since each' - print ' file system was mounted. Each subsequent report contains statistics' - print ' collected during the interval since the previous report.' - print - print ' If the parameter is specified, the value of determines the' - print ' number of reports generated at seconds apart. If the interval' - print ' parameter is specified without the parameter, the command generates' - print ' reports continuously.' - print - print ' If one or more names are specified, statistics for only these' - print ' mount points will be displayed. Otherwise, all NFS mount points on the' - print ' client are listed.' - print + print('usage: %s [ [ ] ] [ ] ' % name) + print() + print(' Version %s' % Mountstats_version) + print() + print(' iostat-like program to display NFS client per-mount statistics.') + print() + print(' The parameter specifies the amount of time in seconds between') + print(' each report. The first report contains statistics for the time since each') + print(' file system was mounted. Each subsequent report contains statistics') + print(' collected during the interval since the previous report.') + print() + print(' If the parameter is specified, the value of determines the') + print(' number of reports generated at seconds apart. If the interval') + print(' parameter is specified without the parameter, the command generates') + print(' reports continuously.') + print() + print(' If one or more names are specified, statistics for only these') + print(' mount points will be displayed. Otherwise, all NFS mount points on the') + print(' client are listed.') + print() def print_iostat_summary(old, new, devices, time): for device in devices: @@ -530,7 +530,7 @@ def iostat_command(): return if arg in ['-v', '--version', 'version']: - print '%s version %s' % (sys.argv[0], Mountstats_version) + print('%s version %s' % (sys.argv[0], Mountstats_version)) return if arg == sys.argv[0]: @@ -543,14 +543,14 @@ def iostat_command(): if interval > 0: interval_seen = True else: - print 'Illegal value' + print('Illegal value') return elif not count_seen: count = int(arg) if count > 0: count_seen = True else: - print 'Illegal value' + print('Illegal value') return # make certain devices contains only NFS mount points @@ -563,13 +563,13 @@ def iostat_command(): check += [device] devices = check else: - for device, descr in mountstats.iteritems(): + for device, descr in mountstats.items(): stats = DeviceData() stats.parse_stats(descr) if stats.is_nfs_mountpoint(): devices += [device] if len(devices) == 0: - print 'No NFS mount points were found' + print('No NFS mount points were found') return old_mountstats = None @@ -608,7 +608,7 @@ try: elif prog == 'ms-iostat': iostat_command() except KeyboardInterrupt: - print 'Caught ^C... exiting' + print('Caught ^C... exiting') sys.exit(1) sys.exit(0) diff --git a/tools/nfs-iostat/nfs-iostat.py b/tools/nfs-iostat/nfs-iostat.py index dfbef87..341cdbf 100644 --- a/tools/nfs-iostat/nfs-iostat.py +++ b/tools/nfs-iostat/nfs-iostat.py @@ -95,7 +95,7 @@ class DeviceData: if words[6] == 'nfs': self.__nfs_data['statvers'] = words[7] elif words[0] == 'age:': - self.__nfs_data['age'] = long(words[1]) + self.__nfs_data['age'] = int(words[1]) elif words[0] == 'opts:': self.__nfs_data['mountoptions'] = ''.join(words[1:]).split(',') elif words[0] == 'caps:': @@ -116,7 +116,7 @@ class DeviceData: elif words[0] == 'bytes:': i = 1 for key in NfsByteCounters: - self.__nfs_data[key] = long(words[i]) + self.__nfs_data[key] = int(words[i]) i += 1 def __parse_rpc_line(self, words): @@ -131,8 +131,8 @@ class DeviceData: self.__rpc_data['rpcsends'] = int(words[4]) self.__rpc_data['rpcreceives'] = int(words[5]) self.__rpc_data['badxids'] = int(words[6]) - self.__rpc_data['inflightsends'] = long(words[7]) - self.__rpc_data['backlogutil'] = long(words[8]) + self.__rpc_data['inflightsends'] = int(words[7]) + self.__rpc_data['backlogutil'] = int(words[8]) elif words[1] == 'tcp': self.__rpc_data['port'] = words[2] self.__rpc_data['bind_count'] = int(words[3]) @@ -142,8 +142,8 @@ class DeviceData: self.__rpc_data['rpcsends'] = int(words[7]) self.__rpc_data['rpcreceives'] = int(words[8]) self.__rpc_data['badxids'] = int(words[9]) - self.__rpc_data['inflightsends'] = long(words[10]) - self.__rpc_data['backlogutil'] = long(words[11]) + self.__rpc_data['inflightsends'] = int(words[10]) + self.__rpc_data['backlogutil'] = int(words[11]) elif words[1] == 'rdma': self.__rpc_data['port'] = words[2] self.__rpc_data['bind_count'] = int(words[3]) @@ -169,7 +169,7 @@ class DeviceData: else: op = words[0][:-1] self.__rpc_data['ops'] += [op] - self.__rpc_data[op] = [long(word) for word in words[1:]] + self.__rpc_data[op] = [int(word) for word in words[1:]] def parse_stats(self, lines): """Turn a list of lines from a mount stat file into a @@ -271,7 +271,7 @@ class DeviceData: nfs_stats = self.__nfs_data lookup_ops = self.__rpc_data['LOOKUP'][0] readdir_ops = self.__rpc_data['READDIR'][0] - if self.__rpc_data.has_key('READDIRPLUS'): + if 'READDIRPLUS' in self.__rpc_data: readdir_ops += self.__rpc_data['READDIRPLUS'][0] dentry_revals = nfs_stats['dentryrevalidates'] @@ -330,7 +330,7 @@ class DeviceData: def __print_rpc_op_stats(self, op, sample_time): """Print generic stats for one RPC op """ - if not self.__rpc_data.has_key(op): + if op not in self.__rpc_data: return rpc_stats = self.__rpc_data[op] @@ -353,14 +353,14 @@ class DeviceData: exe_per_op = 0.0 op += ':' - print('%s' % op.lower().ljust(15)) + print('%s' % op.lower().ljust(15), end='') print(' ops/s\t\t kB/s\t\t kB/op\t\tretrans\t\tavg RTT (ms)\tavg exe (ms)') - print('\t\t%7.3f' % (ops / sample_time)) - print('\t%7.3f' % (kilobytes / sample_time)) - print('\t%7.3f' % kb_per_op) - print(' %7d (%3.1f%%)' % (retrans, retrans_percent)) - print('\t%7.3f' % rtt_per_op) + print('\t\t%7.3f' % (ops / sample_time), end='') + print('\t%7.3f' % (kilobytes / sample_time), end='') + print('\t%7.3f' % kb_per_op, end='') + print(' %7d (%3.1f%%)' % (retrans, retrans_percent), end='') + print('\t%7.3f' % rtt_per_op, end='') print('\t%7.3f' % exe_per_op) def ops(self, sample_time): @@ -392,7 +392,7 @@ class DeviceData: print() print(' op/s\t\trpc bklog') - print('%7.2f' % (sends / sample_time)) + print('%7.2f' % (sends / sample_time), end='') print('\t%7.2f' % backlog) if which == 0: @@ -405,7 +405,7 @@ class DeviceData: elif which == 2: self.__print_rpc_op_stats('LOOKUP', sample_time) self.__print_rpc_op_stats('READDIR', sample_time) - if self.__rpc_data.has_key('READDIRPLUS'): + if 'READDIRPLUS' in self.__rpc_data: self.__print_rpc_op_stats('READDIRPLUS', sample_time) self.__print_dir_cache_stats(sample_time) elif which == 3: @@ -413,6 +413,8 @@ class DeviceData: self.__print_rpc_op_stats('WRITE', sample_time) self.__print_page_stats(sample_time) + sys.stdout.flush() + # # Functions # @@ -450,7 +452,7 @@ def print_iostat_summary(old, new, devices, time, options): if old: # Trim device list to only include intersection of old and new data, # this addresses umounts due to autofs mountpoints - devicelist = filter(lambda x:x in devices,old) + devicelist = [x for x in old if x in devices] else: devicelist = devices diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man index bc1de73..58c0f66 100644 --- a/utils/exportfs/exports.man +++ b/utils/exportfs/exports.man @@ -39,7 +39,7 @@ the export name using a backslash followed by the character code as three octal digits. .PP To apply changes to this file, run -.BR exportfs \-ra +.BR "exportfs \-ra" or restart the NFS server. .PP .SS Machine Name Formats diff --git a/utils/gssd/gssd.man b/utils/gssd/gssd.man index 1df75c5..ac13fd4 100644 --- a/utils/gssd/gssd.man +++ b/utils/gssd/gssd.man @@ -195,11 +195,28 @@ option when starting .BR rpc.gssd . .SH OPTIONS .TP -.B -D -DNS Reverse lookups are not used for determining the -server names pass to GSSAPI. This option will reverses that and forces -the use of DNS Reverse resolution of the server's IP address to -retrieve the server name to use in GSAPI authentication. +.B \-D +The server name passed to GSSAPI for authentication is normally the +name exactly as requested. e.g. for NFS +it is the server name in the "servername:/path" mount request. Only if this +servername appears to be an IP address (IPv4 or IPv6) or an +unqualified name (no dots) will a reverse DNS lookup +will be performed to get the canoncial server name. + +If +.B \-D +is present, a reverse DNS lookup will +.I always +be used, even if the server name looks like a canonical name. So it +is needed if partially qualified, or non canonical names are regularly +used. + +Using +.B \-D +can introduce a security vulnerability, so it is recommended that +.B \-D +not be used, and that canonical names always be used when requesting +services. .TP .B -f Runs diff --git a/utils/gssd/gssd_proc.c b/utils/gssd/gssd_proc.c index af1844c..2d3dbec 100644 --- a/utils/gssd/gssd_proc.c +++ b/utils/gssd/gssd_proc.c @@ -67,7 +67,6 @@ #include #include #include -#include #include "gssd.h" #include "err_util.h" @@ -176,7 +175,6 @@ get_servername(const char *name, const struct sockaddr *sa, const char *addr) char *hostname; char hbuf[NI_MAXHOST]; unsigned char buf[sizeof(struct in6_addr)]; - int servername = 0; if (avoid_dns) { /* @@ -184,15 +182,18 @@ get_servername(const char *name, const struct sockaddr *sa, const char *addr) * If it is an IP address, do the DNS lookup otherwise * skip the DNS lookup. */ - servername = 0; - if (strchr(name, '.') && inet_pton(AF_INET, name, buf) == 1) - servername = 1; /* IPv4 */ - else if (strchr(name, ':') && inet_pton(AF_INET6, name, buf) == 1) - servername = 1; /* or IPv6 */ - - if (servername) { + int is_fqdn = 1; + if (strchr(name, '.') == NULL) + is_fqdn = 0; /* local name */ + else if (inet_pton(AF_INET, name, buf) == 1) + is_fqdn = 0; /* IPv4 address */ + else if (inet_pton(AF_INET6, name, buf) == 1) + is_fqdn = 0; /* IPv6 addrss */ + + if (is_fqdn) { return strdup(name); } + /* Sorry, cannot avoid dns after all */ } switch (sa->sa_family) { @@ -466,8 +467,9 @@ process_clnt_dir(char *dir, char *pdir) } sprintf(clp->dirname, "%s/%s", pdir, dir); if ((clp->dir_fd = open(clp->dirname, O_RDONLY)) == -1) { - printerr(0, "ERROR: can't open %s: %s\n", - clp->dirname, strerror(errno)); + if (errno != ENOENT) + printerr(0, "ERROR: can't open %s: %s\n", + clp->dirname, strerror(errno)); goto fail_destroy_client; } fcntl(clp->dir_fd, F_SETSIG, DNOTIFY_SIGNAL); diff --git a/utils/gssd/krb5_util.c b/utils/gssd/krb5_util.c index 6275dd8..83b9651 100644 --- a/utils/gssd/krb5_util.c +++ b/utils/gssd/krb5_util.c @@ -231,7 +231,7 @@ gssd_find_existing_krb5_ccache(uid_t uid, char *dirname, continue; } if (uid == 0 && !root_uses_machine_creds && - strstr(namelist[i]->d_name, "_machine_")) { + strstr(namelist[i]->d_name, "machine_")) { printerr(3, "CC '%s' not available to root\n", statname); free(namelist[i]); @@ -825,8 +825,10 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname, myhostad[i+1] = 0; retval = get_full_hostname(myhostname, myhostname, sizeof(myhostname)); - if (retval) - goto out; + if (retval) { + /* Don't use myhostname */ + myhostname[0] = 0; + } code = krb5_get_default_realm(context, &default_realm); if (code) { @@ -852,11 +854,19 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname, } /* - * Try the "appropriate" realm first, and if nothing found for that - * realm, try the default realm (if it hasn't already been tried). + * Make sure the preferred_realm, which may have been explicitly set + * on the command line, is tried first. If nothing is found go on with + * the host and local default realm (if that hasn't already been tried). */ i = 0; realm = realmnames[i]; + + if (strcmp (realm, preferred_realm) != 0) { + realm = preferred_realm; + /* resetting the realmnames index */ + i = -1; + } + while (1) { if (realm == NULL) { tried_all = 1; @@ -883,6 +893,8 @@ find_keytab_entry(krb5_context context, krb5_keytab kt, const char *tgtname, myhostad, NULL); } else { + if (!myhostname[0]) + continue; snprintf(spn, sizeof(spn), "%s/%s@%s", svcnames[j], myhostname, realm); code = krb5_build_principal_ext(context, &princ, @@ -1236,7 +1248,7 @@ gssd_refresh_krb5_machine_credential(char *hostname, krb5_keytab kt = NULL;; int retval = 0; char *k5err = NULL; - const char *svcnames[5] = { "$", "root", "nfs", "host", NULL }; + const char *svcnames[] = { "$", "root", "nfs", "host", NULL }; /* * If a specific service name was specified, use it. diff --git a/utils/idmapd/idmapd.c b/utils/idmapd/idmapd.c index beba9c4..b6c6231 100644 --- a/utils/idmapd/idmapd.c +++ b/utils/idmapd/idmapd.c @@ -502,7 +502,7 @@ nfsdcb(int UNUSED(fd), short which, void *data) struct idmap_client *ic = data; struct idmap_msg im; u_char buf[IDMAP_MAXMSGSZ + 1]; - size_t len; + ssize_t len; ssize_t bsiz; char *bp, typebuf[IDMAP_MAXMSGSZ], buf1[IDMAP_MAXMSGSZ], authbuf[IDMAP_MAXMSGSZ], *p; @@ -511,10 +511,14 @@ nfsdcb(int UNUSED(fd), short which, void *data) if (which != EV_READ) goto out; - if ((len = read(ic->ic_fd, buf, sizeof(buf))) <= 0) { + len = read(ic->ic_fd, buf, sizeof(buf)); + if (len == 0) + /* No upcall to read; not necessarily a problem: */ + return; + if (len < 0) { xlog_warn("nfsdcb: read(%s) failed: errno %d (%s)", - ic->ic_path, len?errno:0, - len?strerror(errno):"End of File"); + ic->ic_path, errno, + strerror(errno)); nfsdreopen_one(ic); return; } diff --git a/utils/mount/configfile.c b/utils/mount/configfile.c index 6f2ee75..68b9f93 100644 --- a/utils/mount/configfile.c +++ b/utils/mount/configfile.c @@ -73,6 +73,8 @@ struct mnt_alias { }; int mnt_alias_sz = (sizeof(mnt_alias_tab)/sizeof(mnt_alias_tab[0])); +static int strict; + /* * See if the option is an alias, if so return the * real mount option along with the argument type. @@ -286,7 +288,7 @@ conf_parse_mntopts(char *section, char *arg, char *opts) char *nvalue, *ptr; int argtype; - list = conf_get_tag_list(section); + list = conf_get_tag_list(section, arg); TAILQ_FOREACH(node, &list->fields, link) { /* * Do not overwrite options if already exists @@ -310,7 +312,15 @@ conf_parse_mntopts(char *section, char *arg, char *opts) if (strcasecmp(value, "false") == 0) { if (argtype != MNT_NOARG) snprintf(buf, BUFSIZ, "no%s", field); + else if (strcasecmp(field, "bg") == 0) + snprintf(buf, BUFSIZ, "fg"); + else if (strcasecmp(field, "fg") == 0) + snprintf(buf, BUFSIZ, "bg"); + else if (strcasecmp(field, "sloppy") == 0) + strict = 1; } else if (strcasecmp(value, "true") == 0) { + if ((strcasecmp(field, "sloppy") == 0) && strict) + continue; snprintf(buf, BUFSIZ, "%s", field); } else { nvalue = strdup(value); @@ -345,6 +355,7 @@ char *conf_get_mntopts(char *spec, char *mount_point, char *ptr, *server, *config_opts; int optlen = 0; + strict = 0; SLIST_INIT(&head); list_size = 0; /* diff --git a/utils/mount/network.c b/utils/mount/network.c index 4be48cd..e2cdcaf 100644 --- a/utils/mount/network.c +++ b/utils/mount/network.c @@ -65,11 +65,6 @@ extern int nfs_mount_data_version; extern char *progname; extern int verbose; -static const char *nfs_ns_pgmtbl[] = { - "status", - NULL, -}; - static const char *nfs_mnt_pgmtbl[] = { "mount", "mountd", @@ -761,18 +756,6 @@ int probe_bothports(clnt_addr_t *mnt_server, clnt_addr_t *nfs_server) &nfs_server->pmap); } -static int nfs_probe_statd(void) -{ - struct sockaddr_in addr = { - .sin_family = AF_INET, - .sin_addr.s_addr = htonl(INADDR_LOOPBACK), - }; - rpcprog_t program = nfs_getrpcbyname(NSMPROG, nfs_ns_pgmtbl); - - return nfs_getport_ping(SAFE_SOCKADDR(&addr), sizeof(addr), - program, (rpcvers_t)1, IPPROTO_UDP); -} - /** * start_statd - attempt to start rpc.statd * diff --git a/utils/mount/nfs.man b/utils/mount/nfs.man index a8ec46c..2a42b93 100644 --- a/utils/mount/nfs.man +++ b/utils/mount/nfs.man @@ -84,6 +84,20 @@ in .SS "Options supported by all versions" These options are valid to use with any NFS version. .TP 1.5i +.BI nfsvers= n +The NFS protocol version number used to contact the server's NFS service. +If the server does not support the requested version, the mount request +fails. +If this option is not specified, the client negotiates a suitable version +with +the server, trying version 4 first, version 3 second, and version 2 last. +.TP 1.5i +.BI vers= n +This option is an alternative to the +.B nfsvers +option. +It is included for compatibility with other operating systems +.TP 1.5i .BR soft " / " hard Determines the recovery behavior of the NFS client after an NFS request times out. @@ -621,18 +635,6 @@ Using this option ensures that reports the proper maximum component length to applications in such cases. .TP 1.5i -.BI nfsvers= n -The NFS protocol version number used to contact the server's NFS service. -If the server does not support the requested version, the mount request fails. -If this option is not specified, the client negotiates a suitable version with -the server, trying version 4 first, version 3 second, and version 2 last. -.TP 1.5i -.BI vers= n -This option is an alternative to the -.B nfsvers -option. -It is included for compatibility with other operating systems. -.TP 1.5i .BR lock " / " nolock Selects whether to use the NLM sideband protocol to lock files on the server. If neither option is specified (or if diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c index 737927c..517aa62 100644 --- a/utils/mountd/cache.c +++ b/utils/mountd/cache.c @@ -347,20 +347,26 @@ static char *next_mnt(void **v, char *p) static int is_subdirectory(char *child, char *parent) { + /* Check is child is strictly a subdirectory of + * parent or a more distant descendant. + */ size_t l = strlen(parent); - if (strcmp(parent, "/") == 0) + if (strcmp(parent, "/") == 0 && child[1] != 0) return 1; - return strcmp(child, parent) == 0 - || (strncmp(child, parent, l) == 0 && child[l] == '/'); + return (strncmp(child, parent, l) == 0 && child[l] == '/'); } static int path_matches(nfs_export *exp, char *path) { - if (exp->m_export.e_flags & NFSEXP_CROSSMOUNT) - return is_subdirectory(path, exp->m_export.e_path); - return strcmp(path, exp->m_export.e_path) == 0; + /* Does the path match the export? I.e. is it an + * exact match, or does the export have CROSSMOUNT, and path + * is a descendant? + */ + return strcmp(path, exp->m_export.e_path) == 0 + || ((exp->m_export.e_flags & NFSEXP_CROSSMOUNT) + && is_subdirectory(path, exp->m_export.e_path)); } static int @@ -369,15 +375,13 @@ export_matches(nfs_export *exp, char *dom, char *path, struct addrinfo *ai) return path_matches(exp, path) && client_matches(exp, dom, ai); } -/* True iff e1 is a child of e2 and e2 has crossmnt set: */ +/* True iff e1 is a child of e2 (or descendant) and e2 has crossmnt set: */ static bool subexport(struct exportent *e1, struct exportent *e2) { char *p1 = e1->e_path, *p2 = e2->e_path; - size_t l2 = strlen(p2); return e2->e_flags & NFSEXP_CROSSMOUNT - && strncmp(p1, p2, l2) == 0 - && p1[l2] == '/'; + && is_subdirectory(p1, p2); } struct parsed_fsid { diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c index e87c0a9..6db92f0 100644 --- a/utils/nfsd/nfsd.c +++ b/utils/nfsd/nfsd.c @@ -99,8 +99,8 @@ main(int argc, char **argv) char *p, *progname, *port; char *haddr = NULL; int socket_up = 0; - int minorvers41 = 0; /* nfsv4 minor version */ - unsigned int versbits = NFSCTL_ALLBITS; + int minorvers = NFS4_VERDEFAULT; /* nfsv4 minor version */ + unsigned int versbits = NFSCTL_VERDEFAULT; unsigned int protobits = NFSCTL_ALLBITS; unsigned int proto4 = 0; unsigned int proto6 = 0; @@ -160,11 +160,11 @@ main(int argc, char **argv) case 4: if (*p == '.') { int i = atoi(p+1); - if (i != 1) { + if (i > 2) { fprintf(stderr, "%s: unsupported minor version\n", optarg); exit(1); } - minorvers41 = -1; + NFSCTL_VERUNSET(minorvers, i); break; } case 3: @@ -181,11 +181,11 @@ main(int argc, char **argv) case 4: if (*p == '.') { int i = atoi(p+1); - if (i != 1) { + if (i > 2) { fprintf(stderr, "%s: unsupported minor version\n", optarg); exit(1); } - minorvers41 = 1; + NFSCTL_VERSET(minorvers, i); break; } case 3: @@ -282,7 +282,7 @@ main(int argc, char **argv) * registered with rpcbind. Note that on older kernels w/o the right * interfaces, these are a no-op. */ - nfssvc_setvers(versbits, minorvers41); + nfssvc_setvers(versbits, minorvers); error = nfssvc_set_sockets(AF_INET, proto4, haddr, port); if (!error) diff --git a/utils/nfsd/nfssvc.c b/utils/nfsd/nfssvc.c index 683008e..8b85846 100644 --- a/utils/nfsd/nfssvc.c +++ b/utils/nfsd/nfssvc.c @@ -269,7 +269,7 @@ nfssvc_set_sockets(const int family, const unsigned int protobits, } void -nfssvc_setvers(unsigned int ctlbits, int minorvers41) +nfssvc_setvers(unsigned int ctlbits, int minorvers) { int fd, n, off; char *ptr; @@ -280,9 +280,12 @@ nfssvc_setvers(unsigned int ctlbits, int minorvers41) if (fd < 0) return; - if (minorvers41) - off += snprintf(ptr+off, sizeof(buf) - off, "%c4.1", - minorvers41 > 0 ? '+' : '-'); + for (n = NFS4_MINMINOR; n <= NFS4_MAXMINOR; n++) { + if (NFSCTL_VERISSET(minorvers, n)) + off += snprintf(ptr+off, sizeof(buf) - off, "+4.%d ", n); + else + off += snprintf(ptr+off, sizeof(buf) - off, "-4.%d ", n); + } for (n = NFSD_MINVERS; n <= NFSD_MAXVERS; n++) { if (NFSCTL_VERISSET(ctlbits, n)) off += snprintf(ptr+off, sizeof(buf) - off, "+%d ", n); diff --git a/utils/nfsdcltrack/nfsdcltrack.man b/utils/nfsdcltrack/nfsdcltrack.man index 47007df..6940788 100644 --- a/utils/nfsdcltrack/nfsdcltrack.man +++ b/utils/nfsdcltrack/nfsdcltrack.man @@ -1,53 +1,3 @@ -.\" Automatically generated by Pod::Man 2.25 (Pod::Simple 3.16) -.\" -.\" Standard preamble: -.\" ======================================================================== -.de Sp \" Vertical space (when we can't use .PP) -.if t .sp .5v -.if n .sp -.. -.de Vb \" Begin verbatim text -.ft CW -.nf -.ne \\$1 -.. -.de Ve \" End verbatim text -.ft R -.fi -.. -.\" Set up some character translations and predefined strings. \*(-- will -.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left -.\" double quote, and \*(R" will give a right double quote. \*(C+ will -.\" give a nicer C++. Capital omega is used to do unbreakable dashes and -.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, -.\" nothing in troff, for use with C<>. -.tr \(*W- -.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' -.ie n \{\ -. ds -- \(*W- -. ds PI pi -. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch -. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch -. ds L" "" -. ds R" "" -. ds C` "" -. ds C' "" -'br\} -.el\{\ -. ds -- \|\(em\| -. ds PI \(*p -. ds L" `` -. ds R" '' -'br\} -.\" -.\" Escape single quotes in literal strings from groff's Unicode transform. -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.\" -.\" If the F register is turned on, we'll generate index entries on stderr for -.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index -.\" entries marked with X<> in POD. Of course, you'll have to process the -.\" output yourself in some meaningful fashion. .ie \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" @@ -59,70 +9,6 @@ . de IX .. .\} -.\" -.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). -.\" Fear. Run. Save yourself. No user-serviceable parts. -. \" fudge factors for nroff and troff -.if n \{\ -. ds #H 0 -. ds #V .8m -. ds #F .3m -. ds #[ \f1 -. ds #] \fP -.\} -.if t \{\ -. ds #H ((1u-(\\\\n(.fu%2u))*.13m) -. ds #V .6m -. ds #F 0 -. ds #[ \& -. ds #] \& -.\} -. \" simple accents for nroff and troff -.if n \{\ -. ds ' \& -. ds ` \& -. ds ^ \& -. ds , \& -. ds ~ ~ -. ds / -.\} -.if t \{\ -. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" -. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' -. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' -. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' -. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' -. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' -.\} -. \" troff and (daisy-wheel) nroff accents -.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' -.ds 8 \h'\*(#H'\(*b\h'-\*(#H' -.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] -.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' -.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' -.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] -.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] -.ds ae a\h'-(\w'a'u*4/10)'e -.ds Ae A\h'-(\w'A'u*4/10)'E -. \" corrections for vroff -.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' -.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' -. \" for low resolution devices (crt and lpr) -.if \n(.H>23 .if \n(.V>19 \ -\{\ -. ds : e -. ds 8 ss -. ds o a -. ds d- d\h'-1'\(ga -. ds D- D\h'-1'\(hy -. ds th \o'bp' -. ds Th \o'LP' -. ds ae ae -. ds Ae AE -.\} -.rm #[ #] #H #V #F C -.\" ======================================================================== -.\" .IX Title "NFSDCLTRACK 8" .TH NFSDCLTRACK 8 "2012-10-24" "" "" .\" For nroff, turn off justification. Always turn off hyphenation; it makes diff --git a/utils/nfsidmap/Makefile.am b/utils/nfsidmap/Makefile.am index c0675c4..737a219 100644 --- a/utils/nfsidmap/Makefile.am +++ b/utils/nfsidmap/Makefile.am @@ -1,9 +1,10 @@ ## Process this file with automake to produce Makefile.in man8_MANS = nfsidmap.man - sbin_PROGRAMS = nfsidmap + nfsidmap_SOURCES = nfsidmap.c nfsidmap_LDADD = $(LIBNFSIDMAP) -lkeyutils ../../support/nfs/libnfs.a MAINTAINERCLEANFILES = Makefile.in +EXTRA_DIST = id_resolver.conf diff --git a/utils/nfsidmap/id_resolver.conf b/utils/nfsidmap/id_resolver.conf new file mode 100644 index 0000000..2c156c6 --- /dev/null +++ b/utils/nfsidmap/id_resolver.conf @@ -0,0 +1 @@ +create id_resolver * * /usr/sbin/nfsidmap -t 600 %k %d diff --git a/utils/statd/statd.c b/utils/statd/statd.c index 652546c..8c51bcc 100644 --- a/utils/statd/statd.c +++ b/utils/statd/statd.c @@ -28,6 +28,7 @@ #include "statd.h" #include "nfslib.h" +#include "nfsrpc.h" #include "nsm.h" /* Socket operations */ @@ -237,6 +238,12 @@ int main (int argc, char **argv) /* Set hostname */ MY_NAME = NULL; + /* Refuse to start if another statd is running */ + if (nfs_probe_statd()) { + fprintf(stderr, "Statd service already running!\n"); + exit(1); + } + /* Process command line switches */ while ((arg = getopt_long(argc, argv, "h?vVFNH:dn:p:o:P:L", longopts, NULL)) != EOF) { switch (arg) {