xref: /illumos-gate/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c (revision 037cac007b685e7ea79f6ef7e8e62bfd342a4d56)
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 *path, 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->path, path, sizeof (ioc->path));
175 		(void) strlcpy(ioc->name, name, sizeof (ioc->name));
176 		rc = smb_kmod_ioctl(SMB_IOC_UNSHARE, &ioc->hdr,
177 		    sizeof (smb_ioc_share_t));
178 		free(ioc);
179 	}
180 	return (rc);
181 }
182 
183 int
184 smb_kmod_get_usernum(uint32_t *punum)
185 {
186 	smb_ioc_usernum_t ioc;
187 	int rc;
188 
189 	ioc.num = 0;
190 	rc = smb_kmod_ioctl(SMB_IOC_USER_NUMBER, &ioc.hdr, sizeof (ioc));
191 	if (rc == 0)
192 		*punum = ioc.num;
193 
194 	return (rc);
195 }
196 
197 int
198 smb_kmod_get_userlist(smb_ulist_t *ulist)
199 {
200 	smb_opipe_context_t	*ctx;
201 	smb_ioc_ulist_t		*ioc;
202 	uint32_t		ioc_len;
203 	uint8_t			*data;
204 	uint32_t		data_len;
205 	uint32_t		unum;
206 	int			rc;
207 
208 	smb_ulist_cleanup(ulist);
209 
210 	rc = smb_kmod_get_usernum(&unum);
211 	if ((rc != 0) || (unum == 0))
212 		return (rc);
213 
214 	ioc_len = sizeof (smb_ioc_ulist_t) + SMB_IOC_DATA_SIZE;
215 	ioc = malloc(ioc_len);
216 	if (ioc == NULL)
217 		return (ENOMEM);
218 
219 	ctx = malloc(sizeof (smb_opipe_context_t) * unum);
220 	if (ctx == NULL) {
221 		free(ioc);
222 		return (ENOMEM);
223 	}
224 	ulist->ul_users = ctx;
225 
226 	while (ulist->ul_cnt < unum) {
227 		ioc->cookie = ulist->ul_cnt;
228 		ioc->data_len = SMB_IOC_DATA_SIZE;
229 		rc = smb_kmod_ioctl(SMB_IOC_USER_LIST, &ioc->hdr,
230 		    ioc_len);
231 		if (rc != 0)
232 			break;
233 
234 		if ((ulist->ul_cnt + ioc->num) > unum)
235 			ioc->num = unum - ulist->ul_cnt;
236 
237 		if (ioc->num == 0)
238 			break;
239 
240 		data = ioc->data;
241 		data_len = ioc->data_len;
242 		while (ioc->num > 0) {
243 			uint_t	bd = 0;
244 
245 			rc = smb_opipe_context_decode(ctx, data, data_len, &bd);
246 			if (rc != 0)
247 				break;
248 
249 			ctx++;
250 			ioc->num--;
251 			ulist->ul_cnt++;
252 			data += bd;
253 			data_len -= bd;
254 		}
255 	}
256 
257 	if (rc != 0)
258 		smb_ulist_cleanup(ulist);
259 
260 	free(ioc);
261 	return (rc);
262 }
263 
264 void
265 smb_kmod_unbind(void)
266 {
267 	if (smbdrv_fd != -1) {
268 		(void) close(smbdrv_fd);
269 		smbdrv_fd = -1;
270 	}
271 }
272 
273 static int
274 smb_kmod_ioctl(int cmd, smb_ioc_header_t *ioc, uint32_t len)
275 {
276 	int rc = EINVAL;
277 
278 	ioc->version = SMB_IOC_VERSION;
279 	ioc->cmd = cmd;
280 	ioc->len = len;
281 	ioc->crc = 0;
282 	ioc->crc = smb_crc_gen((uint8_t *)ioc, sizeof (smb_ioc_header_t));
283 
284 	if (smbdrv_fd != -1) {
285 		if (ioctl(smbdrv_fd, cmd, ioc) < 0)
286 			rc = errno;
287 		else
288 			rc = 0;
289 	}
290 	return (rc);
291 }
292