129bd2886SAlan Wright /*
229bd2886SAlan Wright  * CDDL HEADER START
329bd2886SAlan Wright  *
429bd2886SAlan Wright  * The contents of this file are subject to the terms of the
529bd2886SAlan Wright  * Common Development and Distribution License (the "License").
629bd2886SAlan Wright  * You may not use this file except in compliance with the License.
729bd2886SAlan Wright  *
829bd2886SAlan Wright  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
929bd2886SAlan Wright  * or http://www.opensolaris.org/os/licensing.
1029bd2886SAlan Wright  * See the License for the specific language governing permissions
1129bd2886SAlan Wright  * and limitations under the License.
1229bd2886SAlan Wright  *
1329bd2886SAlan Wright  * When distributing Covered Code, include this CDDL HEADER in each
1429bd2886SAlan Wright  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1529bd2886SAlan Wright  * If applicable, add the following below this CDDL HEADER, with the
1629bd2886SAlan Wright  * fields enclosed by brackets "[]" replaced with your own identifying
1729bd2886SAlan Wright  * information: Portions Copyright [yyyy] [name of copyright owner]
1829bd2886SAlan Wright  *
1929bd2886SAlan Wright  * CDDL HEADER END
2029bd2886SAlan Wright  */
2129bd2886SAlan Wright /*
22148c5f43SAlan Wright  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
233e2c0c09SMatt Barden  * Copyright 2017 Nexenta Systems, Inc.  All rights reserved.
245f3b52abSGordon Ross  * Copyright 2017 Joyent, Inc.
25814e0daaSGordon Ross  * Copyright 2022 RackTop Systems, Inc.
2629bd2886SAlan Wright  */
2729bd2886SAlan Wright 
2829bd2886SAlan Wright #include <sys/types.h>
2929bd2886SAlan Wright #include <sys/stat.h>
3029bd2886SAlan Wright #include <sys/ioccom.h>
3129bd2886SAlan Wright #include <sys/param.h>
3229bd2886SAlan Wright #include <stddef.h>
3329bd2886SAlan Wright #include <stdio.h>
3429bd2886SAlan Wright #include <string.h>
3529bd2886SAlan Wright #include <strings.h>
3629bd2886SAlan Wright #include <stdlib.h>
3729bd2886SAlan Wright #include <unistd.h>
3829bd2886SAlan Wright #include <fcntl.h>
3929bd2886SAlan Wright #include <errno.h>
4029bd2886SAlan Wright 
4129bd2886SAlan Wright #include <smbsrv/smb_xdr.h>
4229bd2886SAlan Wright #include <smbsrv/smbinfo.h>
4329bd2886SAlan Wright #include <smbsrv/smb_ioctl.h>
4429bd2886SAlan Wright #include <smbsrv/libsmb.h>
4529bd2886SAlan Wright 
461e4c938bSGordon Ross #define	SMBDRV_DEVICE_PATH		"/dev/smbsrv"
4729bd2886SAlan Wright 
48b819cea2SGordon Ross int smb_kmod_ioctl(int, smb_ioc_header_t *, uint32_t);
4929bd2886SAlan Wright 
5029bd2886SAlan Wright 
5129bd2886SAlan Wright int	smbdrv_fd = -1;
5229bd2886SAlan Wright 
53*34bbc83aSGordon Ross /*
54*34bbc83aSGordon Ross  * Open the smbsrv driver.
55*34bbc83aSGordon Ross  * The smb daemon (smbd) opens the "control" device (/dev/smbsrv)
56*34bbc83aSGordon Ross  * and other consumers open the library device (/dev/smbsrv1)
57*34bbc83aSGordon Ross  */
5829bd2886SAlan Wright int
smb_kmod_bind(boolean_t smbd)59*34bbc83aSGordon Ross smb_kmod_bind(boolean_t smbd)
6029bd2886SAlan Wright {
61*34bbc83aSGordon Ross 	int fd;
62*34bbc83aSGordon Ross 
6329bd2886SAlan Wright 	if (smbdrv_fd != -1)
6429bd2886SAlan Wright 		(void) close(smbdrv_fd);
6529bd2886SAlan Wright 
66*34bbc83aSGordon Ross 	if (smbd) {
67*34bbc83aSGordon Ross 		fd = open(SMBDRV_DEVICE_PATH, 0);
68*34bbc83aSGordon Ross 	} else {
69*34bbc83aSGordon Ross 		fd = open(SMBDRV_DEVICE_PATH "1", 0);
7029bd2886SAlan Wright 	}
71*34bbc83aSGordon Ross 	if (fd < 0)
72*34bbc83aSGordon Ross 		return (errno);
73*34bbc83aSGordon Ross 
74*34bbc83aSGordon Ross 	smbdrv_fd = fd;
7529bd2886SAlan Wright 
7629bd2886SAlan Wright 	return (0);
7729bd2886SAlan Wright }
7829bd2886SAlan Wright 
79fd9ee8b5Sjoyce mcintosh boolean_t
smb_kmod_isbound(void)80fd9ee8b5Sjoyce mcintosh smb_kmod_isbound(void)
81fd9ee8b5Sjoyce mcintosh {
82fd9ee8b5Sjoyce mcintosh 	return ((smbdrv_fd == -1) ? B_FALSE : B_TRUE);
83fd9ee8b5Sjoyce mcintosh }
84fd9ee8b5Sjoyce mcintosh 
8512b65585SGordon Ross /* See also: smbsrv smb_server_store_cfg */
8629bd2886SAlan Wright int
smb_kmod_setcfg(smb_kmod_cfg_t * cfg)8729bd2886SAlan Wright smb_kmod_setcfg(smb_kmod_cfg_t *cfg)
8829bd2886SAlan Wright {
892cf6b79fSGordon Ross 	smb_ioc_cfg_t ioc = {0};
9029bd2886SAlan Wright 
9129bd2886SAlan Wright 	ioc.maxworkers = cfg->skc_maxworkers;
9229bd2886SAlan Wright 	ioc.maxconnections = cfg->skc_maxconnections;
9329bd2886SAlan Wright 	ioc.keepalive = cfg->skc_keepalive;
9429bd2886SAlan Wright 	ioc.restrict_anon = cfg->skc_restrict_anon;
9529bd2886SAlan Wright 	ioc.signing_enable = cfg->skc_signing_enable;
9629bd2886SAlan Wright 	ioc.signing_required = cfg->skc_signing_required;
9729bd2886SAlan Wright 	ioc.oplock_enable = cfg->skc_oplock_enable;
9829bd2886SAlan Wright 	ioc.sync_enable = cfg->skc_sync_enable;
9929bd2886SAlan Wright 	ioc.secmode = cfg->skc_secmode;
10083d2dfe6SGordon Ross 	ioc.netbios_enable = cfg->skc_netbios_enable;
10112b65585SGordon Ross 	ioc.ipv6_enable = cfg->skc_ipv6_enable;
102cb174861Sjoyce mcintosh 	ioc.print_enable = cfg->skc_print_enable;
1035f1ef25cSAram Hăvărneanu 	ioc.traverse_mounts = cfg->skc_traverse_mounts;
104814e0daaSGordon Ross 	ioc.short_names = cfg->skc_short_names;
105814e0daaSGordon Ross 
106a90cf9f2SGordon Ross 	ioc.max_protocol = cfg->skc_max_protocol;
1073e2c0c09SMatt Barden 	ioc.min_protocol = cfg->skc_min_protocol;
108148c5f43SAlan Wright 	ioc.exec_flags = cfg->skc_execflags;
10912b65585SGordon Ross 	ioc.negtok_len = cfg->skc_negtok_len;
1102cf6b79fSGordon Ross 	ioc.max_opens = cfg->skc_max_opens;
1112cf6b79fSGordon Ross 
112148c5f43SAlan Wright 	ioc.version = cfg->skc_version;
113a90cf9f2SGordon Ross 	ioc.initial_credits = cfg->skc_initial_credits;
114a90cf9f2SGordon Ross 	ioc.maximum_credits = cfg->skc_maximum_credits;
1151160dcf7SMatt Barden 	ioc.encrypt = cfg->skc_encrypt;
116b0bb0d63SGordon Ross 	ioc.encrypt_ciphers = cfg->skc_encrypt_ciphers;
11729bd2886SAlan Wright 
11812b65585SGordon Ross 	(void) memcpy(ioc.machine_uuid, cfg->skc_machine_uuid, sizeof (uuid_t));
11912b65585SGordon Ross 	(void) memcpy(ioc.negtok, cfg->skc_negtok, sizeof (ioc.negtok));
12012b65585SGordon Ross 	(void) memcpy(ioc.native_os, cfg->skc_native_os,
12112b65585SGordon Ross 	    sizeof (ioc.native_os));
12212b65585SGordon Ross 	(void) memcpy(ioc.native_lm, cfg->skc_native_lm,
12312b65585SGordon Ross 	    sizeof (ioc.native_lm));
12412b65585SGordon Ross 
12529bd2886SAlan Wright 	(void) strlcpy(ioc.nbdomain, cfg->skc_nbdomain, sizeof (ioc.nbdomain));
12629bd2886SAlan Wright 	(void) strlcpy(ioc.fqdn, cfg->skc_fqdn, sizeof (ioc.fqdn));
12729bd2886SAlan Wright 	(void) strlcpy(ioc.hostname, cfg->skc_hostname, sizeof (ioc.hostname));
12829bd2886SAlan Wright 	(void) strlcpy(ioc.system_comment, cfg->skc_system_comment,
12929bd2886SAlan Wright 	    sizeof (ioc.system_comment));
13029bd2886SAlan Wright 
13129bd2886SAlan Wright 	return (smb_kmod_ioctl(SMB_IOC_CONFIG, &ioc.hdr, sizeof (ioc)));
13229bd2886SAlan Wright }
13329bd2886SAlan Wright 
13429bd2886SAlan Wright int
smb_kmod_setgmtoff(int32_t gmtoff)13529bd2886SAlan Wright smb_kmod_setgmtoff(int32_t gmtoff)
13629bd2886SAlan Wright {
13729bd2886SAlan Wright 	smb_ioc_gmt_t ioc;
13829bd2886SAlan Wright 
13929bd2886SAlan Wright 	ioc.offset = gmtoff;
14029bd2886SAlan Wright 	return (smb_kmod_ioctl(SMB_IOC_GMTOFF, &ioc.hdr,
14129bd2886SAlan Wright 	    sizeof (ioc)));
14229bd2886SAlan Wright }
14329bd2886SAlan Wright 
14429bd2886SAlan Wright int
smb_kmod_start(int opipe,int lmshr,int udoor)14529bd2886SAlan Wright smb_kmod_start(int opipe, int lmshr, int udoor)
14629bd2886SAlan Wright {
14729bd2886SAlan Wright 	smb_ioc_start_t ioc;
14829bd2886SAlan Wright 
14929bd2886SAlan Wright 	ioc.opipe = opipe;
15029bd2886SAlan Wright 	ioc.lmshrd = lmshr;
15129bd2886SAlan Wright 	ioc.udoor = udoor;
15229bd2886SAlan Wright 	return (smb_kmod_ioctl(SMB_IOC_START, &ioc.hdr, sizeof (ioc)));
15329bd2886SAlan Wright }
15429bd2886SAlan Wright 
1559fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States void
smb_kmod_stop(void)1569fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_kmod_stop(void)
1579fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
1589fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_ioc_header_t ioc;
1599fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1609fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	(void) smb_kmod_ioctl(SMB_IOC_STOP, &ioc, sizeof (ioc));
1619fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
1629fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1639fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States int
smb_kmod_event_notify(uint32_t txid)1649fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States smb_kmod_event_notify(uint32_t txid)
1659fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States {
1669fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	smb_ioc_event_t ioc;
1679fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
1689fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	ioc.txid = txid;
1699fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 	return (smb_kmod_ioctl(SMB_IOC_EVENT, &ioc.hdr, sizeof (ioc)));
1709fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States }
1719fb67ea3Safshin salek ardakani - Sun Microsystems - Irvine United States 
17229bd2886SAlan Wright int
smb_kmod_share(nvlist_t * shrlist)173148c5f43SAlan Wright smb_kmod_share(nvlist_t *shrlist)
17429bd2886SAlan Wright {
17529bd2886SAlan Wright 	smb_ioc_share_t *ioc;
176148c5f43SAlan Wright 	uint32_t ioclen;
177148c5f43SAlan Wright 	char *shrbuf = NULL;
178148c5f43SAlan Wright 	size_t bufsz;
17929bd2886SAlan Wright 	int rc = ENOMEM;
18029bd2886SAlan Wright 
181148c5f43SAlan Wright 	if ((rc = nvlist_pack(shrlist, &shrbuf, &bufsz, NV_ENCODE_XDR, 0)) != 0)
182148c5f43SAlan Wright 		return (rc);
18329bd2886SAlan Wright 
184148c5f43SAlan Wright 	ioclen = sizeof (smb_ioc_share_t) + bufsz;
185148c5f43SAlan Wright 
186148c5f43SAlan Wright 	if ((ioc = malloc(ioclen)) != NULL) {
187148c5f43SAlan Wright 		ioc->shrlen = bufsz;
188148c5f43SAlan Wright 		bcopy(shrbuf, ioc->shr, bufsz);
189148c5f43SAlan Wright 		rc = smb_kmod_ioctl(SMB_IOC_SHARE, &ioc->hdr, ioclen);
19029bd2886SAlan Wright 		free(ioc);
19129bd2886SAlan Wright 	}
192148c5f43SAlan Wright 
193148c5f43SAlan Wright 	free(shrbuf);
19429bd2886SAlan Wright 	return (rc);
19529bd2886SAlan Wright }
19629bd2886SAlan Wright 
19729bd2886SAlan Wright int
smb_kmod_unshare(nvlist_t * shrlist)198148c5f43SAlan Wright smb_kmod_unshare(nvlist_t *shrlist)
19929bd2886SAlan Wright {
20029bd2886SAlan Wright 	smb_ioc_share_t *ioc;
201148c5f43SAlan Wright 	uint32_t ioclen;
202148c5f43SAlan Wright 	char *shrbuf = NULL;
203148c5f43SAlan Wright 	size_t bufsz;
20429bd2886SAlan Wright 	int rc = ENOMEM;
20529bd2886SAlan Wright 
206148c5f43SAlan Wright 	if ((rc = nvlist_pack(shrlist, &shrbuf, &bufsz, NV_ENCODE_XDR, 0)) != 0)
207148c5f43SAlan Wright 		return (rc);
20829bd2886SAlan Wright 
209148c5f43SAlan Wright 	ioclen = sizeof (smb_ioc_share_t) + bufsz;
210148c5f43SAlan Wright 
211148c5f43SAlan Wright 	if ((ioc = malloc(ioclen)) != NULL) {
212148c5f43SAlan Wright 		ioc->shrlen = bufsz;
213148c5f43SAlan Wright 		bcopy(shrbuf, ioc->shr, bufsz);
214148c5f43SAlan Wright 		rc = smb_kmod_ioctl(SMB_IOC_UNSHARE, &ioc->hdr, ioclen);
21529bd2886SAlan Wright 		free(ioc);
21629bd2886SAlan Wright 	}
217148c5f43SAlan Wright 
218148c5f43SAlan Wright 	free(shrbuf);
21929bd2886SAlan Wright 	return (rc);
22029bd2886SAlan Wright }
22129bd2886SAlan Wright 
222cb174861Sjoyce mcintosh int
smb_kmod_shareinfo(char * shrname,boolean_t * shortnames)223cb174861Sjoyce mcintosh smb_kmod_shareinfo(char *shrname, boolean_t *shortnames)
224cb174861Sjoyce mcintosh {
225cb174861Sjoyce mcintosh 	smb_ioc_shareinfo_t ioc;
226cb174861Sjoyce mcintosh 	int rc;
227cb174861Sjoyce mcintosh 
228cb174861Sjoyce mcintosh 	bzero(&ioc, sizeof (ioc));
229cb174861Sjoyce mcintosh 	(void) strlcpy(ioc.shrname, shrname, MAXNAMELEN);
230cb174861Sjoyce mcintosh 
231cb174861Sjoyce mcintosh 	rc = smb_kmod_ioctl(SMB_IOC_SHAREINFO, &ioc.hdr, sizeof (ioc));
232cb174861Sjoyce mcintosh 	if (rc == 0)
233cb174861Sjoyce mcintosh 		*shortnames = ioc.shortnames;
234cb174861Sjoyce mcintosh 	else
235cb174861Sjoyce mcintosh 		*shortnames = B_TRUE;
236cb174861Sjoyce mcintosh 
237cb174861Sjoyce mcintosh 	return (rc);
238cb174861Sjoyce mcintosh }
239cb174861Sjoyce mcintosh 
24097264293SGordon Ross /*
24197264293SGordon Ross  * Does the client have any access in this share?
24297264293SGordon Ross  */
24397264293SGordon Ross int
smb_kmod_shareaccess(smb_netuserinfo_t * ui,smb_share_t * si)24497264293SGordon Ross smb_kmod_shareaccess(smb_netuserinfo_t *ui, smb_share_t *si)
24597264293SGordon Ross {
24697264293SGordon Ross 	smb_ioc_shareaccess_t ioc;
24797264293SGordon Ross 	int rc;
24897264293SGordon Ross 
24997264293SGordon Ross 	bzero(&ioc, sizeof (ioc));
25097264293SGordon Ross 	ioc.session_id	= ui->ui_session_id;
25197264293SGordon Ross 	ioc.user_id	= ui->ui_user_id;
25297264293SGordon Ross 	(void) strlcpy(ioc.shrname, si->shr_name, MAXNAMELEN);
25397264293SGordon Ross 
25497264293SGordon Ross 	rc = smb_kmod_ioctl(SMB_IOC_SHAREACCESS, &ioc.hdr, sizeof (ioc));
25597264293SGordon Ross 
25697264293SGordon Ross 	return (rc);
25797264293SGordon Ross }
25897264293SGordon Ross 
25929bd2886SAlan Wright int
smb_kmod_get_open_num(smb_opennum_t * opennum)2601fcced4cSJordan Brown smb_kmod_get_open_num(smb_opennum_t *opennum)
26129bd2886SAlan Wright {
2621fcced4cSJordan Brown 	smb_ioc_opennum_t ioc;
26329bd2886SAlan Wright 	int rc;
26429bd2886SAlan Wright 
2651fcced4cSJordan Brown 	bzero(&ioc, sizeof (ioc));
2661fcced4cSJordan Brown 	ioc.qualtype = opennum->qualtype;
2671fcced4cSJordan Brown 	(void) strlcpy(ioc.qualifier, opennum->qualifier, MAXNAMELEN);
2681fcced4cSJordan Brown 
2691fcced4cSJordan Brown 	rc = smb_kmod_ioctl(SMB_IOC_NUMOPEN, &ioc.hdr, sizeof (ioc));
2701fcced4cSJordan Brown 	if (rc == 0) {
2711fcced4cSJordan Brown 		opennum->open_users = ioc.open_users;
2721fcced4cSJordan Brown 		opennum->open_trees = ioc.open_trees;
2731fcced4cSJordan Brown 		opennum->open_files = ioc.open_files;
2741fcced4cSJordan Brown 	}
27529bd2886SAlan Wright 
27629bd2886SAlan Wright 	return (rc);
27729bd2886SAlan Wright }
27829bd2886SAlan Wright 
279cb174861Sjoyce mcintosh int
smb_kmod_get_spool_doc(uint32_t * spool_num,char * username,char * path,smb_inaddr_t * ipaddr)280cb174861Sjoyce mcintosh smb_kmod_get_spool_doc(uint32_t *spool_num, char *username,
281cb174861Sjoyce mcintosh     char *path, smb_inaddr_t *ipaddr)
282cb174861Sjoyce mcintosh {
283cb174861Sjoyce mcintosh 	smb_ioc_spooldoc_t ioc;
284cb174861Sjoyce mcintosh 	int rc;
285cb174861Sjoyce mcintosh 
286cb174861Sjoyce mcintosh 	bzero(&ioc, sizeof (ioc));
287cb174861Sjoyce mcintosh 	rc = smb_kmod_ioctl(SMB_IOC_SPOOLDOC, &ioc.hdr, sizeof (ioc));
288cb174861Sjoyce mcintosh 	if (rc == 0) {
289cb174861Sjoyce mcintosh 		*spool_num = ioc.spool_num;
290cb174861Sjoyce mcintosh 		(void) strlcpy(username, ioc.username, MAXNAMELEN);
291cb174861Sjoyce mcintosh 		(void) strlcpy(path, ioc.path, MAXPATHLEN);
292cb174861Sjoyce mcintosh 		*ipaddr = ioc.ipaddr;
293cb174861Sjoyce mcintosh 	}
294cb174861Sjoyce mcintosh 	return (rc);
295cb174861Sjoyce mcintosh }
296cb174861Sjoyce mcintosh 
2971fcced4cSJordan Brown /*
2981fcced4cSJordan Brown  * Initialization for an smb_kmod_enum request.  If this call succeeds,
2991fcced4cSJordan Brown  * smb_kmod_enum_fini() must be called later to deallocate resources.
3001fcced4cSJordan Brown  */
3011fcced4cSJordan Brown smb_netsvc_t *
smb_kmod_enum_init(smb_svcenum_t * request)3021fcced4cSJordan Brown smb_kmod_enum_init(smb_svcenum_t *request)
3031fcced4cSJordan Brown {
3041fcced4cSJordan Brown 	smb_netsvc_t		*ns;
3051fcced4cSJordan Brown 	smb_svcenum_t		*svcenum;
3061fcced4cSJordan Brown 	smb_ioc_svcenum_t	*ioc;
3071fcced4cSJordan Brown 	uint32_t		ioclen;
3081fcced4cSJordan Brown 
3091fcced4cSJordan Brown 	if ((ns = calloc(1, sizeof (smb_netsvc_t))) == NULL)
3101fcced4cSJordan Brown 		return (NULL);
3111fcced4cSJordan Brown 
3121fcced4cSJordan Brown 	ioclen = sizeof (smb_ioc_svcenum_t) + SMB_IOC_DATA_SIZE;
3131fcced4cSJordan Brown 	if ((ioc = malloc(ioclen)) == NULL) {
3141fcced4cSJordan Brown 		free(ns);
3151fcced4cSJordan Brown 		return (NULL);
3161fcced4cSJordan Brown 	}
3171fcced4cSJordan Brown 
3181fcced4cSJordan Brown 	bzero(ioc, ioclen);
3191fcced4cSJordan Brown 	svcenum = &ioc->svcenum;
3201fcced4cSJordan Brown 	svcenum->se_type   = request->se_type;
3211fcced4cSJordan Brown 	svcenum->se_level  = request->se_level;
3221fcced4cSJordan Brown 	svcenum->se_bavail = SMB_IOC_DATA_SIZE;
3231fcced4cSJordan Brown 	svcenum->se_nlimit = request->se_nlimit;
3241fcced4cSJordan Brown 	svcenum->se_nskip = request->se_nskip;
3251fcced4cSJordan Brown 	svcenum->se_buflen = SMB_IOC_DATA_SIZE;
3261fcced4cSJordan Brown 
3271fcced4cSJordan Brown 	list_create(&ns->ns_list, sizeof (smb_netsvcitem_t),
3281fcced4cSJordan Brown 	    offsetof(smb_netsvcitem_t, nsi_lnd));
3291fcced4cSJordan Brown 
3301fcced4cSJordan Brown 	ns->ns_ioc = ioc;
3311fcced4cSJordan Brown 	ns->ns_ioclen = ioclen;
3321fcced4cSJordan Brown 	return (ns);
3331fcced4cSJordan Brown }
3341fcced4cSJordan Brown 
3351fcced4cSJordan Brown /*
3361fcced4cSJordan Brown  * Cleanup resources allocated via smb_kmod_enum_init and smb_kmod_enum.
3371fcced4cSJordan Brown  */
3381fcced4cSJordan Brown void
smb_kmod_enum_fini(smb_netsvc_t * ns)3391fcced4cSJordan Brown smb_kmod_enum_fini(smb_netsvc_t *ns)
3401fcced4cSJordan Brown {
3411fcced4cSJordan Brown 	list_t			*lst;
3421fcced4cSJordan Brown 	smb_netsvcitem_t	*item;
3431fcced4cSJordan Brown 	smb_netuserinfo_t	*user;
3441fcced4cSJordan Brown 	smb_netconnectinfo_t	*tree;
3451fcced4cSJordan Brown 	smb_netfileinfo_t	*ofile;
3461fcced4cSJordan Brown 	uint32_t		se_type;
3471fcced4cSJordan Brown 
3481fcced4cSJordan Brown 	if (ns == NULL)
3491fcced4cSJordan Brown 		return;
3501fcced4cSJordan Brown 
3511fcced4cSJordan Brown 	lst = &ns->ns_list;
3521fcced4cSJordan Brown 	se_type = ns->ns_ioc->svcenum.se_type;
3531fcced4cSJordan Brown 
3541fcced4cSJordan Brown 	while ((item = list_head(lst)) != NULL) {
3551fcced4cSJordan Brown 		list_remove(lst, item);
3561fcced4cSJordan Brown 
3571fcced4cSJordan Brown 		switch (se_type) {
3581fcced4cSJordan Brown 		case SMB_SVCENUM_TYPE_USER:
3591fcced4cSJordan Brown 			user = &item->nsi_un.nsi_user;
3601fcced4cSJordan Brown 			free(user->ui_domain);
3611fcced4cSJordan Brown 			free(user->ui_account);
3621fcced4cSJordan Brown 			free(user->ui_workstation);
3631fcced4cSJordan Brown 			break;
3641fcced4cSJordan Brown 		case SMB_SVCENUM_TYPE_TREE:
3651fcced4cSJordan Brown 			tree = &item->nsi_un.nsi_tree;
3661fcced4cSJordan Brown 			free(tree->ci_username);
3671fcced4cSJordan Brown 			free(tree->ci_share);
3681fcced4cSJordan Brown 			break;
3691fcced4cSJordan Brown 		case SMB_SVCENUM_TYPE_FILE:
3701fcced4cSJordan Brown 			ofile = &item->nsi_un.nsi_ofile;
3711fcced4cSJordan Brown 			free(ofile->fi_path);
3721fcced4cSJordan Brown 			free(ofile->fi_username);
3731fcced4cSJordan Brown 			break;
3741fcced4cSJordan Brown 		default:
3751fcced4cSJordan Brown 			break;
3761fcced4cSJordan Brown 		}
3771fcced4cSJordan Brown 	}
3781fcced4cSJordan Brown 
3791fcced4cSJordan Brown 	list_destroy(&ns->ns_list);
3801fcced4cSJordan Brown 	free(ns->ns_items);
3811fcced4cSJordan Brown 	free(ns->ns_ioc);
3821fcced4cSJordan Brown 	free(ns);
3831fcced4cSJordan Brown }
3841fcced4cSJordan Brown 
3851fcced4cSJordan Brown /*
3861fcced4cSJordan Brown  * Enumerate users, connections or files.
3871fcced4cSJordan Brown  */
38829bd2886SAlan Wright int
smb_kmod_enum(smb_netsvc_t * ns)3891fcced4cSJordan Brown smb_kmod_enum(smb_netsvc_t *ns)
39029bd2886SAlan Wright {
3911fcced4cSJordan Brown 	smb_ioc_svcenum_t	*ioc;
3921fcced4cSJordan Brown 	uint32_t		ioclen;
3931fcced4cSJordan Brown 	smb_svcenum_t		*svcenum;
3941fcced4cSJordan Brown 	smb_netsvcitem_t	*items;
3951fcced4cSJordan Brown 	smb_netuserinfo_t	*user;
3961fcced4cSJordan Brown 	smb_netconnectinfo_t	*tree;
3971fcced4cSJordan Brown 	smb_netfileinfo_t	*ofile;
39829bd2886SAlan Wright 	uint8_t			*data;
3991fcced4cSJordan Brown 	uint32_t		len;
4001fcced4cSJordan Brown 	uint32_t		se_type;
4011fcced4cSJordan Brown 	uint_t			nbytes;
4021fcced4cSJordan Brown 	int			i;
40329bd2886SAlan Wright 	int			rc;
40429bd2886SAlan Wright 
4051fcced4cSJordan Brown 	ioc = ns->ns_ioc;
4061fcced4cSJordan Brown 	ioclen = ns->ns_ioclen;
4071fcced4cSJordan Brown 	rc = smb_kmod_ioctl(SMB_IOC_SVCENUM, &ioc->hdr, ioclen);
4081fcced4cSJordan Brown 	if (rc != 0)
40929bd2886SAlan Wright 		return (rc);
41029bd2886SAlan Wright 
4111fcced4cSJordan Brown 	svcenum = &ioc->svcenum;
4121fcced4cSJordan Brown 	items = calloc(svcenum->se_nitems, sizeof (smb_netsvcitem_t));
4131fcced4cSJordan Brown 	if (items == NULL)
41429bd2886SAlan Wright 		return (ENOMEM);
41529bd2886SAlan Wright 
4161fcced4cSJordan Brown 	ns->ns_items = items;
4171fcced4cSJordan Brown 	se_type = ns->ns_ioc->svcenum.se_type;
4181fcced4cSJordan Brown 	data = svcenum->se_buf;
4191fcced4cSJordan Brown 	len = svcenum->se_bused;
42029bd2886SAlan Wright 
4211fcced4cSJordan Brown 	for (i = 0; i < svcenum->se_nitems; ++i) {
4221fcced4cSJordan Brown 		switch (se_type) {
4231fcced4cSJordan Brown 		case SMB_SVCENUM_TYPE_USER:
4241fcced4cSJordan Brown 			user = &items->nsi_un.nsi_user;
4251fcced4cSJordan Brown 			rc = smb_netuserinfo_decode(user, data, len, &nbytes);
42629bd2886SAlan Wright 			break;
4271fcced4cSJordan Brown 		case SMB_SVCENUM_TYPE_TREE:
4281fcced4cSJordan Brown 			tree = &items->nsi_un.nsi_tree;
4291fcced4cSJordan Brown 			rc = smb_netconnectinfo_decode(tree, data, len,
4301fcced4cSJordan Brown 			    &nbytes);
43129bd2886SAlan Wright 			break;
4321fcced4cSJordan Brown 		case SMB_SVCENUM_TYPE_FILE:
4331fcced4cSJordan Brown 			ofile = &items->nsi_un.nsi_ofile;
4341fcced4cSJordan Brown 			rc = smb_netfileinfo_decode(ofile, data, len, &nbytes);
4351fcced4cSJordan Brown 			break;
4361fcced4cSJordan Brown 		default:
4371fcced4cSJordan Brown 			rc = -1;
4381fcced4cSJordan Brown 			break;
4391fcced4cSJordan Brown 		}
44029bd2886SAlan Wright 
4411fcced4cSJordan Brown 		if (rc != 0)
4421fcced4cSJordan Brown 			return (EINVAL);
44329bd2886SAlan Wright 
4441fcced4cSJordan Brown 		list_insert_tail(&ns->ns_list, items);
44529bd2886SAlan Wright 
4461fcced4cSJordan Brown 		++items;
4471fcced4cSJordan Brown 		data += nbytes;
4481fcced4cSJordan Brown 		len -= nbytes;
44929bd2886SAlan Wright 	}
45029bd2886SAlan Wright 
4511fcced4cSJordan Brown 	return (0);
4521fcced4cSJordan Brown }
4531fcced4cSJordan Brown 
4541fcced4cSJordan Brown /*
4551fcced4cSJordan Brown  * A NULL pointer is a wildcard indicator, which we pass on
4561fcced4cSJordan Brown  * as an empty string (by virtue of the bzero).
4571fcced4cSJordan Brown  */
4581fcced4cSJordan Brown int
smb_kmod_session_close(const char * client,const char * username)4591fcced4cSJordan Brown smb_kmod_session_close(const char *client, const char *username)
4601fcced4cSJordan Brown {
4611fcced4cSJordan Brown 	smb_ioc_session_t ioc;
4621fcced4cSJordan Brown 	int rc;
4631fcced4cSJordan Brown 
4641fcced4cSJordan Brown 	bzero(&ioc, sizeof (ioc));
4651fcced4cSJordan Brown 
4661fcced4cSJordan Brown 	if (client != NULL)
4671fcced4cSJordan Brown 		(void) strlcpy(ioc.client, client, MAXNAMELEN);
4681fcced4cSJordan Brown 	if (username != NULL)
4691fcced4cSJordan Brown 		(void) strlcpy(ioc.username, username, MAXNAMELEN);
4701fcced4cSJordan Brown 
4711fcced4cSJordan Brown 	rc = smb_kmod_ioctl(SMB_IOC_SESSION_CLOSE, &ioc.hdr, sizeof (ioc));
4721fcced4cSJordan Brown 	return (rc);
4731fcced4cSJordan Brown }
4741fcced4cSJordan Brown 
4751fcced4cSJordan Brown int
smb_kmod_file_close(uint32_t uniqid)4761fcced4cSJordan Brown smb_kmod_file_close(uint32_t uniqid)
4771fcced4cSJordan Brown {
4781fcced4cSJordan Brown 	smb_ioc_fileid_t ioc;
4791fcced4cSJordan Brown 	int rc;
4801fcced4cSJordan Brown 
4811fcced4cSJordan Brown 	bzero(&ioc, sizeof (ioc));
4821fcced4cSJordan Brown 	ioc.uniqid = uniqid;
48329bd2886SAlan Wright 
4841fcced4cSJordan Brown 	rc = smb_kmod_ioctl(SMB_IOC_FILE_CLOSE, &ioc.hdr, sizeof (ioc));
48529bd2886SAlan Wright 	return (rc);
48629bd2886SAlan Wright }
48729bd2886SAlan Wright 
48829bd2886SAlan Wright void
smb_kmod_unbind(void)48929bd2886SAlan Wright smb_kmod_unbind(void)
49029bd2886SAlan Wright {
49129bd2886SAlan Wright 	if (smbdrv_fd != -1) {
49229bd2886SAlan Wright 		(void) close(smbdrv_fd);
49329bd2886SAlan Wright 		smbdrv_fd = -1;
49429bd2886SAlan Wright 	}
49529bd2886SAlan Wright }
49629bd2886SAlan Wright 
497b819cea2SGordon Ross /*
498b819cea2SGordon Ross  * Note: The user-space smbd-d provides it own version of this function
499b819cea2SGordon Ross  * which directly calls the "kernel" module code (in user space).
500b819cea2SGordon Ross  */
501b819cea2SGordon Ross int
smb_kmod_ioctl(int cmd,smb_ioc_header_t * ioc,uint32_t len)50229bd2886SAlan Wright smb_kmod_ioctl(int cmd, smb_ioc_header_t *ioc, uint32_t len)
50329bd2886SAlan Wright {
50429bd2886SAlan Wright 	int rc = EINVAL;
50529bd2886SAlan Wright 
50629bd2886SAlan Wright 	ioc->version = SMB_IOC_VERSION;
50729bd2886SAlan Wright 	ioc->cmd = cmd;
50829bd2886SAlan Wright 	ioc->len = len;
50929bd2886SAlan Wright 	ioc->crc = 0;
51029bd2886SAlan Wright 	ioc->crc = smb_crc_gen((uint8_t *)ioc, sizeof (smb_ioc_header_t));
51129bd2886SAlan Wright 
51229bd2886SAlan Wright 	if (smbdrv_fd != -1) {
51329bd2886SAlan Wright 		if (ioctl(smbdrv_fd, cmd, ioc) < 0)
51429bd2886SAlan Wright 			rc = errno;
51529bd2886SAlan Wright 		else
51629bd2886SAlan Wright 			rc = 0;
51729bd2886SAlan Wright 	}
51829bd2886SAlan Wright 	return (rc);
51929bd2886SAlan Wright }
520