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.
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.
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]
22 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
26 #include <sys/types.h>
28 #include <sys/ioccom.h>
29 #include <sys/param.h>
39 #include <smbsrv/smb_xdr.h>
40 #include <smbsrv/smbinfo.h>
41 #include <smbsrv/smb_ioctl.h>
42 #include <smbsrv/libsmb.h>
44 #define SMBDRV_DEVICE_PATH "/dev/smbsrv"
45 #define SMB_IOC_DATA_SIZE (256 * 1024)
47 int smb_kmod_ioctl(int, smb_ioc_header_t
*, uint32_t);
56 (void) close(smbdrv_fd
);
58 if ((smbdrv_fd
= open(SMBDRV_DEVICE_PATH
, O_RDONLY
)) < 0) {
67 smb_kmod_isbound(void)
69 return ((smbdrv_fd
== -1) ? B_FALSE
: B_TRUE
);
72 /* See also: smbsrv smb_server_store_cfg */
74 smb_kmod_setcfg(smb_kmod_cfg_t
*cfg
)
78 ioc
.maxworkers
= cfg
->skc_maxworkers
;
79 ioc
.maxconnections
= cfg
->skc_maxconnections
;
80 ioc
.keepalive
= cfg
->skc_keepalive
;
81 ioc
.restrict_anon
= cfg
->skc_restrict_anon
;
82 ioc
.signing_enable
= cfg
->skc_signing_enable
;
83 ioc
.signing_required
= cfg
->skc_signing_required
;
84 ioc
.oplock_enable
= cfg
->skc_oplock_enable
;
85 ioc
.sync_enable
= cfg
->skc_sync_enable
;
86 ioc
.secmode
= cfg
->skc_secmode
;
87 ioc
.netbios_enable
= cfg
->skc_netbios_enable
;
88 ioc
.ipv6_enable
= cfg
->skc_ipv6_enable
;
89 ioc
.print_enable
= cfg
->skc_print_enable
;
90 ioc
.traverse_mounts
= cfg
->skc_traverse_mounts
;
91 ioc
.max_protocol
= cfg
->skc_max_protocol
;
92 ioc
.exec_flags
= cfg
->skc_execflags
;
93 ioc
.negtok_len
= cfg
->skc_negtok_len
;
94 ioc
.version
= cfg
->skc_version
;
95 ioc
.initial_credits
= cfg
->skc_initial_credits
;
96 ioc
.maximum_credits
= cfg
->skc_maximum_credits
;
98 (void) memcpy(ioc
.machine_uuid
, cfg
->skc_machine_uuid
, sizeof (uuid_t
));
99 (void) memcpy(ioc
.negtok
, cfg
->skc_negtok
, sizeof (ioc
.negtok
));
100 (void) memcpy(ioc
.native_os
, cfg
->skc_native_os
,
101 sizeof (ioc
.native_os
));
102 (void) memcpy(ioc
.native_lm
, cfg
->skc_native_lm
,
103 sizeof (ioc
.native_lm
));
105 (void) strlcpy(ioc
.nbdomain
, cfg
->skc_nbdomain
, sizeof (ioc
.nbdomain
));
106 (void) strlcpy(ioc
.fqdn
, cfg
->skc_fqdn
, sizeof (ioc
.fqdn
));
107 (void) strlcpy(ioc
.hostname
, cfg
->skc_hostname
, sizeof (ioc
.hostname
));
108 (void) strlcpy(ioc
.system_comment
, cfg
->skc_system_comment
,
109 sizeof (ioc
.system_comment
));
111 return (smb_kmod_ioctl(SMB_IOC_CONFIG
, &ioc
.hdr
, sizeof (ioc
)));
115 smb_kmod_setgmtoff(int32_t gmtoff
)
120 return (smb_kmod_ioctl(SMB_IOC_GMTOFF
, &ioc
.hdr
,
125 smb_kmod_start(int opipe
, int lmshr
, int udoor
)
132 return (smb_kmod_ioctl(SMB_IOC_START
, &ioc
.hdr
, sizeof (ioc
)));
138 smb_ioc_header_t ioc
;
140 (void) smb_kmod_ioctl(SMB_IOC_STOP
, &ioc
, sizeof (ioc
));
144 smb_kmod_event_notify(uint32_t txid
)
149 return (smb_kmod_ioctl(SMB_IOC_EVENT
, &ioc
.hdr
, sizeof (ioc
)));
153 smb_kmod_share(nvlist_t
*shrlist
)
155 smb_ioc_share_t
*ioc
;
161 if ((rc
= nvlist_pack(shrlist
, &shrbuf
, &bufsz
, NV_ENCODE_XDR
, 0)) != 0)
164 ioclen
= sizeof (smb_ioc_share_t
) + bufsz
;
166 if ((ioc
= malloc(ioclen
)) != NULL
) {
168 bcopy(shrbuf
, ioc
->shr
, bufsz
);
169 rc
= smb_kmod_ioctl(SMB_IOC_SHARE
, &ioc
->hdr
, ioclen
);
178 smb_kmod_unshare(nvlist_t
*shrlist
)
180 smb_ioc_share_t
*ioc
;
186 if ((rc
= nvlist_pack(shrlist
, &shrbuf
, &bufsz
, NV_ENCODE_XDR
, 0)) != 0)
189 ioclen
= sizeof (smb_ioc_share_t
) + bufsz
;
191 if ((ioc
= malloc(ioclen
)) != NULL
) {
193 bcopy(shrbuf
, ioc
->shr
, bufsz
);
194 rc
= smb_kmod_ioctl(SMB_IOC_UNSHARE
, &ioc
->hdr
, ioclen
);
203 smb_kmod_shareinfo(char *shrname
, boolean_t
*shortnames
)
205 smb_ioc_shareinfo_t ioc
;
208 bzero(&ioc
, sizeof (ioc
));
209 (void) strlcpy(ioc
.shrname
, shrname
, MAXNAMELEN
);
211 rc
= smb_kmod_ioctl(SMB_IOC_SHAREINFO
, &ioc
.hdr
, sizeof (ioc
));
213 *shortnames
= ioc
.shortnames
;
215 *shortnames
= B_TRUE
;
221 smb_kmod_get_open_num(smb_opennum_t
*opennum
)
223 smb_ioc_opennum_t ioc
;
226 bzero(&ioc
, sizeof (ioc
));
227 ioc
.qualtype
= opennum
->qualtype
;
228 (void) strlcpy(ioc
.qualifier
, opennum
->qualifier
, MAXNAMELEN
);
230 rc
= smb_kmod_ioctl(SMB_IOC_NUMOPEN
, &ioc
.hdr
, sizeof (ioc
));
232 opennum
->open_users
= ioc
.open_users
;
233 opennum
->open_trees
= ioc
.open_trees
;
234 opennum
->open_files
= ioc
.open_files
;
241 smb_kmod_get_spool_doc(uint32_t *spool_num
, char *username
,
242 char *path
, smb_inaddr_t
*ipaddr
)
244 smb_ioc_spooldoc_t ioc
;
247 bzero(&ioc
, sizeof (ioc
));
248 rc
= smb_kmod_ioctl(SMB_IOC_SPOOLDOC
, &ioc
.hdr
, sizeof (ioc
));
250 *spool_num
= ioc
.spool_num
;
251 (void) strlcpy(username
, ioc
.username
, MAXNAMELEN
);
252 (void) strlcpy(path
, ioc
.path
, MAXPATHLEN
);
253 *ipaddr
= ioc
.ipaddr
;
259 * Initialization for an smb_kmod_enum request. If this call succeeds,
260 * smb_kmod_enum_fini() must be called later to deallocate resources.
263 smb_kmod_enum_init(smb_svcenum_t
*request
)
266 smb_svcenum_t
*svcenum
;
267 smb_ioc_svcenum_t
*ioc
;
270 if ((ns
= calloc(1, sizeof (smb_netsvc_t
))) == NULL
)
273 ioclen
= sizeof (smb_ioc_svcenum_t
) + SMB_IOC_DATA_SIZE
;
274 if ((ioc
= malloc(ioclen
)) == NULL
) {
280 svcenum
= &ioc
->svcenum
;
281 svcenum
->se_type
= request
->se_type
;
282 svcenum
->se_level
= request
->se_level
;
283 svcenum
->se_bavail
= SMB_IOC_DATA_SIZE
;
284 svcenum
->se_nlimit
= request
->se_nlimit
;
285 svcenum
->se_nskip
= request
->se_nskip
;
286 svcenum
->se_buflen
= SMB_IOC_DATA_SIZE
;
288 list_create(&ns
->ns_list
, sizeof (smb_netsvcitem_t
),
289 offsetof(smb_netsvcitem_t
, nsi_lnd
));
292 ns
->ns_ioclen
= ioclen
;
297 * Cleanup resources allocated via smb_kmod_enum_init and smb_kmod_enum.
300 smb_kmod_enum_fini(smb_netsvc_t
*ns
)
303 smb_netsvcitem_t
*item
;
304 smb_netuserinfo_t
*user
;
305 smb_netconnectinfo_t
*tree
;
306 smb_netfileinfo_t
*ofile
;
313 se_type
= ns
->ns_ioc
->svcenum
.se_type
;
315 while ((item
= list_head(lst
)) != NULL
) {
316 list_remove(lst
, item
);
319 case SMB_SVCENUM_TYPE_USER
:
320 user
= &item
->nsi_un
.nsi_user
;
321 free(user
->ui_domain
);
322 free(user
->ui_account
);
323 free(user
->ui_workstation
);
325 case SMB_SVCENUM_TYPE_TREE
:
326 tree
= &item
->nsi_un
.nsi_tree
;
327 free(tree
->ci_username
);
328 free(tree
->ci_share
);
330 case SMB_SVCENUM_TYPE_FILE
:
331 ofile
= &item
->nsi_un
.nsi_ofile
;
332 free(ofile
->fi_path
);
333 free(ofile
->fi_username
);
340 list_destroy(&ns
->ns_list
);
347 * Enumerate users, connections or files.
350 smb_kmod_enum(smb_netsvc_t
*ns
)
352 smb_ioc_svcenum_t
*ioc
;
354 smb_svcenum_t
*svcenum
;
355 smb_netsvcitem_t
*items
;
356 smb_netuserinfo_t
*user
;
357 smb_netconnectinfo_t
*tree
;
358 smb_netfileinfo_t
*ofile
;
367 ioclen
= ns
->ns_ioclen
;
368 rc
= smb_kmod_ioctl(SMB_IOC_SVCENUM
, &ioc
->hdr
, ioclen
);
372 svcenum
= &ioc
->svcenum
;
373 items
= calloc(svcenum
->se_nitems
, sizeof (smb_netsvcitem_t
));
377 ns
->ns_items
= items
;
378 se_type
= ns
->ns_ioc
->svcenum
.se_type
;
379 data
= svcenum
->se_buf
;
380 len
= svcenum
->se_bused
;
382 for (i
= 0; i
< svcenum
->se_nitems
; ++i
) {
384 case SMB_SVCENUM_TYPE_USER
:
385 user
= &items
->nsi_un
.nsi_user
;
386 rc
= smb_netuserinfo_decode(user
, data
, len
, &nbytes
);
388 case SMB_SVCENUM_TYPE_TREE
:
389 tree
= &items
->nsi_un
.nsi_tree
;
390 rc
= smb_netconnectinfo_decode(tree
, data
, len
,
393 case SMB_SVCENUM_TYPE_FILE
:
394 ofile
= &items
->nsi_un
.nsi_ofile
;
395 rc
= smb_netfileinfo_decode(ofile
, data
, len
, &nbytes
);
405 list_insert_tail(&ns
->ns_list
, items
);
416 * A NULL pointer is a wildcard indicator, which we pass on
417 * as an empty string (by virtue of the bzero).
420 smb_kmod_session_close(const char *client
, const char *username
)
422 smb_ioc_session_t ioc
;
425 bzero(&ioc
, sizeof (ioc
));
428 (void) strlcpy(ioc
.client
, client
, MAXNAMELEN
);
429 if (username
!= NULL
)
430 (void) strlcpy(ioc
.username
, username
, MAXNAMELEN
);
432 rc
= smb_kmod_ioctl(SMB_IOC_SESSION_CLOSE
, &ioc
.hdr
, sizeof (ioc
));
437 smb_kmod_file_close(uint32_t uniqid
)
439 smb_ioc_fileid_t ioc
;
442 bzero(&ioc
, sizeof (ioc
));
445 rc
= smb_kmod_ioctl(SMB_IOC_FILE_CLOSE
, &ioc
.hdr
, sizeof (ioc
));
450 smb_kmod_unbind(void)
452 if (smbdrv_fd
!= -1) {
453 (void) close(smbdrv_fd
);
459 * Note: The user-space smbd-d provides it own version of this function
460 * which directly calls the "kernel" module code (in user space).
463 smb_kmod_ioctl(int cmd
, smb_ioc_header_t
*ioc
, uint32_t len
)
467 ioc
->version
= SMB_IOC_VERSION
;
471 ioc
->crc
= smb_crc_gen((uint8_t *)ioc
, sizeof (smb_ioc_header_t
));
473 if (smbdrv_fd
!= -1) {
474 if (ioctl(smbdrv_fd
, cmd
, ioc
) < 0)