/* * This routine handles the b_hitquery(). It does the following : * - Look for the msg_id in the pending list. * - If found : * - Call b_hitquery() to the uphost. * - Add the b_hitquery_reply->host to the local cache. * - If not found : * - This hitquery() came quite late and the local cache entry from pending * has been freed. Hence, ignore the response. * NOTE : We have a reaper_thread() which wakes up every minute and frees all * pending requests which are older than a minute. */ bool_t b_hitquery_1_svc(b_hitquery_reply *argp, void *result, struct svc_req *rqstp) { bool_t retval = TRUE; query_node_t *node; b_hitquery_reply req; CLIENT *clnt; int i; char *p; enum clnt_stat stat; int ret; int broadcast = 0; #ifdef DEBUG printf("b_hitquery_1_svc() : Received b_hitquery for %s\n", argp->fname); #endif /* * Search for the msg_id in the pending queue. */ node = find_node(&argp->id); /* * If the query request is found on the local queue and we are not the * uphost relay the response back. * Else, the response is late (beyond 60 secs) and hence the reaper thread * has possibly reaped the query. Hence, do nothing. */ if (node && strcmp(node->req.uphost, localhostname) != 0) { /* * We have the query details. Bubble up this response to the upstream * host. */ clnt = clnt_create(node->req.uphost, OBTAINPROG, OBTAINVER, "tcp"); if (clnt == NULL) { clnt_pcreateerror(node->req.uphost); printf("b_hitquery_1_svc() : Failed to relay the response to : %s\n", node->req.uphost); } else { if (clnt_control(clnt, CLSET_TIMEOUT, (char *)&zero_timeout) == FALSE) { printf("Failed to set the timeout value to zero\n"); printf("Cannot make oneway RPC calls and hence behaviour could be unpredictable\n"); } req.id = argp->id; req.cnt = argp->cnt; strcpy(req.fname, argp->fname); memcpy(req.hosts, argp->hosts, BUFSIZE); memcpy(req.hosts, argp->hosts, BUFSIZE); memcpy(req.pflags, argp->pflags, sizeof(req.pflags)); memcpy(req.vers, argp->vers, sizeof(req.vers)); memcpy(req.ttrs, argp->ttrs, sizeof(req.ttrs)); memcpy(req.mtimes, argp->mtimes, sizeof(req.mtimes)); stat = b_hitquery_1(&req, &ret, clnt); if (stat != RPC_TIMEDOUT && stat != RPC_SUCCESS) { clnt_perror(clnt, "b_hitquery failed"); } clnt_destroy(clnt); } } /* * Record the results in the local cache (/tmp/indsvr/) so that we can reuse * this info for the next queries for this file. */ for (i = 0, p = argp->hosts; i < argp->cnt; i++) { add_peer(argp->fname, p, ); p = p + MAXHOSTNAME; } if (node) { node->recv++; #ifdef DEBUG printf("b_hitquery_1_svc:recv = %d sent = %d\n", node->recv, node->sent); #endif /* * Add code to signal the search_1_svc() which is wait for all the * responses to arrive. */ if (node->recv >= node->sent) { #ifdef DEBUG printf("broadcasting : so that search_1_svc() can respond back\n"); #endif pthread_cond_broadcast(&node->allhome_cv); } pthread_mutex_unlock(&node->node_lock); } #ifdef DEBUG printf("b_hitquery_1_svc: Done for file %s\n", argp->fname); #endif return retval; }
/* * rtime.c: remote version * of "printime.c" */ #include <stdio.h> #include "time.h" /* time.h generated by rpcgen */ main(int argc, char **argv) { CLIENT *clnt; char *result; char *server; char *message; if (argc != 3) { fprintf(stderr, "usage: %s host messagen", argv[0]); exit(1); } server = argv[1]; message = argv[2]; /* * Create client "handle" used for * calling TIMEPROG on the server * designated on the command line. */ //clnt = clnt_create(server, TIMEPROG, PRINTIMEVERS, "visible"); clnt = clnt_create(server, TIMEPROG, PRINTIMEVERS, "TCP"); if (clnt == (CLIENT *)NULL) { /* * Couldn't establish connection * with server. * Print error message and die. */ clnt_pcreateerror(server); exit(1); } /* * Call the remote procedure * "printime" on the server */ result =*printime_1(&message,clnt); if (result== (char *)NULL) { /* * An error occurred while calling * the server. * Print error message and die. */ clnt_perror(clnt, server); exit(1); } /* Okay, we successfully called * the remote procedure. */ if (strcmp(result,"Error")==0){ /* * Server was unable to print * the time. * Print error message and die. */ fprintf(stderr, "%s: could not get the timen",argv[0]); exit(1); } printf("From the Time Server ...%s",result); clnt_destroy( clnt ); exit(0); }
/* * b_query_propagate : * This routine is used by both search_svc_1() and b_query_svc_1() to propagate * the query to the peers. * * RETURN VALUE : * If it relays the requests to its peers then it adds this request to a * local pending queue and returns a pointer to that request. * * Outline of the routine: * - Checks if we already have received this query (check on the pending list * for the msg_id of the received message. * - If we already have processed this don't do anything. * - Decrement the TTL. If TTL is zero after that don't relay it anymore but * do the following : * - Look at the local cache and call b_hitquery() with the results to * the uphost. * - If we have not processed it we do the following : * - Create a new query_req. Add it to the pending list. * - Walk the list of peers and do the following : * - Check if the cached index file already has the name of the * peer. * - If the peer name is not in the cache send it a b_query() * request. * - Look at the local cache and call b_hitquery() with the results to * the uphost. */ query_node_t * b_query_propagate(b_query_req *argp, int flag) { bool_t retval = TRUE; query_node_t *node; b_query_req req; peers_t my_cache; CLIENT *clnt; int i, cnt; enum clnt_stat stat; int ret; node = find_node(&argp->id); /* * We already have processed msg_id. Hence, we have nothing to do now. */ if (node) { pthread_mutex_unlock(&node->node_lock); #ifdef DEBUG printf("b_query_propagate: This request for file %s from %s is already processed\n", argp->fname, argp->uphost); #endif return (NULL); } /* * We did not find a matching node. So, this is a new request and we need to * process it. */ /* * Check if this request should be relayed to the peers. */ if (argp->ttl <= 1) { /* * We don't need to relay this to the peers. */ return (NULL); } node = (query_node_t *)malloc(sizeof(query_node_t)); if (node == NULL) { printf("Failed to allocate query_node_t. Hence not processing this request.\n"); printf("Hoping the reaper thread will reap some memory\n"); return (NULL); } node->req.id = argp->id; strcpy(node->req.uphost, argp->uphost); strcpy(node->req.fname, argp->fname); node->req.ttl = argp->ttl - 1; /* Decrement the TTL by one */ node->sent = 0; node->recv = 0; node->next = NULL; pthread_mutex_init(&node->node_lock, NULL); pthread_cond_init(&node->allhome_cv, NULL); /* * Build the request that we need to send. */ req.id = argp->id; strcpy(req.uphost, localhostname); strcpy(req.fname, argp->fname); req.ttl = argp->ttl - 1; (void) insert_node(node); /* * Lock the node. This is to avoid processing of responses * even before we are done with the propagation of requests to all the peers. */ pthread_mutex_lock(&node->node_lock); /* * Get the peers list from the cache. */ cnt = build_peers_from_cache(argp->fname, &my_cache); #ifdef DEBUG printf("b_query_propagate: my_cache.count = %d peers.count = %d\n", my_cache.count, peers.count); #endif /*if (my_cache.count < peers.count) { */ { /* * We have some peers to whom we need to relay the request. */ for (i = 0; i < peers.count; i++) { /* * Check if we have already an entry for this peer cached. * If yes, continue to the next peer. * Also, Skip the uphost from whom we received this query. */ if (strcmp(peers.peer[i], argp->uphost) == 0) { #ifdef DEBUG printf("b_query_propagate: Skipping the uphost %s\n", argp->uphost); #endif continue; } #ifdef DEBUG printf("b_query_propagate: Looking for %s in my_cache\n", peers.peer[i]); #endif if (peer_in_cache(&my_cache, peers.peer[i])) { #ifdef DEBUG printf("b_query_propagate: peer_in_cache(%s) return TRUE\n", peers.peer[i]); #endif continue; } /* * Use the cached client handler to make a call. If not create * one. */ #ifdef DEBUG printf("b_query_propagate(): Relaying query to %s for file %s\n", peers.peer[i], argp->fname); printf("Creating clnt handle for peer[%s]\n", peers.peer[i]); #endif clnt = clnt_create(peers.peer[i], OBTAINPROG, OBTAINVER, "tcp"); if (clnt == NULL) { clnt_pcreateerror (peers.peer[i]); /* * Make a call only if we have a valid handle. We try to create * a handle above. Ideally that should succeed. But, if we * failed to create a client handle possible the peer is having * problems. Hence ignore it and continue. */ continue; } /* * Now make a one-way RPC call to relay the message. */ if (clnt_control(clnt, CLSET_TIMEOUT, (char *)&zero_timeout) == FALSE) { printf("Failed to set the timeout value to zero\n"); printf("Cannot make oneway RPC calls and hence behaviour could be unpredictable\n"); } stat = b_query_1(&req, &ret, clnt); if (stat != RPC_SUCCESS && stat != RPC_TIMEDOUT) { clnt_perror(clnt, "b_query failed"); continue; } clnt_destroy(clnt); #ifdef DEBUG printf("Called the b_query(%s)\n", peers.peer[i]); #endif node->sent++; } } /* * Free up memory from my_cache. */ for (i = 0; i < my_cache.count; i++) { free(my_cache.peer[i]); } /* * If the caller does not wanted the node locked. */ if (flag == UNLOCKED) { pthread_mutex_unlock(&node->node_lock); } return (node); }
/* * This routine looks for the file in the local index directory * ("/tmp/indsvr/<filename>") and sends back the host names to uphost. * * It sends one RPC call with MAXCOUNT hosts in each of them. */ int send_local_cache(char *fname_req, msg_id id, char *uphost) { b_hitquery_reply res; char fname[MAXPATHLEN]; char *p; FILE *fh; int fd; CLIENT *clnt; enum clnt_stat ret; int tmp; if (!fname_req || !uphost) { return (SUCCESS); } sprintf(fname, "%s/%s", SERVER_DIR, fname_req); fh = fopen(fname, "r"); if (fh == NULL) { printf("send_local_cache: Failed to open filename %s : errno = %d\n", fname, errno); return SUCCESS; } fd = fileno(fh); clnt = clnt_create(uphost, OBTAINPROG, OBTAINVER, "tcp"); if (clnt == NULL) { clnt_pcreateerror(uphost); fclose(fh); close(fd); printf("send_local_cache(): Failed to contact hitquery to : %s\n", uphost); return FAILED; } if (clnt_control(clnt, CLSET_TIMEOUT, (char *)&zero_timeout) == FALSE) { printf("Failed to set the timeout value to zero\n"); printf("Cannot make one-way RPC call :-(\n"); } flock(fd, LOCK_SH); res.id = id; strcpy(res.fname, fname_req); res.cnt = 0; p = res.hosts; while (fscanf(fh, "%s\n", p) != EOF) { res.cnt++; if (res.cnt == MAXCOUNT) { flock(fd, LOCK_UN); /* * Make one-way RPC call to send the response back. */ #ifdef DEBUG printf("send_local_cache: Sending response to %s for file %s\n", uphost, res.fname); #endif ret = b_hitquery_1(&res, &tmp, clnt); if (ret != RPC_SUCCESS && ret != RPC_TIMEDOUT) { clnt_perror(clnt, "b_hitquery failed"); } res.cnt = 0; flock(fd, LOCK_SH); } p += MAXHOSTNAME; } flock(fd, LOCK_UN); fclose(fh); close(fd); ret = b_hitquery_1(&res, &tmp, clnt); if (ret != RPC_SUCCESS && ret != RPC_TIMEDOUT) { clnt_perror(clnt, "b_hitquery failed"); } clnt_destroy(clnt); }
static void test_client(int argc, const char **argv) { rpcproc_t prog = 123456; rpcvers_t vers = 1; const char *netid = "tcp"; char hostname[128], service[128+5]; CLIENT *client; AUTH *auth; const char **mechs; rpc_gss_options_req_t options_req; rpc_gss_options_ret_t options_ret; rpc_gss_service_t svc; struct timeval tv; enum clnt_stat stat; if (argc == 2) strlcpy(hostname, argv[1], sizeof(hostname)); else gethostname(hostname, sizeof(hostname)); client = clnt_create(hostname, prog, vers, netid); if (!client) { printf("rpc_createerr.cf_stat = %d\n", rpc_createerr.cf_stat); printf("rpc_createerr.cf_error.re_errno = %d\n", rpc_createerr.cf_error.re_errno); return; } strcpy(service, "host"); strcat(service, "@"); strcat(service, hostname); mechs = rpc_gss_get_mechanisms(); auth = NULL; while (*mechs) { options_req.req_flags = GSS_C_MUTUAL_FLAG; options_req.time_req = 600; options_req.my_cred = GSS_C_NO_CREDENTIAL; options_req.input_channel_bindings = NULL; auth = rpc_gss_seccreate(client, service, *mechs, rpc_gss_svc_none, NULL, &options_req, &options_ret); if (auth) break; mechs++; } if (!auth) { clnt_pcreateerror("rpc_gss_seccreate"); printf("Can't authenticate with server %s.\n", hostname); exit(1); } client->cl_auth = auth; for (svc = rpc_gss_svc_none; svc <= rpc_gss_svc_privacy; svc++) { const char *svc_names[] = { "rpc_gss_svc_default", "rpc_gss_svc_none", "rpc_gss_svc_integrity", "rpc_gss_svc_privacy" }; int num; rpc_gss_set_defaults(auth, svc, NULL); tv.tv_sec = 5; tv.tv_usec = 0; num = 42; stat = CLNT_CALL(client, 1, (xdrproc_t) xdr_int, (char *) &num, (xdrproc_t) xdr_int, (char *) &num, tv); if (stat == RPC_SUCCESS) { printf("succeeded with %s\n", svc_names[svc]); if (num != 142) printf("unexpected reply %d\n", num); } else { clnt_perror(client, "call failed"); } } AUTH_DESTROY(auth); CLNT_DESTROY(client); }
int nfsmount(const char *spec, const char *node, int *flags, char **orig_opts, char **extra_opts) { char hostdir[1024]; CLIENT *mclient; char *hostname; char *dirname; char new_opts[1024]; fhandle root_fhandle; struct timeval total_timeout; enum clnt_stat clnt_stat; static struct nfs_mount_data data; char *opts, *opt, *opteq; int val; struct hostent *hp; struct sockaddr_in server_addr; int msock, fsock; struct timeval pertry_timeout; struct fhstatus status; char *s; int port; int bg; int soft; int intr; int posix; int nocto; int noac; int retry; msock = fsock = -1; mclient = NULL; strcpy(hostdir, spec); if ((s = (strchr(hostdir, ':')))) { hostname = hostdir; dirname = s + 1; *s = '\0'; } else { fprintf(stderr, "mount: " "directory to mount not in host:dir format\n"); goto fail; } if (hostname[0] >= '0' && hostname[0] <= '9') { server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = inet_addr(hostname); } else if ((hp = gethostbyname(hostname)) == NULL) { fprintf(stderr, "mount: can't get address for %s\n", hostname); goto fail; } else { server_addr.sin_family = AF_INET; memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length); } /* add IP address to mtab options for use when unmounting */ sprintf(new_opts, "%s%saddr=%s", *orig_opts ? *orig_opts : "", *orig_opts ? "," : "", inet_ntoa(server_addr.sin_addr)); *orig_opts = strdup(new_opts); /* set default options */ data.rsize = 0; /* let kernel decide */ data.wsize = 0; /* let kernel decide */ data.timeo = 7; data.retrans = 3; data.acregmin = 3; data.acregmax = 60; data.acdirmin = 30; data.acdirmax = 60; port = 2049; bg = 0; soft = 0; intr = 0; posix = 0; nocto = 0; noac = 0; retry = 10000; /* parse options */ if ((opts = *extra_opts)) { for (opt = strtok(opts, ","); opt; opt = strtok(NULL, ",")) { if ((opteq = strchr(opt, '='))) { val = atoi(opteq + 1); *opteq = '\0'; if (!strcmp(opt, "rsize")) data.rsize = val; else if (!strcmp(opt, "wsize")) data.wsize = val; else if (!strcmp(opt, "timeo")) data.timeo = val; else if (!strcmp(opt, "retrans")) data.retrans = val; else if (!strcmp(opt, "acregmin")) data.acregmin = val; else if (!strcmp(opt, "acregmax")) data.acregmax = val; else if (!strcmp(opt, "acdirmin")) data.acdirmin = val; else if (!strcmp(opt, "acdirmax")) data.acdirmax = val; else if (!strcmp(opt, "actimeo")) { data.acregmin = val; data.acregmax = val; data.acdirmin = val; data.acdirmax = val; } else if (!strcmp(opt, "port")) port = val; else if (!strcmp(opt, "retry")) retry = val; else { printf("unknown nfs mount parameter: " "%s=%d\n", opt, val); goto fail; } } else { val = 1; if (!strncmp(opt, "no", 2)) { val = 0; opt += 2; } if (!strcmp(opt, "bg")) bg = val; else if (!strcmp(opt, "fg")) bg = !val; else if (!strcmp(opt, "soft")) soft = val; else if (!strcmp(opt, "hard")) soft = !val; else if (!strcmp(opt, "intr")) intr = val; else if (!strcmp(opt, "posix")) posix = val; else if (!strcmp(opt, "cto")) nocto = !val; else if (!strcmp(opt, "ac")) noac = !val; else { printf("unknown nfs mount option: " "%s%s\n", val ? "" : "no", opt); goto fail; } } } } data.flags = (soft ? NFS_MOUNT_SOFT : 0) | (intr ? NFS_MOUNT_INTR : 0) | (posix ? NFS_MOUNT_POSIX : 0) | (nocto ? NFS_MOUNT_NOCTO : 0) | (noac ? NFS_MOUNT_NOAC : 0); #if 0 printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", data.rsize, data.wsize, data.timeo, data.retrans); printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n", data.acregmin, data.acregmax, data.acdirmin, data.acdirmax); printf("port = %d, bg = %d, retry = %d, flags = %.8x\n", port, bg, retry, data.flags); printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n", (data.flags & NFS_MOUNT_SOFT) != 0, (data.flags & NFS_MOUNT_INTR) != 0, (data.flags & NFS_MOUNT_POSIX) != 0, (data.flags & NFS_MOUNT_NOCTO) != 0, (data.flags & NFS_MOUNT_NOAC) != 0); goto fail; #endif /* create mount deamon client */ pertry_timeout.tv_sec = 3; pertry_timeout.tv_usec = 0; total_timeout.tv_sec = 20; total_timeout.tv_usec = 0; server_addr.sin_port = 0; msock = RPC_ANYSOCK; if ((mclient = clntudp_create(&server_addr, MOUNTPROG, MOUNTVERS, pertry_timeout, &msock)) == NULL) { clnt_pcreateerror("mount clntudp_create"); goto fail; } mclient->cl_auth = authunix_create_default(); /* try to mount hostname:dirname */ clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, xdr_dirpath, &dirname, xdr_fhstatus, &status, total_timeout); if (clnt_stat != RPC_SUCCESS) { clnt_perror(mclient, "rpc mount"); goto fail; } if (status.fhs_status != 0) { fprintf(stderr, "mount: %s:%s failed, reason given by server: %s\n", hostname, dirname, nfs_strerror(status.fhs_status)); goto fail; } memcpy((char *) &root_fhandle, (char *) status.fhstatus_u.fhs_fhandle, sizeof (root_fhandle)); /* create nfs socket for kernel */ fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (fsock < 0) { perror("nfs socket"); goto fail; } if (bindresvport(fsock, 0) < 0) { perror("nfs bindresvport"); goto fail; } server_addr.sin_port = htons(port); if (connect(fsock, (struct sockaddr *) &server_addr, sizeof (server_addr)) < 0) { perror("nfs connect"); goto fail; } /* prepare data structure for kernel */ data.version = NFS_MOUNT_VERSION; data.fd = fsock; memcpy((char *) &data.root, (char *) &root_fhandle, sizeof (root_fhandle)); memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr)); strncpy(data.hostname, hostname, sizeof(data.hostname)); *extra_opts = (char *) &data; /* clean up */ auth_destroy(mclient->cl_auth); clnt_destroy(mclient); close(msock); return 0; /* abort */ fail: if (msock != -1) { auth_destroy(mclient->cl_auth); clnt_destroy(mclient); close(msock); } if (fsock != -1) close(fsock); return 1; }
int umountfs(char *name, char **typelist) { enum clnt_stat clnt_stat; struct hostent *hp; struct mtablist *mtab; struct sockaddr_in saddr; struct timeval pertry, try; CLIENT *clp; size_t len; int so, speclen, do_rpc; char *mntonname, *mntfromname; char *mntfromnamerev; char *nfsdirname, *orignfsdirname; char *resolved, realname[MAXPATHLEN]; char *type, *delimp, *hostp, *origname; len = 0; mtab = NULL; mntfromname = mntonname = delimp = hostp = orignfsdirname = NULL; /* * 1. Check if the name exists in the mounttable. */ (void)checkmntlist(name, &mntfromname, &mntonname, &type); /* * 2. Remove trailing slashes if there are any. After that * we look up the name in the mounttable again. */ if (mntfromname == NULL && mntonname == NULL) { speclen = strlen(name); for (speclen = strlen(name); speclen > 1 && name[speclen - 1] == '/'; speclen--) name[speclen - 1] = '\0'; (void)checkmntlist(name, &mntfromname, &mntonname, &type); resolved = name; /* Save off original name in origname */ if ((origname = strdup(name)) == NULL) err(1, "strdup"); /* * 3. Check if the deprecated nfs-syntax with an '@' * has been used and translate it to the ':' syntax. * Look up the name in the mounttable again. */ if (mntfromname == NULL && mntonname == NULL) { if ((delimp = strrchr(name, '@')) != NULL) { hostp = delimp + 1; if (*hostp != '\0') { /* * Make both '@' and ':' * notations equal */ char *host = strdup(hostp); len = strlen(hostp); if (host == NULL) err(1, "strdup"); memmove(name + len + 1, name, (size_t)(delimp - name)); name[len] = ':'; memmove(name, host, len); free(host); } for (speclen = strlen(name); speclen > 1 && name[speclen - 1] == '/'; speclen--) name[speclen - 1] = '\0'; name[len + speclen + 1] = '\0'; (void)checkmntlist(name, &mntfromname, &mntonname, &type); resolved = name; } /* * 4. Check if a relative mountpoint has been * specified. This should happen as last check, * the order is important. To prevent possible * nfs-hangs, we just call realpath(3) on the * basedir of mountpoint and add the dirname again. * Check the name in mounttable one last time. */ if (mntfromname == NULL && mntonname == NULL) { (void)strcpy(name, origname); if ((getrealname(name, realname)) != NULL) { (void)checkmntlist(realname, &mntfromname, &mntonname, &type); resolved = realname; } /* * All tests failed, return to main() */ if (mntfromname == NULL && mntonname == NULL) { (void)strcpy(name, origname); warnx("%s: not currently mounted", origname); free(origname); return (1); } } } free(origname); } else resolved = name; if (checkvfsname(type, typelist)) return (1); hp = NULL; nfsdirname = NULL; if (!strcmp(type, "nfs")) { if ((nfsdirname = strdup(mntfromname)) == NULL) err(1, "strdup"); orignfsdirname = nfsdirname; if ((delimp = strchr(nfsdirname, ':')) != NULL) { *delimp = '\0'; hostp = nfsdirname; if ((hp = gethostbyname(hostp)) == NULL) { warnx("can't get net id for host"); } nfsdirname = delimp + 1; } } /* * Check if the reverse entrys of the mounttable are really the * same as the normal ones. */ if ((mntfromnamerev = strdup(getmntname(getmntname(mntfromname, NULL, MNTON, &type, NAME), NULL, MNTFROM, &type, NAME))) == NULL) err(1, "strdup"); /* * Mark the uppermost mount as unmounted. */ (void)getmntname(mntfromname, mntonname, NOTHING, &type, MARK); /* * If several equal mounts are in the mounttable, check the order * and warn the user if necessary. */ if (strcmp(mntfromnamerev, mntfromname ) != 0 && strcmp(resolved, mntonname) != 0) { warnx("cannot umount %s, %s\n " "is mounted there, umount it first", mntonname, mntfromnamerev); /* call getmntname again to set mntcheck[i] to 0 */ (void)getmntname(mntfromname, mntonname, NOTHING, &type, UNMARK); return (1); } free(mntfromnamerev); /* * Check if we have to start the rpc-call later. * If there are still identical nfs-names mounted, * we skip the rpc-call. Obviously this has to * happen before unmount(2), but it should happen * after the previous namecheck. */ if (strcmp(type, "nfs") == 0 && getmntname(mntfromname, NULL, NOTHING, &type, COUNT) != NULL) do_rpc = 1; else do_rpc = 0; if (!namematch(hp)) return (1); if (unmount(mntonname, fflag) != 0 ) { warn("unmount of %s failed", mntonname); return (1); } if (vflag) (void)printf("%s: unmount from %s\n", mntfromname, mntonname); /* * Report to mountd-server which nfsname * has been unmounted. */ if (hp != NULL && !(fflag & MNT_FORCE) && do_rpc) { memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; saddr.sin_port = 0; memmove(&saddr.sin_addr, hp->h_addr, MIN(hp->h_length, sizeof(saddr.sin_addr))); pertry.tv_sec = 3; pertry.tv_usec = 0; so = RPC_ANYSOCK; if ((clp = clntudp_create(&saddr, RPCPROG_MNT, RPCMNT_VER1, pertry, &so)) == NULL) { clnt_pcreateerror("Cannot MNT PRC"); return (1); } clp->cl_auth = authunix_create_default(); try.tv_sec = 20; try.tv_usec = 0; clnt_stat = clnt_call(clp, RPCMNT_UMOUNT, xdr_dir, nfsdirname, xdr_void, (caddr_t)0, try); if (clnt_stat != RPC_SUCCESS) { clnt_perror(clp, "Bad MNT RPC"); return (1); } /* * Remove the unmounted entry from /var/db/mounttab. */ if (read_mtab(mtab)) { mtab = mtabhead; clean_mtab(hostp, nfsdirname); if(!write_mtab()) warnx("cannot remove entry %s:%s", hostp, nfsdirname); free_mtab(); } free(orignfsdirname); auth_destroy(clp->cl_auth); clnt_destroy(clp); }