xref: /illumos-gate/usr/src/lib/libsmbfs/smb/iod_cl.c (revision 46b592853d0f4f11781b6b0a7533f267c6aee132)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Client-side interface to the IO Daemon (IOD)
29  */
30 
31 #include <errno.h>
32 #include <fcntl.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <stdlib.h>
36 #include <unistd.h>
37 #include <netdb.h>
38 #include <libintl.h>
39 #include <door.h>
40 
41 #include <sys/byteorder.h>
42 #include <sys/types.h>
43 #include <sys/fcntl.h>
44 #include <sys/ioctl.h>
45 #include <sys/time.h>
46 #include <sys/socket.h>
47 
48 #include <netinet/in.h>
49 #include <netinet/tcp.h>
50 #include <arpa/inet.h>
51 
52 #include <netsmb/smb_lib.h>
53 #include <netsmb/netbios.h>
54 #include <netsmb/nb_lib.h>
55 #include <netsmb/smb_dev.h>
56 
57 #include "charsets.h"
58 #include "private.h"
59 
60 static const char smbiod_path[] = "/usr/lib/smbfs/smbiod";
61 
62 /*
63  * This is constant for the life of a process,
64  * and initialized at startup, so no locks.
65  */
66 static char door_path[40];
67 static int iod_start_timeout = 10;	/* seconds */
68 
69 char *
70 smb_iod_door_path(void)
71 {
72 	static const char fmtR[] = "/var/run/smbiod-%d";
73 	static const char fmtU[] = "/tmp/.smbiod-%d";
74 	const char *fmt;
75 	uid_t uid;
76 
77 	if (door_path[0] == '\0') {
78 		uid = getuid();
79 		fmt = (uid == 0) ? fmtR : fmtU;
80 		snprintf(door_path, sizeof (door_path), fmt, uid);
81 	}
82 
83 	return (door_path);
84 }
85 
86 /*
87  * Open the door (client side) and
88  * find out if the service is there.
89  */
90 int
91 smb_iod_open_door(int *fdp)
92 {
93 	door_arg_t da;
94 	char *path;
95 	int fd, rc;
96 	int err = 0;
97 
98 	path = smb_iod_door_path();
99 	fd = open(path, O_RDONLY, 0);
100 	if (fd < 0)
101 		return (errno);
102 
103 	/*
104 	 * Make sure the IOD is running.
105 	 * Pass NULL args.
106 	 */
107 	memset(&da, 0, sizeof (da));
108 	da.rbuf = (void *) &err;
109 	da.rsize = sizeof (err);
110 	rc = door_call(fd, &da);
111 	if (rc < 0) {
112 		err = errno;
113 		close(fd);
114 		return (err);
115 	}
116 	if (err != 0) {
117 		close(fd);
118 		return (err);
119 	}
120 
121 	/* This handle controls per-process resources. */
122 	(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
123 
124 	*fdp = fd;
125 	return (0);
126 }
127 
128 /*
129  * Start the IOD (if not already running) and
130  * wait until its door service is ready.
131  * On success, sets ctx->ct_door_fd
132  */
133 int
134 smb_iod_start(smb_ctx_t *ctx)
135 {
136 	int err, pid, tmo;
137 	int fd = -1;
138 
139 	err = smb_iod_open_door(&fd);
140 	if (err == 0)
141 		goto OK;
142 
143 	pid = vfork();
144 	if (pid < 0)
145 		return (errno);
146 
147 	/*
148 	 * child: start smbiod
149 	 */
150 	if (pid == 0) {
151 		char *argv[2];
152 		argv[0] = "smbiod";
153 		argv[1] = NULL;
154 		execv(smbiod_path, argv);
155 		_exit(1);
156 	}
157 
158 	/*
159 	 * parent: wait for smbiod to start
160 	 */
161 	tmo = iod_start_timeout;
162 	while (--tmo >= 0) {
163 		sleep(1);
164 		err = smb_iod_open_door(&fd);
165 		if (err == 0)
166 			goto OK;
167 	}
168 	return (err);
169 
170 OK:
171 	/* Save the door fd. */
172 	if (ctx->ct_door_fd != -1)
173 		close(ctx->ct_door_fd);
174 	ctx->ct_door_fd = fd;
175 
176 	return (0);
177 }
178 
179 
180 /*
181  * Ask the IOD to connect using the info in ctx.
182  * Called by newvc.
183  */
184 int
185 smb_iod_cl_newvc(smb_ctx_t *ctx)
186 {
187 	door_arg_t da;
188 	int err = 0;
189 
190 	/* Should already have the IOD door. */
191 	if (ctx->ct_door_fd < 0)
192 		return (EINVAL);
193 
194 	da.data_ptr = (void *) &ctx->ct_iod_ssn;
195 	da.data_size = sizeof (ctx->ct_iod_ssn);
196 	da.desc_ptr = NULL;
197 	da.desc_num = 0;
198 	da.rbuf = (void *) &err;
199 	da.rsize = sizeof (err);
200 	if (door_call(ctx->ct_door_fd, &da) < 0) {
201 		err = errno;
202 		DPRINT("door_call, err=%d", err);
203 	}
204 
205 	return (err);
206 }
207