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