xref: /illumos-gate/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c (revision 29bd28862cfb8abbd3a0f0a4b17e08bbc3652836)
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  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/ioccom.h>
29 #include <sys/param.h>
30 #include <stddef.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <strings.h>
34 #include <stdlib.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 
39 #include <smbsrv/smb_xdr.h>
40 #include <smbsrv/smbinfo.h>
41 #include <smbsrv/smb_ioctl.h>
42 #include <smbsrv/smb_ioctl.h>
43 #include <smbsrv/libsmb.h>
44 
45 #define	SMBDRV_DEVICE_PATH		"/devices/pseudo/smbsrv@0:smbsrv"
46 #define	SMB_IOC_DATA_SIZE		(256 * 1024)
47 
48 static int smb_kmod_ioctl(int, smb_ioc_header_t *, uint32_t);
49 
50 
51 int	smbdrv_fd = -1;
52 
53 int
54 smb_kmod_bind(void)
55 {
56 	if (smbdrv_fd != -1)
57 		(void) close(smbdrv_fd);
58 
59 	if ((smbdrv_fd = open(SMBDRV_DEVICE_PATH, 0)) < 0) {
60 		smbdrv_fd = -1;
61 		return (errno);
62 	}
63 
64 	return (0);
65 }
66 
67 int
68 smb_kmod_setcfg(smb_kmod_cfg_t *cfg)
69 {
70 	smb_ioc_cfg_t ioc;
71 
72 	ioc.maxworkers = cfg->skc_maxworkers;
73 	ioc.maxconnections = cfg->skc_maxconnections;
74 	ioc.keepalive = cfg->skc_keepalive;
75 	ioc.restrict_anon = cfg->skc_restrict_anon;
76 	ioc.signing_enable = cfg->skc_signing_enable;
77 	ioc.signing_required = cfg->skc_signing_required;
78 	ioc.oplock_enable = cfg->skc_oplock_enable;
79 	ioc.sync_enable = cfg->skc_sync_enable;
80 	ioc.secmode = cfg->skc_secmode;
81 	ioc.ipv6_enable = cfg->skc_ipv6_enable;
82 
83 	(void) strlcpy(ioc.nbdomain, cfg->skc_nbdomain, sizeof (ioc.nbdomain));
84 	(void) strlcpy(ioc.fqdn, cfg->skc_fqdn, sizeof (ioc.fqdn));
85 	(void) strlcpy(ioc.hostname, cfg->skc_hostname, sizeof (ioc.hostname));
86 	(void) strlcpy(ioc.system_comment, cfg->skc_system_comment,
87 	    sizeof (ioc.system_comment));
88 
89 	return (smb_kmod_ioctl(SMB_IOC_CONFIG, &ioc.hdr, sizeof (ioc)));
90 }
91 
92 int
93 smb_kmod_setgmtoff(int32_t gmtoff)
94 {
95 	smb_ioc_gmt_t ioc;
96 
97 	ioc.offset = gmtoff;
98 	return (smb_kmod_ioctl(SMB_IOC_GMTOFF, &ioc.hdr,
99 	    sizeof (ioc)));
100 }
101 
102 int
103 smb_kmod_start(int opipe, int lmshr, int udoor)
104 {
105 	smb_ioc_start_t ioc;
106 
107 	ioc.opipe = opipe;
108 	ioc.lmshrd = lmshr;
109 	ioc.udoor = udoor;
110 	return (smb_kmod_ioctl(SMB_IOC_START, &ioc.hdr, sizeof (ioc)));
111 }
112 
113 int
114 smb_kmod_tcplisten(int error)
115 {
116 	smb_ioc_listen_t ioc;
117 
118 	ioc.error = error;
119 	return (smb_kmod_ioctl(SMB_IOC_TCP_LISTEN, &ioc.hdr, sizeof (ioc)));
120 }
121 
122 int
123 smb_kmod_nbtlisten(int error)
124 {
125 	smb_ioc_listen_t ioc;
126 
127 	ioc.error = error;
128 	return (smb_kmod_ioctl(SMB_IOC_NBT_LISTEN, &ioc.hdr, sizeof (ioc)));
129 }
130 
131 int
132 smb_kmod_tcpreceive(void)
133 {
134 	smb_ioc_header_t ioc;
135 
136 	return (smb_kmod_ioctl(SMB_IOC_TCP_RECEIVE, &ioc, sizeof (ioc)));
137 }
138 
139 int
140 smb_kmod_nbtreceive(void)
141 {
142 	smb_ioc_header_t ioc;
143 
144 	return (smb_kmod_ioctl(SMB_IOC_NBT_RECEIVE, &ioc, sizeof (ioc)));
145 }
146 
147 int
148 smb_kmod_share(char *path, char *name)
149 {
150 	smb_ioc_share_t *ioc;
151 	int rc = ENOMEM;
152 
153 	ioc = malloc(sizeof (smb_ioc_share_t));
154 
155 	if (ioc != NULL) {
156 		(void) strlcpy(ioc->path, path, sizeof (ioc->path));
157 		(void) strlcpy(ioc->name, name, sizeof (ioc->name));
158 		rc = smb_kmod_ioctl(SMB_IOC_SHARE, &ioc->hdr,
159 		    sizeof (smb_ioc_share_t));
160 		free(ioc);
161 	}
162 	return (rc);
163 }
164 
165 int
166 smb_kmod_unshare(char *name)
167 {
168 	smb_ioc_share_t *ioc;
169 	int rc = ENOMEM;
170 
171 	ioc = malloc(sizeof (smb_ioc_share_t));
172 
173 	if (ioc != NULL) {
174 		(void) strlcpy(ioc->name, name, sizeof (ioc->name));
175 		rc = smb_kmod_ioctl(SMB_IOC_UNSHARE, &ioc->hdr,
176 		    sizeof (smb_ioc_share_t));
177 		free(ioc);
178 	}
179 	return (rc);
180 }
181 
182 int
183 smb_kmod_get_usernum(uint32_t *punum)
184 {
185 	smb_ioc_usernum_t ioc;
186 	int rc;
187 
188 	ioc.num = 0;
189 	rc = smb_kmod_ioctl(SMB_IOC_USER_NUMBER, &ioc.hdr, sizeof (ioc));
190 	if (rc == 0)
191 		*punum = ioc.num;
192 
193 	return (rc);
194 }
195 
196 int
197 smb_kmod_get_userlist(smb_ulist_t *ulist)
198 {
199 	smb_opipe_context_t	*ctx;
200 	smb_ioc_ulist_t		*ioc;
201 	uint32_t		ioc_len;
202 	uint8_t			*data;
203 	uint32_t		data_len;
204 	uint32_t		unum;
205 	int			rc;
206 
207 	smb_ulist_cleanup(ulist);
208 
209 	rc = smb_kmod_get_usernum(&unum);
210 	if ((rc != 0) || (unum == 0))
211 		return (rc);
212 
213 	ioc_len = sizeof (smb_ioc_ulist_t) + SMB_IOC_DATA_SIZE;
214 	ioc = malloc(ioc_len);
215 	if (ioc == NULL)
216 		return (ENOMEM);
217 
218 	ctx = malloc(sizeof (smb_opipe_context_t) * unum);
219 	if (ctx == NULL) {
220 		free(ioc);
221 		return (ENOMEM);
222 	}
223 	ulist->ul_users = ctx;
224 
225 	while (ulist->ul_cnt < unum) {
226 		ioc->cookie = ulist->ul_cnt;
227 		ioc->data_len = SMB_IOC_DATA_SIZE;
228 		rc = smb_kmod_ioctl(SMB_IOC_USER_LIST, &ioc->hdr,
229 		    ioc_len);
230 		if (rc != 0)
231 			break;
232 
233 		if ((ulist->ul_cnt + ioc->num) > unum)
234 			ioc->num = unum - ulist->ul_cnt;
235 
236 		if (ioc->num == 0)
237 			break;
238 
239 		data = ioc->data;
240 		data_len = ioc->data_len;
241 		while (ioc->num > 0) {
242 			uint_t	bd = 0;
243 
244 			rc = smb_opipe_context_decode(ctx, data, data_len, &bd);
245 			if (rc != 0)
246 				break;
247 
248 			ctx++;
249 			ioc->num--;
250 			ulist->ul_cnt++;
251 			data += bd;
252 			data_len -= bd;
253 		}
254 	}
255 
256 	if (rc != 0)
257 		smb_ulist_cleanup(ulist);
258 
259 	free(ioc);
260 	return (rc);
261 }
262 
263 void
264 smb_kmod_unbind(void)
265 {
266 	if (smbdrv_fd != -1) {
267 		(void) close(smbdrv_fd);
268 		smbdrv_fd = -1;
269 	}
270 }
271 
272 static int
273 smb_kmod_ioctl(int cmd, smb_ioc_header_t *ioc, uint32_t len)
274 {
275 	int rc = EINVAL;
276 
277 	ioc->version = SMB_IOC_VERSION;
278 	ioc->cmd = cmd;
279 	ioc->len = len;
280 	ioc->crc = 0;
281 	ioc->crc = smb_crc_gen((uint8_t *)ioc, sizeof (smb_ioc_header_t));
282 
283 	if (smbdrv_fd != -1) {
284 		if (ioctl(smbdrv_fd, cmd, ioc) < 0)
285 			rc = errno;
286 		else
287 			rc = 0;
288 	}
289 	return (rc);
290 }
291