1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate * 22*7c478bd9Sstevel@tonic-gate * Copyright 2003 Sun Microsystems, Inc. All rights reserved. 23*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 24*7c478bd9Sstevel@tonic-gate */ 25*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 26*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 27*7c478bd9Sstevel@tonic-gate 28*7c478bd9Sstevel@tonic-gate /* 29*7c478bd9Sstevel@tonic-gate * mount_nfs.c - procedural interface to the NFS mount operation 30*7c478bd9Sstevel@tonic-gate */ 31*7c478bd9Sstevel@tonic-gate 32*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 33*7c478bd9Sstevel@tonic-gate 34*7c478bd9Sstevel@tonic-gate #define NFSCLIENT 35*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 36*7c478bd9Sstevel@tonic-gate #include <memory.h> 37*7c478bd9Sstevel@tonic-gate #include <netconfig.h> 38*7c478bd9Sstevel@tonic-gate #include <netdb.h> 39*7c478bd9Sstevel@tonic-gate #include <netdir.h> 40*7c478bd9Sstevel@tonic-gate #include <netinet/in.h> 41*7c478bd9Sstevel@tonic-gate #include <stdarg.h> 42*7c478bd9Sstevel@tonic-gate #include <stdio.h> 43*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 44*7c478bd9Sstevel@tonic-gate #include <string.h> 45*7c478bd9Sstevel@tonic-gate #include <unistd.h> 46*7c478bd9Sstevel@tonic-gate #include <syslog.h> 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 49*7c478bd9Sstevel@tonic-gate #include <rpc/clnt_soc.h> 50*7c478bd9Sstevel@tonic-gate #include <rpc/pmap_prot.h> 51*7c478bd9Sstevel@tonic-gate #include <nfs/nfs.h> 52*7c478bd9Sstevel@tonic-gate #include <nfs/mount.h> 53*7c478bd9Sstevel@tonic-gate #include <rpcsvc/mount.h> 54*7c478bd9Sstevel@tonic-gate #include <errno.h> 55*7c478bd9Sstevel@tonic-gate #include <sys/mntent.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/mnttab.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/mount.h> 58*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 59*7c478bd9Sstevel@tonic-gate #include <sys/socket.h> 60*7c478bd9Sstevel@tonic-gate #include <sys/stat.h> 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate #define TIME_MAX 16 63*7c478bd9Sstevel@tonic-gate 64*7c478bd9Sstevel@tonic-gate extern int Debug; 65*7c478bd9Sstevel@tonic-gate extern time_t time_now; 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate extern FILE *setmntent(char *, char *); 68*7c478bd9Sstevel@tonic-gate extern void errprintf(char *, char *, ...); 69*7c478bd9Sstevel@tonic-gate 70*7c478bd9Sstevel@tonic-gate FILE *setmntent(char *, char *); 71*7c478bd9Sstevel@tonic-gate void endmntent(FILE *); 72*7c478bd9Sstevel@tonic-gate enum clnt_stat pingnfs(char *, rpcvers_t *); 73*7c478bd9Sstevel@tonic-gate struct netbuf *get_addr(char *, int, int, struct netconfig **); 74*7c478bd9Sstevel@tonic-gate struct knetconfig *get_knconf(struct netconfig *); 75*7c478bd9Sstevel@tonic-gate void netbuf_free(struct netbuf *); 76*7c478bd9Sstevel@tonic-gate void free_knconf(struct knetconfig *); 77*7c478bd9Sstevel@tonic-gate 78*7c478bd9Sstevel@tonic-gate /* 79*7c478bd9Sstevel@tonic-gate * mount_nfs - mount a file system using NFS 80*7c478bd9Sstevel@tonic-gate * 81*7c478bd9Sstevel@tonic-gate * Returns: 0 if OK, 1 if error. 82*7c478bd9Sstevel@tonic-gate * The "error" string returns the error message. 83*7c478bd9Sstevel@tonic-gate */ 84*7c478bd9Sstevel@tonic-gate int 85*7c478bd9Sstevel@tonic-gate mount_nfs(fsname, dir, error) 86*7c478bd9Sstevel@tonic-gate char *fsname; 87*7c478bd9Sstevel@tonic-gate char *dir; 88*7c478bd9Sstevel@tonic-gate char *error; 89*7c478bd9Sstevel@tonic-gate { 90*7c478bd9Sstevel@tonic-gate struct sockaddr_in sin; 91*7c478bd9Sstevel@tonic-gate struct hostent *hp; 92*7c478bd9Sstevel@tonic-gate struct fhstatus fhs; 93*7c478bd9Sstevel@tonic-gate char host[256]; 94*7c478bd9Sstevel@tonic-gate char *path; 95*7c478bd9Sstevel@tonic-gate char opts[32]; 96*7c478bd9Sstevel@tonic-gate struct stat st; 97*7c478bd9Sstevel@tonic-gate int s = -1; 98*7c478bd9Sstevel@tonic-gate struct timeval timeout; 99*7c478bd9Sstevel@tonic-gate CLIENT *client; 100*7c478bd9Sstevel@tonic-gate enum clnt_stat rpc_stat; 101*7c478bd9Sstevel@tonic-gate int printed1 = 0; 102*7c478bd9Sstevel@tonic-gate int printed2 = 0; 103*7c478bd9Sstevel@tonic-gate unsigned winks = 1; /* seconds of sleep time */ 104*7c478bd9Sstevel@tonic-gate struct mnttab mnt; 105*7c478bd9Sstevel@tonic-gate FILE *mnted; 106*7c478bd9Sstevel@tonic-gate int flags; 107*7c478bd9Sstevel@tonic-gate struct nfs_args args; 108*7c478bd9Sstevel@tonic-gate struct netconfig *nconf, *udpnconf; 109*7c478bd9Sstevel@tonic-gate char tbuf[TIME_MAX]; 110*7c478bd9Sstevel@tonic-gate rpcvers_t vers; 111*7c478bd9Sstevel@tonic-gate rpcvers_t nfsvers; 112*7c478bd9Sstevel@tonic-gate char *fstype; 113*7c478bd9Sstevel@tonic-gate struct mountres3 res3; 114*7c478bd9Sstevel@tonic-gate nfs_fh3 fh3; 115*7c478bd9Sstevel@tonic-gate int *auths; 116*7c478bd9Sstevel@tonic-gate int count; 117*7c478bd9Sstevel@tonic-gate 118*7c478bd9Sstevel@tonic-gate if (Debug) 119*7c478bd9Sstevel@tonic-gate printf("mount_nfs request: mount %s\tdir %s\n", fsname, dir); 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate if (Debug && errno) 122*7c478bd9Sstevel@tonic-gate printf("ERRNO set on mount_nfs entry: %d\n", errno); 123*7c478bd9Sstevel@tonic-gate 124*7c478bd9Sstevel@tonic-gate path = strchr(fsname, ':'); 125*7c478bd9Sstevel@tonic-gate if (path == NULL) { 126*7c478bd9Sstevel@tonic-gate errprintf(error, "No host name in %s\n", fsname); 127*7c478bd9Sstevel@tonic-gate return (1); 128*7c478bd9Sstevel@tonic-gate } 129*7c478bd9Sstevel@tonic-gate *path = '\0'; 130*7c478bd9Sstevel@tonic-gate strcpy(host, fsname); 131*7c478bd9Sstevel@tonic-gate *path++ = ':'; 132*7c478bd9Sstevel@tonic-gate if (*path == '\0') { 133*7c478bd9Sstevel@tonic-gate /* 134*7c478bd9Sstevel@tonic-gate * handle the special case of importing a root file system 135*7c478bd9Sstevel@tonic-gate */ 136*7c478bd9Sstevel@tonic-gate strcpy(path, "/"); 137*7c478bd9Sstevel@tonic-gate } 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate if (Debug) { 140*7c478bd9Sstevel@tonic-gate printf("mount_nfs:\tpath == %s\n", path); 141*7c478bd9Sstevel@tonic-gate printf("\t\tdir == %s\n", dir); 142*7c478bd9Sstevel@tonic-gate printf("\t\tgethostbyname host == %s\n", host); 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* 146*7c478bd9Sstevel@tonic-gate * Get server's address 147*7c478bd9Sstevel@tonic-gate */ 148*7c478bd9Sstevel@tonic-gate if ((hp = gethostbyname(host)) == NULL) { 149*7c478bd9Sstevel@tonic-gate errprintf(error, "mount %s: %s not in hosts database\n", 150*7c478bd9Sstevel@tonic-gate fsname, host); 151*7c478bd9Sstevel@tonic-gate return (1); 152*7c478bd9Sstevel@tonic-gate } 153*7c478bd9Sstevel@tonic-gate 154*7c478bd9Sstevel@tonic-gate if (Debug && errno) 155*7c478bd9Sstevel@tonic-gate printf("ERRNO set after gethostbyname: %d\n", errno); 156*7c478bd9Sstevel@tonic-gate 157*7c478bd9Sstevel@tonic-gate if (Debug) { 158*7c478bd9Sstevel@tonic-gate fprintf(stderr, "gethostbyname:\n\th_name %s\n\t", hp->h_name); 159*7c478bd9Sstevel@tonic-gate if (hp->h_aliases[0] && *hp->h_aliases[0]) 160*7c478bd9Sstevel@tonic-gate fprintf(stderr, "h_aliases %s\n\t", hp->h_aliases[0]); 161*7c478bd9Sstevel@tonic-gate else 162*7c478bd9Sstevel@tonic-gate fprintf(stderr, "h_aliases %s\n\t", "<none>"); 163*7c478bd9Sstevel@tonic-gate if (hp->h_addrtype == AF_INET) 164*7c478bd9Sstevel@tonic-gate fprintf(stderr, 165*7c478bd9Sstevel@tonic-gate "h_addrtype AF_INET\n\th_adth_length %u\n\t", 166*7c478bd9Sstevel@tonic-gate hp->h_length); 167*7c478bd9Sstevel@tonic-gate else 168*7c478bd9Sstevel@tonic-gate fprintf(stderr, "h_addrtype %u\n\th_adth_length %u\n\t", 169*7c478bd9Sstevel@tonic-gate hp->h_addrtype, hp->h_length); 170*7c478bd9Sstevel@tonic-gate if (hp->h_addr_list[0] && *hp->h_addr_list[0]) 171*7c478bd9Sstevel@tonic-gate fprintf(stderr, "h_addr_list <apparent list>\n"); 172*7c478bd9Sstevel@tonic-gate else 173*7c478bd9Sstevel@tonic-gate fprintf(stderr, "h_addr_list %s\n", "<none>"); 174*7c478bd9Sstevel@tonic-gate } 175*7c478bd9Sstevel@tonic-gate 176*7c478bd9Sstevel@tonic-gate if (pingnfs(host, &nfsvers) != RPC_SUCCESS) { 177*7c478bd9Sstevel@tonic-gate errprintf(error, "host %s not responding to ping\n", host); 178*7c478bd9Sstevel@tonic-gate return (1); 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate if (Debug) 182*7c478bd9Sstevel@tonic-gate printf("pingnfs: succeeds.\n"); 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate vers = nfsvers; 185*7c478bd9Sstevel@tonic-gate 186*7c478bd9Sstevel@tonic-gate if (Debug) 187*7c478bd9Sstevel@tonic-gate printf("clnt_create for mountproc (%d)\n", errno); 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate client = clnt_create_vers(host, MOUNTPROG, &vers, MOUNTVERS, vers, 190*7c478bd9Sstevel@tonic-gate "udp"); 191*7c478bd9Sstevel@tonic-gate if (client == NULL) { 192*7c478bd9Sstevel@tonic-gate errprintf(error, "%s %s\n", host, 193*7c478bd9Sstevel@tonic-gate clnt_spcreateerror("mount server not responding")); 194*7c478bd9Sstevel@tonic-gate return (1); 195*7c478bd9Sstevel@tonic-gate } 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate if (Debug) 198*7c478bd9Sstevel@tonic-gate printf("call bindudp_resvport for mountproc (%d)\n", errno); 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate if (bindudp_resvport(client) < 0) { 201*7c478bd9Sstevel@tonic-gate errprintf(error, "mount %s:%s: %s\n", host, path, 202*7c478bd9Sstevel@tonic-gate "Couldn't bind to reserved port"); 203*7c478bd9Sstevel@tonic-gate if (Debug) 204*7c478bd9Sstevel@tonic-gate printf("could not bind to reserved port\n"); 205*7c478bd9Sstevel@tonic-gate clnt_destroy(client); 206*7c478bd9Sstevel@tonic-gate return (1); 207*7c478bd9Sstevel@tonic-gate } 208*7c478bd9Sstevel@tonic-gate 209*7c478bd9Sstevel@tonic-gate if (client->cl_auth) 210*7c478bd9Sstevel@tonic-gate auth_destroy(client->cl_auth); 211*7c478bd9Sstevel@tonic-gate if ((client->cl_auth = authsys_create_default()) == NULL) { 212*7c478bd9Sstevel@tonic-gate errprintf(error, "mount %s:%s: %s\n", host, path, 213*7c478bd9Sstevel@tonic-gate "Couldn't create authsys structure"); 214*7c478bd9Sstevel@tonic-gate if (Debug) 215*7c478bd9Sstevel@tonic-gate printf("could not create authsys structure\n"); 216*7c478bd9Sstevel@tonic-gate clnt_destroy(client); 217*7c478bd9Sstevel@tonic-gate return (1); 218*7c478bd9Sstevel@tonic-gate } 219*7c478bd9Sstevel@tonic-gate 220*7c478bd9Sstevel@tonic-gate /* #ifdef NOWAY 221*7c478bd9Sstevel@tonic-gate /* if (Debug) 222*7c478bd9Sstevel@tonic-gate /* printf("authsys_create_default called for mountproc\n"); 223*7c478bd9Sstevel@tonic-gate /* client->cl_auth = authsys_create_default(); 224*7c478bd9Sstevel@tonic-gate /* #endif 225*7c478bd9Sstevel@tonic-gate /* */ 226*7c478bd9Sstevel@tonic-gate 227*7c478bd9Sstevel@tonic-gate /* set mount args */ 228*7c478bd9Sstevel@tonic-gate memset(&args, 0, sizeof(args)); 229*7c478bd9Sstevel@tonic-gate 230*7c478bd9Sstevel@tonic-gate /* Get fhandle of remote path from server's mountd */ 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate timeout.tv_usec = 0; 233*7c478bd9Sstevel@tonic-gate timeout.tv_sec = 25; 234*7c478bd9Sstevel@tonic-gate 235*7c478bd9Sstevel@tonic-gate switch (vers) { 236*7c478bd9Sstevel@tonic-gate case MOUNTVERS: 237*7c478bd9Sstevel@tonic-gate case MOUNTVERS_POSIX: 238*7c478bd9Sstevel@tonic-gate rpc_stat = clnt_call(client, MOUNTPROC_MNT, 239*7c478bd9Sstevel@tonic-gate xdr_dirpath, (caddr_t)&path, 240*7c478bd9Sstevel@tonic-gate xdr_fhstatus, (caddr_t)&fhs, timeout); 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate if (rpc_stat != RPC_SUCCESS) { 243*7c478bd9Sstevel@tonic-gate /* Given the way "clnt_sperror" works, the "%s" */ 244*7c478bd9Sstevel@tonic-gate /* following the "not responding" is correct. */ 245*7c478bd9Sstevel@tonic-gate errprintf(error, "mount server %s not responding %s\n", 246*7c478bd9Sstevel@tonic-gate host, clnt_sperror(client, "")); 247*7c478bd9Sstevel@tonic-gate clnt_destroy(client); 248*7c478bd9Sstevel@tonic-gate return (1); 249*7c478bd9Sstevel@tonic-gate } 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate clnt_destroy(client); 252*7c478bd9Sstevel@tonic-gate 253*7c478bd9Sstevel@tonic-gate if ((errno = fhs.fhs_status) != MNT_OK) { 254*7c478bd9Sstevel@tonic-gate if (errno == EACCES) { 255*7c478bd9Sstevel@tonic-gate errprintf(error, 256*7c478bd9Sstevel@tonic-gate "rexd mount: not in EXPORT list for %s\n", 257*7c478bd9Sstevel@tonic-gate fsname); 258*7c478bd9Sstevel@tonic-gate } else { 259*7c478bd9Sstevel@tonic-gate errprintf(error, "rexd mount: error %d %s\n", 260*7c478bd9Sstevel@tonic-gate errno, strerror(errno)); 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate return (1); 263*7c478bd9Sstevel@tonic-gate } 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate args.fh = (caddr_t)&fhs.fhstatus_u.fhs_fhandle; 266*7c478bd9Sstevel@tonic-gate fstype = MNTTYPE_NFS; 267*7c478bd9Sstevel@tonic-gate break; 268*7c478bd9Sstevel@tonic-gate case MOUNTVERS3: 269*7c478bd9Sstevel@tonic-gate memset((char *)&res3, '\0', sizeof (res3)); 270*7c478bd9Sstevel@tonic-gate rpc_stat = clnt_call(client, MOUNTPROC_MNT, 271*7c478bd9Sstevel@tonic-gate xdr_dirpath, (char *)&path, 272*7c478bd9Sstevel@tonic-gate xdr_mountres3, (char *)&res3, timeout); 273*7c478bd9Sstevel@tonic-gate 274*7c478bd9Sstevel@tonic-gate if (rpc_stat != RPC_SUCCESS) { 275*7c478bd9Sstevel@tonic-gate /* Given the way "clnt_sperror" works, the "%s" */ 276*7c478bd9Sstevel@tonic-gate /* following the "not responding" is correct. */ 277*7c478bd9Sstevel@tonic-gate errprintf(error, "mount server %s not responding %s\n", 278*7c478bd9Sstevel@tonic-gate host, clnt_sperror(client, "")); 279*7c478bd9Sstevel@tonic-gate clnt_destroy(client); 280*7c478bd9Sstevel@tonic-gate return (1); 281*7c478bd9Sstevel@tonic-gate } 282*7c478bd9Sstevel@tonic-gate 283*7c478bd9Sstevel@tonic-gate clnt_destroy(client); 284*7c478bd9Sstevel@tonic-gate 285*7c478bd9Sstevel@tonic-gate if ((errno = res3.fhs_status) != MNT_OK) { 286*7c478bd9Sstevel@tonic-gate if (errno == EACCES) { 287*7c478bd9Sstevel@tonic-gate errprintf(error, 288*7c478bd9Sstevel@tonic-gate "rexd mount: not in EXPORT list for %s\n", 289*7c478bd9Sstevel@tonic-gate fsname); 290*7c478bd9Sstevel@tonic-gate } else { 291*7c478bd9Sstevel@tonic-gate errprintf(error, "rexd mount: error %d %s\n", 292*7c478bd9Sstevel@tonic-gate errno, strerror(errno)); 293*7c478bd9Sstevel@tonic-gate } 294*7c478bd9Sstevel@tonic-gate return (1); 295*7c478bd9Sstevel@tonic-gate } 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate auths = 298*7c478bd9Sstevel@tonic-gate res3.mountres3_u.mountinfo.auth_flavors.auth_flavors_val; 299*7c478bd9Sstevel@tonic-gate count = 300*7c478bd9Sstevel@tonic-gate res3.mountres3_u.mountinfo.auth_flavors.auth_flavors_len; 301*7c478bd9Sstevel@tonic-gate if (count > 0) { 302*7c478bd9Sstevel@tonic-gate if (auths[0] == AUTH_DES) 303*7c478bd9Sstevel@tonic-gate args.flags |= NFSMNT_SECURE; 304*7c478bd9Sstevel@tonic-gate } 305*7c478bd9Sstevel@tonic-gate 306*7c478bd9Sstevel@tonic-gate fh3.fh3_length = 307*7c478bd9Sstevel@tonic-gate res3.mountres3_u.mountinfo.fhandle.fhandle3_len; 308*7c478bd9Sstevel@tonic-gate memcpy(fh3.fh3_u.data, 309*7c478bd9Sstevel@tonic-gate res3.mountres3_u.mountinfo.fhandle.fhandle3_val, 310*7c478bd9Sstevel@tonic-gate fh3.fh3_length); 311*7c478bd9Sstevel@tonic-gate args.fh = (caddr_t)&fh3; 312*7c478bd9Sstevel@tonic-gate fstype = MNTTYPE_NFS3; 313*7c478bd9Sstevel@tonic-gate break; 314*7c478bd9Sstevel@tonic-gate default: 315*7c478bd9Sstevel@tonic-gate errprintf(error, "rexd mount: unknown MOUNT version %ld\n", 316*7c478bd9Sstevel@tonic-gate vers); 317*7c478bd9Sstevel@tonic-gate return (1); 318*7c478bd9Sstevel@tonic-gate } 319*7c478bd9Sstevel@tonic-gate 320*7c478bd9Sstevel@tonic-gate 321*7c478bd9Sstevel@tonic-gate /* 322*7c478bd9Sstevel@tonic-gate * remote mount the fhandle on the local path. 323*7c478bd9Sstevel@tonic-gate */ 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate args.hostname = host; 326*7c478bd9Sstevel@tonic-gate args.flags = NFSMNT_HOSTNAME; 327*7c478bd9Sstevel@tonic-gate args.flags |= NFSMNT_INT; /* default is "intr" */ 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate args.addr = get_addr(host, NFS_PROGRAM, nfsvers, &nconf); 330*7c478bd9Sstevel@tonic-gate if (args.addr == NULL) { 331*7c478bd9Sstevel@tonic-gate errprintf(error, "%s: no NFS service", host); 332*7c478bd9Sstevel@tonic-gate return (1); 333*7c478bd9Sstevel@tonic-gate } 334*7c478bd9Sstevel@tonic-gate 335*7c478bd9Sstevel@tonic-gate args.flags |= NFSMNT_KNCONF; 336*7c478bd9Sstevel@tonic-gate args.knconf = get_knconf(nconf); 337*7c478bd9Sstevel@tonic-gate if (args.knconf == NULL) { 338*7c478bd9Sstevel@tonic-gate netbuf_free(args.addr); 339*7c478bd9Sstevel@tonic-gate return (1); 340*7c478bd9Sstevel@tonic-gate } 341*7c478bd9Sstevel@tonic-gate 342*7c478bd9Sstevel@tonic-gate if (Debug) 343*7c478bd9Sstevel@tonic-gate printf("start mount system call (%d)\n", errno); 344*7c478bd9Sstevel@tonic-gate 345*7c478bd9Sstevel@tonic-gate flags = MS_NOSUID | MS_DATA; 346*7c478bd9Sstevel@tonic-gate 347*7c478bd9Sstevel@tonic-gate /* Provide the mounted resource name when mounting. */ 348*7c478bd9Sstevel@tonic-gate if (mount(fsname, dir, flags, fstype, &args, sizeof(args)) < 0) { 349*7c478bd9Sstevel@tonic-gate netbuf_free(args.addr); 350*7c478bd9Sstevel@tonic-gate free_knconf(args.knconf); 351*7c478bd9Sstevel@tonic-gate errprintf(error, "unable to mount %s on %s: %s\n", 352*7c478bd9Sstevel@tonic-gate fsname, dir, strerror(errno)); 353*7c478bd9Sstevel@tonic-gate return (1); 354*7c478bd9Sstevel@tonic-gate } 355*7c478bd9Sstevel@tonic-gate 356*7c478bd9Sstevel@tonic-gate if (Debug) 357*7c478bd9Sstevel@tonic-gate printf("end mount system call (%d)\n", errno); 358*7c478bd9Sstevel@tonic-gate 359*7c478bd9Sstevel@tonic-gate /* 360*7c478bd9Sstevel@tonic-gate * stat the new mount and get its dev 361*7c478bd9Sstevel@tonic-gate */ 362*7c478bd9Sstevel@tonic-gate if (stat(dir, &st) < 0) { 363*7c478bd9Sstevel@tonic-gate errprintf(error, "couldn't stat %s\n", dir); 364*7c478bd9Sstevel@tonic-gate return (1); 365*7c478bd9Sstevel@tonic-gate } 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate if (Debug) 368*7c478bd9Sstevel@tonic-gate printf("stat of new mount (%d)\n", errno); 369*7c478bd9Sstevel@tonic-gate 370*7c478bd9Sstevel@tonic-gate (void) sprintf(opts, "rw,noquota,hard,intr,dev=%x", st.st_dev); 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate /* 373*7c478bd9Sstevel@tonic-gate * update /etc/mtab 374*7c478bd9Sstevel@tonic-gate */ 375*7c478bd9Sstevel@tonic-gate 376*7c478bd9Sstevel@tonic-gate mnt.mnt_special = fsname; 377*7c478bd9Sstevel@tonic-gate mnt.mnt_mountp = dir; 378*7c478bd9Sstevel@tonic-gate mnt.mnt_fstype = MNTTYPE_NFS; 379*7c478bd9Sstevel@tonic-gate mnt.mnt_mntopts = opts; 380*7c478bd9Sstevel@tonic-gate (void) sprintf(tbuf, "%ld", time(0L)); 381*7c478bd9Sstevel@tonic-gate mnt.mnt_time = tbuf; 382*7c478bd9Sstevel@tonic-gate 383*7c478bd9Sstevel@tonic-gate return (0); 384*7c478bd9Sstevel@tonic-gate } 385*7c478bd9Sstevel@tonic-gate 386*7c478bd9Sstevel@tonic-gate #define UNMOUNTTRIES 6 387*7c478bd9Sstevel@tonic-gate /* 388*7c478bd9Sstevel@tonic-gate * umount_nfs - unmount a file system when finished 389*7c478bd9Sstevel@tonic-gate */ 390*7c478bd9Sstevel@tonic-gate int 391*7c478bd9Sstevel@tonic-gate umount_nfs(fsname, dir) 392*7c478bd9Sstevel@tonic-gate char *fsname, *dir; 393*7c478bd9Sstevel@tonic-gate { 394*7c478bd9Sstevel@tonic-gate char *p; 395*7c478bd9Sstevel@tonic-gate char *hostname; 396*7c478bd9Sstevel@tonic-gate int s = -1; 397*7c478bd9Sstevel@tonic-gate struct timeval timeout; 398*7c478bd9Sstevel@tonic-gate CLIENT *client; 399*7c478bd9Sstevel@tonic-gate enum clnt_stat rpc_stat; 400*7c478bd9Sstevel@tonic-gate int count = 0; 401*7c478bd9Sstevel@tonic-gate 402*7c478bd9Sstevel@tonic-gate if (Debug) 403*7c478bd9Sstevel@tonic-gate printf("umount: fsname %s dir %s\n", fsname, dir); 404*7c478bd9Sstevel@tonic-gate /* 405*7c478bd9Sstevel@tonic-gate * Give the filesystem time to become un-busy when unmounting. 406*7c478bd9Sstevel@tonic-gate * If child aborted and is takes a core dump, we may receive the 407*7c478bd9Sstevel@tonic-gate * SIGCHLD before the core dump is completed. 408*7c478bd9Sstevel@tonic-gate */ 409*7c478bd9Sstevel@tonic-gate while (umount(dir) == -1) { 410*7c478bd9Sstevel@tonic-gate if (errno != EBUSY) { 411*7c478bd9Sstevel@tonic-gate perror(dir); 412*7c478bd9Sstevel@tonic-gate return (1); 413*7c478bd9Sstevel@tonic-gate } 414*7c478bd9Sstevel@tonic-gate 415*7c478bd9Sstevel@tonic-gate if (++count > UNMOUNTTRIES) 416*7c478bd9Sstevel@tonic-gate return (1); 417*7c478bd9Sstevel@tonic-gate sleep(10); 418*7c478bd9Sstevel@tonic-gate } 419*7c478bd9Sstevel@tonic-gate 420*7c478bd9Sstevel@tonic-gate if (Debug) 421*7c478bd9Sstevel@tonic-gate printf("umount_nfs: unmounting %s\n", dir); 422*7c478bd9Sstevel@tonic-gate 423*7c478bd9Sstevel@tonic-gate if ((p = strchr(fsname, ':')) == NULL) 424*7c478bd9Sstevel@tonic-gate return (1); 425*7c478bd9Sstevel@tonic-gate *p++ = 0; 426*7c478bd9Sstevel@tonic-gate hostname = fsname; 427*7c478bd9Sstevel@tonic-gate 428*7c478bd9Sstevel@tonic-gate 429*7c478bd9Sstevel@tonic-gate if ((client = clnt_create(hostname, MOUNTPROG, MOUNTVERS, "udp")) 430*7c478bd9Sstevel@tonic-gate == NULL) { 431*7c478bd9Sstevel@tonic-gate clnt_spcreateerror("Warning on umount create:"); 432*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\n\r"); 433*7c478bd9Sstevel@tonic-gate return (1); 434*7c478bd9Sstevel@tonic-gate } 435*7c478bd9Sstevel@tonic-gate if (bindudp_resvport(client) < 0) { 436*7c478bd9Sstevel@tonic-gate errprintf(NULL, "umount %s:%s:%s", hostname, p, 437*7c478bd9Sstevel@tonic-gate "Could not bind to reserved port\n"); 438*7c478bd9Sstevel@tonic-gate clnt_destroy(client); 439*7c478bd9Sstevel@tonic-gate return (1); 440*7c478bd9Sstevel@tonic-gate } 441*7c478bd9Sstevel@tonic-gate 442*7c478bd9Sstevel@tonic-gate /* #ifdef NOWAWY 443*7c478bd9Sstevel@tonic-gate /* client->cl_auth = authunix_create_default(); 444*7c478bd9Sstevel@tonic-gate /* #endif /* NOWAY */ 445*7c478bd9Sstevel@tonic-gate /* */ 446*7c478bd9Sstevel@tonic-gate 447*7c478bd9Sstevel@tonic-gate timeout.tv_usec = 0; 448*7c478bd9Sstevel@tonic-gate timeout.tv_sec = 25; 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate rpc_stat = clnt_call(client, MOUNTPROC_UMNT, xdr_dirpath, (caddr_t) &p, 451*7c478bd9Sstevel@tonic-gate xdr_void, (char *)NULL, timeout); 452*7c478bd9Sstevel@tonic-gate 453*7c478bd9Sstevel@tonic-gate clnt_destroy(client); 454*7c478bd9Sstevel@tonic-gate 455*7c478bd9Sstevel@tonic-gate if (rpc_stat != RPC_SUCCESS) { 456*7c478bd9Sstevel@tonic-gate clnt_perror(client, "Warning: umount:"); 457*7c478bd9Sstevel@tonic-gate fprintf(stderr, "\n\r"); 458*7c478bd9Sstevel@tonic-gate return (1); 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate return (0); 462*7c478bd9Sstevel@tonic-gate } 463*7c478bd9Sstevel@tonic-gate 464*7c478bd9Sstevel@tonic-gate 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate 467*7c478bd9Sstevel@tonic-gate static struct mnttab * 468*7c478bd9Sstevel@tonic-gate dupmnttab(mnt) 469*7c478bd9Sstevel@tonic-gate struct mnttab *mnt; 470*7c478bd9Sstevel@tonic-gate { 471*7c478bd9Sstevel@tonic-gate struct mnttab *new; 472*7c478bd9Sstevel@tonic-gate void freemnttab(); 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate new = (struct mnttab *)malloc(sizeof (*new)); 475*7c478bd9Sstevel@tonic-gate if (new == NULL) 476*7c478bd9Sstevel@tonic-gate goto alloc_failed; 477*7c478bd9Sstevel@tonic-gate memset((char *)new, 0, sizeof (*new)); 478*7c478bd9Sstevel@tonic-gate new->mnt_special = strdup(mnt->mnt_special); 479*7c478bd9Sstevel@tonic-gate if (new->mnt_special == NULL) 480*7c478bd9Sstevel@tonic-gate goto alloc_failed; 481*7c478bd9Sstevel@tonic-gate new->mnt_mountp = strdup(mnt->mnt_mountp); 482*7c478bd9Sstevel@tonic-gate if (new->mnt_mountp == NULL) 483*7c478bd9Sstevel@tonic-gate goto alloc_failed; 484*7c478bd9Sstevel@tonic-gate new->mnt_fstype = strdup(mnt->mnt_fstype); 485*7c478bd9Sstevel@tonic-gate if (new->mnt_fstype == NULL) 486*7c478bd9Sstevel@tonic-gate goto alloc_failed; 487*7c478bd9Sstevel@tonic-gate if (mnt->mnt_mntopts != NULL) 488*7c478bd9Sstevel@tonic-gate if ((new->mnt_mntopts = strdup(mnt->mnt_mntopts)) == NULL) 489*7c478bd9Sstevel@tonic-gate goto alloc_failed; 490*7c478bd9Sstevel@tonic-gate if (mnt->mnt_time != NULL) 491*7c478bd9Sstevel@tonic-gate if ((new->mnt_time = strdup(mnt->mnt_time)) == NULL) 492*7c478bd9Sstevel@tonic-gate goto alloc_failed; 493*7c478bd9Sstevel@tonic-gate 494*7c478bd9Sstevel@tonic-gate return (new); 495*7c478bd9Sstevel@tonic-gate 496*7c478bd9Sstevel@tonic-gate alloc_failed: 497*7c478bd9Sstevel@tonic-gate errprintf(NULL, "dupmnttab: memory allocation failed\n"); 498*7c478bd9Sstevel@tonic-gate freemnttab(new); 499*7c478bd9Sstevel@tonic-gate return (NULL); 500*7c478bd9Sstevel@tonic-gate } 501*7c478bd9Sstevel@tonic-gate 502*7c478bd9Sstevel@tonic-gate 503*7c478bd9Sstevel@tonic-gate 504*7c478bd9Sstevel@tonic-gate /* 505*7c478bd9Sstevel@tonic-gate * Free a single mnttab structure 506*7c478bd9Sstevel@tonic-gate */ 507*7c478bd9Sstevel@tonic-gate static void 508*7c478bd9Sstevel@tonic-gate freemnttab(mnt) 509*7c478bd9Sstevel@tonic-gate struct mnttab *mnt; 510*7c478bd9Sstevel@tonic-gate { 511*7c478bd9Sstevel@tonic-gate if (mnt) { 512*7c478bd9Sstevel@tonic-gate if (mnt->mnt_special) 513*7c478bd9Sstevel@tonic-gate free(mnt->mnt_special); 514*7c478bd9Sstevel@tonic-gate if (mnt->mnt_mountp) 515*7c478bd9Sstevel@tonic-gate free(mnt->mnt_mountp); 516*7c478bd9Sstevel@tonic-gate if (mnt->mnt_fstype) 517*7c478bd9Sstevel@tonic-gate free(mnt->mnt_fstype); 518*7c478bd9Sstevel@tonic-gate if (mnt->mnt_mntopts) 519*7c478bd9Sstevel@tonic-gate free(mnt->mnt_mntopts); 520*7c478bd9Sstevel@tonic-gate if (mnt->mnt_time) 521*7c478bd9Sstevel@tonic-gate free(mnt->mnt_time); 522*7c478bd9Sstevel@tonic-gate free(mnt); 523*7c478bd9Sstevel@tonic-gate } 524*7c478bd9Sstevel@tonic-gate } 525*7c478bd9Sstevel@tonic-gate 526*7c478bd9Sstevel@tonic-gate 527*7c478bd9Sstevel@tonic-gate /* the following structure is used to build a list of */ 528*7c478bd9Sstevel@tonic-gate /* mnttab structures from /etc/mnttab. */ 529*7c478bd9Sstevel@tonic-gate struct mntlist { 530*7c478bd9Sstevel@tonic-gate struct mnttab *mntl_mnt; 531*7c478bd9Sstevel@tonic-gate struct mntlist *mntl_next; 532*7c478bd9Sstevel@tonic-gate }; 533*7c478bd9Sstevel@tonic-gate 534*7c478bd9Sstevel@tonic-gate 535*7c478bd9Sstevel@tonic-gate /* 536*7c478bd9Sstevel@tonic-gate * Free a list of mnttab structures 537*7c478bd9Sstevel@tonic-gate */ 538*7c478bd9Sstevel@tonic-gate static void 539*7c478bd9Sstevel@tonic-gate freemntlist(mntl) 540*7c478bd9Sstevel@tonic-gate struct mntlist *mntl; 541*7c478bd9Sstevel@tonic-gate { 542*7c478bd9Sstevel@tonic-gate struct mntlist *mntl_tmp; 543*7c478bd9Sstevel@tonic-gate 544*7c478bd9Sstevel@tonic-gate while (mntl) { 545*7c478bd9Sstevel@tonic-gate freemnttab(mntl->mntl_mnt); 546*7c478bd9Sstevel@tonic-gate mntl_tmp = mntl; 547*7c478bd9Sstevel@tonic-gate mntl = mntl->mntl_next; 548*7c478bd9Sstevel@tonic-gate free(mntl_tmp); 549*7c478bd9Sstevel@tonic-gate } 550*7c478bd9Sstevel@tonic-gate } 551*7c478bd9Sstevel@tonic-gate 552*7c478bd9Sstevel@tonic-gate 553*7c478bd9Sstevel@tonic-gate /* 554*7c478bd9Sstevel@tonic-gate * parsefs - given a name of the form host:/path/name/for/file 555*7c478bd9Sstevel@tonic-gate * connect to the give host and look for the exported file system 556*7c478bd9Sstevel@tonic-gate * that matches. 557*7c478bd9Sstevel@tonic-gate * Returns: pointer to string containing the part of the pathname 558*7c478bd9Sstevel@tonic-gate * within the exported directory. 559*7c478bd9Sstevel@tonic-gate * Returns NULL on errors. 560*7c478bd9Sstevel@tonic-gate */ 561*7c478bd9Sstevel@tonic-gate char * 562*7c478bd9Sstevel@tonic-gate parsefs(fullname, error) 563*7c478bd9Sstevel@tonic-gate char *fullname; 564*7c478bd9Sstevel@tonic-gate char *error; 565*7c478bd9Sstevel@tonic-gate { 566*7c478bd9Sstevel@tonic-gate char *dir, 567*7c478bd9Sstevel@tonic-gate *subdir; 568*7c478bd9Sstevel@tonic-gate struct exportnode *ex = NULL; 569*7c478bd9Sstevel@tonic-gate int err; 570*7c478bd9Sstevel@tonic-gate int bestlen = 0; 571*7c478bd9Sstevel@tonic-gate int len, 572*7c478bd9Sstevel@tonic-gate dirlen; 573*7c478bd9Sstevel@tonic-gate 574*7c478bd9Sstevel@tonic-gate if (Debug && errno) 575*7c478bd9Sstevel@tonic-gate printf("parsefs of %s entered with errno %d %s\n", 576*7c478bd9Sstevel@tonic-gate fullname, errno, strerror(errno)); 577*7c478bd9Sstevel@tonic-gate 578*7c478bd9Sstevel@tonic-gate dir = strchr(fullname, ':'); 579*7c478bd9Sstevel@tonic-gate if (dir == NULL) { 580*7c478bd9Sstevel@tonic-gate 581*7c478bd9Sstevel@tonic-gate errprintf(error, "No host name in %s\n", fullname); 582*7c478bd9Sstevel@tonic-gate return (NULL); 583*7c478bd9Sstevel@tonic-gate } 584*7c478bd9Sstevel@tonic-gate *dir++ = '\0'; 585*7c478bd9Sstevel@tonic-gate 586*7c478bd9Sstevel@tonic-gate if (Debug) 587*7c478bd9Sstevel@tonic-gate printf("parsefs before rpc_call: ERRNO:%d\n", errno); 588*7c478bd9Sstevel@tonic-gate 589*7c478bd9Sstevel@tonic-gate if (err = rpc_call(fullname, MOUNTPROG, MOUNTVERS, MOUNTPROC_EXPORT, 590*7c478bd9Sstevel@tonic-gate xdr_void, 0, xdr_exports, (char *)&ex, "udp")) { 591*7c478bd9Sstevel@tonic-gate 592*7c478bd9Sstevel@tonic-gate if (err == (int)RPC_TIMEDOUT) 593*7c478bd9Sstevel@tonic-gate errprintf(error, "Host %s is not running mountd\n", 594*7c478bd9Sstevel@tonic-gate fullname); 595*7c478bd9Sstevel@tonic-gate else 596*7c478bd9Sstevel@tonic-gate errprintf(error, "RPC error %d with host %s (%s)\n", 597*7c478bd9Sstevel@tonic-gate err, fullname, clnt_sperrno(err)); 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate if (Debug && errno) { 600*7c478bd9Sstevel@tonic-gate printf("parsefs: mount call to %s returned %d %s\n", 601*7c478bd9Sstevel@tonic-gate fullname, 602*7c478bd9Sstevel@tonic-gate err, 603*7c478bd9Sstevel@tonic-gate clnt_sperrno(err)); 604*7c478bd9Sstevel@tonic-gate printf("with errno %d:\t%s\n", errno, strerror(errno)); 605*7c478bd9Sstevel@tonic-gate } 606*7c478bd9Sstevel@tonic-gate return (NULL); 607*7c478bd9Sstevel@tonic-gate } 608*7c478bd9Sstevel@tonic-gate 609*7c478bd9Sstevel@tonic-gate if (Debug) 610*7c478bd9Sstevel@tonic-gate printf("parsefs after rpc_call: ERRNO:%d\n", errno); 611*7c478bd9Sstevel@tonic-gate 612*7c478bd9Sstevel@tonic-gate dirlen = strlen(dir); 613*7c478bd9Sstevel@tonic-gate 614*7c478bd9Sstevel@tonic-gate if (Debug && errno) { 615*7c478bd9Sstevel@tonic-gate printf("parsefs: mount call to %s returned %d %s\n", 616*7c478bd9Sstevel@tonic-gate fullname, 617*7c478bd9Sstevel@tonic-gate err, 618*7c478bd9Sstevel@tonic-gate clnt_sperrno(err)); 619*7c478bd9Sstevel@tonic-gate printf("with errno %d:\t%s\n", errno, strerror(errno)); 620*7c478bd9Sstevel@tonic-gate } 621*7c478bd9Sstevel@tonic-gate 622*7c478bd9Sstevel@tonic-gate if (Debug) 623*7c478bd9Sstevel@tonic-gate printf("parsefs: checking export list:\n"); 624*7c478bd9Sstevel@tonic-gate 625*7c478bd9Sstevel@tonic-gate for (; ex; ex = ex->ex_next) { 626*7c478bd9Sstevel@tonic-gate len = strlen(ex->ex_dir); 627*7c478bd9Sstevel@tonic-gate if (len > bestlen && len <= dirlen && 628*7c478bd9Sstevel@tonic-gate strncmp(dir, ex->ex_dir, len) == 0 && 629*7c478bd9Sstevel@tonic-gate (dir[len] == '/' || dir[len] == '\0')) 630*7c478bd9Sstevel@tonic-gate bestlen = len; 631*7c478bd9Sstevel@tonic-gate 632*7c478bd9Sstevel@tonic-gate if (Debug) 633*7c478bd9Sstevel@tonic-gate printf("\t%d\t%s\n", bestlen, ex->ex_dir); 634*7c478bd9Sstevel@tonic-gate } 635*7c478bd9Sstevel@tonic-gate 636*7c478bd9Sstevel@tonic-gate if (bestlen == 0) { 637*7c478bd9Sstevel@tonic-gate errprintf(error, "%s not exported by %s\n", 638*7c478bd9Sstevel@tonic-gate dir, fullname); 639*7c478bd9Sstevel@tonic-gate return (NULL); 640*7c478bd9Sstevel@tonic-gate } 641*7c478bd9Sstevel@tonic-gate 642*7c478bd9Sstevel@tonic-gate if (dir[bestlen] == '\0') 643*7c478bd9Sstevel@tonic-gate subdir = &dir[bestlen]; 644*7c478bd9Sstevel@tonic-gate else { 645*7c478bd9Sstevel@tonic-gate dir[bestlen] = '\0'; 646*7c478bd9Sstevel@tonic-gate subdir = &dir[bestlen+1]; 647*7c478bd9Sstevel@tonic-gate } 648*7c478bd9Sstevel@tonic-gate *--dir = ':'; 649*7c478bd9Sstevel@tonic-gate 650*7c478bd9Sstevel@tonic-gate return (subdir); 651*7c478bd9Sstevel@tonic-gate } 652*7c478bd9Sstevel@tonic-gate 653*7c478bd9Sstevel@tonic-gate 654*7c478bd9Sstevel@tonic-gate /* 655*7c478bd9Sstevel@tonic-gate * Get the network address for the service identified by "prog" 656*7c478bd9Sstevel@tonic-gate * and "vers" on "hostname". The netconfig address is returned 657*7c478bd9Sstevel@tonic-gate * in the value of "nconfp". 658*7c478bd9Sstevel@tonic-gate * If the hostname is the same as the last call, then the same 659*7c478bd9Sstevel@tonic-gate * transport is used as last time (same netconfig entry). 660*7c478bd9Sstevel@tonic-gate */ 661*7c478bd9Sstevel@tonic-gate 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate static struct netbuf * 664*7c478bd9Sstevel@tonic-gate get_addr(hostname, prog, vers, nconfp) 665*7c478bd9Sstevel@tonic-gate char *hostname; 666*7c478bd9Sstevel@tonic-gate int prog, vers; 667*7c478bd9Sstevel@tonic-gate struct netconfig **nconfp; 668*7c478bd9Sstevel@tonic-gate { 669*7c478bd9Sstevel@tonic-gate static char prevhost[MAXHOSTNAMELEN+1]; 670*7c478bd9Sstevel@tonic-gate static struct netconfig *nconf; 671*7c478bd9Sstevel@tonic-gate static NCONF_HANDLE *nc = NULL; 672*7c478bd9Sstevel@tonic-gate struct netbuf *nb = NULL; 673*7c478bd9Sstevel@tonic-gate struct t_bind *tbind = NULL; 674*7c478bd9Sstevel@tonic-gate struct netconfig *getnetconfig(); 675*7c478bd9Sstevel@tonic-gate struct netconfig *getnetconfigent(); 676*7c478bd9Sstevel@tonic-gate enum clnt_stat cs; 677*7c478bd9Sstevel@tonic-gate struct timeval tv; 678*7c478bd9Sstevel@tonic-gate int fd = -1; 679*7c478bd9Sstevel@tonic-gate 680*7c478bd9Sstevel@tonic-gate if (strcmp(hostname, prevhost) != 0) { 681*7c478bd9Sstevel@tonic-gate if (nc) 682*7c478bd9Sstevel@tonic-gate endnetconfig(nc); 683*7c478bd9Sstevel@tonic-gate nc = setnetconfig(); 684*7c478bd9Sstevel@tonic-gate if (nc == NULL) 685*7c478bd9Sstevel@tonic-gate goto done; 686*7c478bd9Sstevel@tonic-gate retry: 687*7c478bd9Sstevel@tonic-gate /* 688*7c478bd9Sstevel@tonic-gate * If the port number is specified then UDP is needed. 689*7c478bd9Sstevel@tonic-gate * Otherwise any connectionless transport will do. 690*7c478bd9Sstevel@tonic-gate */ 691*7c478bd9Sstevel@tonic-gate while (nconf = getnetconfig(nc)) { 692*7c478bd9Sstevel@tonic-gate if ((nconf->nc_flag & NC_VISIBLE) && 693*7c478bd9Sstevel@tonic-gate nconf->nc_semantics == NC_TPI_CLTS) { 694*7c478bd9Sstevel@tonic-gate break; 695*7c478bd9Sstevel@tonic-gate } 696*7c478bd9Sstevel@tonic-gate } 697*7c478bd9Sstevel@tonic-gate if (nconf == NULL) 698*7c478bd9Sstevel@tonic-gate goto done; 699*7c478bd9Sstevel@tonic-gate (void) strcpy(prevhost, hostname); 700*7c478bd9Sstevel@tonic-gate } 701*7c478bd9Sstevel@tonic-gate 702*7c478bd9Sstevel@tonic-gate fd = t_open(nconf->nc_device, O_RDWR, NULL); 703*7c478bd9Sstevel@tonic-gate if (fd < 0) 704*7c478bd9Sstevel@tonic-gate goto done; 705*7c478bd9Sstevel@tonic-gate 706*7c478bd9Sstevel@tonic-gate tbind = (struct t_bind *) t_alloc(fd, T_BIND, T_ADDR); 707*7c478bd9Sstevel@tonic-gate if (tbind == NULL) 708*7c478bd9Sstevel@tonic-gate goto done; 709*7c478bd9Sstevel@tonic-gate 710*7c478bd9Sstevel@tonic-gate if (rpcb_getaddr(prog, vers, nconf, &tbind->addr, hostname) == 0) { 711*7c478bd9Sstevel@tonic-gate t_free((char *) tbind, T_BIND); 712*7c478bd9Sstevel@tonic-gate tbind = NULL; 713*7c478bd9Sstevel@tonic-gate goto retry; 714*7c478bd9Sstevel@tonic-gate } 715*7c478bd9Sstevel@tonic-gate *nconfp = nconf; 716*7c478bd9Sstevel@tonic-gate 717*7c478bd9Sstevel@tonic-gate /* 718*7c478bd9Sstevel@tonic-gate * Make a copy of the netbuf to return 719*7c478bd9Sstevel@tonic-gate */ 720*7c478bd9Sstevel@tonic-gate nb = (struct netbuf *) malloc(sizeof (struct netbuf)); 721*7c478bd9Sstevel@tonic-gate if (nb == NULL) { 722*7c478bd9Sstevel@tonic-gate errprintf(NULL, "no memory"); 723*7c478bd9Sstevel@tonic-gate goto done; 724*7c478bd9Sstevel@tonic-gate } 725*7c478bd9Sstevel@tonic-gate *nb = tbind->addr; 726*7c478bd9Sstevel@tonic-gate nb->buf = (char *)malloc(nb->len); 727*7c478bd9Sstevel@tonic-gate if (nb->buf == NULL) { 728*7c478bd9Sstevel@tonic-gate errprintf(NULL, "no memory"); 729*7c478bd9Sstevel@tonic-gate free(nb); 730*7c478bd9Sstevel@tonic-gate nb = NULL; 731*7c478bd9Sstevel@tonic-gate goto done; 732*7c478bd9Sstevel@tonic-gate } 733*7c478bd9Sstevel@tonic-gate (void) memcpy(nb->buf, tbind->addr.buf, tbind->addr.len); 734*7c478bd9Sstevel@tonic-gate 735*7c478bd9Sstevel@tonic-gate done: 736*7c478bd9Sstevel@tonic-gate if (tbind) 737*7c478bd9Sstevel@tonic-gate t_free((char *) tbind, T_BIND); 738*7c478bd9Sstevel@tonic-gate if (fd >= 0) 739*7c478bd9Sstevel@tonic-gate (void) t_close(fd); 740*7c478bd9Sstevel@tonic-gate return (nb); 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate static struct knetconfig * 744*7c478bd9Sstevel@tonic-gate get_knconf(nconf) 745*7c478bd9Sstevel@tonic-gate struct netconfig *nconf; 746*7c478bd9Sstevel@tonic-gate { 747*7c478bd9Sstevel@tonic-gate struct stat stbuf; 748*7c478bd9Sstevel@tonic-gate struct knetconfig *k; 749*7c478bd9Sstevel@tonic-gate 750*7c478bd9Sstevel@tonic-gate if (stat(nconf->nc_device, &stbuf) < 0) { 751*7c478bd9Sstevel@tonic-gate errprintf(NULL, "get_knconf: stat %s: %m", nconf->nc_device); 752*7c478bd9Sstevel@tonic-gate return (NULL); 753*7c478bd9Sstevel@tonic-gate } 754*7c478bd9Sstevel@tonic-gate k = (struct knetconfig *) malloc(sizeof (*k)); 755*7c478bd9Sstevel@tonic-gate if (k == NULL) 756*7c478bd9Sstevel@tonic-gate goto nomem; 757*7c478bd9Sstevel@tonic-gate k->knc_semantics = nconf->nc_semantics; 758*7c478bd9Sstevel@tonic-gate k->knc_protofmly = strdup(nconf->nc_protofmly); 759*7c478bd9Sstevel@tonic-gate if (k->knc_protofmly == NULL) 760*7c478bd9Sstevel@tonic-gate goto nomem; 761*7c478bd9Sstevel@tonic-gate k->knc_proto = strdup(nconf->nc_proto); 762*7c478bd9Sstevel@tonic-gate if (k->knc_proto == NULL) 763*7c478bd9Sstevel@tonic-gate goto nomem; 764*7c478bd9Sstevel@tonic-gate k->knc_rdev = stbuf.st_rdev; 765*7c478bd9Sstevel@tonic-gate 766*7c478bd9Sstevel@tonic-gate return (k); 767*7c478bd9Sstevel@tonic-gate 768*7c478bd9Sstevel@tonic-gate nomem: 769*7c478bd9Sstevel@tonic-gate errprintf(NULL, "get_knconf: no memory"); 770*7c478bd9Sstevel@tonic-gate free_knconf(k); 771*7c478bd9Sstevel@tonic-gate return (NULL); 772*7c478bd9Sstevel@tonic-gate } 773*7c478bd9Sstevel@tonic-gate 774*7c478bd9Sstevel@tonic-gate static void 775*7c478bd9Sstevel@tonic-gate free_knconf(k) 776*7c478bd9Sstevel@tonic-gate struct knetconfig *k; 777*7c478bd9Sstevel@tonic-gate { 778*7c478bd9Sstevel@tonic-gate if (k == NULL) 779*7c478bd9Sstevel@tonic-gate return; 780*7c478bd9Sstevel@tonic-gate if (k->knc_protofmly) 781*7c478bd9Sstevel@tonic-gate free(k->knc_protofmly); 782*7c478bd9Sstevel@tonic-gate if (k->knc_proto) 783*7c478bd9Sstevel@tonic-gate free(k->knc_proto); 784*7c478bd9Sstevel@tonic-gate free(k); 785*7c478bd9Sstevel@tonic-gate } 786*7c478bd9Sstevel@tonic-gate 787*7c478bd9Sstevel@tonic-gate static void 788*7c478bd9Sstevel@tonic-gate netbuf_free(nb) 789*7c478bd9Sstevel@tonic-gate struct netbuf *nb; 790*7c478bd9Sstevel@tonic-gate { 791*7c478bd9Sstevel@tonic-gate if (nb == NULL) 792*7c478bd9Sstevel@tonic-gate return; 793*7c478bd9Sstevel@tonic-gate if (nb->buf) 794*7c478bd9Sstevel@tonic-gate free(nb->buf); 795*7c478bd9Sstevel@tonic-gate free(nb); 796*7c478bd9Sstevel@tonic-gate } 797*7c478bd9Sstevel@tonic-gate 798*7c478bd9Sstevel@tonic-gate 799*7c478bd9Sstevel@tonic-gate static enum clnt_stat 800*7c478bd9Sstevel@tonic-gate pingnfs(hostname, versp) 801*7c478bd9Sstevel@tonic-gate char *hostname; 802*7c478bd9Sstevel@tonic-gate rpcvers_t *versp; 803*7c478bd9Sstevel@tonic-gate { 804*7c478bd9Sstevel@tonic-gate CLIENT *cl; 805*7c478bd9Sstevel@tonic-gate enum clnt_stat clnt_stat; 806*7c478bd9Sstevel@tonic-gate static char goodhost[MAXHOSTNAMELEN+1]; 807*7c478bd9Sstevel@tonic-gate static char deadhost[MAXHOSTNAMELEN+1]; 808*7c478bd9Sstevel@tonic-gate static time_t goodtime, deadtime; 809*7c478bd9Sstevel@tonic-gate int cache_time = 60; /* sec */ 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate if (goodtime > time_now && strcmp(hostname, goodhost) == 0) 812*7c478bd9Sstevel@tonic-gate return (RPC_SUCCESS); 813*7c478bd9Sstevel@tonic-gate if (deadtime > time_now && strcmp(hostname, deadhost) == 0) 814*7c478bd9Sstevel@tonic-gate return (RPC_TIMEDOUT); 815*7c478bd9Sstevel@tonic-gate 816*7c478bd9Sstevel@tonic-gate if (Debug) 817*7c478bd9Sstevel@tonic-gate printf("ping %s ", hostname); 818*7c478bd9Sstevel@tonic-gate 819*7c478bd9Sstevel@tonic-gate /* ping the NFS nullproc on the server */ 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate cl = clnt_create_vers(hostname, NFS_PROGRAM, versp, NFS_VERSMIN, 822*7c478bd9Sstevel@tonic-gate NFS_VERSMAX, "udp"); 823*7c478bd9Sstevel@tonic-gate if (cl == NULL) { 824*7c478bd9Sstevel@tonic-gate errprintf(NULL, "pingnfs: %s%s", 825*7c478bd9Sstevel@tonic-gate hostname, clnt_spcreateerror("")); 826*7c478bd9Sstevel@tonic-gate if (Debug) 827*7c478bd9Sstevel@tonic-gate printf("clnt_create failed\n"); 828*7c478bd9Sstevel@tonic-gate clnt_stat = RPC_TIMEDOUT; 829*7c478bd9Sstevel@tonic-gate } else { 830*7c478bd9Sstevel@tonic-gate clnt_stat = RPC_SUCCESS; 831*7c478bd9Sstevel@tonic-gate clnt_destroy(cl); 832*7c478bd9Sstevel@tonic-gate } 833*7c478bd9Sstevel@tonic-gate 834*7c478bd9Sstevel@tonic-gate if (clnt_stat == RPC_SUCCESS) { 835*7c478bd9Sstevel@tonic-gate (void) strcpy(goodhost, hostname); 836*7c478bd9Sstevel@tonic-gate goodtime = time_now + cache_time; 837*7c478bd9Sstevel@tonic-gate } else { 838*7c478bd9Sstevel@tonic-gate (void) strcpy(deadhost, hostname); 839*7c478bd9Sstevel@tonic-gate deadtime = time_now + cache_time; 840*7c478bd9Sstevel@tonic-gate } 841*7c478bd9Sstevel@tonic-gate 842*7c478bd9Sstevel@tonic-gate if (Debug) 843*7c478bd9Sstevel@tonic-gate (void) printf("%s\n", clnt_stat == RPC_SUCCESS ? 844*7c478bd9Sstevel@tonic-gate "OK" : "NO RESPONSE"); 845*7c478bd9Sstevel@tonic-gate 846*7c478bd9Sstevel@tonic-gate return (clnt_stat); 847*7c478bd9Sstevel@tonic-gate } 848*7c478bd9Sstevel@tonic-gate 849*7c478bd9Sstevel@tonic-gate static int bindudp_resvport(client) 850*7c478bd9Sstevel@tonic-gate CLIENT *client; 851*7c478bd9Sstevel@tonic-gate { 852*7c478bd9Sstevel@tonic-gate struct netconfig *udpnconf; 853*7c478bd9Sstevel@tonic-gate int clfd; 854*7c478bd9Sstevel@tonic-gate int rv; 855*7c478bd9Sstevel@tonic-gate 856*7c478bd9Sstevel@tonic-gate /* check for superuser as reserved ports are for superuser only */ 857*7c478bd9Sstevel@tonic-gate if (geteuid()) { 858*7c478bd9Sstevel@tonic-gate errno = EACCES; 859*7c478bd9Sstevel@tonic-gate return (-1); 860*7c478bd9Sstevel@tonic-gate } 861*7c478bd9Sstevel@tonic-gate 862*7c478bd9Sstevel@tonic-gate if (clnt_control(client, CLGET_FD, (char *) &clfd) == FALSE) { 863*7c478bd9Sstevel@tonic-gate errprintf(NULL, "Could not get file dscriptor for client handle\n"); 864*7c478bd9Sstevel@tonic-gate return (-1); 865*7c478bd9Sstevel@tonic-gate } 866*7c478bd9Sstevel@tonic-gate 867*7c478bd9Sstevel@tonic-gate if (Debug) 868*7c478bd9Sstevel@tonic-gate printf("Clnt_control success, clfd = %d\n", clfd); 869*7c478bd9Sstevel@tonic-gate 870*7c478bd9Sstevel@tonic-gate if (t_getstate(clfd) != T_UNBND) { 871*7c478bd9Sstevel@tonic-gate if (t_unbind(clfd) < 0) { 872*7c478bd9Sstevel@tonic-gate return (-1); 873*7c478bd9Sstevel@tonic-gate } 874*7c478bd9Sstevel@tonic-gate } 875*7c478bd9Sstevel@tonic-gate 876*7c478bd9Sstevel@tonic-gate if ((udpnconf = getnetconfigent("udp")) == (struct netconfig *) NULL) { 877*7c478bd9Sstevel@tonic-gate errprintf(NULL, "no netconfig information about \"udp\"\n"); 878*7c478bd9Sstevel@tonic-gate return (-1); 879*7c478bd9Sstevel@tonic-gate } 880*7c478bd9Sstevel@tonic-gate 881*7c478bd9Sstevel@tonic-gate if (Debug) { 882*7c478bd9Sstevel@tonic-gate printf("getnetconfigent success\n"); 883*7c478bd9Sstevel@tonic-gate } 884*7c478bd9Sstevel@tonic-gate 885*7c478bd9Sstevel@tonic-gate if ((rv = netdir_options(udpnconf, ND_SET_RESERVEDPORT, clfd, 886*7c478bd9Sstevel@tonic-gate (char *) NULL)) == -1) { 887*7c478bd9Sstevel@tonic-gate if (Debug) { 888*7c478bd9Sstevel@tonic-gate printf("netdir_options fails rv=%d\n", rv); 889*7c478bd9Sstevel@tonic-gate } 890*7c478bd9Sstevel@tonic-gate 891*7c478bd9Sstevel@tonic-gate errprintf(NULL, netdir_sperror()); 892*7c478bd9Sstevel@tonic-gate return (-1); 893*7c478bd9Sstevel@tonic-gate } 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate if (Debug) 896*7c478bd9Sstevel@tonic-gate printf("netdir_options success rv = %d\n", rv); 897*7c478bd9Sstevel@tonic-gate 898*7c478bd9Sstevel@tonic-gate freenetconfigent(udpnconf); 899*7c478bd9Sstevel@tonic-gate return (0); 900*7c478bd9Sstevel@tonic-gate } 901