xref: /onnv-gate/usr/src/lib/libsmbfs/smb/iod_cl.c (revision 10367:56de61e9a99e)
110023SGordon.Ross@Sun.COM /*
210023SGordon.Ross@Sun.COM  * CDDL HEADER START
310023SGordon.Ross@Sun.COM  *
410023SGordon.Ross@Sun.COM  * The contents of this file are subject to the terms of the
510023SGordon.Ross@Sun.COM  * Common Development and Distribution License (the "License").
610023SGordon.Ross@Sun.COM  * You may not use this file except in compliance with the License.
710023SGordon.Ross@Sun.COM  *
810023SGordon.Ross@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
910023SGordon.Ross@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1010023SGordon.Ross@Sun.COM  * See the License for the specific language governing permissions
1110023SGordon.Ross@Sun.COM  * and limitations under the License.
1210023SGordon.Ross@Sun.COM  *
1310023SGordon.Ross@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1410023SGordon.Ross@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1510023SGordon.Ross@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1610023SGordon.Ross@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1710023SGordon.Ross@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1810023SGordon.Ross@Sun.COM  *
1910023SGordon.Ross@Sun.COM  * CDDL HEADER END
2010023SGordon.Ross@Sun.COM  */
2110023SGordon.Ross@Sun.COM 
2210023SGordon.Ross@Sun.COM /*
2310023SGordon.Ross@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
2410023SGordon.Ross@Sun.COM  * Use is subject to license terms.
2510023SGordon.Ross@Sun.COM  */
2610023SGordon.Ross@Sun.COM 
2710023SGordon.Ross@Sun.COM /*
2810023SGordon.Ross@Sun.COM  * Client-side interface to the IO Daemon (IOD)
2910023SGordon.Ross@Sun.COM  */
3010023SGordon.Ross@Sun.COM 
3110023SGordon.Ross@Sun.COM #include <errno.h>
3210023SGordon.Ross@Sun.COM #include <fcntl.h>
3310023SGordon.Ross@Sun.COM #include <stdio.h>
3410023SGordon.Ross@Sun.COM #include <string.h>
3510023SGordon.Ross@Sun.COM #include <stdlib.h>
3610023SGordon.Ross@Sun.COM #include <unistd.h>
3710023SGordon.Ross@Sun.COM #include <netdb.h>
3810023SGordon.Ross@Sun.COM #include <libintl.h>
3910023SGordon.Ross@Sun.COM #include <door.h>
4010023SGordon.Ross@Sun.COM 
4110023SGordon.Ross@Sun.COM #include <sys/byteorder.h>
4210023SGordon.Ross@Sun.COM #include <sys/types.h>
4310023SGordon.Ross@Sun.COM #include <sys/fcntl.h>
4410023SGordon.Ross@Sun.COM #include <sys/ioctl.h>
4510023SGordon.Ross@Sun.COM #include <sys/time.h>
4610023SGordon.Ross@Sun.COM #include <sys/socket.h>
4710023SGordon.Ross@Sun.COM 
4810023SGordon.Ross@Sun.COM #include <netinet/in.h>
4910023SGordon.Ross@Sun.COM #include <netinet/tcp.h>
5010023SGordon.Ross@Sun.COM #include <arpa/inet.h>
5110023SGordon.Ross@Sun.COM 
5210023SGordon.Ross@Sun.COM #include <netsmb/smb_lib.h>
5310023SGordon.Ross@Sun.COM #include <netsmb/netbios.h>
5410023SGordon.Ross@Sun.COM #include <netsmb/nb_lib.h>
5510023SGordon.Ross@Sun.COM #include <netsmb/smb_dev.h>
5610023SGordon.Ross@Sun.COM 
5710023SGordon.Ross@Sun.COM #include "charsets.h"
5810023SGordon.Ross@Sun.COM #include "private.h"
5910023SGordon.Ross@Sun.COM 
6010023SGordon.Ross@Sun.COM static const char smbiod_path[] = "/usr/lib/smbfs/smbiod";
6110023SGordon.Ross@Sun.COM 
6210023SGordon.Ross@Sun.COM /*
6310023SGordon.Ross@Sun.COM  * This is constant for the life of a process,
6410023SGordon.Ross@Sun.COM  * and initialized at startup, so no locks.
6510023SGordon.Ross@Sun.COM  */
6610023SGordon.Ross@Sun.COM static char door_path[40];
67*10367SGordon.Ross@Sun.COM static int iod_start_timeout = 10;	/* seconds */
6810023SGordon.Ross@Sun.COM 
6910023SGordon.Ross@Sun.COM char *
7010023SGordon.Ross@Sun.COM smb_iod_door_path(void)
7110023SGordon.Ross@Sun.COM {
7210023SGordon.Ross@Sun.COM 	static const char fmtR[] = "/var/run/smbiod-%d";
7310023SGordon.Ross@Sun.COM 	static const char fmtU[] = "/tmp/.smbiod-%d";
7410023SGordon.Ross@Sun.COM 	const char *fmt;
7510023SGordon.Ross@Sun.COM 	uid_t uid;
7610023SGordon.Ross@Sun.COM 
7710023SGordon.Ross@Sun.COM 	if (door_path[0] == '\0') {
7810023SGordon.Ross@Sun.COM 		uid = getuid();
7910023SGordon.Ross@Sun.COM 		fmt = (uid == 0) ? fmtR : fmtU;
8010023SGordon.Ross@Sun.COM 		snprintf(door_path, sizeof (door_path), fmt, uid);
8110023SGordon.Ross@Sun.COM 	}
8210023SGordon.Ross@Sun.COM 
8310023SGordon.Ross@Sun.COM 	return (door_path);
8410023SGordon.Ross@Sun.COM }
8510023SGordon.Ross@Sun.COM 
8610023SGordon.Ross@Sun.COM /*
8710023SGordon.Ross@Sun.COM  * Open the door (client side) and
8810023SGordon.Ross@Sun.COM  * find out if the service is there.
8910023SGordon.Ross@Sun.COM  */
9010023SGordon.Ross@Sun.COM int
9110023SGordon.Ross@Sun.COM smb_iod_open_door(int *fdp)
9210023SGordon.Ross@Sun.COM {
9310023SGordon.Ross@Sun.COM 	door_arg_t da;
9410023SGordon.Ross@Sun.COM 	char *path;
9510023SGordon.Ross@Sun.COM 	int fd, rc;
9610023SGordon.Ross@Sun.COM 	int err = 0;
9710023SGordon.Ross@Sun.COM 
9810023SGordon.Ross@Sun.COM 	path = smb_iod_door_path();
9910023SGordon.Ross@Sun.COM 	fd = open(path, O_RDONLY, 0);
10010023SGordon.Ross@Sun.COM 	if (fd < 0)
10110023SGordon.Ross@Sun.COM 		return (errno);
10210023SGordon.Ross@Sun.COM 
10310023SGordon.Ross@Sun.COM 	/*
10410023SGordon.Ross@Sun.COM 	 * Make sure the IOD is running.
10510023SGordon.Ross@Sun.COM 	 * Pass NULL args.
10610023SGordon.Ross@Sun.COM 	 */
10710023SGordon.Ross@Sun.COM 	memset(&da, 0, sizeof (da));
10810023SGordon.Ross@Sun.COM 	da.rbuf = (void *) &err;
10910023SGordon.Ross@Sun.COM 	da.rsize = sizeof (err);
11010023SGordon.Ross@Sun.COM 	rc = door_call(fd, &da);
11110023SGordon.Ross@Sun.COM 	if (rc < 0) {
11210023SGordon.Ross@Sun.COM 		err = errno;
11310023SGordon.Ross@Sun.COM 		close(fd);
11410023SGordon.Ross@Sun.COM 		return (err);
11510023SGordon.Ross@Sun.COM 	}
11610023SGordon.Ross@Sun.COM 	if (err != 0) {
11710023SGordon.Ross@Sun.COM 		close(fd);
11810023SGordon.Ross@Sun.COM 		return (err);
11910023SGordon.Ross@Sun.COM 	}
12010023SGordon.Ross@Sun.COM 
12110023SGordon.Ross@Sun.COM 	/* This handle controls per-process resources. */
12210023SGordon.Ross@Sun.COM 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
12310023SGordon.Ross@Sun.COM 
12410023SGordon.Ross@Sun.COM 	*fdp = fd;
12510023SGordon.Ross@Sun.COM 	return (0);
12610023SGordon.Ross@Sun.COM }
12710023SGordon.Ross@Sun.COM 
12810023SGordon.Ross@Sun.COM /*
129*10367SGordon.Ross@Sun.COM  * Start the IOD (if not already running) and
130*10367SGordon.Ross@Sun.COM  * wait until its door service is ready.
131*10367SGordon.Ross@Sun.COM  * On success, sets ctx->ct_door_fd
13210023SGordon.Ross@Sun.COM  */
133*10367SGordon.Ross@Sun.COM int
134*10367SGordon.Ross@Sun.COM smb_iod_start(smb_ctx_t *ctx)
13510023SGordon.Ross@Sun.COM {
136*10367SGordon.Ross@Sun.COM 	int err, pid, tmo;
137*10367SGordon.Ross@Sun.COM 	int fd = -1;
138*10367SGordon.Ross@Sun.COM 
139*10367SGordon.Ross@Sun.COM 	err = smb_iod_open_door(&fd);
140*10367SGordon.Ross@Sun.COM 	if (err == 0)
141*10367SGordon.Ross@Sun.COM 		goto OK;
14210023SGordon.Ross@Sun.COM 
14310023SGordon.Ross@Sun.COM 	pid = vfork();
14410023SGordon.Ross@Sun.COM 	if (pid < 0)
14510023SGordon.Ross@Sun.COM 		return (errno);
14610023SGordon.Ross@Sun.COM 
14710023SGordon.Ross@Sun.COM 	/*
14810023SGordon.Ross@Sun.COM 	 * child: start smbiod
14910023SGordon.Ross@Sun.COM 	 */
15010023SGordon.Ross@Sun.COM 	if (pid == 0) {
15110023SGordon.Ross@Sun.COM 		char *argv[2];
15210023SGordon.Ross@Sun.COM 		argv[0] = "smbiod";
15310023SGordon.Ross@Sun.COM 		argv[1] = NULL;
15410023SGordon.Ross@Sun.COM 		execv(smbiod_path, argv);
155*10367SGordon.Ross@Sun.COM 		_exit(1);
15610023SGordon.Ross@Sun.COM 	}
15710023SGordon.Ross@Sun.COM 
15810023SGordon.Ross@Sun.COM 	/*
15910023SGordon.Ross@Sun.COM 	 * parent: wait for smbiod to start
16010023SGordon.Ross@Sun.COM 	 */
161*10367SGordon.Ross@Sun.COM 	tmo = iod_start_timeout;
162*10367SGordon.Ross@Sun.COM 	while (--tmo >= 0) {
16310023SGordon.Ross@Sun.COM 		sleep(1);
164*10367SGordon.Ross@Sun.COM 		err = smb_iod_open_door(&fd);
16510023SGordon.Ross@Sun.COM 		if (err == 0)
166*10367SGordon.Ross@Sun.COM 			goto OK;
16710023SGordon.Ross@Sun.COM 	}
168*10367SGordon.Ross@Sun.COM 	return (err);
16910023SGordon.Ross@Sun.COM 
170*10367SGordon.Ross@Sun.COM OK:
171*10367SGordon.Ross@Sun.COM 	/* Save the door fd. */
172*10367SGordon.Ross@Sun.COM 	if (ctx->ct_door_fd != -1)
173*10367SGordon.Ross@Sun.COM 		close(ctx->ct_door_fd);
174*10367SGordon.Ross@Sun.COM 	ctx->ct_door_fd = fd;
175*10367SGordon.Ross@Sun.COM 
176*10367SGordon.Ross@Sun.COM 	return (0);
17710023SGordon.Ross@Sun.COM }
17810023SGordon.Ross@Sun.COM 
17910023SGordon.Ross@Sun.COM 
18010023SGordon.Ross@Sun.COM /*
181*10367SGordon.Ross@Sun.COM  * Ask the IOD to connect using the info in ctx.
182*10367SGordon.Ross@Sun.COM  * Called by newvc.
18310023SGordon.Ross@Sun.COM  */
18410023SGordon.Ross@Sun.COM int
18510023SGordon.Ross@Sun.COM smb_iod_cl_newvc(smb_ctx_t *ctx)
18610023SGordon.Ross@Sun.COM {
18710023SGordon.Ross@Sun.COM 	door_arg_t da;
188*10367SGordon.Ross@Sun.COM 	int err = 0;
18910023SGordon.Ross@Sun.COM 
190*10367SGordon.Ross@Sun.COM 	/* Should already have the IOD door. */
191*10367SGordon.Ross@Sun.COM 	if (ctx->ct_door_fd < 0)
192*10367SGordon.Ross@Sun.COM 		return (EINVAL);
19310023SGordon.Ross@Sun.COM 
19410023SGordon.Ross@Sun.COM 	da.data_ptr = (void *) &ctx->ct_iod_ssn;
19510023SGordon.Ross@Sun.COM 	da.data_size = sizeof (ctx->ct_iod_ssn);
19610023SGordon.Ross@Sun.COM 	da.desc_ptr = NULL;
19710023SGordon.Ross@Sun.COM 	da.desc_num = 0;
19810023SGordon.Ross@Sun.COM 	da.rbuf = (void *) &err;
19910023SGordon.Ross@Sun.COM 	da.rsize = sizeof (err);
200*10367SGordon.Ross@Sun.COM 	if (door_call(ctx->ct_door_fd, &da) < 0) {
20110023SGordon.Ross@Sun.COM 		err = errno;
20210023SGordon.Ross@Sun.COM 		DPRINT("door_call, err=%d", err);
20310023SGordon.Ross@Sun.COM 	}
20410023SGordon.Ross@Sun.COM 
20510023SGordon.Ross@Sun.COM 	return (err);
20610023SGordon.Ross@Sun.COM }
207