amq.c revision 38494
11638Srgrimes/* 21638Srgrimes * Copyright (c) 1997-1998 Erez Zadok 31638Srgrimes * Copyright (c) 1990 Jan-Simon Pendry 41638Srgrimes * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 51638Srgrimes * Copyright (c) 1990 The Regents of the University of California. 61638Srgrimes * All rights reserved. 71638Srgrimes * 81638Srgrimes * This code is derived from software contributed to Berkeley by 91638Srgrimes * Jan-Simon Pendry at Imperial College, London. 101638Srgrimes * 111638Srgrimes * Redistribution and use in source and binary forms, with or without 121638Srgrimes * modification, are permitted provided that the following conditions 131638Srgrimes * are met: 141638Srgrimes * 1. Redistributions of source code must retain the above copyright 151638Srgrimes * notice, this list of conditions and the following disclaimer. 161638Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 171638Srgrimes * notice, this list of conditions and the following disclaimer in the 181638Srgrimes * documentation and/or other materials provided with the distribution. 191638Srgrimes * 3. All advertising materials mentioning features or use of this software 201638Srgrimes * must display the following acknowledgement: 211638Srgrimes * This product includes software developed by the University of 221638Srgrimes * California, Berkeley and its contributors. 231638Srgrimes * 4. Neither the name of the University nor the names of its contributors 241638Srgrimes * may be used to endorse or promote products derived from this software 251638Srgrimes * without specific prior written permission. 261638Srgrimes * 271638Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 281638Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 291638Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 301638Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 311638Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 321638Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3350476Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 341638Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35201118Strasz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 361638Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3779538Sru * SUCH DAMAGE. 381638Srgrimes * 391638Srgrimes * %W% (Berkeley) %G% 401638Srgrimes * 411638Srgrimes * $Id: amq.c,v 5.2.2.1 1992/02/09 15:09:16 jsp beta $ 4284306Sru * 431638Srgrimes */ 441638Srgrimes 451638Srgrimes/* 461638Srgrimes * Automounter query tool 471638Srgrimes */ 481638Srgrimes 491638Srgrimes#ifndef lint 501638Srgrimeschar copyright[] = "\ 511638Srgrimes@(#)Copyright (c) 1997-1998 Erez Zadok\n\ 521638Srgrimes@(#)Copyright (c) 1990 Jan-Simon Pendry\n\ 531638Srgrimes@(#)Copyright (c) 1990 Imperial College of Science, Technology & Medicine\n\ 5471101Sru@(#)Copyright (c) 1990 The Regents of the University of California.\n\ 551638Srgrimes@(#)All rights reserved.\n"; 561638Srgrimes#if __GNUC__ < 2 571638Srgrimesstatic char rcsid[] = "$Id: amq.c,v 6.0 1997-1998/01/01 15:09:16 ezk $"; 581638Srgrimesstatic char sccsid[] = "%W% (Berkeley) %G%"; 591638Srgrimes#endif /* __GNUC__ < 2 */ 601638Srgrimes#endif /* not lint */ 611638Srgrimes 621638Srgrimes#ifdef HAVE_CONFIG_H 631638Srgrimes# include <config.h> 64117011Sru#endif /* HAVE_CONFIG_H */ 65117011Sru#include <am_defs.h> 661638Srgrimes#include <amq.h> 671638Srgrimes 681638Srgrimes/* locals */ 69117011Sruchar *progname; 70117011Srustatic int flush_flag; 711638Srgrimesstatic int minfo_flag; 721638Srgrimesstatic int getpid_flag; 731638Srgrimesstatic int unmount_flag; 7471101Srustatic int stats_flag; 751638Srgrimesstatic int getvers_flag; 761638Srgrimesstatic int amd_program_number = AMQ_PROGRAM; 771638Srgrimesstatic int use_tcp_flag, use_udp_flag; 781638Srgrimesstatic char *debug_opts; 791638Srgrimesstatic char *amq_logfile; 801638Srgrimesstatic char *mount_map; 811638Srgrimesstatic char *xlog_optstr; 821638Srgrimesstatic char localhost[] = "localhost"; 83117011Srustatic char *def_server = localhost; 84117011Sru 851638Srgrimes/* externals */ 86117011Sruextern int optind; 87117011Sruextern char *optarg; 881638Srgrimes 891638Srgrimes/* forward decalrations */ 901638Srgrimes#ifdef HAVE_TRANSPORT_TYPE_TLI 911638Srgrimesstatic CLIENT *get_secure_amd_client(char *host, struct timeval *tv, int *sock); 921638Srgrimesstatic int amq_bind_resv_port(int td, u_short *pp); 931638Srgrimes#else /* not HAVE_TRANSPORT_TYPE_TLI */ 94117011Srustatic int privsock(int ty); 95117011Sru#endif /* not HAVE_TRANSPORT_TYPE_TLI */ 961638Srgrimes 971638Srgrimes/* dummy variables */ 981638Srgrimeschar hostname[MAXHOSTNAMELEN]; 991638Srgrimesint orig_umask, foreground, debug_flags; 1001638Srgrimespid_t mypid; 1011638Srgrimesserv_state amd_state; 1021638Srgrimes 1031638Srgrimes/* structures */ 1041638Srgrimesenum show_opt { 1051638Srgrimes Full, Stats, Calc, Short, ShowDone 1061638Srgrimes}; 1071638Srgrimes 1081638Srgrimes 109117011Sru/* 110117011Sru * If (e) is Calc then just calculate the sizes 1111638Srgrimes * Otherwise display the mount node on stdout 1121638Srgrimes */ 113131530Srustatic void 114131530Srushow_mti(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *twid) 1151638Srgrimes{ 116201115Strasz switch (e) { 1171638Srgrimes case Calc: 1181638Srgrimes { 1191638Srgrimes int mw = strlen(mt->mt_mountinfo); 1201638Srgrimes int dw = strlen(mt->mt_directory); 121201115Strasz int tw = strlen(mt->mt_type); 1221638Srgrimes if (mw > *mwid) 123201115Strasz *mwid = mw; 124201115Strasz if (dw > *dwid) 1251638Srgrimes *dwid = dw; 1261638Srgrimes if (tw > *twid) 1271638Srgrimes *twid = tw; 1281638Srgrimes } 129201115Strasz break; 130201115Strasz 131201115Strasz case Full: 132201115Strasz { 1331638Srgrimes struct tm *tp = localtime((time_t *) &mt->mt_mounttime); 1341638Srgrimes printf("%-*.*s %-*.*s %-*.*s %s\n\t%-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n", 1351638Srgrimes *dwid, *dwid, 1361638Srgrimes *mt->mt_directory ? mt->mt_directory : "/", /* XXX */ 1371638Srgrimes *twid, *twid, 1381638Srgrimes mt->mt_type, 1391638Srgrimes *mwid, *mwid, 1401638Srgrimes mt->mt_mountinfo, 1411638Srgrimes mt->mt_mountpoint, 1421638Srgrimes 1431638Srgrimes mt->mt_mountuid, 1441638Srgrimes mt->mt_getattr, 1451638Srgrimes mt->mt_lookup, 1461638Srgrimes mt->mt_readdir, 14781296Ssheldonh mt->mt_readlink, 14881296Ssheldonh mt->mt_statfs, 1491638Srgrimes 1501638Srgrimes tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year, 1511638Srgrimes tp->tm_mon + 1, tp->tm_mday, 1521638Srgrimes tp->tm_hour, tp->tm_min, tp->tm_sec); 1531638Srgrimes } 1541638Srgrimes break; 1551638Srgrimes 1561638Srgrimes case Stats: 1571638Srgrimes { 1581638Srgrimes struct tm *tp = localtime((time_t *) &mt->mt_mounttime); 1591638Srgrimes printf("%-*.*s %-5d %-7d %-6d %-7d %-7d %-6d %02d/%02d/%02d %02d:%02d:%02d\n", 1601638Srgrimes *dwid, *dwid, 1611638Srgrimes *mt->mt_directory ? mt->mt_directory : "/", /* XXX */ 1621638Srgrimes 1631638Srgrimes mt->mt_mountuid, 1641638Srgrimes mt->mt_getattr, 1651638Srgrimes mt->mt_lookup, 1661638Srgrimes mt->mt_readdir, 1671638Srgrimes mt->mt_readlink, 1681638Srgrimes mt->mt_statfs, 1691638Srgrimes 1701638Srgrimes tp->tm_year > 99 ? tp->tm_year - 100 : tp->tm_year, 1711638Srgrimes tp->tm_mon + 1, tp->tm_mday, 1721638Srgrimes tp->tm_hour, tp->tm_min, tp->tm_sec); 1731638Srgrimes } 1741638Srgrimes break; 1751638Srgrimes 1761638Srgrimes case Short: 1771638Srgrimes { 1781638Srgrimes printf("%-*.*s %-*.*s %-*.*s %s\n", 1791638Srgrimes *dwid, *dwid, 1801638Srgrimes *mt->mt_directory ? mt->mt_directory : "/", 1811638Srgrimes *twid, *twid, 1821638Srgrimes mt->mt_type, 1831638Srgrimes *mwid, *mwid, 1841638Srgrimes mt->mt_mountinfo, 1851638Srgrimes mt->mt_mountpoint); 1861638Srgrimes } 1871638Srgrimes break; 1881638Srgrimes 1891638Srgrimes default: 1901638Srgrimes break; 1911638Srgrimes } 1921638Srgrimes} 1931638Srgrimes 1941638Srgrimes/* 1951638Srgrimes * Display a mount tree. 1961638Srgrimes */ 1971638Srgrimesstatic void 1981638Srgrimesshow_mt(amq_mount_tree *mt, enum show_opt e, int *mwid, int *dwid, int *pwid) 1991638Srgrimes{ 200117011Sru while (mt) { 201117011Sru show_mti(mt, e, mwid, dwid, pwid); 2021638Srgrimes show_mt(mt->mt_next, e, mwid, dwid, pwid); 2031638Srgrimes mt = mt->mt_child; 204117011Sru } 205141846Sru} 2061638Srgrimes 2071638Srgrimesstatic void 2081638Srgrimesshow_mi(amq_mount_info_list *ml, enum show_opt e, int *mwid, int *dwid, int *twid) 2091638Srgrimes{ 210117011Sru int i; 211117011Sru 212141846Sru switch (e) { 2131638Srgrimes 214117011Sru case Calc: 215117011Sru { 2161638Srgrimes for (i = 0; i < ml->amq_mount_info_list_len; i++) { 2171638Srgrimes amq_mount_info *mi = &ml->amq_mount_info_list_val[i]; 2181638Srgrimes int mw = strlen(mi->mi_mountinfo); 2191638Srgrimes int dw = strlen(mi->mi_mountpt); 2201638Srgrimes int tw = strlen(mi->mi_type); 2211638Srgrimes if (mw > *mwid) 2221638Srgrimes *mwid = mw; 2231638Srgrimes if (dw > *dwid) 2241638Srgrimes *dwid = dw; 2251638Srgrimes if (tw > *twid) 2261638Srgrimes *twid = tw; 227171065Sremko } 2281638Srgrimes } 2291638Srgrimes break; 2301638Srgrimes 2311638Srgrimes case Full: 2321638Srgrimes { 2331638Srgrimes for (i = 0; i < ml->amq_mount_info_list_len; i++) { 2341638Srgrimes amq_mount_info *mi = &ml->amq_mount_info_list_val[i]; 235117011Sru printf("%-*.*s %-*.*s %-*.*s %-3d %s is %s", 236117011Sru *mwid, *mwid, mi->mi_mountinfo, 2371638Srgrimes *dwid, *dwid, mi->mi_mountpt, 2381638Srgrimes *twid, *twid, mi->mi_type, 2391638Srgrimes mi->mi_refc, mi->mi_fserver, 2401638Srgrimes mi->mi_up > 0 ? "up" : 2411638Srgrimes mi->mi_up < 0 ? "starting" : "down"); 2421638Srgrimes if (mi->mi_error > 0) { 2431638Srgrimes extern int sys_nerr; 2441638Srgrimes if (mi->mi_error < sys_nerr) 2451638Srgrimes printf(" (%s)", sys_errlist[mi->mi_error]); 2461638Srgrimes else 2471638Srgrimes printf(" (Error %d)", mi->mi_error); 248117011Sru } else if (mi->mi_error < 0) { 249117011Sru fputs(" (in progress)", stdout); 250117011Sru } 2511638Srgrimes fputc('\n', stdout); 2521638Srgrimes } 2531638Srgrimes } 254117011Sru break; 255117011Sru 2561638Srgrimes default: 2571638Srgrimes break; 2581638Srgrimes } 2591638Srgrimes} 2601638Srgrimes 2611638Srgrimes 262119893Sru/* 263117011Sru * Display general mount statistics 264117011Sru */ 2651638Srgrimesstatic void 266117011Srushow_ms(amq_mount_stats *ms) 267117011Sru{ 2681638Srgrimes printf("\ 2691638Srgrimesrequests stale mount mount unmount\n\ 2701638Srgrimesdeferred fhandles ok failed failed\n\ 271131530Sru%-9d %-9d %-9d %-9d %-9d\n", 2721638Srgrimes ms->as_drops, ms->as_stale, ms->as_mok, ms->as_merr, ms->as_uerr); 2731638Srgrimes} 2741638Srgrimes 2751638Srgrimes 2761638Srgrimes#if defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) 2771638Srgrimesstatic char * 278117011Srucluster_server(void) 279117011Sru{ 2801638Srgrimes struct cct_entry *cp; 281117011Sru 282117011Sru if (cnodeid() == 0) { 2831638Srgrimes /* 2841638Srgrimes * Not clustered 285119893Sru */ 2861638Srgrimes return def_server; 2871638Srgrimes } 2881638Srgrimes while (cp = getccent()) 2891638Srgrimes if (cp->cnode_type == 'r') 2901638Srgrimes return cp->cnode_name; 2911638Srgrimes 2921638Srgrimes return def_server; 2931638Srgrimes} 2941638Srgrimes#endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */ 2951638Srgrimes 2961638Srgrimes 2971638Srgrimes/* 2981638Srgrimes * MAIN 2991638Srgrimes */ 3001638Srgrimesint 301117011Srumain(int argc, char *argv[]) 302117011Sru{ 3031638Srgrimes int opt_ch; 3041638Srgrimes int errs = 0; 3051638Srgrimes char *server; 3061638Srgrimes struct sockaddr_in server_addr; 307117011Sru int s; /* to pass the Amd security check, we must use a priv port */ 308117011Sru CLIENT *clnt = NULL; 3091638Srgrimes struct hostent *hp; 3101638Srgrimes int nodefault = 0; 3111638Srgrimes struct timeval tv; 3121638Srgrimes#ifndef HAVE_TRANSPORT_TYPE_TLI 3131638Srgrimes enum clnt_stat cs; 3141638Srgrimes#endif /* not HAVE_TRANSPORT_TYPE_TLI */ 3151638Srgrimes 3161638Srgrimes 3171638Srgrimes /* 3181638Srgrimes * Compute program name 3191638Srgrimes */ 3201638Srgrimes if (argv[0]) { 3211638Srgrimes progname = strrchr(argv[0], '/'); 3221638Srgrimes if (progname && progname[1]) 3231638Srgrimes progname++; 3241638Srgrimes else 3251638Srgrimes progname = argv[0]; 32613744Smpp } 3271638Srgrimes if (!progname) 3281638Srgrimes progname = "amq"; 3291638Srgrimes 3301638Srgrimes /* 3311638Srgrimes * Parse arguments 3321638Srgrimes */ 3331638Srgrimes while ((opt_ch = getopt(argc, argv, "fh:l:msuvx:D:M:pP:TU")) != EOF) 3341638Srgrimes switch (opt_ch) { 3351638Srgrimes case 'f': 3361638Srgrimes flush_flag = 1; 3371638Srgrimes nodefault = 1; 3381638Srgrimes break; 3391638Srgrimes 3401638Srgrimes case 'h': 3411638Srgrimes def_server = optarg; 3421638Srgrimes break; 3431638Srgrimes 3441638Srgrimes case 'l': 3451638Srgrimes amq_logfile = optarg; 3461638Srgrimes nodefault = 1; 3471638Srgrimes break; 3481638Srgrimes 3491638Srgrimes case 'm': 3501638Srgrimes minfo_flag = 1; 3511638Srgrimes nodefault = 1; 3521638Srgrimes break; 3531638Srgrimes 3541638Srgrimes case 'p': 35581158Ssheldonh getpid_flag = 1; 35681158Ssheldonh nodefault = 1; 35781158Ssheldonh break; 35881158Ssheldonh 35981158Ssheldonh case 's': 36081158Ssheldonh stats_flag = 1; 36181158Ssheldonh nodefault = 1; 36281158Ssheldonh break; 36381158Ssheldonh 36481158Ssheldonh case 'u': 3651638Srgrimes unmount_flag = 1; 36620920Swosch nodefault = 1; 3671638Srgrimes break; 36879217Sru 3691638Srgrimes case 'v': 37020920Swosch getvers_flag = 1; 37120920Swosch nodefault = 1; 372 break; 373 374 case 'x': 375 xlog_optstr = optarg; 376 nodefault = 1; 377 break; 378 379 case 'D': 380 debug_opts = optarg; 381 nodefault = 1; 382 break; 383 384 case 'M': 385 mount_map = optarg; 386 nodefault = 1; 387 break; 388 389 case 'P': 390 amd_program_number = atoi(optarg); 391 break; 392 393 case 'T': 394 use_tcp_flag = 1; 395 break; 396 397 case 'U': 398 use_udp_flag = 1; 399 break; 400 401 default: 402 errs = 1; 403 break; 404 } 405 406 if (optind == argc) { 407 if (unmount_flag) 408 errs = 1; 409 } 410 if (errs) { 411 show_usage: 412 fprintf(stderr, "\ 413Usage: %s [-h host] [[-f] [-m] [-p] [-v] [-s]] | [[-u] directory ...]]\n\ 414\t[-l logfile|\"syslog\"] [-x log_flags] [-D dbg_opts] [-M mapent]\n\ 415\t[-P prognum] [-T] [-U]\n", progname); 416 exit(1); 417 } 418 419 /* set use_udp and use_tcp flags both to on if none are defined */ 420 if (!use_tcp_flag && !use_udp_flag) 421 use_tcp_flag = use_udp_flag = 1; 422 423#if defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) 424 /* 425 * Figure out root server of cluster 426 */ 427 if (def_server == localhost) 428 server = cluster_server(); 429 else 430#endif /* defined(HAVE_CLUSTER_H) && defined(HAVE_CNODEID) && defined(HAVE_GETCCENT) */ 431 server = def_server; 432 433 /* 434 * Get address of server 435 */ 436 if ((hp = gethostbyname(server)) == 0 && !STREQ(server, localhost)) { 437 fprintf(stderr, "%s: Can't get address of %s\n", progname, server); 438 exit(1); 439 } 440 memset(&server_addr, 0, sizeof server_addr); 441 server_addr.sin_family = AF_INET; 442 if (hp) { 443 memmove((voidp) &server_addr.sin_addr, (voidp) hp->h_addr, 444 sizeof(server_addr.sin_addr)); 445 } else { 446 /* fake "localhost" */ 447 server_addr.sin_addr.s_addr = htonl(0x7f000001); 448 } 449 450 /* 451 * Create RPC endpoint 452 */ 453 tv.tv_sec = 5; /* 5 seconds for timeout or per retry */ 454 tv.tv_usec = 0; 455 456#ifdef HAVE_TRANSPORT_TYPE_TLI 457 clnt = get_secure_amd_client(server, &tv, &s); 458 if (!clnt && use_tcp_flag) /* try tcp first */ 459 clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "tcp"); 460 if (!clnt && use_udp_flag) { /* try udp next */ 461 clnt = clnt_create(server, amd_program_number, AMQ_VERSION, "udp"); 462 /* if ok, set timeout (valid for connectionless transports only) */ 463 if (clnt) 464 clnt_control(clnt, CLSET_RETRY_TIMEOUT, (char *) &tv); 465 } 466#else /* not HAVE_TRANSPORT_TYPE_TLI */ 467 468 /* first check if remote portmapper is up */ 469 cs = pmap_ping(&server_addr); 470 if (cs == RPC_TIMEDOUT) { 471 fprintf(stderr, "%s: failed to contact portmapper on host \"%s\". %s\n", 472 progname, server, clnt_sperrno(cs)); 473 exit(1); 474 } 475 476 /* portmapper exists: get remote amd info from it */ 477 if (!clnt && use_tcp_flag) { /* try tcp first */ 478 s = RPC_ANYSOCK; 479 clnt = clnttcp_create(&server_addr, amd_program_number, 480 AMQ_VERSION, &s, 0, 0); 481 } 482 if (!clnt && use_udp_flag) { /* try udp next */ 483 /* XXX: do we need to close(s) ? */ 484 s = privsock(SOCK_DGRAM); 485 clnt = clntudp_create(&server_addr, amd_program_number, 486 AMQ_VERSION, tv, &s); 487 } 488#endif /* not HAVE_TRANSPORT_TYPE_TLI */ 489 if (!clnt) { 490 fprintf(stderr, "%s: ", progname); 491 clnt_pcreateerror(server); 492 exit(1); 493 } 494 495 /* 496 * Control debugging 497 */ 498 if (debug_opts) { 499 int *rc; 500 amq_setopt opt; 501 opt.as_opt = AMOPT_DEBUG; 502 opt.as_str = debug_opts; 503 rc = amqproc_setopt_1(&opt, clnt); 504 if (rc && *rc < 0) { 505 fprintf(stderr, "%s: daemon not compiled for debug\n", progname); 506 errs = 1; 507 } else if (!rc || *rc > 0) { 508 fprintf(stderr, "%s: debug setting for \"%s\" failed\n", progname, debug_opts); 509 errs = 1; 510 } 511 } 512 513 /* 514 * Control logging 515 */ 516 if (xlog_optstr) { 517 int *rc; 518 amq_setopt opt; 519 opt.as_opt = AMOPT_XLOG; 520 opt.as_str = xlog_optstr; 521 rc = amqproc_setopt_1(&opt, clnt); 522 if (!rc || *rc) { 523 fprintf(stderr, "%s: setting log level to \"%s\" failed\n", progname, xlog_optstr); 524 errs = 1; 525 } 526 } 527 528 /* 529 * Control log file 530 */ 531 if (amq_logfile) { 532 int *rc; 533 amq_setopt opt; 534 opt.as_opt = AMOPT_LOGFILE; 535 opt.as_str = amq_logfile; 536 rc = amqproc_setopt_1(&opt, clnt); 537 if (!rc || *rc) { 538 fprintf(stderr, "%s: setting logfile to \"%s\" failed\n", progname, amq_logfile); 539 errs = 1; 540 } 541 } 542 543 /* 544 * Flush map cache 545 */ 546 if (flush_flag) { 547 int *rc; 548 amq_setopt opt; 549 opt.as_opt = AMOPT_FLUSHMAPC; 550 opt.as_str = ""; 551 rc = amqproc_setopt_1(&opt, clnt); 552 if (!rc || *rc) { 553 fprintf(stderr, "%s: amd on %s cannot flush the map cache\n", progname, server); 554 errs = 1; 555 } 556 } 557 558 /* 559 * Mount info 560 */ 561 if (minfo_flag) { 562 int dummy; 563 amq_mount_info_list *ml = amqproc_getmntfs_1(&dummy, clnt); 564 if (ml) { 565 int mwid = 0, dwid = 0, twid = 0; 566 show_mi(ml, Calc, &mwid, &dwid, &twid); 567 mwid++; 568 dwid++; 569 twid++; 570 show_mi(ml, Full, &mwid, &dwid, &twid); 571 572 } else { 573 fprintf(stderr, "%s: amd on %s cannot provide mount info\n", progname, server); 574 } 575 } 576 577 /* 578 * Mount map 579 */ 580 if (mount_map) { 581 int *rc; 582 do { 583 rc = amqproc_mount_1(&mount_map, clnt); 584 } while (rc && *rc < 0); 585 if (!rc || *rc > 0) { 586 if (rc) 587 errno = *rc; 588 else 589 errno = ETIMEDOUT; 590 fprintf(stderr, "%s: could not start new ", progname); 591 perror("autmount point"); 592 } 593 } 594 595 /* 596 * Get Version 597 */ 598 if (getvers_flag) { 599 amq_string *spp = amqproc_getvers_1((voidp) 0, clnt); 600 if (spp && *spp) { 601 fputs(*spp, stdout); 602 XFREE(*spp); 603 } else { 604 fprintf(stderr, "%s: failed to get version information\n", progname); 605 errs = 1; 606 } 607 } 608 609 /* 610 * Get PID of amd 611 */ 612 if (getpid_flag) { 613 int *ip = amqproc_getpid_1((voidp) 0, clnt); 614 if (ip && *ip) { 615 printf("%d\n", *ip); 616 } else { 617 fprintf(stderr, "%s: failed to get PID of amd\n", progname); 618 errs = 1; 619 } 620 } 621 622 /* 623 * Apply required operation to all remaining arguments 624 */ 625 if (optind < argc) { 626 do { 627 char *fs = argv[optind++]; 628 if (unmount_flag) { 629 /* 630 * Unmount request 631 */ 632 amqproc_umnt_1(&fs, clnt); 633 } else { 634 /* 635 * Stats request 636 */ 637 amq_mount_tree_p *mtp = amqproc_mnttree_1(&fs, clnt); 638 if (mtp) { 639 amq_mount_tree *mt = *mtp; 640 if (mt) { 641 int mwid = 0, dwid = 0, twid = 0; 642 show_mt(mt, Calc, &mwid, &dwid, &twid); 643 mwid++; 644 dwid++, twid++; 645 printf("%-*.*s Uid Getattr Lookup RdDir RdLnk Statfs Mounted@\n", 646 dwid, dwid, "What"); 647 show_mt(mt, Stats, &mwid, &dwid, &twid); 648 } else { 649 fprintf(stderr, "%s: %s not automounted\n", progname, fs); 650 } 651 xdr_pri_free((XDRPROC_T_TYPE) xdr_amq_mount_tree_p, (caddr_t) mtp); 652 } else { 653 fprintf(stderr, "%s: ", progname); 654 clnt_perror(clnt, server); 655 errs = 1; 656 } 657 } 658 } while (optind < argc); 659 660 } else if (unmount_flag) { 661 goto show_usage; 662 663 } else if (stats_flag) { 664 amq_mount_stats *ms = amqproc_stats_1((voidp) 0, clnt); 665 if (ms) { 666 show_ms(ms); 667 } else { 668 fprintf(stderr, "%s: ", progname); 669 clnt_perror(clnt, server); 670 errs = 1; 671 } 672 673 } else if (!nodefault) { 674 amq_mount_tree_list *mlp = amqproc_export_1((voidp) 0, clnt); 675 if (mlp) { 676 enum show_opt e = Calc; 677 int mwid = 0, dwid = 0, pwid = 0; 678 while (e != ShowDone) { 679 int i; 680 for (i = 0; i < mlp->amq_mount_tree_list_len; i++) { 681 show_mt(mlp->amq_mount_tree_list_val[i], 682 e, &mwid, &dwid, &pwid); 683 } 684 mwid++; 685 dwid++, pwid++; 686 if (e == Calc) 687 e = Short; 688 else if (e == Short) 689 e = ShowDone; 690 } 691 692 } else { 693 fprintf(stderr, "%s: ", progname); 694 clnt_perror(clnt, server); 695 errs = 1; 696 } 697 } 698 exit(errs); 699 return errs; /* should never reache here */ 700} 701 702 703#ifdef HAVE_TRANSPORT_TYPE_TLI 704 705/* 706 * How to bind to reserved ports. 707 * TLI handle (socket) and port version. 708 */ 709/* defined here so that it does not have to resolve it with libamu.a */ 710static int 711amq_bind_resv_port(int td, u_short *pp) 712{ 713 int rc = -1, port; 714 struct t_bind *treq, *tret; 715 struct sockaddr_in *sin; 716 717 treq = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR); 718 if (!treq) { 719 plog(XLOG_ERROR, "t_alloc 1"); 720 return -1; 721 } 722 tret = (struct t_bind *) t_alloc(td, T_BIND, T_ADDR); 723 if (!tret) { 724 t_free((char *) treq, T_BIND); 725 plog(XLOG_ERROR, "t_alloc 2"); 726 return -1; 727 } 728 memset((char *) treq->addr.buf, 0, treq->addr.len); 729 sin = (struct sockaddr_in *) treq->addr.buf; 730 sin->sin_family = AF_INET; 731 treq->qlen = 0; 732 treq->addr.len = treq->addr.maxlen; 733 errno = EADDRINUSE; 734 port = IPPORT_RESERVED; 735 736 do { 737 --port; 738 sin->sin_port = htons(port); 739 rc = t_bind(td, treq, tret); 740 if (rc < 0) { 741 } else { 742 if (memcmp(treq->addr.buf, tret->addr.buf, tret->addr.len) == 0) 743 break; 744 else 745 t_unbind(td); 746 } 747 } while ((rc < 0 || errno == EADDRINUSE) && (int) port > IPPORT_RESERVED / 2); 748 749 if (pp) { 750 if (rc == 0) 751 *pp = port; 752 else 753 plog(XLOG_ERROR, "could not t_bind to any reserved port"); 754 } 755 t_free((char *) tret, T_BIND); 756 t_free((char *) treq, T_BIND); 757 return rc; 758} 759 760 761/* 762 * Create a secure rpc client attached to the amd daemon. 763 */ 764static CLIENT * 765get_secure_amd_client(char *host, struct timeval *tv, int *sock) 766{ 767 CLIENT *client; 768 struct netbuf nb; 769 struct netconfig *nc, *pm_nc; 770 struct sockaddr_in sin; 771 772 773 nb.maxlen = sizeof(sin); 774 nb.buf = (char *) &sin; 775 776 /* 777 * Ensure that remote portmapper is alive 778 * (must use connectionless netconfig). 779 */ 780 if ((pm_nc = getnetconfigent(NC_UDP)) != NULL) { 781 enum clnt_stat cs; 782 783 cs = rpcb_rmtcall(pm_nc, 784 host, 785 amd_program_number, 786 AMQ_VERSION, 787 AMQPROC_NULL, 788 (XDRPROC_T_TYPE) xdr_void, 789 NULL, 790 (XDRPROC_T_TYPE) xdr_void, 791 NULL, 792 *tv, 793 NULL); 794 if (cs == RPC_TIMEDOUT) { 795 fprintf(stderr, "%s: failed to contact portmapper on host \"%s\". %s\n", 796 progname, host, clnt_sperrno(cs)); 797 exit(1); 798 } 799 } 800 801 /* 802 * First transport type to try: TCP 803 */ 804 if (use_tcp_flag) { 805 /* Find amd address on TCP */ 806 nc = getnetconfigent(NC_TCP); 807 if (!nc) { 808 fprintf(stderr, "getnetconfig for tcp failed: %s\n", nc_sperror()); 809 goto tryudp; 810 } 811 812 if (!rpcb_getaddr(amd_program_number, AMQ_VERSION, nc, &nb, host)) { 813 /* 814 * don't pring error messages here, since amd might legitimately 815 * serve udp only 816 */ 817 goto tryudp; 818 } 819 /* Create priviledged TCP socket */ 820 *sock = t_open(nc->nc_device, O_RDWR, 0); 821 822 if (*sock < 0) { 823 fprintf(stderr, "t_open %s: %m\n", nc->nc_device); 824 goto tryudp; 825 } 826 if (amq_bind_resv_port(*sock, (u_short *) 0) < 0) 827 goto tryudp; 828 829 client = clnt_vc_create(*sock, &nb, amd_program_number, AMQ_VERSION, 0, 0); 830 if (!client) { 831 fprintf(stderr, "clnt_vc_create failed"); 832 t_close(*sock); 833 goto tryudp; 834 } 835 /* tcp succeeded */ 836 return client; 837 } 838 839tryudp: 840 /* 841 * TCP failed so try UDP 842 */ 843 if (use_udp_flag) { 844 /* find amd address on UDP */ 845 nc = getnetconfigent(NC_UDP); 846 if (!nc) { 847 fprintf(stderr, "getnetconfig for udp failed: %s\n", nc_sperror()); 848 return NULL; 849 } 850 if (!rpcb_getaddr(amd_program_number, AMQ_VERSION, nc, &nb, host)) { 851 fprintf(stderr, "%s\n", 852 clnt_spcreateerror("couldn't get amd address on udp")); 853 return NULL; 854 } 855 /* create priviledged UDP socket */ 856 *sock = t_open(nc->nc_device, O_RDWR, 0); 857 858 if (*sock < 0) { 859 fprintf(stderr, "t_open %s: %m\n", nc->nc_device); 860 return NULL; /* neither tcp not udp succeeded */ 861 } 862 if (amq_bind_resv_port(*sock, (u_short *) 0) < 0) 863 return NULL; 864 865 client = clnt_dg_create(*sock, &nb, amd_program_number, AMQ_VERSION, 0, 0); 866 if (!client) { 867 fprintf(stderr, "clnt_dg_create failed\n"); 868 t_close(*sock); 869 return NULL; /* neither tcp not udp succeeded */ 870 } 871 if (clnt_control(client, CLSET_RETRY_TIMEOUT, (char *) tv) == FALSE) { 872 fprintf(stderr, "clnt_control CLSET_RETRY_TIMEOUT for udp failed\n"); 873 clnt_destroy(client); 874 return NULL; /* neither tcp not udp succeeded */ 875 } 876 /* udp succeeded */ 877 return client; 878 } 879 880 /* should never get here */ 881 return NULL; 882} 883 884#else /* not HAVE_TRANSPORT_TYPE_TLI */ 885 886/* 887 * inetresport creates a datagram socket and attempts to bind it to a 888 * secure port. 889 * returns: The bound socket, or -1 to indicate an error. 890 */ 891static int 892inetresport(int ty) 893{ 894 int alport; 895 struct sockaddr_in addr; 896 int fd; 897 898 /* Use internet address family */ 899 addr.sin_family = AF_INET; 900 addr.sin_addr.s_addr = INADDR_ANY; 901 if ((fd = socket(AF_INET, ty, 0)) < 0) 902 return -1; 903 904 for (alport = IPPORT_RESERVED - 1; alport > IPPORT_RESERVED / 2 + 1; alport--) { 905 addr.sin_port = htons((u_short) alport); 906 if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) >= 0) 907 return fd; 908 if (errno != EADDRINUSE) { 909 close(fd); 910 return -1; 911 } 912 } 913 close(fd); 914 errno = EAGAIN; 915 return -1; 916} 917 918 919/* 920 * Privsock() calls inetresport() to attempt to bind a socket to a secure 921 * port. If inetresport() fails, privsock returns a magic socket number which 922 * indicates to RPC that it should make its own socket. 923 * returns: A privileged socket # or RPC_ANYSOCK. 924 */ 925static int 926privsock(int ty) 927{ 928 int sock = inetresport(ty); 929 930 if (sock < 0) { 931 errno = 0; 932 /* Couldn't get a secure port, let RPC make an insecure one */ 933 sock = RPC_ANYSOCK; 934 } 935 return sock; 936} 937 938#endif /* not HAVE_TRANSPORT_TYPE_TLI */ 939