138494Sobrien/* 2310490Scy * Copyright (c) 1997-2014 Erez Zadok 338494Sobrien * Copyright (c) 1990 Jan-Simon Pendry 438494Sobrien * Copyright (c) 1990 Imperial College of Science, Technology & Medicine 538494Sobrien * Copyright (c) 1990 The Regents of the University of California. 638494Sobrien * All rights reserved. 738494Sobrien * 838494Sobrien * This code is derived from software contributed to Berkeley by 938494Sobrien * Jan-Simon Pendry at Imperial College, London. 1038494Sobrien * 1138494Sobrien * Redistribution and use in source and binary forms, with or without 1238494Sobrien * modification, are permitted provided that the following conditions 1338494Sobrien * are met: 1438494Sobrien * 1. Redistributions of source code must retain the above copyright 1538494Sobrien * notice, this list of conditions and the following disclaimer. 1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1738494Sobrien * notice, this list of conditions and the following disclaimer in the 1838494Sobrien * documentation and/or other materials provided with the distribution. 19310490Scy * 3. Neither the name of the University nor the names of its contributors 2038494Sobrien * may be used to endorse or promote products derived from this software 2138494Sobrien * without specific prior written permission. 2238494Sobrien * 2338494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2438494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2538494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2638494Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2738494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2838494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2938494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3038494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3138494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3238494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3338494Sobrien * SUCH DAMAGE. 3438494Sobrien * 3538494Sobrien * 36174313Sobrien * File: am-utils/fixmount/fixmount.c 3738494Sobrien * 3838494Sobrien */ 3938494Sobrien 4038494Sobrien#ifdef HAVE_CONFIG_H 4138494Sobrien# include <config.h> 4238494Sobrien#endif /* HAVE_CONFIG_H */ 4338494Sobrien#include <am_defs.h> 4438494Sobrien 4538494Sobrien#define CREATE_TIMEOUT 2 /* seconds */ 4638494Sobrien#define CALL_TIMEOUT 5 /* seconds */ 4738494Sobrien 4838494Sobrien/* Constant defs */ 4938494Sobrien#define ALL 1 5038494Sobrien#define DIRS 2 5138494Sobrien 5238494Sobrien#define DODUMP 0x1 5338494Sobrien#define DOEXPORTS 0x2 5438494Sobrien#define DOREMOVE 0x4 5538494Sobrien#define DOVERIFY 0x8 5638494Sobrien#define DOREMALL 0x10 5738494Sobrien 5838494Sobrienextern int fixmount_check_mount(char *host, struct in_addr hostaddr, char *path); 5938494Sobrien 6038494Sobrienstatic char dir_path[NFS_MAXPATHLEN]; 6138494Sobrienstatic char localhost[] = "localhost"; 6238500Sobrienstatic char thishost[MAXHOSTNAMELEN + 1] = ""; 6338494Sobrienstatic exports mntexports; 6438494Sobrienstatic int quiet = 0; 6538494Sobrienstatic int type = 0; 6638494Sobrienstatic jmp_buf before_rpc; 6738494Sobrienstatic mountlist mntdump; 6838494Sobrienstatic struct in_addr thisaddr; 6938494Sobrienstatic CLIENT *clnt_create_timeout(char *, struct timeval *); 7038494Sobrien 7138494SobrienRETSIGTYPE create_timeout(int); 7238494Sobrienint is_same_host(char *, char *, struct in_addr); 7338494Sobrienint main(int, char *[]); 7438494Sobrienint remove_all(CLIENT *, char *); 7538494Sobrienint remove_mount(CLIENT *, char *, mountlist, int); 7638494Sobrienvoid fix_rmtab(CLIENT *, char *, mountlist, int, int); 7738494Sobrienvoid print_dump(mountlist); 7838494Sobrienvoid usage(void); 7938494Sobrien 8038494Sobrien 8138494Sobrienvoid 8238494Sobrienusage(void) 8338494Sobrien{ 8438494Sobrien fprintf(stderr, "usage: fixmount [-adervAqf] [-h hostname] host ...\n"); 8538494Sobrien exit(1); 8638494Sobrien} 8738494Sobrien 8838494Sobrien 8938494Sobrien/* 9038494Sobrien * Check hostname against other name and its IP address 9138494Sobrien */ 9238494Sobrienint 9338494Sobrienis_same_host(char *name1, char *name2, struct in_addr addr2) 9438494Sobrien{ 9538494Sobrien if (strcasecmp(name1, name2) == 0) { 9638494Sobrien return 1; 9738494Sobrien } else if (addr2.s_addr == INADDR_NONE) { 9838494Sobrien return 0; 9938494Sobrien } else { 10038494Sobrien static char lasthost[MAXHOSTNAMELEN] = ""; 10138494Sobrien static struct in_addr addr1; 10238494Sobrien struct hostent *he; 10338494Sobrien 10438494Sobrien /* 10538494Sobrien * To save nameserver lookups, and because this function 10638494Sobrien * is typically called repeatedly on the same names, 10738494Sobrien * cache the last lookup result and reuse it if possible. 10838494Sobrien */ 10938494Sobrien if (strcasecmp(name1, lasthost) == 0) { 11038494Sobrien return (addr1.s_addr == addr2.s_addr); 11138494Sobrien } else if (!(he = gethostbyname(name1))) { 11238494Sobrien return 0; 11338494Sobrien } else { 114310490Scy xstrlcpy(lasthost, name1, sizeof(lasthost)); 11538494Sobrien memcpy(&addr1, he->h_addr, sizeof(addr1)); 11638494Sobrien return (addr1.s_addr == addr2.s_addr); 11738494Sobrien } 11838494Sobrien } 11938494Sobrien} 12038494Sobrien 12138494Sobrien 12238494Sobrien/* 12338494Sobrien * Print the binary tree in inorder so that output is sorted. 12438494Sobrien */ 12538494Sobrienvoid 12638494Sobrienprint_dump(mountlist mp) 12738494Sobrien{ 12838494Sobrien if (mp == NULL) 12938494Sobrien return; 13038494Sobrien if (is_same_host(mp->ml_hostname, thishost, thisaddr)) { 13138494Sobrien switch (type) { 13238494Sobrien case ALL: 13338494Sobrien printf("%s:%s\n", mp->ml_hostname, mp->ml_directory); 13438494Sobrien break; 13538494Sobrien case DIRS: 13638494Sobrien printf("%s\n", mp->ml_directory); 13738494Sobrien break; 13838494Sobrien default: 13938494Sobrien printf("%s\n", mp->ml_hostname); 14038494Sobrien break; 14138494Sobrien }; 14238494Sobrien } 14338494Sobrien if (mp->ml_next) 14438494Sobrien print_dump(mp->ml_next); 14538494Sobrien} 14638494Sobrien 14738494Sobrien 14838494Sobrien/* 14938494Sobrien * remove entry from remote rmtab 15038494Sobrien */ 15138494Sobrienint 15238494Sobrienremove_mount(CLIENT *client, char *host, mountlist ml, int fixit) 15338494Sobrien{ 15438494Sobrien enum clnt_stat estat; 15538494Sobrien struct timeval tv; 15638494Sobrien char *pathp = dir_path; 15738494Sobrien 158174313Sobrien xstrlcpy(dir_path, ml->ml_directory, sizeof(dir_path)); 15938494Sobrien 16038494Sobrien if (!fixit) { 16138494Sobrien printf("%s: bogus mount %s:%s\n", host, ml->ml_hostname, ml->ml_directory); 16238494Sobrien fflush(stdout); 16338494Sobrien } else { 16438494Sobrien printf("%s: removing %s:%s\n", host, ml->ml_hostname, ml->ml_directory); 16538494Sobrien fflush(stdout); 16638494Sobrien 16738494Sobrien tv.tv_sec = CALL_TIMEOUT; 16838494Sobrien tv.tv_usec = 0; 16938494Sobrien 17038494Sobrien if ((estat = clnt_call(client, 17138494Sobrien MOUNTPROC_UMNT, 17238494Sobrien (XDRPROC_T_TYPE) xdr_dirpath, 17338494Sobrien (char *) &pathp, 17438494Sobrien (XDRPROC_T_TYPE) xdr_void, 175310490Scy (char *) NULL, 17638494Sobrien tv)) != RPC_SUCCESS) { 17738494Sobrien fprintf(stderr, "%s:%s MOUNTPROC_UMNT: ", 17838494Sobrien host, ml->ml_directory); 17938494Sobrien clnt_perrno(estat); 18038494Sobrien fflush(stderr); 18138494Sobrien return -1; 18238494Sobrien } 18338494Sobrien } 18438494Sobrien return 0; 18538494Sobrien} 18638494Sobrien 18738494Sobrien 18838494Sobrien/* 18938494Sobrien * fix mount list on remote host 19038494Sobrien */ 19138494Sobrienvoid 19238494Sobrienfix_rmtab(CLIENT *client, char *host, mountlist mp, int fixit, int force) 19338494Sobrien{ 19438494Sobrien mountlist p; 19538494Sobrien struct hostent *he; 19638494Sobrien struct in_addr hostaddr; 19738494Sobrien 19838494Sobrien /* 19938494Sobrien * Obtain remote address for comparisons 20038494Sobrien */ 20138494Sobrien if ((he = gethostbyname(host))) { 20238494Sobrien memcpy(&hostaddr, he->h_addr, sizeof(hostaddr)); 20338494Sobrien } else { 20438494Sobrien hostaddr.s_addr = INADDR_NONE; 20538494Sobrien } 20638494Sobrien 20738494Sobrien for (p = mp; p; p = p->ml_next) { 20838494Sobrien if (is_same_host(p->ml_hostname, thishost, thisaddr)) { 20938494Sobrien if (force || !fixmount_check_mount(host, hostaddr, p->ml_directory)) 21038494Sobrien remove_mount(client, host, p, fixit); 21138494Sobrien } 21238494Sobrien } 21338494Sobrien} 21438494Sobrien 21538494Sobrien 21638494Sobrien/* 21738494Sobrien * remove all entries from remote rmtab 21838494Sobrien */ 21938494Sobrienint 22038494Sobrienremove_all(CLIENT *client, char *host) 22138494Sobrien{ 22238494Sobrien enum clnt_stat estat; 22338494Sobrien struct timeval tv; 22438494Sobrien 22538494Sobrien printf("%s: removing ALL\n", host); 22638494Sobrien fflush(stdout); 22738494Sobrien 22838494Sobrien tv.tv_sec = CALL_TIMEOUT; 22938494Sobrien tv.tv_usec = 0; 23038494Sobrien 23138494Sobrien if ((estat = clnt_call(client, 23238494Sobrien MOUNTPROC_UMNTALL, 23338494Sobrien (XDRPROC_T_TYPE) xdr_void, 234310490Scy (char *) NULL, 23538494Sobrien (XDRPROC_T_TYPE) xdr_void, 236310490Scy (char *) NULL, 23738494Sobrien tv)) != RPC_SUCCESS) { 23838494Sobrien /* 23938494Sobrien * RPC_SYSTEMERROR is returned even if all went well 24038494Sobrien */ 24138494Sobrien if (estat != RPC_SYSTEMERROR) { 24238494Sobrien fprintf(stderr, "%s MOUNTPROC_UMNTALL: ", host); 24338494Sobrien clnt_perrno(estat); 24438494Sobrien fflush(stderr); 24538494Sobrien return -1; 24638494Sobrien } 24738494Sobrien } 24838494Sobrien 24938494Sobrien return 0; 25038494Sobrien} 25138494Sobrien 25238494Sobrien 25338494Sobrien/* 25438494Sobrien * This command queries the NFS mount daemon for it's mount list and/or 25538494Sobrien * it's exports list and prints them out. 25638494Sobrien * See "NFS: Network File System Protocol Specification, RFC1094, Appendix A" 25738494Sobrien * for detailed information on the protocol. 25838494Sobrien */ 25938494Sobrienint 26038494Sobrienmain(int argc, char *argv[]) 26138494Sobrien{ 26238494Sobrien AUTH *auth; 26338494Sobrien CLIENT *client; 26438494Sobrien char *host; 26538494Sobrien enum clnt_stat estat; 26638494Sobrien exports exp; 26738494Sobrien extern char *optarg; 26838494Sobrien extern int optind; 26938494Sobrien groups grp; 27038494Sobrien int ch; 27138494Sobrien int force = 0; 27238494Sobrien int morethanone; 27338494Sobrien register int rpcs = 0; 27438494Sobrien struct timeval tv; 27538494Sobrien 27638500Sobrien while ((ch = getopt(argc, argv, "adervAqfh:")) != -1) 27738494Sobrien switch ((char) ch) { 27838494Sobrien 27938494Sobrien case 'a': 28038494Sobrien if (type == 0) { 28138494Sobrien type = ALL; 28238494Sobrien rpcs |= DODUMP; 28338494Sobrien } else 28438494Sobrien usage(); 28538494Sobrien break; 28638494Sobrien 28738494Sobrien case 'd': 28838494Sobrien if (type == 0) { 28938494Sobrien type = DIRS; 29038494Sobrien rpcs |= DODUMP; 29138494Sobrien } else 29238494Sobrien usage(); 29338494Sobrien break; 29438494Sobrien 29538494Sobrien case 'e': 29638494Sobrien rpcs |= DOEXPORTS; 29738494Sobrien break; 29838494Sobrien 29938494Sobrien case 'r': 30038494Sobrien rpcs |= DOREMOVE; 30138494Sobrien break; 30238494Sobrien 30338494Sobrien case 'A': 30438494Sobrien rpcs |= DOREMALL; 30538494Sobrien break; 30638494Sobrien 30738494Sobrien case 'v': 30838494Sobrien rpcs |= DOVERIFY; 30938494Sobrien break; 31038494Sobrien 31138494Sobrien case 'q': 31238494Sobrien quiet = 1; 31338494Sobrien break; 31438494Sobrien 31538494Sobrien case 'f': 31638494Sobrien force = 1; 31738494Sobrien break; 31838494Sobrien 31938494Sobrien case 'h': 320174313Sobrien xstrlcpy(thishost, optarg, sizeof(thishost)); 32138494Sobrien break; 32238494Sobrien 32338494Sobrien case '?': 32438494Sobrien default: 32538494Sobrien usage(); 32638494Sobrien } 32738494Sobrien 32838494Sobrien if (optind == argc) 32938494Sobrien usage(); 33038494Sobrien 33138494Sobrien if (rpcs == 0) 33238494Sobrien rpcs = DODUMP; 33338494Sobrien 33438494Sobrien if (!*thishost) { 33538494Sobrien struct hostent *he; 33638494Sobrien 33738494Sobrien if (gethostname(thishost, sizeof(thishost)) < 0) { 33838494Sobrien perror("gethostname"); 33938494Sobrien exit(1); 34038494Sobrien } 34141145Sobrien thishost[sizeof(thishost) - 1] = '\0'; 34238494Sobrien 34338494Sobrien /* 34438494Sobrien * We need the hostname as it appears to the other side's 34538494Sobrien * mountd, so get our own hostname by reverse address 34638494Sobrien * resolution. 34738494Sobrien */ 34838494Sobrien if (!(he = gethostbyname(thishost))) { 34938494Sobrien fprintf(stderr, "gethostbyname failed on %s\n", 35038494Sobrien thishost); 35138494Sobrien exit(1); 35238494Sobrien } 35338494Sobrien memcpy(&thisaddr, he->h_addr, sizeof(thisaddr)); 35438494Sobrien if (!(he = gethostbyaddr((char *) &thisaddr, sizeof(thisaddr), 35538494Sobrien he->h_addrtype))) { 35638494Sobrien fprintf(stderr, "gethostbyaddr failed on %s\n", 35738494Sobrien inet_ntoa(thisaddr)); 35838494Sobrien exit(1); 35938494Sobrien } 360174313Sobrien xstrlcpy(thishost, he->h_name, sizeof(thishost)); 36138494Sobrien } else { 36238494Sobrien thisaddr.s_addr = INADDR_NONE; 36338494Sobrien } 36438494Sobrien 36538494Sobrien if (!(auth = authunix_create_default())) { 36638494Sobrien fprintf(stderr, "couldn't create authentication handle\n"); 36738494Sobrien exit(1); 36838494Sobrien } 36938494Sobrien morethanone = (optind + 1 < argc); 37038494Sobrien 37138494Sobrien for (; optind < argc; optind++) { 37238494Sobrien 37338494Sobrien host = argv[optind]; 37438494Sobrien tv.tv_sec = CREATE_TIMEOUT; 37538494Sobrien tv.tv_usec = 0; 37638494Sobrien 37738494Sobrien if (!(client = clnt_create_timeout(host, &tv))) 37838494Sobrien continue; 37938494Sobrien 38038494Sobrien client->cl_auth = auth; 38138494Sobrien tv.tv_sec = CALL_TIMEOUT; 38238494Sobrien tv.tv_usec = 0; 38338494Sobrien 38438494Sobrien if (rpcs & (DODUMP | DOREMOVE | DOVERIFY)) 38538494Sobrien if ((estat = clnt_call(client, 38638494Sobrien MOUNTPROC_DUMP, 38738494Sobrien (XDRPROC_T_TYPE) xdr_void, 388310490Scy (char *) NULL, 38938494Sobrien (XDRPROC_T_TYPE) xdr_mountlist, 39038494Sobrien (char *) &mntdump, 39138494Sobrien tv)) != RPC_SUCCESS) { 39238494Sobrien fprintf(stderr, "%s: MOUNTPROC_DUMP: ", host); 39338494Sobrien clnt_perrno(estat); 39438494Sobrien fflush(stderr); 39538494Sobrien mntdump = NULL; 39638494Sobrien goto next; 39738494Sobrien } 39838494Sobrien if (rpcs & DOEXPORTS) 39938494Sobrien if ((estat = clnt_call(client, 40038494Sobrien MOUNTPROC_EXPORT, 40138494Sobrien (XDRPROC_T_TYPE) xdr_void, 402310490Scy (char *) NULL, 40338494Sobrien (XDRPROC_T_TYPE) xdr_exports, 40438494Sobrien (char *) &mntexports, 40538494Sobrien tv)) != RPC_SUCCESS) { 40638494Sobrien fprintf(stderr, "%s: MOUNTPROC_EXPORT: ", host); 40738494Sobrien clnt_perrno(estat); 40838494Sobrien fflush(stderr); 40938494Sobrien mntexports = NULL; 41038494Sobrien goto next; 41138494Sobrien } 41238494Sobrien 41338494Sobrien /* Now just print out the results */ 41438494Sobrien if ((rpcs & (DODUMP | DOEXPORTS)) && 41538494Sobrien morethanone) { 41638494Sobrien printf(">>> %s <<<\n", host); 41738494Sobrien fflush(stdout); 41838494Sobrien } 41938494Sobrien 42038494Sobrien if (rpcs & DODUMP) { 42138494Sobrien print_dump(mntdump); 42238494Sobrien } 42338494Sobrien 42438494Sobrien if (rpcs & DOEXPORTS) { 42538494Sobrien exp = mntexports; 42638494Sobrien while (exp) { 42738494Sobrien printf("%-35s", exp->ex_dir); 42838494Sobrien grp = exp->ex_groups; 42938494Sobrien if (grp == NULL) { 43038494Sobrien printf("Everyone\n"); 43138494Sobrien } else { 43238494Sobrien while (grp) { 43338494Sobrien printf("%s ", grp->gr_name); 43438494Sobrien grp = grp->gr_next; 43538494Sobrien } 43638494Sobrien printf("\n"); 43738494Sobrien } 43838494Sobrien exp = exp->ex_next; 43938494Sobrien } 44038494Sobrien } 44138494Sobrien 44238494Sobrien if (rpcs & DOVERIFY) 44338494Sobrien fix_rmtab(client, host, mntdump, 0, force); 44438494Sobrien 44538494Sobrien if (rpcs & DOREMOVE) 44638494Sobrien fix_rmtab(client, host, mntdump, 1, force); 44738494Sobrien 44838494Sobrien if (rpcs & DOREMALL) 44938494Sobrien remove_all(client, host); 45038494Sobrien 45138494Sobrien next: 45238494Sobrien if (mntdump) 45338494Sobrien (void) clnt_freeres(client, 45438494Sobrien (XDRPROC_T_TYPE) xdr_mountlist, 45538494Sobrien (char *) &mntdump); 45638494Sobrien if (mntexports) 45738494Sobrien (void) clnt_freeres(client, 45838494Sobrien (XDRPROC_T_TYPE) xdr_exports, 45938494Sobrien (char *) &mntexports); 46038494Sobrien 46138494Sobrien clnt_destroy(client); 46238494Sobrien } 46338494Sobrien exit(0); 46438494Sobrien return 0; /* should never reach here */ 46538494Sobrien} 46638494Sobrien 46738494Sobrien 46838494SobrienRETSIGTYPE 46938494Sobriencreate_timeout(int sig) 47038494Sobrien{ 47138494Sobrien signal(SIGALRM, SIG_DFL); 47238494Sobrien longjmp(before_rpc, 1); 47338494Sobrien} 47438494Sobrien 47538494Sobrien 47638494Sobrien#ifndef HAVE_TRANSPORT_TYPE_TLI 47738494Sobrien/* 47838494Sobrien * inetresport creates a datagram socket and attempts to bind it to a 47938494Sobrien * secure port. 48038494Sobrien * returns: The bound socket, or -1 to indicate an error. 48138494Sobrien */ 48238494Sobrienstatic int 48338494Sobrieninetresport(int ty) 48438494Sobrien{ 48538494Sobrien int alport; 48638494Sobrien struct sockaddr_in addr; 48738494Sobrien int fd; 48838494Sobrien 489174313Sobrien memset(&addr, 0, sizeof(addr)); 490174313Sobrien /* as per POSIX, sin_len need not be set (used internally by kernel) */ 491174313Sobrien 492174313Sobrien addr.sin_family = AF_INET; /* use internet address family */ 49338494Sobrien addr.sin_addr.s_addr = INADDR_ANY; 49438494Sobrien if ((fd = socket(AF_INET, ty, 0)) < 0) 49538494Sobrien return -1; 49638494Sobrien 49738494Sobrien for (alport = IPPORT_RESERVED - 1; alport > IPPORT_RESERVED / 2 + 1; alport--) { 49838494Sobrien addr.sin_port = htons((u_short) alport); 49938494Sobrien if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) >= 0) 50038494Sobrien return fd; 50138494Sobrien if (errno != EADDRINUSE) { 50238494Sobrien close(fd); 50338494Sobrien return -1; 50438494Sobrien } 50538494Sobrien } 50638494Sobrien close(fd); 50738494Sobrien errno = EAGAIN; 50838494Sobrien return -1; 50938494Sobrien} 51038494Sobrien 51138494Sobrien 51238494Sobrien/* 51338494Sobrien * Privsock() calls inetresport() to attempt to bind a socket to a secure 51438494Sobrien * port. If inetresport() fails, privsock returns a magic socket number which 51538494Sobrien * indicates to RPC that it should make its own socket. 51638494Sobrien * returns: A privileged socket # or RPC_ANYSOCK. 51738494Sobrien */ 51838494Sobrienstatic int 51938494Sobrienprivsock(int ty) 52038494Sobrien{ 52138494Sobrien int sock = inetresport(ty); 52238494Sobrien 52338494Sobrien if (sock < 0) { 52438494Sobrien errno = 0; 52538494Sobrien /* Couldn't get a secure port, let RPC make an insecure one */ 52638494Sobrien sock = RPC_ANYSOCK; 52738494Sobrien } 52838494Sobrien return sock; 52938494Sobrien} 53038494Sobrien#endif /* not HAVE_TRANSPORT_TYPE_TLI */ 53138494Sobrien 53238494Sobrien 53338494Sobrienstatic CLIENT * 53438494Sobrienclnt_create_timeout(char *host, struct timeval *tvp) 53538494Sobrien{ 53638494Sobrien CLIENT *clnt; 53738494Sobrien struct sockaddr_in host_addr; 53838494Sobrien struct hostent *hp; 53938494Sobrien#ifndef HAVE_TRANSPORT_TYPE_TLI 54038494Sobrien int s; 54138494Sobrien#endif /* not HAVE_TRANSPORT_TYPE_TLI */ 54238494Sobrien 54338494Sobrien if (setjmp(before_rpc)) { 54438494Sobrien if (!quiet) { 54538494Sobrien fprintf(stderr, "%s: ", host); 54638494Sobrien clnt_perrno(RPC_TIMEDOUT); 54738494Sobrien fprintf(stderr, "\n"); 54838494Sobrien fflush(stderr); 54938494Sobrien } 55038494Sobrien return NULL; 55138494Sobrien } 55238494Sobrien signal(SIGALRM, create_timeout); 55338494Sobrien ualarm(tvp->tv_sec * 1000000 + tvp->tv_usec, 0); 55438494Sobrien 55538494Sobrien /* 55638494Sobrien * Get address of host 55738494Sobrien */ 55838494Sobrien if ((hp = gethostbyname(host)) == 0 && !STREQ(host, localhost)) { 55938494Sobrien fprintf(stderr, "can't get address of %s\n", host); 56038494Sobrien return NULL; 56138494Sobrien } 562174313Sobrien memset(&host_addr, 0, sizeof(host_addr)); 563174313Sobrien /* as per POSIX, sin_len need not be set (used internally by kernel) */ 56438494Sobrien host_addr.sin_family = AF_INET; 56538494Sobrien if (hp) { 56638494Sobrien memmove((voidp) &host_addr.sin_addr, (voidp) hp->h_addr, 56738494Sobrien sizeof(host_addr.sin_addr)); 56838494Sobrien } else { 56938494Sobrien /* fake "localhost" */ 57038494Sobrien host_addr.sin_addr.s_addr = htonl(0x7f000001); 57138494Sobrien } 57238494Sobrien 57338494Sobrien#ifdef HAVE_TRANSPORT_TYPE_TLI 57438494Sobrien /* try TCP first (in case return data is large), then UDP */ 57538494Sobrien clnt = clnt_create(host, MOUNTPROG, MOUNTVERS, "tcp"); 57638494Sobrien if (!clnt) 57738494Sobrien clnt = clnt_create(host, MOUNTPROG, MOUNTVERS, "udp"); 57838494Sobrien#else /* not HAVE_TRANSPORT_TYPE_TLI */ 57938494Sobrien s = RPC_ANYSOCK; 58038494Sobrien clnt = clnttcp_create(&host_addr, MOUNTPROG, MOUNTVERS, &s, 0, 0); 58138494Sobrien if (!clnt) { 58238494Sobrien /* XXX: do we need to close(s) ? */ 58338494Sobrien s = privsock(SOCK_DGRAM); 58438494Sobrien clnt = clntudp_create(&host_addr, MOUNTPROG, MOUNTVERS, *tvp, &s); 58538494Sobrien } 58638494Sobrien#endif /* not HAVE_TRANSPORT_TYPE_TLI */ 58738494Sobrien 58838494Sobrien if (!clnt) { 58938494Sobrien ualarm(0, 0); 59038494Sobrien if (!quiet) { 59138494Sobrien clnt_pcreateerror(host); 59238494Sobrien fflush(stderr); 59338494Sobrien } 59438494Sobrien return NULL; 59538494Sobrien } 59638494Sobrien 59738494Sobrien ualarm(0, 0); 59838494Sobrien return clnt; 59938494Sobrien} 600