1119418Sobrien/* $OpenBSD: showmount.c,v 1.24 2022/01/28 06:18:42 guenther Exp $ */ 291396Stmm/* $NetBSD: showmount.c,v 1.7 1996/05/01 18:14:10 cgd Exp $ */ 3178589Smarius 491396Stmm/* 591396Stmm * Copyright (c) 1989, 1993, 1995 691396Stmm * The Regents of the University of California. All rights reserved. 791396Stmm * 891396Stmm * This code is derived from software contributed to Berkeley by 991396Stmm * Rick Macklem at The University of Guelph. 1091396Stmm * 1191396Stmm * Redistribution and use in source and binary forms, with or without 1291396Stmm * modification, are permitted provided that the following conditions 1391396Stmm * are met: 1491396Stmm * 1. Redistributions of source code must retain the above copyright 1591396Stmm * notice, this list of conditions and the following disclaimer. 1691396Stmm * 2. Redistributions in binary form must reproduce the above copyright 1791396Stmm * notice, this list of conditions and the following disclaimer in the 1891396Stmm * documentation and/or other materials provided with the distribution. 1991396Stmm * 3. Neither the name of the University nor the names of its contributors 2091396Stmm * may be used to endorse or promote products derived from this software 2191396Stmm * without specific prior written permission. 2291396Stmm * 2391396Stmm * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2491396Stmm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2591396Stmm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2691396Stmm * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2791396Stmm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2891396Stmm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29133731Smarius * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3091396Stmm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3191396Stmm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32119418Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33119418Sobrien * SUCH DAMAGE. 34119418Sobrien */ 3591396Stmm 3691396Stmm#include <sys/socket.h> 3791396Stmm 3891396Stmm#include <netdb.h> 3991396Stmm#include <rpc/rpc.h> 4091396Stmm#include <rpc/pmap_clnt.h> 4191396Stmm#include <rpc/pmap_prot.h> 4291396Stmm#include <nfs/rpcv2.h> 43257176Sglebius 44257176Sglebius#include <stdio.h> 45130026Sphk#include <stdlib.h> 46257176Sglebius#include <string.h> 4791396Stmm#include <unistd.h> 4891396Stmm#include <vis.h> 4991396Stmm#include <err.h> 5091396Stmm 51133731Smarius/* Constant defs */ 52119696Smarcel#define ALL 1 5391396Stmm#define DIRS 2 54133731Smarius 5591396Stmm#define DODUMP 0x1 5691396Stmm#define DOEXPORTS 0x2 5791396Stmm 5891396Stmmstruct mountlist { 5991396Stmm struct mountlist *ml_left; 6091396Stmm struct mountlist *ml_right; 6191396Stmm char ml_host[RPCMNT_NAMELEN+1]; 6291396Stmm char ml_dirp[RPCMNT_PATHLEN+1]; 6391396Stmm}; 6491396Stmm 65119351Smarcelstruct grouplist { 66119351Smarcel struct grouplist *gr_next; 6791396Stmm char gr_name[RPCMNT_NAMELEN+1]; 68119280Simp}; 69119280Simp 7091396Stmmstruct exportslist { 71119351Smarcel struct exportslist *ex_next; 72119351Smarcel struct grouplist *ex_groups; 7391396Stmm char ex_dirp[RPCMNT_PATHLEN+1]; 7491396Stmm}; 7591396Stmm 7691396Stmmstatic struct mountlist *mntdump; 7791396Stmmstatic struct exportslist *exports; 7891396Stmmstatic int type = 0; 7991396Stmm 8091396Stmmvoid print_dump(struct mountlist *); 8191396Stmmvoid usage(void); 8291396Stmmint xdr_mntdump(XDR *, struct mountlist **); 8391396Stmmint xdr_exports(XDR *, struct exportslist **); 8491396Stmm 85108976Stmm/* 86108976Stmm * This command queries the NFS mount daemon for its mount list and/or 87108976Stmm * its exports list and prints them out. 8891396Stmm * See "NFS: Network File System Protocol Specification, RFC1094, Appendix A" 8991396Stmm * and the "Network File System Protocol XXX.." 9091396Stmm * for detailed information on the protocol. 9191396Stmm */ 9291396Stmmint 93108976Stmmmain(int argc, char *argv[]) 94108976Stmm{ 95108976Stmm struct exportslist *exp; 96108976Stmm struct grouplist *grp; 97108976Stmm struct sockaddr_in clnt_sin; 9891396Stmm struct hostent *hp; 9991396Stmm struct timeval timeout; 10091396Stmm int rpcs = 0, mntvers = 1; 10191396Stmm enum clnt_stat estat; 10291396Stmm CLIENT *client; 10391396Stmm char *host; 104227843Smarius int ch, clnt_sock; 10591396Stmm 10691396Stmm if (pledge("stdio rpath inet dns", NULL) == -1) 10791396Stmm err(1, "pledge"); 10891396Stmm 10991396Stmm while ((ch = getopt(argc, argv, "ade3")) != -1) 11091396Stmm switch (ch) { 11191396Stmm case 'a': 11291396Stmm if (type == 0) { 113113506Smdodd type = ALL; 114113506Smdodd rpcs |= DODUMP; 115113506Smdodd } else 11691396Stmm usage(); 117133731Smarius break; 118133731Smarius case 'd': 119133731Smarius if (type == 0) { 120133731Smarius type = DIRS; 12191396Stmm rpcs |= DODUMP; 12291396Stmm } else 12391396Stmm usage(); 12491396Stmm break; 125133731Smarius case 'e': 126178589Smarius rpcs |= DOEXPORTS; 12791396Stmm break; 128143161Simp case '3': 12991396Stmm mntvers = 3; 13091396Stmm break; 13191396Stmm default: 13291396Stmm usage(); 13391396Stmm } 13491396Stmm argc -= optind; 13591396Stmm argv += optind; 136178589Smarius 137178589Smarius if (argc > 0) 138178589Smarius host = *argv; 139178589Smarius else 140178589Smarius host = "localhost"; 141133731Smarius 142133731Smarius if (rpcs == 0) 143133731Smarius rpcs = DODUMP; 144178589Smarius 145133731Smarius if ((hp = gethostbyname(host)) == NULL) { 14691396Stmm fprintf(stderr, "showmount: unknown host %s\n", host); 147117116Stmm exit(1); 14891396Stmm } 149117116Stmm bzero(&clnt_sin, sizeof clnt_sin); 150178589Smarius clnt_sin.sin_family = AF_INET; 15191396Stmm bcopy(hp->h_addr, (char *)&clnt_sin.sin_addr, hp->h_length); 152117116Stmm clnt_sock = RPC_ANYSOCK; 153117116Stmm client = clnttcp_create(&clnt_sin, RPCPROG_MNT, mntvers, 15491396Stmm &clnt_sock, 0, 0); 155178589Smarius if (client == NULL) { 156178589Smarius clnt_pcreateerror("showmount: clnttcp_create"); 15791396Stmm exit(1); 158178470Smarius } 159137982Syongari timeout.tv_sec = 30; 160137982Syongari timeout.tv_usec = 0; 16191396Stmm 16291396Stmm if (pledge("stdio rpath", NULL) == -1) 16391396Stmm err(1, "pledge"); 16491396Stmm 16591396Stmm if (rpcs & DODUMP) { 16691396Stmm estat = clnt_call(client, RPCMNT_DUMP, xdr_void, NULL, 16791396Stmm xdr_mntdump, (char *)&mntdump, timeout); 16891396Stmm if (estat != RPC_SUCCESS) { 16991396Stmm fprintf(stderr, "showmount: Can't do Mountdump rpc: "); 17091396Stmm clnt_perrno(estat); 17191396Stmm exit(1); 172178589Smarius } 173178589Smarius } 174178589Smarius if (rpcs & DOEXPORTS) { 17591396Stmm estat = clnt_call(client, RPCMNT_EXPORT, xdr_void, NULL, 17691396Stmm xdr_exports, (char *)&exports, timeout); 177137982Syongari if (estat != RPC_SUCCESS) { 178137982Syongari fprintf(stderr, "showmount: Can't do Exports rpc: "); 17991396Stmm clnt_perrno(estat); 180178589Smarius exit(1); 181178589Smarius } 182178589Smarius } 18391396Stmm 18491396Stmm /* Now just print out the results */ 18591396Stmm if (rpcs & DODUMP) { 18691396Stmm switch (type) { 18791396Stmm case ALL: 188178589Smarius printf("All mount points on %s:\n", host); 189178589Smarius break; 19091396Stmm case DIRS: 191178589Smarius printf("Directories on %s:\n", host); 192178589Smarius break; 193178589Smarius default: 194178589Smarius printf("Hosts on %s:\n", host); 195178589Smarius break; 196178589Smarius } 19791396Stmm print_dump(mntdump); 198133731Smarius } 199147256Sbrooks if (rpcs & DOEXPORTS) { 200133731Smarius char vp[(RPCMNT_PATHLEN+1)*4]; 201133731Smarius char vn[(RPCMNT_NAMELEN+1)*4]; 202133731Smarius 203133731Smarius printf("Exports list on %s:\n", host); 204133731Smarius exp = exports; 205133731Smarius while (exp) { 206133731Smarius strnvis(vp, exp->ex_dirp, sizeof vp, VIS_CSTYLE); 207133731Smarius printf("%-34s ", vp); 208133731Smarius grp = exp->ex_groups; 209133731Smarius if (grp == NULL) { 210133731Smarius printf("Everyone\n"); 211133731Smarius } else { 212133731Smarius while (grp) { 213133731Smarius strnvis(vn, grp->gr_name, sizeof vn, 214133731Smarius VIS_CSTYLE); 215178589Smarius printf("%s ", vn); 216133731Smarius grp = grp->gr_next; 217133731Smarius } 21891396Stmm printf("\n"); 219178589Smarius } 220178589Smarius exp = exp->ex_next; 221178589Smarius } 222178589Smarius } 223178589Smarius 224178589Smarius exit(0); 225178589Smarius} 226178589Smarius 227178589Smarius/* 228178589Smarius * Xdr routine for retrieving the mount dump list 229178589Smarius */ 230178589Smariusint 231178589Smariusxdr_mntdump(XDR *xdrsp, struct mountlist **mlp) 232178589Smarius{ 233178589Smarius struct mountlist *mp, **otp = NULL, *tp; 234178589Smarius int bool, val, val2; 235178589Smarius char *strp; 236178589Smarius 237178589Smarius *mlp = NULL; 238178589Smarius if (!xdr_bool(xdrsp, &bool)) 239178589Smarius return (0); 240178589Smarius while (bool) { 241178589Smarius mp = malloc(sizeof(struct mountlist)); 242178589Smarius if (mp == NULL) 243178589Smarius return (0); 244178589Smarius mp->ml_left = mp->ml_right = NULL; 245178589Smarius strp = mp->ml_host; 246178589Smarius if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 247178589Smarius return (0); 248133731Smarius strp = mp->ml_dirp; 249133731Smarius if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 250178589Smarius return (0); 251133731Smarius 252133731Smarius /* 253133731Smarius * Build a binary tree on sorted order of either host or dirp. 254133731Smarius * Drop any duplications. 255133731Smarius */ 256178589Smarius if (*mlp == NULL) { 257178589Smarius *mlp = mp; 258178589Smarius } else { 259178589Smarius tp = *mlp; 260178589Smarius while (tp) { 261178589Smarius val = strcmp(mp->ml_host, tp->ml_host); 262133731Smarius val2 = strcmp(mp->ml_dirp, tp->ml_dirp); 263133731Smarius switch (type) { 264133731Smarius case ALL: 265133731Smarius if (val == 0) { 266133731Smarius if (val2 == 0) { 267133731Smarius free((caddr_t)mp); 268133731Smarius goto next; 269133731Smarius } 270133731Smarius val = val2; 271133731Smarius } 272178589Smarius break; 273133731Smarius case DIRS: 274178589Smarius if (val2 == 0) { 275133731Smarius free((caddr_t)mp); 276133731Smarius goto next; 277133731Smarius } 278133731Smarius val = val2; 279178589Smarius break; 280178589Smarius default: 281133731Smarius if (val == 0) { 282178589Smarius free((caddr_t)mp); 283178589Smarius goto next; 284178589Smarius } 285178589Smarius break; 286133731Smarius } 287133731Smarius if (val < 0) { 288133731Smarius otp = &tp->ml_left; 289133731Smarius tp = tp->ml_left; 290178589Smarius } else { 291178589Smarius otp = &tp->ml_right; 292178589Smarius tp = tp->ml_right; 293178589Smarius } 294178589Smarius } 295178589Smarius *otp = mp; 296133731Smarius } 297133731Smariusnext: 298133731Smarius if (!xdr_bool(xdrsp, &bool)) 299133731Smarius return (0); 300133731Smarius } 301133731Smarius return (1); 302138712Smarius} 303178589Smarius 304142117Smarius/* 305142117Smarius * Xdr routine to retrieve exports list 306138712Smarius */ 307178589Smariusint 308138712Smariusxdr_exports(XDR *xdrsp, struct exportslist **exp) 309178589Smarius{ 310138712Smarius struct exportslist *ep; 311133731Smarius struct grouplist *gp; 312142964Smarius int bool, grpbool; 313178589Smarius char *strp; 314178589Smarius 315178589Smarius *exp = NULL; 316178589Smarius if (!xdr_bool(xdrsp, &bool)) 317142964Smarius return (0); 318178589Smarius while (bool) { 319178589Smarius ep = malloc(sizeof(struct exportslist)); 320178589Smarius if (ep == NULL) 321178589Smarius return (0); 322178589Smarius ep->ex_groups = NULL; 323178589Smarius strp = ep->ex_dirp; 324178589Smarius if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 325178589Smarius return (0); 326178589Smarius if (!xdr_bool(xdrsp, &grpbool)) 327178589Smarius return (0); 328178589Smarius while (grpbool) { 329178589Smarius gp = malloc(sizeof(struct grouplist)); 330178589Smarius if (gp == NULL) 331178589Smarius return (0); 332133731Smarius strp = gp->gr_name; 333133731Smarius if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 334133731Smarius return (0); 335133731Smarius gp->gr_next = ep->ex_groups; 336178589Smarius ep->ex_groups = gp; 337178589Smarius if (!xdr_bool(xdrsp, &grpbool)) 338133731Smarius return (0); 339133731Smarius } 340178589Smarius ep->ex_next = *exp; 341178589Smarius *exp = ep; 342133731Smarius if (!xdr_bool(xdrsp, &bool)) 343133731Smarius return (0); 344133731Smarius } 345133731Smarius return (1); 346133731Smarius} 347133731Smarius 34891396Stmmvoid 34991396Stmmusage(void) 35091396Stmm{ 35191396Stmm 35291396Stmm fprintf(stderr, "usage: showmount [-3ade] [host]\n"); 35391396Stmm exit(1); 35491396Stmm} 35591396Stmm 35691396Stmm/* 35791396Stmm * Print the binary tree in inorder so that output is sorted. 358137982Syongari */ 359166901Spisovoid 36091396Stmmprint_dump(struct mountlist *mp) 361108976Stmm{ 36291396Stmm char vn[(RPCMNT_NAMELEN+1)*4]; 36391396Stmm char vp[(RPCMNT_PATHLEN+1)*4]; 36491396Stmm 36591396Stmm if (mp == NULL) 36691396Stmm return; 367178589Smarius if (mp->ml_left) 368178589Smarius print_dump(mp->ml_left); 36991396Stmm switch (type) { 370178589Smarius case ALL: 371178589Smarius strvis(vn, mp->ml_host, VIS_CSTYLE); 372137982Syongari strvis(vp, mp->ml_dirp, VIS_CSTYLE); 373137982Syongari printf("%s:%s\n", vn, vp); 374133599Smarius break; 37591396Stmm case DIRS: 376108976Stmm strvis(vp, mp->ml_dirp, VIS_CSTYLE); 377108976Stmm printf("%s\n", vp); 378108976Stmm break; 379108976Stmm default: 380178589Smarius strvis(vn, mp->ml_host, VIS_CSTYLE); 381178589Smarius printf("%s\n", vn); 382108976Stmm break; 383178589Smarius } 384178589Smarius if (mp->ml_right) 385137982Syongari print_dump(mp->ml_right); 386108976Stmm} 387178589Smarius