1 /* $OpenBSD: showmount.c,v 1.23 2018/04/26 12:42:51 guenther Exp $ */ 2 /* $NetBSD: showmount.c,v 1.7 1996/05/01 18:14:10 cgd Exp $ */ 3 4 /* 5 * Copyright (c) 1989, 1993, 1995 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * Rick Macklem at The University of Guelph. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 */ 35 36 #include <sys/socket.h> 37 38 #include <netdb.h> 39 #include <rpc/rpc.h> 40 #include <rpc/pmap_clnt.h> 41 #include <rpc/pmap_prot.h> 42 #include <nfs/rpcv2.h> 43 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <string.h> 47 #include <unistd.h> 48 #include <vis.h> 49 #include <err.h> 50 51 /* Constant defs */ 52 #define ALL 1 53 #define DIRS 2 54 55 #define DODUMP 0x1 56 #define DOEXPORTS 0x2 57 58 struct mountlist { 59 struct mountlist *ml_left; 60 struct mountlist *ml_right; 61 char ml_host[RPCMNT_NAMELEN+1]; 62 char ml_dirp[RPCMNT_PATHLEN+1]; 63 }; 64 65 struct grouplist { 66 struct grouplist *gr_next; 67 char gr_name[RPCMNT_NAMELEN+1]; 68 }; 69 70 struct exportslist { 71 struct exportslist *ex_next; 72 struct grouplist *ex_groups; 73 char ex_dirp[RPCMNT_PATHLEN+1]; 74 }; 75 76 static struct mountlist *mntdump; 77 static struct exportslist *exports; 78 static int type = 0; 79 80 void print_dump(struct mountlist *); 81 void usage(void); 82 int xdr_mntdump(XDR *, struct mountlist **); 83 int xdr_exports(XDR *, struct exportslist **); 84 85 /* 86 * This command queries the NFS mount daemon for it's mount list and/or 87 * it's exports list and prints them out. 88 * See "NFS: Network File System Protocol Specification, RFC1094, Appendix A" 89 * and the "Network File System Protocol XXX.." 90 * for detailed information on the protocol. 91 */ 92 int 93 main(int argc, char *argv[]) 94 { 95 struct exportslist *exp; 96 struct grouplist *grp; 97 struct sockaddr_in clnt_sin; 98 struct hostent *hp; 99 struct timeval timeout; 100 int rpcs = 0, mntvers = 1; 101 enum clnt_stat estat; 102 CLIENT *client; 103 char *host; 104 int ch, clnt_sock; 105 106 if (pledge("stdio rpath inet dns", NULL) == -1) 107 err(1, "pledge"); 108 109 while ((ch = getopt(argc, argv, "ade3")) != -1) 110 switch (ch) { 111 case 'a': 112 if (type == 0) { 113 type = ALL; 114 rpcs |= DODUMP; 115 } else 116 usage(); 117 break; 118 case 'd': 119 if (type == 0) { 120 type = DIRS; 121 rpcs |= DODUMP; 122 } else 123 usage(); 124 break; 125 case 'e': 126 rpcs |= DOEXPORTS; 127 break; 128 case '3': 129 mntvers = 3; 130 break; 131 default: 132 usage(); 133 } 134 argc -= optind; 135 argv += optind; 136 137 if (argc > 0) 138 host = *argv; 139 else 140 host = "localhost"; 141 142 if (rpcs == 0) 143 rpcs = DODUMP; 144 145 if ((hp = gethostbyname(host)) == NULL) { 146 fprintf(stderr, "showmount: unknown host %s\n", host); 147 exit(1); 148 } 149 bzero(&clnt_sin, sizeof clnt_sin); 150 clnt_sin.sin_family = AF_INET; 151 bcopy(hp->h_addr, (char *)&clnt_sin.sin_addr, hp->h_length); 152 clnt_sock = RPC_ANYSOCK; 153 client = clnttcp_create(&clnt_sin, RPCPROG_MNT, mntvers, 154 &clnt_sock, 0, 0); 155 if (client == NULL) { 156 clnt_pcreateerror("showmount: clnttcp_create"); 157 exit(1); 158 } 159 timeout.tv_sec = 30; 160 timeout.tv_usec = 0; 161 162 if (pledge("stdio rpath", NULL) == -1) 163 err(1, "pledge"); 164 165 if (rpcs & DODUMP) { 166 estat = clnt_call(client, RPCMNT_DUMP, xdr_void, NULL, 167 xdr_mntdump, (char *)&mntdump, timeout); 168 if (estat != RPC_SUCCESS) { 169 fprintf(stderr, "showmount: Can't do Mountdump rpc: "); 170 clnt_perrno(estat); 171 exit(1); 172 } 173 } 174 if (rpcs & DOEXPORTS) { 175 estat = clnt_call(client, RPCMNT_EXPORT, xdr_void, NULL, 176 xdr_exports, (char *)&exports, timeout); 177 if (estat != RPC_SUCCESS) { 178 fprintf(stderr, "showmount: Can't do Exports rpc: "); 179 clnt_perrno(estat); 180 exit(1); 181 } 182 } 183 184 /* Now just print out the results */ 185 if (rpcs & DODUMP) { 186 switch (type) { 187 case ALL: 188 printf("All mount points on %s:\n", host); 189 break; 190 case DIRS: 191 printf("Directories on %s:\n", host); 192 break; 193 default: 194 printf("Hosts on %s:\n", host); 195 break; 196 } 197 print_dump(mntdump); 198 } 199 if (rpcs & DOEXPORTS) { 200 char vp[(RPCMNT_PATHLEN+1)*4]; 201 char vn[(RPCMNT_NAMELEN+1)*4]; 202 203 printf("Exports list on %s:\n", host); 204 exp = exports; 205 while (exp) { 206 strnvis(vp, exp->ex_dirp, sizeof vp, VIS_CSTYLE); 207 printf("%-34s ", vp); 208 grp = exp->ex_groups; 209 if (grp == NULL) { 210 printf("Everyone\n"); 211 } else { 212 while (grp) { 213 strnvis(vn, grp->gr_name, sizeof vn, 214 VIS_CSTYLE); 215 printf("%s ", vn); 216 grp = grp->gr_next; 217 } 218 printf("\n"); 219 } 220 exp = exp->ex_next; 221 } 222 } 223 224 exit(0); 225 } 226 227 /* 228 * Xdr routine for retrieving the mount dump list 229 */ 230 int 231 xdr_mntdump(XDR *xdrsp, struct mountlist **mlp) 232 { 233 struct mountlist *mp, **otp = NULL, *tp; 234 int bool, val, val2; 235 char *strp; 236 237 *mlp = NULL; 238 if (!xdr_bool(xdrsp, &bool)) 239 return (0); 240 while (bool) { 241 mp = malloc(sizeof(struct mountlist)); 242 if (mp == NULL) 243 return (0); 244 mp->ml_left = mp->ml_right = NULL; 245 strp = mp->ml_host; 246 if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 247 return (0); 248 strp = mp->ml_dirp; 249 if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 250 return (0); 251 252 /* 253 * Build a binary tree on sorted order of either host or dirp. 254 * Drop any duplications. 255 */ 256 if (*mlp == NULL) { 257 *mlp = mp; 258 } else { 259 tp = *mlp; 260 while (tp) { 261 val = strcmp(mp->ml_host, tp->ml_host); 262 val2 = strcmp(mp->ml_dirp, tp->ml_dirp); 263 switch (type) { 264 case ALL: 265 if (val == 0) { 266 if (val2 == 0) { 267 free((caddr_t)mp); 268 goto next; 269 } 270 val = val2; 271 } 272 break; 273 case DIRS: 274 if (val2 == 0) { 275 free((caddr_t)mp); 276 goto next; 277 } 278 val = val2; 279 break; 280 default: 281 if (val == 0) { 282 free((caddr_t)mp); 283 goto next; 284 } 285 break; 286 } 287 if (val < 0) { 288 otp = &tp->ml_left; 289 tp = tp->ml_left; 290 } else { 291 otp = &tp->ml_right; 292 tp = tp->ml_right; 293 } 294 } 295 *otp = mp; 296 } 297 next: 298 if (!xdr_bool(xdrsp, &bool)) 299 return (0); 300 } 301 return (1); 302 } 303 304 /* 305 * Xdr routine to retrieve exports list 306 */ 307 int 308 xdr_exports(XDR *xdrsp, struct exportslist **exp) 309 { 310 struct exportslist *ep; 311 struct grouplist *gp; 312 int bool, grpbool; 313 char *strp; 314 315 *exp = NULL; 316 if (!xdr_bool(xdrsp, &bool)) 317 return (0); 318 while (bool) { 319 ep = malloc(sizeof(struct exportslist)); 320 if (ep == NULL) 321 return (0); 322 ep->ex_groups = NULL; 323 strp = ep->ex_dirp; 324 if (!xdr_string(xdrsp, &strp, RPCMNT_PATHLEN)) 325 return (0); 326 if (!xdr_bool(xdrsp, &grpbool)) 327 return (0); 328 while (grpbool) { 329 gp = malloc(sizeof(struct grouplist)); 330 if (gp == NULL) 331 return (0); 332 strp = gp->gr_name; 333 if (!xdr_string(xdrsp, &strp, RPCMNT_NAMELEN)) 334 return (0); 335 gp->gr_next = ep->ex_groups; 336 ep->ex_groups = gp; 337 if (!xdr_bool(xdrsp, &grpbool)) 338 return (0); 339 } 340 ep->ex_next = *exp; 341 *exp = ep; 342 if (!xdr_bool(xdrsp, &bool)) 343 return (0); 344 } 345 return (1); 346 } 347 348 void 349 usage(void) 350 { 351 352 fprintf(stderr, "usage: showmount [-3ade] [host]\n"); 353 exit(1); 354 } 355 356 /* 357 * Print the binary tree in inorder so that output is sorted. 358 */ 359 void 360 print_dump(struct mountlist *mp) 361 { 362 char vn[(RPCMNT_NAMELEN+1)*4]; 363 char vp[(RPCMNT_PATHLEN+1)*4]; 364 365 if (mp == NULL) 366 return; 367 if (mp->ml_left) 368 print_dump(mp->ml_left); 369 switch (type) { 370 case ALL: 371 strvis(vn, mp->ml_host, VIS_CSTYLE); 372 strvis(vp, mp->ml_dirp, VIS_CSTYLE); 373 printf("%s:%s\n", vn, vp); 374 break; 375 case DIRS: 376 strvis(vp, mp->ml_dirp, VIS_CSTYLE); 377 printf("%s\n", vp); 378 break; 379 default: 380 strvis(vn, mp->ml_host, VIS_CSTYLE); 381 printf("%s\n", vn); 382 break; 383 } 384 if (mp->ml_right) 385 print_dump(mp->ml_right); 386 } 387