summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorGordon Ross <gwr@nexenta.com>2013-06-17 10:34:00 -0400
committerGordon Ross <gwr@nexenta.com>2015-06-04 16:46:25 -0400
commitb819cea2f73f98c5662230cc9affc8cc84f77fcf (patch)
treea3677952ded5706400717b9b79b0aeaa3d93a739 /usr/src
parent83d2dfe69259e79314662cf95e6d1f9103dcffe2 (diff)
downloadillumos-gate-b819cea2f73f98c5662230cc9affc8cc84f77fcf.tar.gz
5917 User-mode SMB server
Authored by: Thomas Keiser <thomas.keiser@nexenta.com> Authored by: Albert Lee <trisk@nexenta.com> Reviewed by: Igor Kozhukhov <ikozhukhov@gmail.com> Reviewed by: Richard Lowe <richlowe@richlowe.net> Reviewed by: Albert Lee <trisk@omniti.com> Approved by: Dan McDonald <danmcd@omniti.com>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/Makefile.master7
-rw-r--r--usr/src/cmd/mdb/Makefile.common4
-rw-r--r--usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c79
-rw-r--r--usr/src/cmd/mdb/intel/amd64/libfksmbsrv/Makefile56
-rw-r--r--usr/src/cmd/mdb/intel/ia32/libfksmbsrv/Makefile55
-rw-r--r--usr/src/cmd/smbsrv/Makefile4
-rw-r--r--usr/src/cmd/smbsrv/bind-helper/Makefile45
-rw-r--r--usr/src/cmd/smbsrv/bind-helper/bind-helper.c92
-rw-r--r--usr/src/cmd/smbsrv/fksmbd/.dbxrc26
-rw-r--r--usr/src/cmd/smbsrv/fksmbd/Makefile112
-rw-r--r--usr/src/cmd/smbsrv/fksmbd/README69
-rwxr-xr-xusr/src/cmd/smbsrv/fksmbd/Run.sh45
-rw-r--r--usr/src/cmd/smbsrv/fksmbd/Watch-all.d111
-rw-r--r--usr/src/cmd/smbsrv/fksmbd/fksmbd_door.c158
-rw-r--r--usr/src/cmd/smbsrv/fksmbd/fksmbd_kmod.c151
-rw-r--r--usr/src/cmd/smbsrv/fksmbd/fksmbd_ksock.c108
-rw-r--r--usr/src/cmd/smbsrv/fksmbd/fksmbd_log.c93
-rw-r--r--usr/src/cmd/smbsrv/fksmbd/fksmbd_opipe.c156
-rw-r--r--usr/src/cmd/smbsrv/fksmbd/fksmbd_shr.c125
-rw-r--r--usr/src/cmd/smbsrv/smbadm/smbadm.c4
-rw-r--r--usr/src/cmd/smbsrv/smbd/Makefile35
-rw-r--r--usr/src/cmd/smbsrv/smbd/server.xml2
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd.h38
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c42
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_join.c10
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_logon.c2
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_main.c339
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_nicmon.c18
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c23
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_spool.c31
-rw-r--r--usr/src/cmd/smbsrv/smbd/smbd_syslog.c99
-rw-r--r--usr/src/common/acl/acl_common.c21
-rw-r--r--usr/src/common/smbsrv/smb_door_legacy.c6
-rw-r--r--usr/src/common/smbsrv/smb_inet.c36
-rw-r--r--usr/src/common/smbsrv/smb_match.c5
-rw-r--r--usr/src/common/smbsrv/smb_msgbuf.c8
-rw-r--r--usr/src/common/smbsrv/smb_native.c4
-rw-r--r--usr/src/common/smbsrv/smb_netbios_util.c5
-rw-r--r--usr/src/common/smbsrv/smb_oem.c7
-rw-r--r--usr/src/common/smbsrv/smb_sid.c62
-rw-r--r--usr/src/common/smbsrv/smb_string.c9
-rw-r--r--usr/src/common/smbsrv/smb_token.c6
-rw-r--r--usr/src/common/smbsrv/smb_token_xdr.c2
-rw-r--r--usr/src/common/smbsrv/smb_utf8.c6
-rw-r--r--usr/src/common/smbsrv/smb_xdr.c2
-rw-r--r--usr/src/lib/Makefile4
-rw-r--r--usr/src/lib/libfakekernel/Makefile63
-rw-r--r--usr/src/lib/libfakekernel/Makefile.com75
-rw-r--r--usr/src/lib/libfakekernel/amd64/Makefile32
-rw-r--r--usr/src/lib/libfakekernel/common/clock.c92
-rw-r--r--usr/src/lib/libfakekernel/common/cond.c180
-rw-r--r--usr/src/lib/libfakekernel/common/copy.c50
-rw-r--r--usr/src/lib/libfakekernel/common/cred.c59
-rw-r--r--usr/src/lib/libfakekernel/common/fakekernel.h35
-rw-r--r--usr/src/lib/libfakekernel/common/kiconv.c57
-rw-r--r--usr/src/lib/libfakekernel/common/kmem.c151
-rw-r--r--usr/src/lib/libfakekernel/common/kmisc.c81
-rw-r--r--usr/src/lib/libfakekernel/common/ksocket.c535
-rw-r--r--usr/src/lib/libfakekernel/common/kstat.c45
-rw-r--r--usr/src/lib/libfakekernel/common/llib-lfakekernel19
-rw-r--r--usr/src/lib/libfakekernel/common/mapfile-vers193
-rw-r--r--usr/src/lib/libfakekernel/common/mutex.c95
-rw-r--r--usr/src/lib/libfakekernel/common/printf.c154
-rw-r--r--usr/src/lib/libfakekernel/common/random.c28
-rw-r--r--usr/src/lib/libfakekernel/common/rwlock.c136
-rw-r--r--usr/src/lib/libfakekernel/common/sema.c107
-rw-r--r--usr/src/lib/libfakekernel/common/sys/condvar.h106
-rw-r--r--usr/src/lib/libfakekernel/common/sys/cred.h85
-rw-r--r--usr/src/lib/libfakekernel/common/sys/kiconv.h60
-rw-r--r--usr/src/lib/libfakekernel/common/sys/klwp.h80
-rw-r--r--usr/src/lib/libfakekernel/common/sys/ksynch.h48
-rw-r--r--usr/src/lib/libfakekernel/common/sys/mutex.h100
-rw-r--r--usr/src/lib/libfakekernel/common/sys/proc.h125
-rw-r--r--usr/src/lib/libfakekernel/common/sys/rwlock.h84
-rw-r--r--usr/src/lib/libfakekernel/common/sys/semaphore.h72
-rw-r--r--usr/src/lib/libfakekernel/common/sys/t_lock.h58
-rw-r--r--usr/src/lib/libfakekernel/common/sys/taskq_impl.h59
-rw-r--r--usr/src/lib/libfakekernel/common/sys/thread.h114
-rw-r--r--usr/src/lib/libfakekernel/common/sys/user.h41
-rw-r--r--usr/src/lib/libfakekernel/common/sys/zone.h101
-rw-r--r--usr/src/lib/libfakekernel/common/taskq.c380
-rw-r--r--usr/src/lib/libfakekernel/common/thread.c125
-rw-r--r--usr/src/lib/libfakekernel/common/uio.c64
-rw-r--r--usr/src/lib/libfakekernel/i386/Makefile31
-rw-r--r--usr/src/lib/libfakekernel/sparc/Makefile31
-rw-r--r--usr/src/lib/libfakekernel/sparcv9/Makefile32
-rw-r--r--usr/src/lib/libidmap/common/idmap.h18
-rw-r--r--usr/src/lib/libshare/common/libshare.h3
-rw-r--r--usr/src/lib/libshare/smb/smb_share_doorclnt.c9
-rw-r--r--usr/src/lib/smbsrv/Makefile4
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/Makefile28
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/Makefile.com210
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/amd64/Makefile33
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/fake_lookup.c560
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/fake_nblk.c173
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/fake_vfs.c244
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/fake_vnode.c80
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/fake_vop.c1349
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/fake_xattr.c271
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_cred.c55
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_fem.c63
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c404
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_init.c217
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_kdoor.c275
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_opipe_door.c131
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_sign_pkcs.c89
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/llib-lfksmbsrv19
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/mapfile-vers52
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/reparse.c84
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/sys/kidmap.h183
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/sys/sunddi.h122
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/sys/vfs_opreg.h116
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/sys/vnode.h1438
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/vncache.c322
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/common/vncache.h37
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/i386/Makefile30
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/sparc/Makefile30
-rw-r--r--usr/src/lib/smbsrv/libfksmbsrv/sparcv9/Makefile35
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/Makefile.com3
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c1
-rw-r--r--usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c1
-rw-r--r--usr/src/lib/smbsrv/libsmb/Makefile.com6
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/libsmb.h42
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/mapfile-vers28
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_cfg.c32
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c13
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_idmap.c38
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_info.c12
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_kmod.c9
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_nic.c2
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_sam.c35
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c14
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_syslog.c69
-rw-r--r--usr/src/lib/smbsrv/libsmb/common/smb_util.c218
-rw-r--r--usr/src/lib/smbsrv/libsmbns/Makefile.com2
-rw-r--r--usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c14
-rwxr-xr-xusr/src/tools/quick/make-smbsrv50
-rw-r--r--usr/src/uts/common/Makefile.files14
-rw-r--r--usr/src/uts/common/fs/fs_reparse.h4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_acl.c21
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_common_open.c6
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_common_transact.c4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_delete.c4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_dispatch.c9
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_fem.c133
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_fsops.c59
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_idmap.c411
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_init.c7
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_kdoor.c6
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_kshare.c14
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_kutil.c620
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_lock.c2
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_mangle_name.c15
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_negotiate.c4
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_net.c7
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_node.c10
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c3
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_opipe.c148
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_opipe_door.c188
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_oplock.c1
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_rename.c5
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_server.c28
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_session.c26
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c68
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_sign_kcf.c99
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_signing.c348
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_thread.c313
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_trans2_dfs.c5
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_trans2_find.c7
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_tree.c15
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_user.c14
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_vfs.c3
-rw-r--r--usr/src/uts/common/fs/smbsrv/smb_vops.c12
-rw-r--r--usr/src/uts/common/fs/sockfs/nl7c.c15
-rw-r--r--usr/src/uts/common/nfs/lm.h9
-rw-r--r--usr/src/uts/common/rpc/xdr.h11
-rw-r--r--usr/src/uts/common/smbsrv/alloc.h5
-rw-r--r--usr/src/uts/common/smbsrv/ndr.h8
-rw-r--r--usr/src/uts/common/smbsrv/smb.h3
-rw-r--r--usr/src/uts/common/smbsrv/smb_door.h11
-rw-r--r--usr/src/uts/common/smbsrv/smb_idmap.h4
-rw-r--r--usr/src/uts/common/smbsrv/smb_inet.h6
-rw-r--r--usr/src/uts/common/smbsrv/smb_ioctl.h10
-rw-r--r--usr/src/uts/common/smbsrv/smb_kproto.h40
-rw-r--r--usr/src/uts/common/smbsrv/smb_ktypes.h32
-rw-r--r--usr/src/uts/common/smbsrv/smb_share.h7
-rw-r--r--usr/src/uts/common/smbsrv/smb_signing.h50
-rw-r--r--usr/src/uts/common/smbsrv/smb_token.h20
-rw-r--r--usr/src/uts/common/smbsrv/smb_xdr.h16
-rw-r--r--usr/src/uts/common/sys/acl.h6
-rw-r--r--usr/src/uts/common/sys/class.h4
-rw-r--r--usr/src/uts/common/sys/cmn_err.h11
-rw-r--r--usr/src/uts/common/sys/disp.h9
-rw-r--r--usr/src/uts/common/sys/extdirent.h6
-rw-r--r--usr/src/uts/common/sys/fem.h4
-rw-r--r--usr/src/uts/common/sys/flock.h4
-rw-r--r--usr/src/uts/common/sys/kmem.h5
-rw-r--r--usr/src/uts/common/sys/kstat.h6
-rw-r--r--usr/src/uts/common/sys/mode.h4
-rw-r--r--usr/src/uts/common/sys/random.h4
-rw-r--r--usr/src/uts/common/sys/refstr.h6
-rw-r--r--usr/src/uts/common/sys/select.h10
-rw-r--r--usr/src/uts/common/sys/sid.h8
-rw-r--r--usr/src/uts/common/sys/socket.h4
-rw-r--r--usr/src/uts/common/sys/stream.h3
-rw-r--r--usr/src/uts/common/sys/sunddi.h5
-rw-r--r--usr/src/uts/common/sys/sysmacros.h6
-rw-r--r--usr/src/uts/common/sys/systm.h20
-rw-r--r--usr/src/uts/common/sys/taskq.h4
-rw-r--r--usr/src/uts/common/sys/time.h13
-rw-r--r--usr/src/uts/common/sys/types.h4
-rw-r--r--usr/src/uts/common/sys/uio.h4
-rw-r--r--usr/src/uts/common/sys/vfs.h3
213 files changed, 14578 insertions, 2033 deletions
diff --git a/usr/src/Makefile.master b/usr/src/Makefile.master
index 2330d3194a..892d8b3f1f 100644
--- a/usr/src/Makefile.master
+++ b/usr/src/Makefile.master
@@ -403,7 +403,7 @@ C99MODE= $(C99_DISABLE)
C99LMODE= $(C99MODE:-xc99%=-Xc99%)
# In most places, assignments to these macros should be appended with +=
-# (CPPFLAGS.master allows values to be prepended to CPPFLAGS).
+# (CPPFLAGS.first allows values to be prepended to CPPFLAGS).
sparc_CFLAGS= $(sparc_XARCH) $(CCSTATICSYM)
sparcv9_CFLAGS= $(sparcv9_XARCH) -dalign $(CCVERBOSE) $(V9ABIWARN) $(CCREGSYM) \
$(CCSTATICSYM)
@@ -551,13 +551,14 @@ NATIVE_CFLAGS= $(COPTFLAG) $($(NATIVE_MACH)_CFLAGS) $(CCMODE) \
DTEXTDOM=-DTEXT_DOMAIN=\"$(TEXT_DOMAIN)\" # For messaging.
DTS_ERRNO=-D_TS_ERRNO
+CPPFLAGS.first= # Please keep empty. Only lower makefiles should set this.
CPPFLAGS.master=$(DTEXTDOM) $(DTS_ERRNO) \
$(ENVCPPFLAGS1) $(ENVCPPFLAGS2) $(ENVCPPFLAGS3) $(ENVCPPFLAGS4) \
$(ADJUNCT_PROTO:%=-I%/usr/include)
CPPFLAGS.native=$(ENVCPPFLAGS1) $(ENVCPPFLAGS2) $(ENVCPPFLAGS3) \
$(ENVCPPFLAGS4) -I$(NATIVE_ADJUNCT)/include
-CPPFLAGS= $(CPPFLAGS.master)
-AS_CPPFLAGS= $(CPPFLAGS.master)
+CPPFLAGS= $(CPPFLAGS.first) $(CPPFLAGS.master)
+AS_CPPFLAGS= $(CPPFLAGS.first) $(CPPFLAGS.master)
JAVAFLAGS= -source 1.6 -target 1.6 -Xlint:deprecation,-options
#
diff --git a/usr/src/cmd/mdb/Makefile.common b/usr/src/cmd/mdb/Makefile.common
index 4e282bf001..aca0144fdf 100644
--- a/usr/src/cmd/mdb/Makefile.common
+++ b/usr/src/cmd/mdb/Makefile.common
@@ -19,16 +19,18 @@
# CDDL HEADER END
#
# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
#
# MDB modules used for debugging user processes that every ISA's build
# subdirectory will need to build.
#
-
+
COMMON_MODULES_PROC = \
dof \
libavl \
libc \
libcmdutils \
+ libfksmbsrv \
libnvpair \
libproc \
libpython2.6 \
diff --git a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c
index aafa931091..d184f2a3e8 100644
--- a/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c
+++ b/usr/src/cmd/mdb/common/modules/smbsrv/smbsrv.c
@@ -21,17 +21,23 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <mdb/mdb_modapi.h>
#include <mdb/mdb_ks.h>
#include <sys/thread.h>
-#include <sys/taskq_impl.h>
+#include <sys/taskq.h>
#include <smbsrv/smb_vops.h>
#include <smbsrv/smb.h>
#include <smbsrv/smb_ktypes.h>
+#ifdef _KERNEL
+#define SMBSRV_OBJNAME "smbsrv"
+#else
+#define SMBSRV_OBJNAME "libfksmbsrv.so.1"
+#endif
+
#define SMB_DCMD_INDENT 2
#define ACE_TYPE_TABLEN (ACE_ALL_TYPES + 1)
#define ACE_TYPE_ENTRY(_v_) {_v_, #_v_}
@@ -558,15 +564,17 @@ smb_dcmd_list(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
new_argc = smb_dcmd_setopt(opts, SMB_MDB_MAX_OPTS, new_argv);
- if (mdb_lookup_by_name("smb_servers", &sym) == -1) {
+ if (mdb_lookup_by_obj(SMBSRV_OBJNAME, "smb_servers", &sym) == -1) {
mdb_warn("failed to find symbol smb_servers");
return (DCMD_ERR);
}
- addr = (uintptr_t)sym.st_value + offsetof(smb_llist_t, ll_list);
+ addr = (uintptr_t)sym.st_value + OFFSETOF(smb_llist_t, ll_list);
- if (mdb_pwalk_dcmd("list", "smbsrv", new_argc, new_argv, addr))
+ if (mdb_pwalk_dcmd("list", "smbsrv", new_argc, new_argv, addr)) {
+ mdb_warn("cannot walk smb_server list");
return (DCMD_ERR);
+ }
return (DCMD_OK);
}
@@ -591,10 +599,10 @@ static const char *smb_server_state[SMB_SERVER_STATE_SENTINEL] =
static const smb_exp_t smb_server_exp[] =
{
{ SMB_OPT_ALL_OBJ,
- offsetof(smb_server_t, sv_nbt_daemon.ld_session_list.ll_list),
+ OFFSETOF(smb_server_t, sv_nbt_daemon.ld_session_list.ll_list),
"smbsess", "smb_session"},
{ SMB_OPT_ALL_OBJ,
- offsetof(smb_server_t, sv_tcp_daemon.ld_session_list.ll_list),
+ OFFSETOF(smb_server_t, sv_tcp_daemon.ld_session_list.ll_list),
"smbsess", "smb_session"},
{ 0, 0, NULL, NULL }
};
@@ -684,13 +692,13 @@ static const char *smb_session_state[SMB_SESSION_STATE_SENTINEL] =
static const smb_exp_t smb_session_exp[] =
{
{ SMB_OPT_REQUEST,
- offsetof(smb_session_t, s_req_list.sl_list),
+ OFFSETOF(smb_session_t, s_req_list.sl_list),
"smbreq", "smb_request"},
{ SMB_OPT_USER,
- offsetof(smb_session_t, s_user_list.ll_list),
+ OFFSETOF(smb_session_t, s_user_list.ll_list),
"smbuser", "smb_user"},
{ SMB_OPT_TREE | SMB_OPT_OFILE | SMB_OPT_ODIR,
- offsetof(smb_session_t, s_tree_list.ll_list),
+ OFFSETOF(smb_session_t, s_tree_list.ll_list),
"smbtree", "smb_tree"},
{ 0, 0, NULL, NULL}
};
@@ -879,6 +887,10 @@ smb_dcmd_request(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
}
waiting = 0;
running = 0;
+ /*
+ * Note: mdb_gethrtime() is only available in kmdb
+ */
+#ifdef _KERNEL
if (sr->sr_time_submitted != 0) {
if (sr->sr_time_active != 0) {
waiting = sr->sr_time_active -
@@ -892,6 +904,7 @@ smb_dcmd_request(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
}
waiting /= NANOSEC;
running /= NANOSEC;
+#endif /* _KERNEL */
if (sr->sr_state >= SMB_REQ_STATE_SENTINEL)
state = "INVALID";
@@ -1064,10 +1077,10 @@ static const char *smb_tree_state[SMB_TREE_STATE_SENTINEL] =
static const smb_exp_t smb_tree_exp[] =
{
{ SMB_OPT_OFILE,
- offsetof(smb_tree_t, t_ofile_list.ll_list),
+ OFFSETOF(smb_tree_t, t_ofile_list.ll_list),
"smbofile", "smb_ofile"},
{ SMB_OPT_ODIR,
- offsetof(smb_tree_t, t_odir_list.ll_list),
+ OFFSETOF(smb_tree_t, t_odir_list.ll_list),
"smbodir", "smb_odir"},
{ 0, 0, NULL, NULL}
};
@@ -1372,7 +1385,7 @@ smb_dcmd_kshare(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
"smb_kshare_t", "name", "path");
}
- if (mdb_pwalk("genunix`avl", smb_kshare_cb, &opts, addr) == -1) {
+ if (mdb_pwalk("avl", smb_kshare_cb, &opts, addr) == -1) {
mdb_warn("cannot walk smb_kshare avl");
return (DCMD_ERR);
}
@@ -1594,8 +1607,8 @@ smb_dcmd_node(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
if (node.n_lock_list.ll_count != 0) {
(void) mdb_inc_indent(SMB_DCMD_INDENT);
list_addr = addr +
- offsetof(smb_node_t, n_lock_list) +
- offsetof(smb_llist_t, ll_list);
+ OFFSETOF(smb_node_t, n_lock_list) +
+ OFFSETOF(smb_llist_t, ll_list);
if (mdb_pwalk_dcmd("list", "smblock", 0,
NULL, list_addr)) {
mdb_warn("failed to walk node's active"
@@ -1607,7 +1620,7 @@ smb_dcmd_node(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
mdb_printf("Opportunistic Locks: 0\n");
} else {
oplock_addr =
- addr + offsetof(smb_node_t, n_oplock);
+ addr + OFFSETOF(smb_node_t, n_oplock);
mdb_printf("Opportunistic Lock: %p\n",
oplock_addr);
rc = mdb_call_dcmd("smboplock", oplock_addr,
@@ -1714,7 +1727,8 @@ smb_node_walk_init(mdb_walk_state_t *wsp)
uintptr_t node_hash_table_addr;
if (wsp->walk_addr == NULL) {
- if (mdb_lookup_by_name("smb_node_hash_table", &sym) == -1) {
+ if (mdb_lookup_by_obj(SMBSRV_OBJNAME, "smb_node_hash_table",
+ &sym) == -1) {
mdb_warn("failed to find 'smb_node_hash_table'");
return (WALK_ERR);
}
@@ -1726,7 +1740,7 @@ smb_node_walk_init(mdb_walk_state_t *wsp)
for (i = 0; i < SMBND_HASH_MASK + 1; i++) {
wsp->walk_addr = node_hash_table_addr +
- (i * sizeof (smb_llist_t)) + offsetof(smb_llist_t, ll_list);
+ (i * sizeof (smb_llist_t)) + OFFSETOF(smb_llist_t, ll_list);
if (mdb_layered_walk("list", wsp) == -1) {
mdb_warn("failed to walk 'list'");
return (WALK_ERR);
@@ -1813,8 +1827,8 @@ smb_lock(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
if (lock.l_conflict_list.sl_count != 0) {
(void) mdb_inc_indent(SMB_DCMD_INDENT);
list_addr = addr +
- offsetof(smb_lock_t, l_conflict_list) +
- offsetof(smb_slist_t, sl_list);
+ OFFSETOF(smb_lock_t, l_conflict_list) +
+ OFFSETOF(smb_slist_t, sl_list);
if (mdb_pwalk_dcmd("list", "smb_lock",
0, NULL, list_addr)) {
mdb_warn("failed to walk conflict "
@@ -1921,7 +1935,7 @@ smb_oplock(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
break;
}
- list_addr = addr + offsetof(smb_oplock_t, ol_grants);
+ list_addr = addr + OFFSETOF(smb_oplock_t, ol_grants);
if (mdb_pwalk_dcmd("list", "smboplockgrant",
argc, argv, list_addr)) {
@@ -2084,7 +2098,7 @@ smb_ace_walk_init(mdb_walk_state_t *wsp)
return (WALK_ERR);
}
- wsp->walk_addr += offsetof(smb_acl_t, sl_sorted);
+ wsp->walk_addr += OFFSETOF(smb_acl_t, sl_sorted);
if (mdb_layered_walk("list", wsp) == -1) {
mdb_warn("failed to walk list of ACEs");
@@ -2259,7 +2273,7 @@ smb_sid_print(uintptr_t addr)
int i;
uint64_t authority;
- sid_size = offsetof(smb_sid_t, sid_subauth);
+ sid_size = OFFSETOF(smb_sid_t, sid_subauth);
if (mdb_vread(&sid, sid_size, addr) != sid_size) {
mdb_warn("failed to read struct smb_sid at %p", addr);
@@ -2465,29 +2479,10 @@ smb_obj_list(const char *name, uint_t opts, uint_t flags)
static int
smb_worker_findstack(uintptr_t addr)
{
- kthread_t t;
- taskq_t tq;
char cmd[80];
mdb_arg_t cmdarg;
- if (mdb_vread(&t, sizeof (kthread_t), addr) == -1) {
- mdb_warn("failed to read kthread_t at %p", addr);
- return (DCMD_ERR);
- }
-
- if (mdb_vread(&tq, sizeof (taskq_t), (uintptr_t)t.t_taskq) == -1)
- tq.tq_name[0] = '\0';
-
mdb_inc_indent(2);
-
- mdb_printf("PC: %a", t.t_pc);
- if (t.t_tid == 0) {
- if (tq.tq_name[0] != '\0')
- mdb_printf(" TASKQ: %s\n", tq.tq_name);
- else
- mdb_printf(" THREAD: %a()\n", t.t_startpc);
- }
-
mdb_snprintf(cmd, sizeof (cmd), "<.$c%d", 16);
cmdarg.a_type = MDB_TYPE_STRING;
cmdarg.a_un.a_str = cmd;
diff --git a/usr/src/cmd/mdb/intel/amd64/libfksmbsrv/Makefile b/usr/src/cmd/mdb/intel/amd64/libfksmbsrv/Makefile
new file mode 100644
index 0000000000..d9bcbaf453
--- /dev/null
+++ b/usr/src/cmd/mdb/intel/amd64/libfksmbsrv/Makefile
@@ -0,0 +1,56 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
+
+MODULE = libfksmbsrv.so
+MDBTGT = proc
+
+MODSRCS = smbsrv.c list.c
+
+include ../../../../Makefile.cmd
+include ../../../../Makefile.cmd.64
+include ../../Makefile.amd64
+include ../../../Makefile.module
+
+MODSRCS_DIR = ../../../common/modules/smbsrv
+GENUNIX_DIR = ../../../common/modules/genunix
+
+# Note: need our sys includes _before_ ENVCPPFLAGS, proto etc.
+CPPFLAGS.first += -I../../../../../lib/smbsrv/libfksmbsrv/common
+CPPFLAGS.first += -I../../../../../lib/libfakekernel/common
+
+CPPFLAGS += -I../../../../../uts/common
+
+C99MODE= -xc99=%all
+C99LMODE= -Xc99=%all
+
+dmod/%.o: $(GENUNIX_DIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
+dmod/%.ln: $(GENUNIX_DIR)/%.c
+ $(LINT.c) -c $<
diff --git a/usr/src/cmd/mdb/intel/ia32/libfksmbsrv/Makefile b/usr/src/cmd/mdb/intel/ia32/libfksmbsrv/Makefile
new file mode 100644
index 0000000000..eb63922371
--- /dev/null
+++ b/usr/src/cmd/mdb/intel/ia32/libfksmbsrv/Makefile
@@ -0,0 +1,55 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
+
+MODULE = libfksmbsrv.so
+MDBTGT = proc
+
+MODSRCS = smbsrv.c list.c
+
+include ../../../../Makefile.cmd
+include ../../Makefile.ia32
+include ../../../Makefile.module
+
+MODSRCS_DIR = ../../../common/modules/smbsrv
+GENUNIX_DIR = ../../../common/modules/genunix
+
+# Note: need our sys includes _before_ ENVCPPFLAGS, proto etc.
+CPPFLAGS.first += -I../../../../../lib/smbsrv/libfksmbsrv/common
+CPPFLAGS.first += -I../../../../../lib/libfakekernel/common
+
+CPPFLAGS += -I../../../../../uts/common
+
+C99MODE= -xc99=%all
+C99LMODE= -Xc99=%all
+
+dmod/%.o: $(GENUNIX_DIR)/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
+dmod/%.ln: $(GENUNIX_DIR)/%.c
+ $(LINT.c) -c $<
diff --git a/usr/src/cmd/smbsrv/Makefile b/usr/src/cmd/smbsrv/Makefile
index 86716aa460..641026e8e9 100644
--- a/usr/src/cmd/smbsrv/Makefile
+++ b/usr/src/cmd/smbsrv/Makefile
@@ -22,10 +22,10 @@
# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
-#ident "%Z%%M% %I% %E% SMI"
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
#
-SUBDIRS = smbadm smbd smbstat dtrace
+SUBDIRS = smbadm smbd smbstat dtrace fksmbd bind-helper
MSGSUBDIRS = smbadm smbstat
include ../Makefile.cmd
diff --git a/usr/src/cmd/smbsrv/bind-helper/Makefile b/usr/src/cmd/smbsrv/bind-helper/Makefile
new file mode 100644
index 0000000000..1dfb40e5ba
--- /dev/null
+++ b/usr/src/cmd/smbsrv/bind-helper/Makefile
@@ -0,0 +1,45 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
+
+PROG= bind-helper
+SRCS= bind-helper.c
+
+include ../../Makefile.cmd
+include ../Makefile.smbsrv.defs
+
+LDLIBS += -lsocket -lnsl
+
+ROOTLIBSMBSRVDIR = $(ROOTLIB)/smbsrv
+ROOTLIBSMBSRVPROG = $(PROG:%=$(ROOTLIBSMBSRVDIR)/%)
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+clean:
+ $(RM) $(OBJS)
+
+lint: lint_SRCS
+
+$(PROG): $(OBJS)
+ $(LINK.c) -o $@ $(OBJS) $(LDLIBS)
+ $(POST_PROCESS)
+
+include ../../Makefile.targ
+
+$(ROOTLIBSMBSRVDIR)/%: %
+ $(INS.file)
+
+install: all .WAIT $(ROOTLIBSMBSRVPROG)
diff --git a/usr/src/cmd/smbsrv/bind-helper/bind-helper.c b/usr/src/cmd/smbsrv/bind-helper/bind-helper.c
new file mode 100644
index 0000000000..12ceebc1a8
--- /dev/null
+++ b/usr/src/cmd/smbsrv/bind-helper/bind-helper.c
@@ -0,0 +1,92 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * This program is installed with an RBAC exec_attr
+ * that allows it to bind a reserved address.
+ * (Or just make it setuid root.)
+ *
+ * To grant privileges to the program using RBAC,
+ * add the following line to /etc/security/exec_attr
+ * Forced Privilege:solaris:cmd:::\
+ * /usr/lib/smbsrv/bind-helper:\
+ * privs=net_privaddr,sys_smb\
+ *
+ * Args: family address port
+ * Does a bind on fileno(stdin)
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+int
+main(int argc, char **argv)
+{
+ struct sockaddr sa;
+ /* LINTED E_BAD_PTR_CAST_ALIGN */
+ struct sockaddr_in *sin = (struct sockaddr_in *)&sa;
+ /* LINTED E_BAD_PTR_CAST_ALIGN */
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&sa;
+ int rc, err = 0;
+
+ if (argc < 4) {
+ (void) fprintf(stderr, "usage: %s family address port\n",
+ argv[0]);
+ exit(1);
+ }
+
+ (void) memset(&sa, 0, sizeof (sa));
+ sa.sa_family = atoi(argv[1]);
+ switch (sa.sa_family) {
+ case AF_INET:
+ rc = inet_pton(AF_INET, argv[2], &sin->sin_addr);
+ sin->sin_port = htons(atoi(argv[3]));
+ break;
+ case AF_INET6:
+ rc = inet_pton(AF_INET6, argv[2], &sin6->sin6_addr);
+ sin6->sin6_port = htons(atoi(argv[3]));
+ break;
+ default:
+ rc = 0;
+ break;
+ }
+
+ if (rc > 0)
+ err = 0;
+ else if (rc == 0)
+ err = EINVAL;
+ else if (rc < 0)
+ err = errno;
+ if (err != 0) {
+ (void) fprintf(stderr, "%s: bad proto addr %s %s %s\n",
+ argv[0], argv[1], argv[2], argv[3]);
+ exit(1);
+ }
+
+ if (bind(0, &sa, sizeof (sa)) < 0) {
+ err = errno;
+ (void) fprintf(stderr, "%s: bind: %s\n",
+ argv[0], strerror(err));
+ exit(2);
+ }
+ exit(0);
+}
diff --git a/usr/src/cmd/smbsrv/fksmbd/.dbxrc b/usr/src/cmd/smbsrv/fksmbd/.dbxrc
new file mode 100644
index 0000000000..a29b6b78da
--- /dev/null
+++ b/usr/src/cmd/smbsrv/fksmbd/.dbxrc
@@ -0,0 +1,26 @@
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
+
+# set -o emacs
+
+setenv SMBD_DOOR_NAME /tmp/fksmbd_door
+setenv SMB_SHARE_DNAME /tmp/fksmbshare_door
+
+# fksmbd is always 32-bit
+setenv LD_LIBRARY_PATH ${ROOT}/usr/lib/smbsrv:${ROOT}/usr/lib:${ROOT}/lib
+
+echo 'Do one of: attach ${PID}'
+echo 'or: debug ${ROOT}/usr/lib/smbsrv/fksmbd'
diff --git a/usr/src/cmd/smbsrv/fksmbd/Makefile b/usr/src/cmd/smbsrv/fksmbd/Makefile
new file mode 100644
index 0000000000..cb72f8239e
--- /dev/null
+++ b/usr/src/cmd/smbsrv/fksmbd/Makefile
@@ -0,0 +1,112 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+#
+
+
+PROG= fksmbd
+OBJS_SMBD= \
+ smbd_doorsvc.o \
+ smbd_join.o \
+ smbd_logon.o \
+ smbd_main.o \
+ smbd_nicmon.o \
+ smbd_opipe_doorsvc.o \
+ smbd_share_doorsvc.o \
+ smbd_spool.o \
+ smbd_vss.o \
+
+
+OBJS_LOCAL = \
+ fksmbd_door.o \
+ fksmbd_kmod.o \
+ fksmbd_ksock.o \
+ fksmbd_opipe.o \
+ fksmbd_log.o \
+ fksmbd_shr.o
+
+OBJS= ${OBJS_SMBD} ${OBJS_LOCAL}
+SRCS= ${OBJS_SMBD:%.o=../smbd/%.c} \
+ ${OBJS_LOCAL:.o=.c}
+
+include ../../Makefile.cmd
+include ../../Makefile.ctf
+
+# Note: need our sys includes _before_ ENVCPPFLAGS, proto etc.
+CPPFLAGS.first += -I../../../lib/smbsrv/libfksmbsrv/common
+
+INCS += -I../smbd
+INCS += -I../../../uts/common
+INCS += -I../../../uts/common/smbsrv
+INCS += -I../../../common/smbsrv
+
+C99MODE= -xc99=%all
+C99LMODE= -Xc99=%all
+
+CFLAGS += $(CCVERBOSE)
+CFLAGS64 += $(CCVERBOSE)
+CPPFLAGS += -D_REENTRANT
+CPPFLAGS += -Dsyslog=smb_syslog
+CPPFLAGS += -D_LARGEFILE64_SOURCE=1
+CPPFLAGS += -DFKSMBD
+# Always debug here
+CPPFLAGS += -DDEBUG
+CPPFLAGS += $(INCS)
+
+LDFLAGS += $(ZNOLAZYLOAD)
+LDFLAGS += -R/usr/lib/smbsrv
+LDLIBS += -L$(ROOT)/usr/lib/smbsrv
+LDLIBS += -lfksmbsrv -lfakekernel
+LDLIBS += -lmlsvc -lmlrpc -lsmbns -lsmb
+LDLIBS += -lzfs -lcmdutils -lbsm -lsocket -lnsl -lscf -lumem
+
+LINTFLAGS += -xerroff=E_NAME_DEF_NOT_USED2
+LINTFLAGS += -xerroff=E_INCONS_ARG_DECL2
+LINTFLAGS += -xerroff=E_INCONS_VAL_TYPE_DECL2
+
+ROOTSMBDDIR = $(ROOTLIB)/smbsrv
+ROOTSMBDFILE = $(PROG:%=$(ROOTSMBDDIR)/%)
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(LINK.c) -o $(PROG) $(OBJS) $(LDLIBS)
+ $(POST_PROCESS)
+
+clean:
+ -$(RM) $(OBJS)
+
+lint: lint_SRCS
+
+include ../../Makefile.targ
+
+install: all $(ROOTSMBDFILE)
+
+%.o: ../smbd/%.c
+ $(COMPILE.c) $<
+ $(POST_PROCESS_O)
+
+$(ROOTSMBDDIR)/%: %
+ $(INS.file)
diff --git a/usr/src/cmd/smbsrv/fksmbd/README b/usr/src/cmd/smbsrv/fksmbd/README
new file mode 100644
index 0000000000..63779932d2
--- /dev/null
+++ b/usr/src/cmd/smbsrv/fksmbd/README
@@ -0,0 +1,69 @@
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
+
+This directory builds a program linking all of the SMB server code
+into a user-level process. The result is not a fully functional
+SMB server but is very useful for some kinds of development work.
+
+The architecture of this roughly parallels the in-kernel version,
+where the fksmbd program corresponds to the real smbd, the library
+libfksmbsrv corresponds to the smbsrv kernel module, and all the
+required kernel interfaces are simulated in libfakekernel.
+
+Just as with the kernel code, there are mdb modules that know
+how to walk data structures in libfksmbsrv, etc.
+
+For debugging, etc. it's easiest to run this as a normal user,
+i.e. yourself (not root); but before you can do that, there are
+some prerequisites to take care of:
+
+ a: Install ../bind-helper in /usr/lib/smbsrv/.
+ It needs to be either setuid root (easiest) or added to
+ the exec_attr as described in the top of bind-helper.c
+ (This must be in /usr/lib/smbsrv, not the proto area.)
+
+ b: Setup an SMB account for guest, i.e.
+ Add pam_smb_passwd.so.1 to pam.conf if not already there
+ (other password required pam_smb_passwd.so.1 nowarn)
+ % useradd guest
+ % smbadm enable-user guest
+ % passwd guest (sets the SMB p/w hash too)
+ Make sure guest shows in /var/smb/smbpasswd
+
+ c: chown/chmod the directories: /var/smb /var/run/smb
+ to yourself, mode 755. Reboot will chown these
+ back to root, so repeat this after a reboot.
+
+Now you can run fksmbd from the proto area using this script:
+ ./Run.sh -df
+
+You can also run it under dbx (see the .dbxrc file).
+To run it under mdb (with mdb modules build here):
+ mdb -L $ROOT/usr/lib/mdb/proc:/usr/lib/mdb/proc ...
+where ... is one of: fksmbd, core.nnn, -p $PID
+
+There are also a couple dtrace scripts in here for watching
+either all activity or only selected areas. (see *.d)
+Run these like: dtrace -s Watch-all.d -p $PID -o output
+
+
+Here are a couple simple, handy tests you can try:
+
+smbclient -L localhost -U guest%guest
+
+smbclient //localhost/test -U guest%guest -c dir
+
+smbtorture //localhost/test -U guest%guest base
diff --git a/usr/src/cmd/smbsrv/fksmbd/Run.sh b/usr/src/cmd/smbsrv/fksmbd/Run.sh
new file mode 100755
index 0000000000..f1f4b5973b
--- /dev/null
+++ b/usr/src/cmd/smbsrv/fksmbd/Run.sh
@@ -0,0 +1,45 @@
+#!/bin/sh
+
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
+
+# Helper program to run fksmbd (user-space smbd for debugging)
+# using binaries from the proto area.
+
+[ -n "$ROOT" ] || {
+ echo "Need a bldenv to set ROOT=..."
+ exit 1;
+}
+
+if [[ ! -w /var/smb || ! -w /var/run/smb ]]
+then
+ echo "Need to create/chown/chmod /var/smb /var/run/smb"
+ echo "mkdir -p /var/run/smb"
+ echo "chown -R $USER /var/smb /var/run/smb"
+ echo "chmod -R a+rw /var/smb /var/run/smb"
+ exit 1;
+fi
+
+export SMBD_DOOR_NAME="/tmp/fksmbd_door"
+export SMB_SHARE_DNAME="/tmp/fksmbshare_door"
+
+LD_LIBRARY_PATH=$ROOT/usr/lib/smbsrv:$ROOT/usr/lib:$ROOT/lib
+export LD_LIBRARY_PATH
+
+# normally runs with cwd=/ but this is more careful
+cd /var/smb
+
+# run with the passed options
+exec $ROOT/usr/lib/smbsrv/fksmbd "$@"
diff --git a/usr/src/cmd/smbsrv/fksmbd/Watch-all.d b/usr/src/cmd/smbsrv/fksmbd/Watch-all.d
new file mode 100644
index 0000000000..4a8c007939
--- /dev/null
+++ b/usr/src/cmd/smbsrv/fksmbd/Watch-all.d
@@ -0,0 +1,111 @@
+#!/usr/sbin/dtrace -s
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * User-level dtrace for fksmbd
+ * Usage: dtrace -s Watch-all.d -p $PID
+ */
+
+#pragma D option flowindent
+
+self int trace;
+self int mask;
+
+/*
+ * Trace almost everything
+ */
+pid$target:fksmbd::entry,
+pid$target:libfksmbsrv.so.1::entry,
+pid$target:libmlsvc.so.1::entry,
+pid$target:libmlrpc.so.1::entry,
+pid$target:libsmbns.so.1::entry,
+pid$target:libsmb.so.1::entry
+{
+ self->trace++;
+}
+
+/*
+ * If traced and not masked, print entry/return
+ */
+pid$target:fksmbd::entry,
+pid$target:libfksmbsrv.so.1::entry,
+pid$target:libmlsvc.so.1::entry,
+pid$target:libmlrpc.so.1::entry,
+pid$target:libsmbns.so.1::entry,
+pid$target:libsmb.so.1::entry
+/self->trace > 0 && self->mask == 0/
+{
+ printf("\t0x%x", arg0);
+ printf("\t0x%x", arg1);
+ printf("\t0x%x", arg2);
+ printf("\t0x%x", arg3);
+}
+
+/*
+ * Mask (don't print) all function calls below these functions.
+ * These make many boring, repetitive function calls like
+ * smb_mbtowc, mbc_marshal_...
+ */
+pid$target::fop__getxvattr:entry,
+pid$target::fop__setxvattr:entry,
+pid$target::smb_mbc_vdecodef:entry,
+pid$target::smb_mbc_vencodef:entry,
+pid$target::smb_msgbuf_decode:entry,
+pid$target::smb_msgbuf_encode:entry,
+pid$target::smb_strlwr:entry,
+pid$target::smb_strupr:entry,
+pid$target::smb_wcequiv_strlen:entry
+{
+ self->mask++;
+}
+
+/*
+ * Now inverses of above, unwind order.
+ */
+
+pid$target::fop__getxvattr:return,
+pid$target::fop__setxvattr:return,
+pid$target::smb_mbc_vdecodef:return,
+pid$target::smb_mbc_vencodef:return,
+pid$target::smb_msgbuf_decode:return,
+pid$target::smb_msgbuf_encode:return,
+pid$target::smb_strlwr:return,
+pid$target::smb_strupr:return,
+pid$target::smb_wcequiv_strlen:return
+{
+ self->mask--;
+}
+
+pid$target:fksmbd::return,
+pid$target:libfksmbsrv.so.1::return,
+pid$target:libmlsvc.so.1::return,
+pid$target:libmlrpc.so.1::return,
+pid$target:libsmbns.so.1::return,
+pid$target:libsmb.so.1::return
+/self->trace > 0 && self->mask == 0/
+{
+ printf("\t0x%x", arg1);
+}
+
+pid$target:fksmbd::return,
+pid$target:libfksmbsrv.so.1::return,
+pid$target:libmlsvc.so.1::return,
+pid$target:libmlrpc.so.1::return,
+pid$target:libsmbns.so.1::return,
+pid$target:libsmb.so.1::return
+{
+ self->trace--;
+}
diff --git a/usr/src/cmd/smbsrv/fksmbd/fksmbd_door.c b/usr/src/cmd/smbsrv/fksmbd/fksmbd_door.c
new file mode 100644
index 0000000000..7337cb6d5e
--- /dev/null
+++ b/usr/src/cmd/smbsrv/fksmbd/fksmbd_door.c
@@ -0,0 +1,158 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/list.h>
+#include <assert.h>
+#include <alloca.h>
+#include <door.h>
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <synch.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <strings.h>
+#include <umem.h>
+
+#include <smbsrv/smb_door.h>
+#include <smbsrv/smb_xdr.h>
+#include <smbsrv/smb_token.h>
+#include <smbsrv/libmlsvc.h>
+#include <smbsrv/libsmbns.h>
+#include "smbd.h"
+
+
+/*
+ * Special version of smb_door_dispatch() for the
+ * "fake" smbsrv (running in user space).
+ *
+ * This is called via function pointer from
+ * smbsrv: smb_kdoor_upcall()
+ *
+ * The args and response go RPC encoded, just so we can
+ * borrow some of the common doorsvc code, even though
+ * there's no need for RPC encoding in this scenario.
+ */
+int
+fksmbd_door_dispatch(smb_doorarg_t *da)
+{
+
+ smbd_arg_t dop_arg;
+ smb_doorhdr_t *hdr;
+ char *rbuf = NULL;
+ char *argp = da->da_arg.data_ptr;
+ size_t arg_size = da->da_arg.data_size;
+ size_t hdr_size, rsize;
+
+ /*
+ * Decode
+ *
+ * da->da_arg.data_ptr = (arg data, xdr encoded)
+ * da->da_arg.data_size = (arg data len)
+ */
+
+ bzero(&dop_arg, sizeof (smbd_arg_t));
+ hdr = &dop_arg.hdr;
+ hdr_size = xdr_sizeof(smb_doorhdr_xdr, hdr);
+
+ if ((argp == NULL) || (arg_size < hdr_size)) {
+ syslog(LOG_DEBUG, "fksmbd_door_dispatch: bad args");
+ return (-1);
+ }
+
+ if (smb_doorhdr_decode(hdr, (uint8_t *)argp, hdr_size) == -1) {
+ syslog(LOG_DEBUG, "smbd_door_dispatch: header decode failed");
+ return (-1);
+ }
+
+ if ((hdr->dh_magic != SMB_DOOR_HDR_MAGIC) ||
+ (hdr->dh_flags != SMB_DF_FAKE_KERNEL)) {
+ syslog(LOG_DEBUG, "fksmbd_door_dispatch: invalid header");
+ return (-1);
+ }
+
+ dop_arg.opname = smb_doorhdr_opname(hdr->dh_op);
+ dop_arg.data = argp + hdr_size;
+ dop_arg.datalen = hdr->dh_datalen;
+
+ if (hdr->dh_op == SMB_DR_ASYNC_RESPONSE) {
+ /*
+ * ASYNC_RESPONSE is not used here.
+ */
+ syslog(LOG_DEBUG, "fksmbd_door_dispatch: ASYNC?");
+ return (-1);
+ }
+
+ /*
+ * Dispatch
+ *
+ * Call the common smbd_doorsvc.c code.
+ */
+ (void) smbd_door_dispatch_op(&dop_arg);
+
+ /*
+ * Encode
+ *
+ * da->da_arg.rbuf = (return data buf)
+ * da->da_arg.rsize = (return data size)
+ *
+ * Note that the return data buffer initially
+ * points to the same buffer as the args.
+ * If that's not large enough, umem_alloc.
+ */
+
+ rsize = dop_arg.rsize + hdr_size;
+ rbuf = umem_alloc(rsize, UMEM_DEFAULT);
+ if (rbuf == NULL) {
+ syslog(LOG_DEBUG, "fksmbd_door_dispatch[%s]: alloc %m",
+ dop_arg.opname);
+ return (-1);
+ }
+
+ /* Copy caller's return data after the header. */
+ if (dop_arg.rbuf != NULL) {
+ (void) memcpy(rbuf + hdr_size, dop_arg.rbuf, dop_arg.rsize);
+ free(dop_arg.rbuf);
+ }
+
+ hdr->dh_datalen = dop_arg.rsize;
+ (void) smb_doorhdr_encode(hdr, (uint8_t *)rbuf, hdr_size);
+
+ /* Let's update da->da_hdr too. */
+ da->da_hdr = *hdr;
+
+ /*
+ * Was door_return()
+ * NB: The "fake kernel" smbsrv code will umem_free rbuf.
+ */
+ da->da_arg.rbuf = rbuf;
+ da->da_arg.rsize = rsize;
+
+ return (0);
+}
diff --git a/usr/src/cmd/smbsrv/fksmbd/fksmbd_kmod.c b/usr/src/cmd/smbsrv/fksmbd/fksmbd_kmod.c
new file mode 100644
index 0000000000..067639453b
--- /dev/null
+++ b/usr/src/cmd/smbsrv/fksmbd/fksmbd_kmod.c
@@ -0,0 +1,151 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * These replace NODIRECT functions of the same name in
+ * $SRC/lib/smbsrv/libsmb/common/smb_kmod.c including:
+ * smb_kmod_bind, smb_kmod_ioctl, smb_kmod_isbound,
+ * smb_kmod_start, smb_kmod_stop, smb_kmod_unbind.
+ *
+ * For all the other smb_kmod_... functions, we can just use the
+ * libsmb code because those all call smb_kmod_ioctl, for which
+ * we have an override here.
+ *
+ * The replacment functions here just call the libfksmbsrv code
+ * directly where the real (in-kernel) versions would be entered
+ * via the driver framework (open, close, ioctl). Aside from that,
+ * the call sequences are intentionally the same (where possible).
+ * In particular, that makes it possible to debug startup/teardown
+ * problems in the user-space version of this code.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioccom.h>
+#include <sys/param.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <note.h>
+
+#include <smbsrv/smbinfo.h>
+#include <smbsrv/smb_ioctl.h>
+#include "smbd.h"
+
+boolean_t smbdrv_opened = B_FALSE;
+
+/*
+ * We want to adjust a few things in the standard configuration
+ * passed to the "fake" version of the smbsrv kernel module.
+ *
+ * Reduce the maximum number of connections and workers, just for
+ * convenience while debugging. (Don't want hundreds of threads.)
+ */
+static void
+fksmbd_adjust_config(smb_ioc_header_t *ioc_hdr)
+{
+ smb_ioc_cfg_t *ioc = (smb_ioc_cfg_t *)ioc_hdr;
+
+ ioc->maxconnections = 10;
+ ioc->maxworkers = 20;
+ smbd_report("maxconnections=%d, maxworkers=%d",
+ ioc->maxconnections, ioc->maxworkers);
+}
+
+boolean_t
+smb_kmod_isbound(void)
+{
+ return (smbdrv_opened);
+}
+
+int
+smb_kmod_bind(void)
+{
+ int rc;
+
+ if (smbdrv_opened) {
+ smbdrv_opened = B_FALSE;
+ (void) fksmbsrv_drv_close();
+ }
+
+ rc = fksmbsrv_drv_open();
+ if (rc == 0)
+ smbdrv_opened = B_TRUE;
+
+ return (rc);
+}
+
+void
+smb_kmod_unbind(void)
+{
+ if (smbdrv_opened) {
+ smbdrv_opened = B_FALSE;
+ (void) fksmbsrv_drv_close();
+ }
+}
+
+int
+smb_kmod_ioctl(int cmd, smb_ioc_header_t *ioc, uint32_t len)
+{
+ int rc;
+
+ _NOTE(ARGUNUSED(len));
+
+ if (!smbdrv_opened)
+ return (EBADF);
+
+ if (cmd == SMB_IOC_CONFIG)
+ fksmbd_adjust_config(ioc);
+
+ rc = fksmbsrv_drv_ioctl(cmd, ioc);
+ return (rc);
+}
+
+/* ARGSUSED */
+int
+smb_kmod_start(int opipe, int lmshr, int udoor)
+{
+ smb_ioc_start_t ioc;
+ int rc;
+
+ bzero(&ioc, sizeof (ioc));
+
+ /* These three are unused */
+ ioc.opipe = -1;
+ ioc.lmshrd = -1;
+ ioc.udoor = -1;
+
+ /* These are the "door" dispatch callbacks */
+ ioc.lmshr_func = NULL; /* not used */
+ ioc.opipe_func = (void *)fksmbd_opipe_dispatch;
+ ioc.udoor_func = (void *)fksmbd_door_dispatch;
+
+ rc = smb_kmod_ioctl(SMB_IOC_START, &ioc.hdr, sizeof (ioc));
+ return (rc);
+}
+
+void
+smb_kmod_stop(void)
+{
+ smb_ioc_header_t ioc;
+
+ bzero(&ioc, sizeof (ioc));
+ (void) smb_kmod_ioctl(SMB_IOC_STOP, &ioc, sizeof (ioc));
+}
diff --git a/usr/src/cmd/smbsrv/fksmbd/fksmbd_ksock.c b/usr/src/cmd/smbsrv/fksmbd/fksmbd_ksock.c
new file mode 100644
index 0000000000..46bd4c7947
--- /dev/null
+++ b/usr/src/cmd/smbsrv/fksmbd/fksmbd_ksock.c
@@ -0,0 +1,108 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * fork/exec a privileged helper to do the bind.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/note.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+int
+ksocket_bind_helper(int fd, struct sockaddr *addr, uint_t addrlen)
+{
+ char familystr[8];
+ char portstr[12];
+ char addrstr[INET6_ADDRSTRLEN];
+ char *argv[6];
+ const char *p;
+ /* LINTED E_BAD_PTR_CAST_ALIGN */
+ struct sockaddr_in *sin = (struct sockaddr_in *)addr;
+ /* LINTED E_BAD_PTR_CAST_ALIGN */
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)addr;
+ int pid, err, stat;
+ _NOTE(ARGUNUSED(addrlen));
+
+ (void) snprintf(familystr, sizeof (familystr), "%d", addr->sa_family);
+ switch (addr->sa_family) {
+ case AF_INET:
+ (void) snprintf(portstr, sizeof (portstr), "%d",
+ ntohs(sin->sin_port));
+ p = inet_ntop(AF_INET, &sin->sin_addr,
+ addrstr, sizeof (addrstr));
+ break;
+ case AF_INET6:
+ (void) snprintf(portstr, sizeof (portstr), "%d",
+ ntohs(sin6->sin6_port));
+ p = inet_ntop(AF_INET6, &sin6->sin6_addr,
+ addrstr, sizeof (addrstr));
+ break;
+ default:
+ p = NULL;
+ break;
+ }
+ if (p == NULL) {
+ err = errno;
+ (void) fprintf(stdout, "ksocket_bind_helper, inet_ntop %s\n",
+ strerror(err));
+ return (err);
+ }
+
+ (void) fprintf(stdout, "ksocket_bind_helper, "
+ "family=%s addr=%s port=%s\n",
+ familystr, addrstr, portstr);
+
+ argv[0] = "/usr/bin/pfexec";
+ argv[1] = "/usr/lib/smbsrv/bind-helper";
+ argv[2] = familystr;
+ argv[3] = addrstr;
+ argv[4] = portstr;
+ argv[5] = NULL;
+
+ pid = vfork();
+ if (pid == -1) {
+ err = errno;
+ perror("fork");
+ return (err);
+ }
+ if (pid == 0) {
+ (void) dup2(fd, 0);
+ (void) execv(argv[0], argv);
+ err = errno;
+ perror("execv");
+ return (err);
+ }
+ err = waitpid(pid, &stat, 0);
+ if (err == -1) {
+ err = errno;
+ perror("waitpid");
+ return (err);
+ }
+ if (WIFEXITED(stat)) {
+ err = WEXITSTATUS(stat);
+ if (err == 0)
+ return (0);
+ (void) fprintf(stderr, "helper exit %d\n", err);
+ }
+ return (EACCES);
+}
diff --git a/usr/src/cmd/smbsrv/fksmbd/fksmbd_log.c b/usr/src/cmd/smbsrv/fksmbd/fksmbd_log.c
new file mode 100644
index 0000000000..166dc9ccc2
--- /dev/null
+++ b/usr/src/cmd/smbsrv/fksmbd/fksmbd_log.c
@@ -0,0 +1,93 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <string.h>
+#include <syslog.h>
+#include <sys/strlog.h>
+
+#include <smbsrv/smbinfo.h>
+#include <smbsrv/smb_ioctl.h>
+#include "smbd.h"
+
+#include <libfakekernel/fakekernel.h>
+
+static const char *pri_name[LOG_DEBUG+1] = {
+ "emerg", "alert", "crit", "err", "warning", "notice", "info", "debug"
+};
+
+
+/*
+ * Provide a replacement for libsmb:smb_vsyslog() that just
+ * prints the messages to stdout for "fksmbd" debugging.
+ */
+void
+smb_vsyslog(int pri, const char *fmt, va_list ap)
+{
+ int save_errno = errno;
+ char buf[SMBD_LOG_MSGSIZE];
+ char *newfmt;
+
+ pri &= LOG_PRIMASK;
+
+ if (smbd.s_debug == 0 && pri > LOG_INFO)
+ return;
+
+ newfmt = smb_syslog_fmt_m(buf, sizeof (buf), fmt, save_errno);
+
+ flockfile(stdout);
+ (void) fprintf(stdout, "fksmbd.%s: ", pri_name[pri]);
+ /* LINTED E_SEC_PRINTF_VAR_FMT */
+ (void) vfprintf(stdout, newfmt, ap);
+ (void) fprintf(stdout, "\n");
+ funlockfile(stdout);
+
+ (void) fflush(stdout);
+}
+
+/*
+ * Provide a real function (one that prints something) to replace
+ * the stub in libfakekernel. This prints cmn_err() messages.
+ */
+void
+fakekernel_putlog(char *msg, size_t len, int flags)
+{
+
+ /*
+ * [CE_CONT, CE_NOTE, CE_WARN, CE_PANIC] maps to
+ * [SL_NOTE, SL_NOTE, SL_WARN, SL_FATAL]
+ */
+ if (smbd.s_debug == 0 && (flags & SL_NOTE))
+ return;
+ (void) fwrite(msg, 1, len, stdout);
+ (void) fflush(stdout);
+}
+
+/*
+ * Initialization function called at the start of fksmbd:main().
+ * Call an empty function in both of libfksmbsrv, libfakekernel,
+ * just to force them to load so we can set breakpoints in them
+ * without debugger forceload tricks. This also avoids elfchk
+ * complaints from libfakekernel, which we don't call directly
+ * except for here.
+ */
+void
+fksmbd_init(void)
+{
+ fksmbsrv_drv_load();
+ fakekernel_init();
+}
diff --git a/usr/src/cmd/smbsrv/fksmbd/fksmbd_opipe.c b/usr/src/cmd/smbsrv/fksmbd/fksmbd_opipe.c
new file mode 100644
index 0000000000..7fd8df64d3
--- /dev/null
+++ b/usr/src/cmd/smbsrv/fksmbd/fksmbd_opipe.c
@@ -0,0 +1,156 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <sys/list.h>
+#include <assert.h>
+#include <alloca.h>
+#include <door.h>
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <synch.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <strings.h>
+#include <umem.h>
+
+#include <smbsrv/smb_door.h>
+#include <smbsrv/smb_xdr.h>
+#include <smbsrv/smb_token.h>
+#include <smbsrv/libmlsvc.h>
+#include <smbsrv/libsmbns.h>
+#include "smbd.h"
+
+static int smbd_opipe_exec(uint32_t fid);
+
+
+/*
+ * Process smbd opipe requests.
+ *
+ * This is a special version of smb_opipe_dispatch()
+ * for the "fake" smbsrv (running in user space).
+ * This is called via function pointer from
+ * smbsrv: smb_opipe_door_call()
+ *
+ * Very similar to smbd_opipe_dispatch()
+ */
+int
+fksmbd_opipe_dispatch(door_arg_t *da)
+{
+ uint8_t *buf = (uint8_t *)da->data_ptr;
+ smb_doorhdr_t hdr;
+ size_t hdr_size;
+ uint8_t *data;
+ uint32_t datalen;
+
+ if (!smbd_online())
+ return (-1);
+
+ bzero(&hdr, sizeof (smb_doorhdr_t));
+ hdr_size = xdr_sizeof(smb_doorhdr_xdr, &hdr);
+
+ if (da->data_ptr == NULL || da->data_size < hdr_size)
+ return (-1);
+
+ if (smb_doorhdr_decode(&hdr, buf, hdr_size) == -1)
+ return (-1);
+
+ if ((hdr.dh_magic != SMB_OPIPE_HDR_MAGIC) || (hdr.dh_fid == 0))
+ return (-1);
+
+ if (hdr.dh_datalen > SMB_OPIPE_DOOR_BUFSIZE)
+ hdr.dh_datalen = SMB_OPIPE_DOOR_BUFSIZE;
+
+ data = buf + hdr_size;
+ datalen = hdr.dh_datalen;
+
+ switch (hdr.dh_op) {
+ case SMB_OPIPE_OPEN:
+ hdr.dh_door_rc = ndr_pipe_open(hdr.dh_fid, data, datalen);
+ hdr.dh_datalen = 0;
+ hdr.dh_resid = 0;
+ datalen = hdr_size;
+ break;
+
+ case SMB_OPIPE_CLOSE:
+ hdr.dh_door_rc = ndr_pipe_close(hdr.dh_fid);
+ hdr.dh_datalen = 0;
+ hdr.dh_resid = 0;
+ datalen = hdr_size;
+ break;
+
+ case SMB_OPIPE_READ:
+ data = (uint8_t *)buf + hdr_size;
+ datalen = hdr.dh_datalen;
+ hdr.dh_door_rc = ndr_pipe_read(hdr.dh_fid, data, &datalen,
+ &hdr.dh_resid);
+ hdr.dh_datalen = datalen;
+ datalen += hdr_size;
+ break;
+
+ case SMB_OPIPE_WRITE:
+ hdr.dh_door_rc = ndr_pipe_write(hdr.dh_fid, data, datalen);
+ hdr.dh_datalen = 0;
+ hdr.dh_resid = 0;
+ datalen = hdr_size;
+ break;
+
+ case SMB_OPIPE_EXEC:
+ hdr.dh_door_rc = smbd_opipe_exec(hdr.dh_fid);
+ hdr.dh_datalen = 0;
+ hdr.dh_resid = 0;
+ datalen = hdr_size;
+ break;
+
+ default:
+ return (-1);
+ }
+
+ (void) smb_doorhdr_encode(&hdr, (uint8_t *)buf, hdr_size);
+ return (0);
+}
+
+/*
+ * Normal (from a real kernel) up calls get a thread here.
+ * In the "fake" kernel (all user space) we don't need that.
+ * NB: arg will be freed by ndr_pipe_transact()
+ */
+static int
+smbd_opipe_exec(uint32_t fid)
+{
+ uint32_t *arg;
+
+ if ((arg = malloc(sizeof (uint32_t))) == NULL)
+ return (ENOMEM);
+
+ *arg = fid;
+
+ (void) ndr_pipe_transact(arg);
+
+ return (0);
+}
diff --git a/usr/src/cmd/smbsrv/fksmbd/fksmbd_shr.c b/usr/src/cmd/smbsrv/fksmbd/fksmbd_shr.c
new file mode 100644
index 0000000000..dea6e3fa00
--- /dev/null
+++ b/usr/src/cmd/smbsrv/fksmbd/fksmbd_shr.c
@@ -0,0 +1,125 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * Replace the smb_shr_load() function in libmlsvc, because
+ * fksmbd doesn't want the real shares known by libshare,
+ * instead preferring its own (fake) list of shares.
+ */
+
+#include <sys/types.h>
+
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <syslog.h>
+#include <libshare.h>
+#include <unistd.h>
+#include <note.h>
+
+#include <smbsrv/libsmb.h>
+#include <smbsrv/libsmbns.h>
+#include <smbsrv/libmlsvc.h>
+#include <smbsrv/smb_share.h>
+#include <smbsrv/smb.h>
+
+static void
+new_share(char *name, char *path, char *comment, int flags)
+{
+ smb_share_t si;
+
+ bzero(&si, sizeof (si));
+ (void) strlcpy(si.shr_name, name, MAXNAMELEN);
+ (void) strlcpy(si.shr_path, path, MAXPATHLEN);
+ (void) strlcpy(si.shr_cmnt, comment, SMB_SHARE_CMNT_MAX);
+ si.shr_flags = flags;
+ if (smb_shr_add(&si) != 0) {
+ syslog(LOG_ERR, "failed to add test share: %s",
+ si.shr_name);
+ }
+}
+
+/*
+ * This function loads a list of shares from a text file, where
+ * each line of the file contains:
+ * name path comment
+ *
+ * This is only for fksmbd, for testing.
+ */
+void
+shr_load_file(char *shr_file)
+{
+ char linebuf[1024];
+ FILE *fp;
+ char *p;
+ char *name, *path, *comment;
+
+ fp = fopen(shr_file, "r");
+ if (fp == NULL) {
+ perror(shr_file);
+ return;
+ }
+
+ while ((p = fgets(linebuf, sizeof (linebuf), fp)) != NULL) {
+
+ name = p;
+ p = strpbrk(p, " \t\n");
+ if (p == NULL)
+ continue;
+ *p++ = '\0';
+
+ path = p;
+ p = strpbrk(p, " \t\n");
+ if (p == NULL)
+ comment = "";
+ else {
+ *p++ = '\0';
+
+ comment = p;
+ p = strchr(p, '\n');
+ if (p != NULL)
+ *p++ = '\0';
+ }
+ new_share(name, path, comment, 0);
+ }
+ (void) fclose(fp);
+}
+
+/*ARGSUSED*/
+void *
+smb_shr_load(void *args)
+{
+ char *shr_file;
+ _NOTE(ARGUNUSED(args))
+
+ /*
+ * Not loading the real shares in fksmbd because that
+ * tries to enable the network/smb/server service.
+ * Also, we won't generally have access to everything
+ * in the real shares, because fksmbd runs (only) with
+ * the credentials of the user who runs it.
+ */
+ new_share("test", "/var/smb/test", "fksmbd test share",
+ SMB_SHRF_GUEST_OK);
+
+ /* Allow creating lots of shares for testing. */
+ shr_file = getenv("FKSMBD_SHARE_FILE");
+ if (shr_file != NULL)
+ shr_load_file(shr_file);
+
+ return (NULL);
+}
diff --git a/usr/src/cmd/smbsrv/smbadm/smbadm.c b/usr/src/cmd/smbsrv/smbadm/smbadm.c
index 36e3efa781..2ab0e6e06d 100644
--- a/usr/src/cmd/smbsrv/smbadm/smbadm.c
+++ b/usr/src/cmd/smbsrv/smbadm/smbadm.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -1028,7 +1028,7 @@ smbadm_group_show(int argc, char **argv)
if ((status != SMB_LGRP_NO_MORE) || smb_lgrp_itererror(&gi)) {
if (status != SMB_LGRP_NO_MORE)
- syslog(LOG_ERR, "smb_lgrp_iterate: %s",
+ smb_syslog(LOG_ERR, "smb_lgrp_iterate: %s",
smb_lgrp_strerror(status));
(void) fprintf(stderr,
diff --git a/usr/src/cmd/smbsrv/smbd/Makefile b/usr/src/cmd/smbsrv/smbd/Makefile
index 4f460c1ed8..2927c33ca1 100644
--- a/usr/src/cmd/smbsrv/smbd/Makefile
+++ b/usr/src/cmd/smbsrv/smbd/Makefile
@@ -20,21 +20,24 @@
#
#
# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
#
PROG= smbd
-SRCS= \
- smbd_doorsvc.c \
- smbd_join.c \
- smbd_logon.c \
- smbd_main.c \
- smbd_nicmon.c \
- smbd_opipe_doorsvc.c \
- smbd_share_doorsvc.c \
- smbd_spool.c \
- smbd_vss.c
+OBJS= \
+ smbd_doorsvc.o \
+ smbd_join.o \
+ smbd_logon.o \
+ smbd_main.o \
+ smbd_nicmon.o \
+ smbd_opipe_doorsvc.o \
+ smbd_share_doorsvc.o \
+ smbd_spool.o \
+ smbd_syslog.o \
+ smbd_vss.o
+
+SRCS= $(OBJS:%.o=%.c)
include ../../Makefile.cmd
@@ -50,7 +53,15 @@ $(ROOTMANIFEST):= FILEMODE = 0444
$(ROOTSVCMETHOD):= FILEMODE = 0555
$(ROOTVARSMBDLL):= FILEMODE = 0755
-include ../Makefile.smbsrv.defs
+LINTFLAGS += -xerroff=E_NAME_DEF_NOT_USED2
+
+CFLAGS += $(CCVERBOSE)
+CPPFLAGS += -D_REENTRANT
+CPPFLAGS += -Dsyslog=smb_syslog
+$(NOT_RELEASE_BUILD)CPPFLAGS += -DDEBUG
+
+C99MODE = -xc99=%all
+C99LMODE = -Xc99=%all
LDLIBS += -L$(ROOT)/usr/lib/smbsrv -lmlsvc -lmlrpc -lsmbns -lsmb \
-lzfs -lbsm -lsocket -lnsl -lscf -lumem -lcmdutils
diff --git a/usr/src/cmd/smbsrv/smbd/server.xml b/usr/src/cmd/smbsrv/smbd/server.xml
index 3ab352c8ad..10b0c82a87 100644
--- a/usr/src/cmd/smbsrv/smbd/server.xml
+++ b/usr/src/cmd/smbsrv/smbd/server.xml
@@ -150,6 +150,8 @@ file.
value='true' override='true'/>
<propval name='autohome_map' type='astring'
value='/etc' override='true'/>
+ <propval name='debug' type='integer'
+ value='0' override='true'/>
<propval name='domain_sid' type='astring'
value='' override='true'/>
<propval name='domain_member' type='boolean'
diff --git a/usr/src/cmd/smbsrv/smbd/smbd.h b/usr/src/cmd/smbsrv/smbd/smbd.h
index e0bc6c8f82..750a662e9e 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd.h
+++ b/usr/src/cmd/smbsrv/smbd/smbd.h
@@ -20,8 +20,8 @@
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SMBD_H
@@ -39,6 +39,7 @@ extern "C" {
#include <smbsrv/libsmb.h>
#include <smbsrv/libmlsvc.h>
+void smbd_report(const char *fmt, ...);
int smbd_opipe_start(void);
void smbd_opipe_stop(void);
int smbd_share_start(void);
@@ -74,9 +75,10 @@ typedef struct smbd {
uid_t s_uid; /* UID of current daemon */
gid_t s_gid; /* GID of current daemon */
int s_fg; /* Run in foreground */
+ int s_debug; /* Enable debug output */
+ int s_dbg_stop; /* stop for debugger attach */
boolean_t s_initialized;
boolean_t s_shutting_down; /* shutdown control */
- volatile uint_t s_sigval;
volatile uint_t s_refreshes;
boolean_t s_kbound; /* B_TRUE if bound to kernel */
int s_door_lmshr;
@@ -95,11 +97,11 @@ typedef struct smbd {
pthread_t s_nbt_listener_id;
pthread_t s_tcp_listener_id;
boolean_t s_fatal_error;
- smb_log_hdl_t s_loghd;
} smbd_t;
-#define SMBD_LOGNAME "smbd"
-#define SMBD_LOGSIZE 1024
+extern smbd_t smbd;
+
+#define SMBD_LOG_MSGSIZE 256
#define SMBD_DOOR_NAMESZ 16
@@ -110,6 +112,25 @@ typedef struct smbd_door {
char sd_name[SMBD_DOOR_NAMESZ];
} smbd_door_t;
+#define SMBD_ARG_MAGIC 0x53415247 /* 'SARG' */
+
+/*
+ * Parameter for door operations.
+ */
+typedef struct smbd_arg {
+ uint32_t magic;
+ list_node_t lnd;
+ smb_doorhdr_t hdr;
+ const char *opname;
+ char *data;
+ size_t datalen;
+ char *rbuf;
+ size_t rsize;
+ boolean_t response_ready;
+ boolean_t response_abort;
+ uint32_t status;
+} smbd_arg_t;
+
int smbd_door_start(void);
void smbd_door_stop(void);
void smbd_door_init(smbd_door_t *, const char *);
@@ -117,6 +138,13 @@ void smbd_door_fini(smbd_door_t *);
void smbd_door_enter(smbd_door_t *);
void smbd_door_return(smbd_door_t *, char *, size_t, door_desc_t *, uint_t);
+void *smbd_door_dispatch_op(void *);
+
+/* For fksmbd */
+void fksmbd_init(void);
+int fksmbd_door_dispatch(smb_doorarg_t *);
+int fksmbd_opipe_dispatch(door_arg_t *);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c
index 5fb3695a16..e21a9beaf4 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_doorsvc.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/list.h>
@@ -44,25 +45,6 @@
#include <smbsrv/libsmbns.h>
#include "smbd.h"
-#define SMBD_ARG_MAGIC 0x53415247 /* 'SARG' */
-
-/*
- * Parameter for door operations.
- */
-typedef struct smbd_arg {
- uint32_t magic;
- list_node_t lnd;
- smb_doorhdr_t hdr;
- const char *opname;
- char *data;
- size_t datalen;
- char *rbuf;
- size_t rsize;
- boolean_t response_ready;
- boolean_t response_abort;
- uint32_t status;
-} smbd_arg_t;
-
/*
* The list contains asynchronous requests that have been initiated
* but have not yet been collected (via smbd_dop_async_response).
@@ -127,11 +109,11 @@ static smbd_doorsvc_t smbd_doorsvc;
static int smbd_door_fd = -1;
static int smbd_door_cookie = 0x534D4244; /* SMBD */
static smbd_door_t smbd_door_sdh;
+static char *smbd_door_name = NULL;
static void smbd_door_dispatch(void *, char *, size_t, door_desc_t *, uint_t);
static int smbd_door_dispatch_async(smbd_arg_t *);
static void smbd_door_release_async(smbd_arg_t *);
-static void *smbd_door_dispatch_op(void *);
/*
* Start the smbd door service. Create and bind to a door.
@@ -150,6 +132,10 @@ smbd_door_start(void)
return (-1);
}
+ smbd_door_name = getenv("SMBD_DOOR_NAME");
+ if (smbd_door_name == NULL)
+ smbd_door_name = SMBD_DOOR_NAME;
+
smbd_door_init(&smbd_door_sdh, "doorsrv");
list_create(&smbd_doorsvc.sd_async_list, sizeof (smbd_arg_t),
@@ -165,9 +151,9 @@ smbd_door_start(void)
return (-1);
}
- (void) unlink(SMBD_DOOR_NAME);
+ (void) unlink(smbd_door_name);
- if ((newfd = creat(SMBD_DOOR_NAME, 0644)) < 0) {
+ if ((newfd = creat(smbd_door_name, 0644)) < 0) {
(void) fprintf(stderr, "smb_doorsrv_start: open: %s",
strerror(errno));
(void) door_revoke(smbd_door_fd);
@@ -177,9 +163,9 @@ smbd_door_start(void)
}
(void) close(newfd);
- (void) fdetach(SMBD_DOOR_NAME);
+ (void) fdetach(smbd_door_name);
- if (fattach(smbd_door_fd, SMBD_DOOR_NAME) < 0) {
+ if (fattach(smbd_door_fd, smbd_door_name) < 0) {
(void) fprintf(stderr, "smb_doorsrv_start: fattach: %s",
strerror(errno));
(void) door_revoke(smbd_door_fd);
@@ -202,8 +188,10 @@ smbd_door_stop(void)
smbd_door_fini(&smbd_door_sdh);
+ if (smbd_door_name)
+ (void) fdetach(smbd_door_name);
+
if (smbd_door_fd != -1) {
- (void) fdetach(SMBD_DOOR_NAME);
(void) door_revoke(smbd_door_fd);
smbd_door_fd = -1;
}
@@ -377,7 +365,7 @@ smbd_door_release_async(smbd_arg_t *arg)
* We send a notification when asynchronous (ASYNC) door calls
* from the kernel (SYSSPACE) have completed.
*/
-static void *
+void *
smbd_door_dispatch_op(void *thread_arg)
{
smbd_arg_t *arg = (smbd_arg_t *)thread_arg;
@@ -435,7 +423,7 @@ smbd_door_dispatch_op(void *thread_arg)
void
smbd_door_init(smbd_door_t *sdh, const char *name)
{
- (void) strlcpy(sdh->sd_name, name, SMBD_DOOR_NAMESZ);
+ (void) strlcpy(sdh->sd_name, name, sizeof (sdh->sd_name));
}
void
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_join.c b/usr/src/cmd/smbsrv/smbd/smbd_join.c
index 74d5fac9be..bca6a1c9e9 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_join.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_join.c
@@ -139,7 +139,7 @@ smbd_dc_monitor(void *arg)
}
if (ds_not_responding)
- smb_log(smbd.s_loghd, LOG_NOTICE,
+ syslog(LOG_NOTICE,
"smbd_dc_monitor: domain service not responding");
if (ds_not_responding || ds_cfg_changed) {
@@ -173,13 +173,13 @@ smbd_dc_update(void)
}
if (!smb_locate_dc(domain, "", &info)) {
- smb_log(smbd.s_loghd, LOG_NOTICE,
+ syslog(LOG_NOTICE,
"smbd_dc_update: %s: locate failed", domain);
return;
}
di = &info.d_primary;
- smb_log(smbd.s_loghd, LOG_NOTICE,
+ syslog(LOG_INFO,
"smbd_dc_update: %s: located %s", domain, info.d_dc);
status = mlsvc_netlogon(info.d_dc, di->di_nbname);
@@ -191,11 +191,11 @@ smbd_dc_update(void)
* Restart required because the domain changed
* or the credential chain setup failed.
*/
- smb_log(smbd.s_loghd, LOG_NOTICE,
+ syslog(LOG_NOTICE,
"smbd_dc_update: smb/server restart required");
if (smb_smf_restart_service() != 0)
- smb_log(smbd.s_loghd, LOG_ERR,
+ syslog(LOG_ERR,
"restart failed: run 'svcs -xv smb/server'"
" for more information");
}
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_logon.c b/usr/src/cmd/smbsrv/smbd/smbd_logon.c
index fe27e9cd7f..ad19f46655 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_logon.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_logon.c
@@ -135,7 +135,7 @@ smbd_user_auth_logon(smb_logon_t *user_info)
termid.at_type = AU_IPv4;
} else {
bcopy(&user_info->lg_clnt_ipaddr.a_ip, termid.at_addr,
- IPV6_ADDR_LEN);
+ sizeof (in6_addr_t));
termid.at_type = AU_IPv6;
}
adt_set_termid(ah, &termid);
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_main.c b/usr/src/cmd/smbsrv/smbd/smbd_main.c
index c1bab75fae..a0a8793aba 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_main.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_main.c
@@ -58,6 +58,7 @@
#include <smbsrv/libmlsvc.h>
#include "smbd.h"
+#define SECSPERMIN 60
#define SMBD_ONLINE_WAIT_INTERVAL 10
#define SMBD_REFRESH_INTERVAL 10
#define SMB_DBDIR "/var/smb"
@@ -75,9 +76,6 @@ static void smbd_service_fini(void);
static int smbd_setup_options(int argc, char *argv[]);
static void smbd_usage(FILE *fp);
-static void smbd_report(const char *fmt, ...);
-
-static void smbd_sig_handler(int sig);
static int32_t smbd_gmtoff(void);
static void smbd_localtime_init(void);
@@ -85,25 +83,12 @@ static void *smbd_localtime_monitor(void *arg);
static void smbd_dyndns_init(void);
static void smbd_load_shares(void);
+static void *smbd_share_loader(void *);
-static int smbd_refresh_init(void);
-static void smbd_refresh_fini(void);
-static void *smbd_refresh_monitor(void *);
+static void smbd_refresh_handler(void);
static int smbd_kernel_start(void);
-static pthread_cond_t refresh_cond;
-static pthread_mutex_t refresh_mutex;
-
-/*
- * Mutex to ensure that smbd_service_fini() and smbd_service_init()
- * are atomic w.r.t. one another. Otherwise, if a shutdown begins
- * before initialization is complete, resources can get deallocated
- * while initialization threads are still using them.
- */
-static mutex_t smbd_service_mutex;
-static cond_t smbd_service_cv;
-
smbd_t smbd;
/*
@@ -112,14 +97,16 @@ smbd_t smbd;
int
main(int argc, char *argv[])
{
- struct sigaction act;
sigset_t set;
uid_t uid;
int pfd = -1;
- uint_t sigval;
+ int sigval;
struct rlimit rl;
int orig_limit;
+#ifdef FKSMBD
+ fksmbd_init();
+#endif
smbd.s_pname = basename(argv[0]);
openlog(smbd.s_pname, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
@@ -127,8 +114,16 @@ main(int argc, char *argv[])
return (SMF_EXIT_ERR_FATAL);
if ((uid = getuid()) != smbd.s_uid) {
+#ifdef FKSMBD
+ /* Can't manipulate privileges in daemonize. */
+ if (smbd.s_fg == 0) {
+ smbd.s_fg = 1;
+ smbd_report("user %d (forced -f)", uid);
+ }
+#else /* FKSMBD */
smbd_report("user %d: %s", uid, strerror(EPERM));
return (SMF_EXIT_ERR_FATAL);
+#endif /* FKSMBD */
}
if (is_system_labeled()) {
@@ -152,31 +147,22 @@ main(int argc, char *argv[])
" from %d to %d", orig_limit, rl.rlim_cur);
}
- (void) sigfillset(&set);
- (void) sigdelset(&set, SIGABRT);
-
- (void) sigfillset(&act.sa_mask);
- act.sa_handler = smbd_sig_handler;
- act.sa_flags = 0;
+ /*
+ * Block async signals in all threads.
+ */
+ (void) sigemptyset(&set);
- (void) sigaction(SIGABRT, &act, NULL);
- (void) sigaction(SIGTERM, &act, NULL);
- (void) sigaction(SIGHUP, &act, NULL);
- (void) sigaction(SIGINT, &act, NULL);
- (void) sigaction(SIGPIPE, &act, NULL);
- (void) sigaction(SIGUSR1, &act, NULL);
+ (void) sigaddset(&set, SIGHUP);
+ (void) sigaddset(&set, SIGINT);
+ (void) sigaddset(&set, SIGQUIT);
+ (void) sigaddset(&set, SIGPIPE);
+ (void) sigaddset(&set, SIGTERM);
+ (void) sigaddset(&set, SIGUSR1);
+ (void) sigaddset(&set, SIGUSR2);
- (void) sigdelset(&set, SIGTERM);
- (void) sigdelset(&set, SIGHUP);
- (void) sigdelset(&set, SIGINT);
- (void) sigdelset(&set, SIGPIPE);
- (void) sigdelset(&set, SIGUSR1);
+ (void) sigprocmask(SIG_SETMASK, &set, NULL);
if (smbd.s_fg) {
- (void) sigdelset(&set, SIGTSTP);
- (void) sigdelset(&set, SIGTTIN);
- (void) sigdelset(&set, SIGTTOU);
-
if (smbd_service_init() != 0) {
smbd_report("service initialization failed");
exit(SMF_EXIT_ERR_FATAL);
@@ -198,27 +184,24 @@ main(int argc, char *argv[])
smbd_daemonize_fini(pfd, SMF_EXIT_OK);
}
- (void) atexit(smb_kmod_stop);
-
while (!smbd.s_shutting_down) {
- if (smbd.s_sigval == 0 && smbd.s_refreshes == 0)
- (void) sigsuspend(&set);
-
- sigval = atomic_swap_uint(&smbd.s_sigval, 0);
+ sigval = sigwait(&set);
switch (sigval) {
- case 0:
+ case -1:
+ syslog(LOG_DEBUG, "sigwait failed: %s",
+ strerror(errno));
+ break;
case SIGPIPE:
- case SIGABRT:
break;
case SIGHUP:
syslog(LOG_DEBUG, "refresh requested");
- (void) pthread_cond_signal(&refresh_cond);
+ smbd_refresh_handler();
break;
case SIGUSR1:
- smb_log_dumpall();
+ syslog(LOG_DEBUG, "SIGUSR1 ignored");
break;
default:
@@ -230,8 +213,20 @@ main(int argc, char *argv[])
}
}
+ /*
+ * Allow termination signals while shutting down.
+ */
+ (void) sigemptyset(&set);
+
+ if (smbd.s_fg) {
+ (void) sigaddset(&set, SIGHUP);
+ (void) sigaddset(&set, SIGINT);
+ }
+ (void) sigaddset(&set, SIGTERM);
+
+ (void) sigprocmask(SIG_UNBLOCK, &set, NULL);
+
smbd_service_fini();
- closelog();
return ((smbd.s_fatal_error) ? SMF_EXIT_ERR_FATAL : SMF_EXIT_OK);
}
@@ -440,15 +435,23 @@ smbd_service_init(void)
};
int rc, i;
- (void) mutex_lock(&smbd_service_mutex);
-
smbd.s_pid = getpid();
+
+ /*
+ * Stop for a debugger attach here, which is after the
+ * fork() etc. in smb_daemonize_init()
+ */
+ if (smbd.s_dbg_stop) {
+ smbd_report("pid %d stop for debugger attach", smbd.s_pid);
+ (void) kill(smbd.s_pid, SIGSTOP);
+ }
+ smbd_report("smbd starting, pid %d", smbd.s_pid);
+
for (i = 0; i < sizeof (dir)/sizeof (dir[0]); ++i) {
if ((mkdir(dir[i].name, dir[i].perm) < 0) &&
(errno != EEXIST)) {
smbd_report("mkdir %s: %s", dir[i].name,
strerror(errno));
- (void) mutex_unlock(&smbd_service_mutex);
return (-1);
}
}
@@ -459,11 +462,9 @@ smbd_service_init(void)
strerror(errno));
else
smbd_report("unable to set KRB5CCNAME");
- (void) mutex_unlock(&smbd_service_mutex);
return (-1);
}
- smbd.s_loghd = smb_log_create(SMBD_LOGSIZE, SMBD_LOGNAME);
smb_codepage_init();
rc = smbd_cups_init();
@@ -488,7 +489,6 @@ smbd_service_init(void)
if (rc == SMB_DOMAIN_NOMACHINE_SID) {
smbd_report(
"no machine SID: check idmap configuration");
- (void) mutex_unlock(&smbd_service_mutex);
return (-1);
}
}
@@ -499,7 +499,6 @@ smbd_service_init(void)
if (mlsvc_init() != 0) {
smbd_report("msrpc initialization failed");
- (void) mutex_unlock(&smbd_service_mutex);
return (-1);
}
@@ -507,12 +506,6 @@ smbd_service_init(void)
smbd.s_door_opipe = smbd_opipe_start();
if (smbd.s_door_srv < 0 || smbd.s_door_opipe < 0) {
smbd_report("door initialization failed %s", strerror(errno));
- (void) mutex_unlock(&smbd_service_mutex);
- return (-1);
- }
-
- if (smbd_refresh_init() != 0) {
- (void) mutex_unlock(&smbd_service_mutex);
return (-1);
}
@@ -523,7 +516,6 @@ smbd_service_init(void)
if (smb_shr_start() != 0) {
smbd_report("share initialization failed: %s", strerror(errno));
- (void) mutex_unlock(&smbd_service_mutex);
return (-1);
}
@@ -531,9 +523,8 @@ smbd_service_init(void)
if (smbd.s_door_lmshr < 0)
smbd_report("share initialization failed");
- /* This reloads the kernel config info. */
+ /* Open the driver, load the kernel config. */
if (smbd_kernel_bind() != 0) {
- (void) mutex_unlock(&smbd_service_mutex);
return (-1);
}
@@ -543,34 +534,18 @@ smbd_service_init(void)
smbd.s_initialized = B_TRUE;
smbd_report("service initialized");
- (void) cond_signal(&smbd_service_cv);
- (void) mutex_unlock(&smbd_service_mutex);
+
return (0);
}
/*
* Shutdown smbd and smbsrv kernel services.
*
- * Shutdown will not begin until initialization has completed.
- * Only one thread is allowed to perform the shutdown. Other
- * threads will be blocked on fini_in_progress until the process
- * has exited.
+ * Called only by the main thread.
*/
static void
smbd_service_fini(void)
{
- static uint_t fini_in_progress;
-
- (void) mutex_lock(&smbd_service_mutex);
-
- while (!smbd.s_initialized)
- (void) cond_wait(&smbd_service_cv, &smbd_service_mutex);
-
- if (atomic_swap_uint(&fini_in_progress, 1) != 0) {
- while (fini_in_progress)
- (void) cond_wait(&smbd_service_cv, &smbd_service_mutex);
- /*NOTREACHED*/
- }
smbd.s_shutting_down = B_TRUE;
smbd_report("service shutting down");
@@ -581,7 +556,6 @@ smbd_service_fini(void)
smbd_opipe_stop();
smbd_door_stop();
smbd_spool_stop();
- smbd_refresh_fini();
smbd_kernel_unbind();
smbd_share_stop();
smb_shr_stop();
@@ -596,112 +570,51 @@ smbd_service_fini(void)
smbd.s_initialized = B_FALSE;
smbd_report("service terminated");
- (void) mutex_unlock(&smbd_service_mutex);
- exit((smbd.s_fatal_error) ? SMF_EXIT_ERR_FATAL : SMF_EXIT_OK);
-}
-
-/*
- * smbd_refresh_init()
- *
- * SMB service refresh thread initialization. This thread waits for a
- * refresh event and updates the daemon's view of the configuration
- * before going back to sleep.
- */
-static int
-smbd_refresh_init()
-{
- pthread_attr_t tattr;
- pthread_condattr_t cattr;
- int rc;
-
- (void) pthread_condattr_init(&cattr);
- (void) pthread_cond_init(&refresh_cond, &cattr);
- (void) pthread_condattr_destroy(&cattr);
-
- (void) pthread_mutex_init(&refresh_mutex, NULL);
-
- (void) pthread_attr_init(&tattr);
- (void) pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
- rc = pthread_create(&smbd.s_refresh_tid, &tattr, smbd_refresh_monitor,
- NULL);
- (void) pthread_attr_destroy(&tattr);
-
- if (rc != 0)
- smbd_report("unable to start refresh monitor: %s",
- strerror(errno));
- return (rc);
-}
-
-/*
- * smbd_refresh_fini()
- *
- * Stop the refresh thread.
- */
-static void
-smbd_refresh_fini()
-{
- if ((pthread_self() != smbd.s_refresh_tid) &&
- (smbd.s_refresh_tid != 0)) {
- (void) pthread_cancel(smbd.s_refresh_tid);
- (void) pthread_cond_destroy(&refresh_cond);
- (void) pthread_mutex_destroy(&refresh_mutex);
- }
+ closelog();
}
/*
- * Wait for refresh events. When woken up, update the smbd configuration
+ * Called when SMF sends us a SIGHUP. Update the smbd configuration
* from SMF and check for changes that require service reconfiguration.
- * Throttling is applied to coallesce multiple refresh events when the
- * service is being refreshed repeatedly.
*/
-/*ARGSUSED*/
-static void *
-smbd_refresh_monitor(void *arg)
+static void
+smbd_refresh_handler()
{
- smbd_online_wait("smbd_refresh_monitor");
-
- while (!smbd.s_shutting_down) {
- (void) sleep(SMBD_REFRESH_INTERVAL);
+ int new_debug;
- (void) pthread_mutex_lock(&refresh_mutex);
- while ((atomic_swap_uint(&smbd.s_refreshes, 0) == 0) &&
- (!smbd.s_shutting_down))
- (void) pthread_cond_wait(&refresh_cond, &refresh_mutex);
- (void) pthread_mutex_unlock(&refresh_mutex);
+ if (smbd.s_shutting_down)
+ return;
- if (smbd.s_shutting_down) {
- smbd_service_fini();
- /*NOTREACHED*/
- }
+ smbd.s_refreshes++;
- (void) mutex_lock(&smbd_service_mutex);
+ new_debug = smb_config_get_debug();
+ if (smbd.s_debug || new_debug)
+ smbd_report("debug=%d", new_debug);
+ smbd.s_debug = new_debug;
- smbd_spool_stop();
- smbd_dc_monitor_refresh();
- smb_ccache_remove(SMB_CCACHE_PATH);
+ smbd_spool_stop();
+ smbd_dc_monitor_refresh();
+ smb_ccache_remove(SMB_CCACHE_PATH);
- /*
- * Clear the DNS zones for the existing interfaces
- * before updating the NIC interface list.
- */
- dyndns_clear_zones();
+ /*
+ * Clear the DNS zones for the existing interfaces
+ * before updating the NIC interface list.
+ */
+ dyndns_clear_zones();
- if (smbd_nicmon_refresh() != 0)
- smbd_report("NIC monitor refresh failed");
+ if (smbd_nicmon_refresh() != 0)
+ smbd_report("NIC monitor refresh failed");
- smb_netbios_name_reconfig();
- smb_browser_reconfig();
- dyndns_update_zones();
- (void) smbd_kernel_bind();
- smbd_load_shares();
- smbd_load_printers();
- smbd_spool_start();
+ smb_netbios_name_reconfig();
+ smb_browser_reconfig();
+ dyndns_update_zones();
- (void) mutex_unlock(&smbd_service_mutex);
- }
+ /* This reloads the in-kernel config. */
+ (void) smbd_kernel_bind();
- smbd.s_refresh_tid = 0;
- return (NULL);
+ smbd_load_shares();
+ smbd_load_printers();
+ smbd_spool_start();
}
void
@@ -743,7 +656,7 @@ smbd_online_wait(const char *text)
(void) sleep(SMBD_ONLINE_WAIT_INTERVAL);
if (text != NULL) {
- smb_log(smbd.s_loghd, LOG_DEBUG, "%s: online", text);
+ syslog(LOG_DEBUG, "%s: online", text);
(void) fprintf(stderr, "%s: online\n", text);
}
}
@@ -757,10 +670,15 @@ smbd_online_wait(const char *text)
static int
smbd_already_running(void)
{
- door_info_t info;
- int door;
+ door_info_t info;
+ char *door_name;
+ int door;
- if ((door = open(SMBD_DOOR_NAME, O_RDONLY)) < 0)
+ door_name = getenv("SMBD_DOOR_NAME");
+ if (door_name == NULL)
+ door_name = SMBD_DOOR_NAME;
+
+ if ((door = open(door_name, O_RDONLY)) < 0)
return (0);
if (door_info(door, &info) < 0)
@@ -793,7 +711,7 @@ smbd_kernel_bind(void)
rc = smb_kmod_setcfg(&cfg);
if (rc < 0)
smbd_report("kernel configuration update failed: %s",
- strerror(errno));
+ strerror(rc));
return (rc);
}
@@ -806,10 +724,10 @@ smbd_kernel_bind(void)
smb_kmod_unbind();
else
smbd.s_kbound = B_TRUE;
+ } else {
+ smbd_report("kernel bind error: %s", strerror(rc));
}
- if (rc != 0)
- smbd_report("kernel bind error: %s", strerror(errno));
return (rc);
}
@@ -821,18 +739,24 @@ smbd_kernel_start(void)
smb_load_kconfig(&cfg);
rc = smb_kmod_setcfg(&cfg);
- if (rc != 0)
+ if (rc != 0) {
+ smbd_report("kernel config ioctl error: %s", strerror(rc));
return (rc);
+ }
rc = smb_kmod_setgmtoff(smbd_gmtoff());
- if (rc != 0)
+ if (rc != 0) {
+ smbd_report("kernel gmtoff ioctl error: %s", strerror(rc));
return (rc);
+ }
rc = smb_kmod_start(smbd.s_door_opipe, smbd.s_door_lmshr,
smbd.s_door_srv);
- if (rc != 0)
+ if (rc != 0) {
+ smbd_report("kernel start ioctl error: %s", strerror(rc));
return (rc);
+ }
return (0);
}
@@ -882,13 +806,20 @@ smbd_load_shares(void)
(void) pthread_attr_init(&attr);
(void) pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
- rc = pthread_create(&tid, &attr, smb_shr_load, NULL);
+ rc = pthread_create(&tid, &attr, smbd_share_loader, NULL);
(void) pthread_attr_destroy(&attr);
if (rc != 0)
smbd_report("unable to load disk shares: %s", strerror(errno));
}
+static void *
+smbd_share_loader(void *args)
+{
+ (void) smb_shr_load(args);
+ return (NULL);
+}
+
/*
* Initialization of the localtime thread.
* Returns 0 on success, an error number if thread creation fails.
@@ -974,23 +905,6 @@ smbd_gmtoff(void)
return (gmtoff);
}
-static void
-smbd_sig_handler(int sigval)
-{
- if (smbd.s_sigval == 0)
- (void) atomic_swap_uint(&smbd.s_sigval, sigval);
-
- if (sigval == SIGHUP) {
- atomic_inc_uint(&smbd.s_refreshes);
- (void) pthread_cond_signal(&refresh_cond);
- }
-
- if (sigval == SIGINT || sigval == SIGTERM) {
- smbd.s_shutting_down = B_TRUE;
- (void) pthread_cond_signal(&refresh_cond);
- }
-}
-
/*
* Set up configuration options and parse the command line.
* This function will determine if we will run as a daemon
@@ -1011,14 +925,20 @@ smbd_setup_options(int argc, char *argv[])
if ((grp = getgrnam("sys")) != NULL)
smbd.s_gid = grp->gr_gid;
+ smbd.s_debug = smb_config_get_debug();
smbd.s_fg = smb_config_get_fg_flag();
- while ((c = getopt(argc, argv, ":f")) != -1) {
+ while ((c = getopt(argc, argv, ":dfs")) != -1) {
switch (c) {
+ case 'd':
+ smbd.s_debug++;
+ break;
case 'f':
smbd.s_fg = 1;
break;
-
+ case 's':
+ smbd.s_dbg_stop = 1;
+ break;
case ':':
case '?':
default:
@@ -1034,6 +954,7 @@ static void
smbd_usage(FILE *fp)
{
static char *help[] = {
+ "-d enable debug messages"
"-f run program in foreground"
};
@@ -1045,7 +966,7 @@ smbd_usage(FILE *fp)
(void) fprintf(fp, " %s\n", help[i]);
}
-static void
+void
smbd_report(const char *fmt, ...)
{
char buf[128];
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_nicmon.c b/usr/src/cmd/smbsrv/smbd/smbd_nicmon.c
index bc6739843c..9093499716 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_nicmon.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_nicmon.c
@@ -126,7 +126,7 @@ smbd_nicmon_run_check(void)
smbd_nicmon_enabled = B_TRUE;
if ((hd = smb_smf_scf_init(SMBD_FMRI_PREFIX)) == NULL) {
- smb_log(smbd.s_loghd, LOG_DEBUG,
+ syslog(LOG_DEBUG,
"smbd_nicmon: smb_smf_scf_init failed");
return;
}
@@ -134,7 +134,7 @@ smbd_nicmon_run_check(void)
rc = smb_smf_create_service_pgroup(hd, SMBD_PG_NAME);
if (rc != SMBD_SMF_OK) {
smb_smf_scf_fini(hd);
- smb_log(smbd.s_loghd, LOG_DEBUG,
+ syslog(LOG_DEBUG,
"smbd_nicmon: smb_smf_create_service_pgroup failed");
return;
}
@@ -156,20 +156,20 @@ smbd_nicmon_setup_rtsock(int af)
int flags;
if ((sd = socket(PF_ROUTE, SOCK_RAW, af)) == -1) {
- smb_log(smbd.s_loghd, LOG_ERR,
+ syslog(LOG_ERR,
"smbd_nicmon: routing socket failed: %d", errno);
return (-1);
}
if ((flags = fcntl(sd, F_GETFL, 0)) < 0) {
- smb_log(smbd.s_loghd, LOG_ERR,
+ syslog(LOG_ERR,
"smbd_nicmon: fcntl F_GETFL failed: %d", errno);
(void) close(sd);
return (-1);
}
if ((fcntl(sd, F_SETFL, flags | O_NONBLOCK)) < 0) {
- smb_log(smbd.s_loghd, LOG_ERR,
+ syslog(LOG_ERR,
"smbd_nicmon: fcntl F_SETFL failed: %d", errno);
(void) close(sd);
return (-1);
@@ -199,7 +199,7 @@ smbd_nicmon_needscan(int sock)
if (nbytes < rtm->rtm_msglen) {
if ((throttle % SMBD_NICMON_THROTTLE) == 0) {
- smb_log(smbd.s_loghd, LOG_DEBUG,
+ syslog(LOG_DEBUG,
"smbd_nicmon: short read: %d of %d",
nbytes, rtm->rtm_msglen);
}
@@ -230,7 +230,7 @@ smbd_nicmon_setup_eventpipe(int *read_pipe, int *write_pipe)
int fds[2];
if ((pipe(fds)) < 0) {
- smb_log(smbd.s_loghd, LOG_ERR,
+ syslog(LOG_ERR,
"smbd_nicmon: event pipe failed: %d", errno);
return (-1);
}
@@ -284,7 +284,7 @@ smbd_nicmon_daemon(void *arg)
if (errno == EINTR)
continue;
if ((throttle % SMBD_NICMON_THROTTLE) == 0)
- smb_log(smbd.s_loghd, LOG_DEBUG,
+ syslog(LOG_DEBUG,
"smbd_nicmon: poll failed: %d", errno);
++throttle;
break;
@@ -309,7 +309,7 @@ smbd_nicmon_daemon(void *arg)
if (smbd_nicmon_enabled && nic_changed &&
smbd_nicmon_caller_fmri) {
if (smf_refresh_instance(smbd_nicmon_caller_fmri) != 0)
- smb_log(smbd.s_loghd, LOG_ERR,
+ syslog(LOG_ERR,
"smbd_nicmon: %s refresh failed",
smbd_nicmon_caller_fmri);
}
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c
index 887e8c5b22..768be5feec 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_share_doorsvc.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -57,7 +58,8 @@ static void smbd_share_dispatch(void *, char *, size_t, door_desc_t *, uint_t);
int
smbd_share_start(void)
{
- int newfd;
+ int newfd;
+ const char *door_name;
(void) pthread_mutex_lock(&smb_share_dsrv_mtx);
@@ -77,9 +79,13 @@ smbd_share_start(void)
return (-1);
}
- (void) unlink(SMB_SHARE_DNAME);
+ door_name = getenv("SMB_SHARE_DNAME");
+ if (door_name == NULL)
+ door_name = SMB_SHARE_DNAME;
- if ((newfd = creat(SMB_SHARE_DNAME, 0644)) < 0) {
+ (void) unlink(door_name);
+
+ if ((newfd = creat(door_name, 0644)) < 0) {
syslog(LOG_ERR, "smbd_share_start: open: %s",
strerror(errno));
(void) door_revoke(smb_share_dsrv_fd);
@@ -89,9 +95,9 @@ smbd_share_start(void)
}
(void) close(newfd);
- (void) fdetach(SMB_SHARE_DNAME);
+ (void) fdetach(door_name);
- if (fattach(smb_share_dsrv_fd, SMB_SHARE_DNAME) < 0) {
+ if (fattach(smb_share_dsrv_fd, door_name) < 0) {
syslog(LOG_ERR, "smbd_share_start: fattach: %s",
strerror(errno));
(void) door_revoke(smb_share_dsrv_fd);
@@ -115,7 +121,12 @@ smbd_share_stop(void)
smbd_door_fini(&smb_share_sdh);
if (smb_share_dsrv_fd != -1) {
- (void) fdetach(SMB_SHARE_DNAME);
+ const char *door_name;
+
+ door_name = getenv("SMB_SHARE_DNAME");
+ if (door_name == NULL)
+ door_name = SMB_SHARE_DNAME;
+ (void) fdetach(door_name);
(void) door_revoke(smb_share_dsrv_fd);
smb_share_dsrv_fd = -1;
}
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_spool.c b/usr/src/cmd/smbsrv/smbd/smbd_spool.c
index 844484e918..aa040c4150 100644
--- a/usr/src/cmd/smbsrv/smbd/smbd_spool.c
+++ b/usr/src/cmd/smbsrv/smbd/smbd_spool.c
@@ -29,6 +29,7 @@
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/atomic.h>
#include <strings.h>
#include <syslog.h>
#include <signal.h>
@@ -115,7 +116,7 @@ smbd_spool_start(void)
(void) pthread_attr_destroy(&attr);
if (rc != 0)
- smb_log(smbd.s_loghd, LOG_NOTICE,
+ syslog(LOG_NOTICE,
"failed to start print monitor: %s", strerror(errno));
}
@@ -201,12 +202,12 @@ smbd_spool_copyfile(smb_inaddr_t *ipaddr, char *username, char *path,
char uri[HTTP_MAX_URI]; /* printer-uri attribute */
char new_jobname[SMBD_PJOBLEN];
smbd_printjob_t pjob;
- char clientname[INET6_ADDRSTRLEN];
+ char clientname[INET6_ADDRSTRLEN];
struct stat sbuf;
int rc = 1;
if (stat(path, &sbuf)) {
- smb_log(smbd.s_loghd, LOG_INFO, "smbd_spool_copyfile: %s: %s",
+ syslog(LOG_INFO, "smbd_spool_copyfile: %s: %s",
path, strerror(errno));
return;
}
@@ -217,7 +218,7 @@ smbd_spool_copyfile(smb_inaddr_t *ipaddr, char *username, char *path,
*/
if (sbuf.st_size == 0) {
if (remove(path) != 0)
- smb_log(smbd.s_loghd, LOG_INFO,
+ syslog(LOG_INFO,
"smbd_spool_copyfile: cannot remove %s: %s",
path, strerror(errno));
return;
@@ -227,13 +228,13 @@ smbd_spool_copyfile(smb_inaddr_t *ipaddr, char *username, char *path,
return;
if ((http = cups->httpConnect("localhost", 631)) == NULL) {
- smb_log(smbd.s_loghd, LOG_INFO,
+ syslog(LOG_INFO,
"smbd_spool_copyfile: cupsd not running");
return;
}
if ((request = cups->ippNew()) == NULL) {
- smb_log(smbd.s_loghd, LOG_INFO,
+ syslog(LOG_INFO,
"smbd_spool_copyfile: ipp not running");
return;
}
@@ -272,7 +273,7 @@ smbd_spool_copyfile(smb_inaddr_t *ipaddr, char *username, char *path,
if (smb_inet_ntop(ipaddr, clientname,
SMB_IPSTRLEN(ipaddr->a_family)) == NULL) {
- smb_log(smbd.s_loghd, LOG_INFO,
+ syslog(LOG_INFO,
"smbd_spool_copyfile: %s: unknown client", clientname);
goto out;
}
@@ -291,7 +292,7 @@ smbd_spool_copyfile(smb_inaddr_t *ipaddr, char *username, char *path,
pjob.pj_filename);
if (response != NULL) {
if (response->request.status.status_code >= IPP_OK_CONFLICT) {
- smb_log(smbd.s_loghd, LOG_ERR,
+ syslog(LOG_ERR,
"smbd_spool_copyfile: printer %s: %s",
SMBD_PRINTER,
cups->ippErrorString(cups->cupsLastError()));
@@ -300,7 +301,7 @@ smbd_spool_copyfile(smb_inaddr_t *ipaddr, char *username, char *path,
rc = 0;
}
} else {
- smb_log(smbd.s_loghd, LOG_ERR,
+ syslog(LOG_ERR,
"smbd_spool_copyfile: unable to print to %s",
cups->ippErrorString(cups->cupsLastError()));
}
@@ -331,7 +332,7 @@ smbd_cups_init(void)
if ((smb_cups.cups_hdl = dlopen("libcups.so.2", RTLD_NOW)) == NULL) {
(void) mutex_unlock(&smbd_cups_mutex);
- smb_log(smbd.s_loghd, LOG_DEBUG,
+ syslog(LOG_DEBUG,
"smbd_cups_init: cannot open libcups");
return (ENOENT);
}
@@ -380,7 +381,7 @@ smbd_cups_init(void)
(void) dlclose(smb_cups.cups_hdl);
smb_cups.cups_hdl = NULL;
(void) mutex_unlock(&smbd_cups_mutex);
- smb_log(smbd.s_loghd, LOG_DEBUG,
+ syslog(LOG_DEBUG,
"smbd_cups_init: cannot load libcups");
return (ENOENT);
}
@@ -427,7 +428,7 @@ smbd_load_printers(void)
(void) pthread_attr_destroy(&attr);
if (rc != 0)
- smb_log(smbd.s_loghd, LOG_NOTICE,
+ syslog(LOG_NOTICE,
"unable to load printer shares: %s", strerror(errno));
}
@@ -453,7 +454,7 @@ smbd_share_printers(void *arg)
return (NULL);
if (smb_shr_get(SMB_SHARE_PRINT, &si) != NERR_Success) {
- smb_log(smbd.s_loghd, LOG_DEBUG,
+ syslog(LOG_DEBUG,
"smbd_share_printers unable to load %s", SMB_SHARE_PRINT);
return (NULL);
}
@@ -470,10 +471,10 @@ smbd_share_printers(void *arg)
nerr = smb_shr_add(&si);
if (nerr == NERR_Success || nerr == NERR_DuplicateShare)
- smb_log(smbd.s_loghd, LOG_DEBUG,
+ syslog(LOG_DEBUG,
"shared printer: %s", si.shr_name);
else
- smb_log(smbd.s_loghd, LOG_DEBUG,
+ syslog(LOG_DEBUG,
"smbd_share_printers: unable to add share %s: %u",
si.shr_name, nerr);
}
diff --git a/usr/src/cmd/smbsrv/smbd/smbd_syslog.c b/usr/src/cmd/smbsrv/smbd/smbd_syslog.c
new file mode 100644
index 0000000000..46389ce226
--- /dev/null
+++ b/usr/src/cmd/smbsrv/smbd/smbd_syslog.c
@@ -0,0 +1,99 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <string.h>
+#include <syslog.h>
+
+#include <smbsrv/smbinfo.h>
+#include <smbsrv/smb_ioctl.h>
+#include "smbd.h"
+
+#define CBUFSIZ 26 /* ctime(3c) */
+
+static const char *pri_name[LOG_DEBUG+1] = {
+ "emerg", "alert", "crit", "err", "warning", "notice", "info", "debug"
+};
+
+static void
+smb_svc_log(int pri, const char *fmt, va_list ap)
+{
+ static time_t prev_ts;
+ char fbuf[SMBD_LOG_MSGSIZE];
+ char cbuf[CBUFSIZ];
+ char *newfmt;
+ time_t ts;
+ int save_errno = errno;
+
+ pri &= LOG_PRIMASK;
+ if (smbd.s_debug == 0 && pri == LOG_DEBUG)
+ return;
+
+ ts = time(NULL);
+ if (prev_ts != ts) {
+ prev_ts = ts;
+ /* NB: cbuf has \n */
+ (void) fprintf(stdout, "@ %s",
+ ctime_r(&ts, cbuf, sizeof (cbuf)));
+ }
+
+ newfmt = smb_syslog_fmt_m(fbuf, sizeof (fbuf), fmt, save_errno);
+
+ flockfile(stdout);
+ (void) fprintf(stdout, "smbd.%s: ", pri_name[pri]);
+ /* LINTED E_SEC_PRINTF_VAR_FMT */
+ (void) vfprintf(stdout, newfmt, ap);
+ (void) fprintf(stdout, "\n");
+ funlockfile(stdout);
+
+ (void) fflush(stdout);
+}
+
+/*
+ * Provide a replacement for libsmb:smb_vsyslog() that prints messages
+ * both to the normal sysloc(3c), and to stdout, which ends up in:
+ * /var/svc/log/network-smb-server:default.log
+ * It's much easier to follow debug messages in the service log.
+ */
+void
+smb_vsyslog(int pri, const char *fmt, va_list ap)
+{
+ va_list tap;
+
+ va_copy(tap, ap);
+ smb_svc_log(pri, fmt, tap);
+ va_end(tap);
+
+ vsyslog(pri, fmt, ap);
+}
+
+/*
+ * An override for libsmb:smb_trace(). As the comment there says:
+ *
+ * This function is designed to be used with dtrace, i.e. see:
+ * usr/src/cmd/smbsrv/dtrace/smbd-all.d
+ *
+ * Outside of dtrace, the messages passed to this function usually
+ * lack sufficient context to be useful, so don't log them.
+ * However, if you insist, set debug >= 3 and this will log them.
+ */
+void
+smb_trace(const char *s)
+{
+ if (smbd.s_debug >= 3)
+ (void) fprintf(stdout, "smbd.trace: %s\n", s);
+}
diff --git a/usr/src/common/acl/acl_common.c b/usr/src/common/acl/acl_common.c
index 494c5f73f4..6cfcb77937 100644
--- a/usr/src/common/acl/acl_common.c
+++ b/usr/src/common/acl/acl_common.c
@@ -20,13 +20,16 @@
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/errno.h>
#include <sys/avl.h>
-#if defined(_KERNEL)
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+#include <sys/debug.h>
+#include <sys/kmem.h>
#include <sys/systm.h>
#include <sys/sysmacros.h>
#include <acl/acl_common.h>
@@ -221,7 +224,7 @@ cmp2acls(void *a, void *b)
static void *
cacl_realloc(void *ptr, size_t size, size_t new_size)
{
-#if defined(_KERNEL)
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
void *tmp;
tmp = kmem_alloc(new_size, KM_SLEEP);
@@ -236,7 +239,7 @@ cacl_realloc(void *ptr, size_t size, size_t new_size)
static int
cacl_malloc(void **ptr, size_t size)
{
-#if defined(_KERNEL)
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
*ptr = kmem_zalloc(size, KM_SLEEP);
return (0);
#else
@@ -252,7 +255,7 @@ cacl_malloc(void **ptr, size_t size)
static void
cacl_free(void *ptr, size_t size)
{
-#if defined(_KERNEL)
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
kmem_free(ptr, size);
#else
free(ptr);
@@ -1462,7 +1465,7 @@ convert_ace_to_aent(ace_t *acebufp, int acecnt, boolean_t isdir,
int error = 0;
aclent_t *aclentp, *dfaclentp;
int aclcnt, dfaclcnt;
- int aclsz, dfaclsz;
+ int aclsz, dfaclsz = 0;
error = ln_ace_to_aent(acebufp, acecnt, owner, group,
&aclentp, &aclcnt, &dfaclentp, &dfaclcnt, isdir);
@@ -1553,11 +1556,11 @@ acl_translate(acl_t *aclp, int target_flavor, boolean_t isdir, uid_t owner,
out:
-#if !defined(_KERNEL)
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+ return (error);
+#else
errno = error;
return (-1);
-#else
- return (error);
#endif
}
diff --git a/usr/src/common/smbsrv/smb_door_legacy.c b/usr/src/common/smbsrv/smb_door_legacy.c
index 9568cda48f..985b83eb7a 100644
--- a/usr/src/common/smbsrv/smb_door_legacy.c
+++ b/usr/src/common/smbsrv/smb_door_legacy.c
@@ -21,13 +21,15 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Legacy encode/decode routines for door clients and servers.
*/
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
#include <errno.h>
#include <string.h>
#include <strings.h>
@@ -152,7 +154,7 @@ smb_dr_get_string(smb_dr_ctx_t *ctx)
*(buf + len) = '\0';
}
} else {
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
ctx->status = errno;
#else
ctx->status = ENOMEM;
diff --git a/usr/src/common/smbsrv/smb_inet.c b/usr/src/common/smbsrv/smb_inet.c
index 5822a49b24..2d56870fda 100644
--- a/usr/src/common/smbsrv/smb_inet.c
+++ b/usr/src/common/smbsrv/smb_inet.c
@@ -21,21 +21,31 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
* This file was originally generated using rpcgen.
*/
-#ifndef _KERNEL
-#include <string.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-#endif /* !_KERNEL */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
-#include <inet/tcp.h>
+
+#if !defined(_KERNEL)
+#include <errno.h>
+#include <string.h>
+#include <strings.h>
+#include <arpa/inet.h>
+#else /* !_KERNEL */
+#include <sys/errno.h>
+#include <sys/sunddi.h>
+/* Don't want the rest of what's in inet/ip.h */
+extern char *inet_ntop(int, const void *, char *, int);
+extern int inet_pton(int, char *, void *);
+#endif /* !_KERNEL */
+
#include <smbsrv/smb_inet.h>
const struct in6_addr ipv6addr_any = IN6ADDR_ANY_INIT;
@@ -50,7 +60,7 @@ smb_inet_equal(smb_inaddr_t *ip1, smb_inaddr_t *ip2)
if ((ip1->a_family == AF_INET6) &&
(ip2->a_family == AF_INET6) &&
- (!memcmp(&ip1->a_ipv6, &ip2->a_ipv6, IPV6_ADDR_LEN)))
+ (!memcmp(&ip1->a_ipv6, &ip2->a_ipv6, sizeof (in6_addr_t))))
return (B_TRUE);
else
return (B_FALSE);
@@ -66,7 +76,7 @@ smb_inet_same_subnet(smb_inaddr_t *ip1, smb_inaddr_t *ip2, uint32_t v4mask)
if ((ip1->a_family == AF_INET6) &&
(ip2->a_family == AF_INET6) &&
- (!memcmp(&ip1->a_ipv6, &ip2->a_ipv6, IPV6_ADDR_LEN)))
+ (!memcmp(&ip1->a_ipv6, &ip2->a_ipv6, sizeof (in6_addr_t))))
return (B_TRUE);
else
return (B_FALSE);
@@ -82,7 +92,7 @@ smb_inet_iszero(smb_inaddr_t *ipaddr)
return (B_TRUE);
if ((ipaddr->a_family == AF_INET6) &&
- !memcmp(&ipaddr->a_ipv6, ipsz, IPV6_ADDR_LEN))
+ !memcmp(&ipaddr->a_ipv6, ipsz, sizeof (in6_addr_t)))
return (B_TRUE);
else
return (B_FALSE);
@@ -91,5 +101,11 @@ smb_inet_iszero(smb_inaddr_t *ipaddr)
const char *
smb_inet_ntop(smb_inaddr_t *addr, char *buf, int size)
{
- return ((char *)inet_ntop(addr->a_family, (char *)addr, buf, size));
+ /* Lint avoidance. */
+#if !defined(_KERNEL)
+ size_t sz = (size_t)size;
+#else
+ int sz = size;
+#endif
+ return ((char *)inet_ntop(addr->a_family, addr, buf, sz));
}
diff --git a/usr/src/common/smbsrv/smb_match.c b/usr/src/common/smbsrv/smb_match.c
index 1a81af96b3..e687e3cc9f 100644
--- a/usr/src/common/smbsrv/smb_match.c
+++ b/usr/src/common/smbsrv/smb_match.c
@@ -21,14 +21,15 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
#include <stdlib.h>
#include <string.h>
#else
#include <sys/types.h>
+#include <sys/systm.h>
#include <sys/sunddi.h>
#endif
#include <smbsrv/string.h>
diff --git a/usr/src/common/smbsrv/smb_msgbuf.c b/usr/src/common/smbsrv/smb_msgbuf.c
index 2530a4f5ef..ff94a6243b 100644
--- a/usr/src/common/smbsrv/smb_msgbuf.c
+++ b/usr/src/common/smbsrv/smb_msgbuf.c
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -33,7 +35,7 @@
#include <sys/types.h>
#include <sys/varargs.h>
#include <sys/byteorder.h>
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
#include <stdlib.h>
#include <syslog.h>
#include <string.h>
@@ -161,7 +163,7 @@ smb_msgbuf_term(smb_msgbuf_t *mb)
while (item) {
tmp = item;
item = item->next;
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
free(tmp);
#else
kmem_free(tmp, tmp->size);
@@ -645,7 +647,7 @@ smb_msgbuf_malloc(smb_msgbuf_t *mb, size_t size)
size += sizeof (smb_msgbuf_mlist_t);
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
if ((item = malloc(size)) == NULL)
return (NULL);
#else
diff --git a/usr/src/common/smbsrv/smb_native.c b/usr/src/common/smbsrv/smb_native.c
index 592121461f..3489f28530 100644
--- a/usr/src/common/smbsrv/smb_native.c
+++ b/usr/src/common/smbsrv/smb_native.c
@@ -21,6 +21,8 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -28,7 +30,7 @@
* LanMan names to values.
*/
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#include <sys/types.h>
#include <sys/sunddi.h>
#else
diff --git a/usr/src/common/smbsrv/smb_netbios_util.c b/usr/src/common/smbsrv/smb_netbios_util.c
index 90ce36a1ed..803be49f2c 100644
--- a/usr/src/common/smbsrv/smb_netbios_util.c
+++ b/usr/src/common/smbsrv/smb_netbios_util.c
@@ -19,12 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#include <sys/types.h>
#include <sys/sunddi.h>
#else
diff --git a/usr/src/common/smbsrv/smb_oem.c b/usr/src/common/smbsrv/smb_oem.c
index c459fa2c6d..3917400f91 100644
--- a/usr/src/common/smbsrv/smb_oem.c
+++ b/usr/src/common/smbsrv/smb_oem.c
@@ -19,16 +19,17 @@
* CDDL HEADER END
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
* Support for oem <-> unicode translations.
*/
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
#include <stdlib.h>
#include <thread.h>
#include <synch.h>
@@ -307,7 +308,7 @@ oem_get_ucspage(uint32_t cpid)
static void
oem_codepage_init(uint32_t cpid)
{
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
static mutex_t mutex;
(void) mutex_lock(&mutex);
diff --git a/usr/src/common/smbsrv/smb_sid.c b/usr/src/common/smbsrv/smb_sid.c
index 763b3616f5..2a10ca767e 100644
--- a/usr/src/common/smbsrv/smb_sid.c
+++ b/usr/src/common/smbsrv/smb_sid.c
@@ -20,18 +20,19 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
#include <stdio.h>
#include <strings.h>
#include <stdlib.h>
#include <syslog.h>
-#include <smbsrv/libsmb.h>
-#else /* _KERNEL */
+#else /* !_KERNEL && !_FAKE_KERNEL */
#include <sys/types.h>
+#include <sys/systm.h>
#include <sys/sunddi.h>
-#endif /* _KERNEL */
+#endif /* !_KERNEL && !_FAKE_KERNEL */
#include <smbsrv/smb_sid.h>
@@ -150,14 +151,19 @@ smb_sid_t *
smb_sid_split(smb_sid_t *sid, uint32_t *rid)
{
smb_sid_t *domsid;
+ int size;
if (!smb_sid_isvalid(sid) || (sid->sid_subauthcnt == 0))
return (NULL);
- if ((domsid = smb_sid_dup(sid)) == NULL)
+ /* We will reduce sid_subauthcnt by one. */
+ size = smb_sid_len(sid) - sizeof (uint32_t);
+ if ((domsid = smb_sid_alloc(size)) == NULL)
return (NULL);
- --domsid->sid_subauthcnt;
+ bcopy(sid, domsid, size);
+ domsid->sid_subauthcnt = sid->sid_subauthcnt - 1;
+
if (rid)
*rid = domsid->sid_subauth[domsid->sid_subauthcnt];
@@ -183,7 +189,7 @@ smb_sid_splitstr(char *strsid, uint32_t *rid)
*p++ = '\0';
if (rid) {
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
unsigned long sua = 0;
(void) ddi_strtoul(p, NULL, 10, &sua);
*rid = (uint32_t)sua;
@@ -255,25 +261,6 @@ smb_sid_indomain(smb_sid_t *domain_sid, smb_sid_t *sid)
return (B_TRUE);
}
-#ifndef _KERNEL
-/*
- * smb_sid_islocal
- *
- * Check a SID to see if it belongs to the local domain.
- */
-boolean_t
-smb_sid_islocal(smb_sid_t *sid)
-{
- smb_domain_t di;
- boolean_t islocal = B_FALSE;
-
- if (smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di))
- islocal = smb_sid_indomain(di.di_binsid, sid);
-
- return (islocal);
-}
-#endif /* _KERNEL */
-
/*
* smb_sid_tostr
*
@@ -322,7 +309,7 @@ smb_sid_tostr(const smb_sid_t *sid, char *strsid)
* On success, a pointer to a SID is returned. Otherwise a null pointer
* is returned.
*/
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
smb_sid_t *
smb_sid_fromstr(const char *sidstr)
{
@@ -448,7 +435,7 @@ static smb_sid_t *
smb_sid_alloc(size_t size)
{
smb_sid_t *sid;
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
sid = kmem_alloc(size, KM_SLEEP);
#else
sid = malloc(size);
@@ -459,7 +446,7 @@ smb_sid_alloc(size_t size)
void
smb_sid_free(smb_sid_t *sid)
{
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
if (sid == NULL)
return;
@@ -468,20 +455,3 @@ smb_sid_free(smb_sid_t *sid)
free(sid);
#endif
}
-
-#ifndef _KERNEL
-void
-smb_ids_free(smb_ids_t *ids)
-{
- smb_id_t *id;
- int i;
-
- if ((ids != NULL) && (ids->i_ids != NULL)) {
- id = ids->i_ids;
- for (i = 0; i < ids->i_cnt; i++, id++)
- smb_sid_free(id->i_sid);
-
- free(ids->i_ids);
- }
-}
-#endif
diff --git a/usr/src/common/smbsrv/smb_string.c b/usr/src/common/smbsrv/smb_string.c
index 992c660c7a..8400c51ea1 100644
--- a/usr/src/common/smbsrv/smb_string.c
+++ b/usr/src/common/smbsrv/smb_string.c
@@ -19,12 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#include <sys/types.h>
#include <sys/sunddi.h>
#else
@@ -442,7 +443,7 @@ smb_unc_init(const char *path, smb_unc_t *unc)
bzero(unc, sizeof (smb_unc_t));
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
unc->unc_buf = smb_mem_strdup(path);
#else
if ((unc->unc_buf = strdup(path)) == NULL)
@@ -493,7 +494,7 @@ smb_unc_free(smb_unc_t *unc)
if (unc == NULL)
return;
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
smb_mem_free(unc->unc_buf);
#else
free(unc->unc_buf);
diff --git a/usr/src/common/smbsrv/smb_token.c b/usr/src/common/smbsrv/smb_token.c
index 573a20d369..b77b9a44a0 100644
--- a/usr/src/common/smbsrv/smb_token.c
+++ b/usr/src/common/smbsrv/smb_token.c
@@ -21,13 +21,15 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
* NT Token library (kernel/user)
*/
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#include <sys/types.h>
#include <sys/cmn_err.h>
#include <sys/kmem.h>
@@ -93,7 +95,7 @@ smb_token_valid(smb_token_t *token)
return (B_TRUE);
}
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
/*
* Encode: structure -> flat buffer (buffer size)
* Pre-condition: obj is non-null.
diff --git a/usr/src/common/smbsrv/smb_token_xdr.c b/usr/src/common/smbsrv/smb_token_xdr.c
index 8c13321fad..6b44899768 100644
--- a/usr/src/common/smbsrv/smb_token_xdr.c
+++ b/usr/src/common/smbsrv/smb_token_xdr.c
@@ -27,7 +27,7 @@
* This file was originally generated using rpcgen.
*/
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
#include <stdlib.h>
#endif /* !_KERNEL */
#include <smbsrv/wintypes.h>
diff --git a/usr/src/common/smbsrv/smb_utf8.c b/usr/src/common/smbsrv/smb_utf8.c
index a328e32f7b..3b84363dbd 100644
--- a/usr/src/common/smbsrv/smb_utf8.c
+++ b/usr/src/common/smbsrv/smb_utf8.c
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -48,7 +50,7 @@
* October 1996
*/
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#include <sys/types.h>
#include <sys/sunddi.h>
#else
@@ -210,7 +212,7 @@ smb_wcstombs(char *mbstring, const smb_wchar_t *wcstring, size_t nbytes)
{
char *start = mbstring;
const smb_wchar_t *wcp = wcstring;
- smb_wchar_t wide_char;
+ smb_wchar_t wide_char = 0;
char buf[4];
size_t len;
diff --git a/usr/src/common/smbsrv/smb_xdr.c b/usr/src/common/smbsrv/smb_xdr.c
index fc9153394d..54e0cc8222 100644
--- a/usr/src/common/smbsrv/smb_xdr.c
+++ b/usr/src/common/smbsrv/smb_xdr.c
@@ -24,7 +24,7 @@
*/
#include <sys/sunddi.h>
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
#include <string.h>
#include <strings.h>
#include <stddef.h>
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile
index 6d8588d839..144d9cfa3d 100644
--- a/usr/src/lib/Makefile
+++ b/usr/src/lib/Makefile
@@ -253,6 +253,7 @@ SUBDIRS += \
libvrrpadm \
libvscan \
libgrubmgmt \
+ libfakekernel \
smbsrv \
libilb \
scsi \
@@ -403,6 +404,7 @@ HDRSUBDIRS= \
libdtrace_jni \
libelfsign \
libeti \
+ libfakekernel \
libfru \
libfstyp \
libgen \
@@ -648,7 +650,7 @@ libexacct/demo: libexacct libproject libsocket libnsl
libtsalarm: libpcp
smbsrv: libsocket libnsl libmd libxnet libpthread librt \
libshare libidmap pkcs11 libsqlite libcryptoutil \
- libreparse libcmdutils
+ libreparse libcmdutils libfakekernel
libv12n: libds libuuid
libvrrpadm: libsocket libdladm libscf
libvscan: libscf
diff --git a/usr/src/lib/libfakekernel/Makefile b/usr/src/lib/libfakekernel/Makefile
new file mode 100644
index 0000000000..34ed30c6a1
--- /dev/null
+++ b/usr/src/lib/libfakekernel/Makefile
@@ -0,0 +1,63 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
+
+include ../Makefile.lib
+
+HDRS= fakekernel.h
+HDRDIR= common
+
+ROOTHDRDIR= $(ROOT)/usr/include/libfakekernel
+ROOTHDRS= $(HDRS:%=$(ROOTHDRDIR)/%)
+
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET= all
+clean := TARGET= clean
+clobber := TARGET= clobber
+install := TARGET= install
+lint := TARGET= lint
+
+.KEEP_STATE:
+
+all clean clobber install lint: $(SUBDIRS)
+
+install_h: $(ROOTHDRDIR) $(ROOTHDRS)
+
+check: $(CHECKHDRS)
+
+$(ROOTHDRDIR)/%: $(HDRDIR)/%
+ $(INS.file)
+
+$(ROOTHDRDIR):
+ $(INS.dir)
+
+$(MACH) $(MACH64): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
diff --git a/usr/src/lib/libfakekernel/Makefile.com b/usr/src/lib/libfakekernel/Makefile.com
new file mode 100644
index 0000000000..a6a35c96e0
--- /dev/null
+++ b/usr/src/lib/libfakekernel/Makefile.com
@@ -0,0 +1,75 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
+
+LIBRARY = libfakekernel.a
+VERS = .1
+
+COBJS = \
+ cred.o \
+ clock.o \
+ cond.o \
+ copy.o \
+ kiconv.o \
+ kmem.o \
+ kmisc.o \
+ ksocket.o \
+ kstat.o \
+ mutex.o \
+ printf.o \
+ random.o \
+ rwlock.o \
+ sema.o \
+ taskq.o \
+ thread.o \
+ uio.o
+
+OBJECTS= $(COBJS)
+
+include ../../Makefile.lib
+
+SRCDIR= ../common
+
+LIBS = $(DYNLIB) $(LINTLIB)
+SRCS= $(COBJS:%.o=$(SRCDIR)/%.c)
+
+$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
+
+C99MODE = -xc99=%all
+C99LMODE = -Xc99=%all
+
+# Note: need our sys includes _before_ ENVCPPFLAGS, proto etc.
+CPPFLAGS.first += -I../common
+
+CFLAGS += $(CCVERBOSE)
+CPPFLAGS += $(INCS) -D_REENTRANT -D_FAKE_KERNEL
+CPPFLAGS += -D_FILE_OFFSET_BITS=64
+
+# Could make this $(NOT_RELEASE_BUILD) but as the main purpose of
+# this library is for debugging, let's always define DEBUG here.
+CPPFLAGS += -DDEBUG
+
+LINTCHECKFLAGS += -erroff=E_INCONS_ARG_DECL2
+LINTCHECKFLAGS += -erroff=E_INCONS_VAL_TYPE_DECL2
+LINTCHECKFLAGS += -erroff=E_INCONS_VAL_TYPE_USED2
+
+LDLIBS += -lumem -lcryptoutil -lsocket -lc
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+lint: lintcheck
+
+include ../../Makefile.targ
diff --git a/usr/src/lib/libfakekernel/amd64/Makefile b/usr/src/lib/libfakekernel/amd64/Makefile
new file mode 100644
index 0000000000..6792bbc3bb
--- /dev/null
+++ b/usr/src/lib/libfakekernel/amd64/Makefile
@@ -0,0 +1,32 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2004 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/libfakekernel/common/clock.c b/usr/src/lib/libfakekernel/common/clock.c
new file mode 100644
index 0000000000..dde86bdcfd
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/clock.c
@@ -0,0 +1,92 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
+
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/thread.h>
+#include <sys/proc.h>
+
+#include <sys/poll.h>
+
+#include <time.h>
+
+int hz = 1000;
+int tick_per_msec = 0;
+int msec_per_tick = 1;
+int usec_per_tick = 1000;
+int nsec_per_tick = 1000000;
+time_t boot_time = 0;
+
+#pragma init(_boot_time_init)
+static int
+_boot_time_init(void)
+{
+ boot_time = time(NULL);
+ return (0);
+}
+
+clock_t
+ddi_get_lbolt(void)
+{
+ hrtime_t hrt;
+
+ hrt = gethrtime();
+ return (hrt / nsec_per_tick);
+}
+
+int64_t
+ddi_get_lbolt64(void)
+{
+ hrtime_t hrt;
+
+ hrt = gethrtime();
+ return (hrt / nsec_per_tick);
+}
+
+void
+clock2ts(clock_t clk, timespec_t *ts)
+{
+ ts->tv_sec = clk / hz;
+ ts->tv_nsec = (clk % hz) * (NANOSEC / hz);
+}
+
+hrtime_t
+gethrtime_unscaled(void)
+{
+ return (gethrtime());
+}
+
+void
+gethrestime(timespec_t *ts)
+{
+ hrtime_t hrt;
+
+ hrt = gethrtime();
+ ts->tv_sec = hrt / NANOSEC;
+ ts->tv_nsec = hrt % NANOSEC;
+}
+
+time_t
+gethrestime_sec(void)
+{
+ return (time(NULL));
+}
+
+/* ARGSUSED */
+void
+scalehrtime(hrtime_t *t)
+{
+}
diff --git a/usr/src/lib/libfakekernel/common/cond.c b/usr/src/lib/libfakekernel/common/cond.c
new file mode 100644
index 0000000000..0ed2ea7b73
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/cond.c
@@ -0,0 +1,180 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * condvar(9f)
+ */
+
+/* This is the API we're emulating */
+#include <sys/condvar.h>
+
+#include <sys/errno.h>
+#include <sys/debug.h>
+#include <sys/thread.h>
+
+/* avoiding synch.h */
+int _lwp_cond_wait(lwp_cond_t *, lwp_mutex_t *);
+int _lwp_cond_timedwait(lwp_cond_t *, lwp_mutex_t *, timespec_t *);
+int _lwp_cond_reltimedwait(lwp_cond_t *, lwp_mutex_t *, timespec_t *);
+int _lwp_cond_signal(lwp_cond_t *);
+int _lwp_cond_broadcast(lwp_cond_t *);
+
+
+extern clock_t ddi_get_lbolt(void);
+extern void clock2ts(clock_t, timespec_t *);
+
+static int cv__wait(kcondvar_t *, kmutex_t *, int);
+static clock_t cv__twait(kcondvar_t *, kmutex_t *, clock_t, int);
+
+static const lwp_cond_t default_cv =
+ {{{0, 0, 0, 0}, USYNC_THREAD, _COND_MAGIC}, 0};
+
+
+/* ARGSUSED */
+void
+cv_init(kcondvar_t *cv, char *name, kcv_type_t typ, void *arg)
+{
+ *cv = default_cv;
+}
+
+/* ARGSUSED */
+void
+cv_destroy(kcondvar_t *cv)
+{
+}
+
+void
+cv_signal(kcondvar_t *cv)
+{
+ (void) _lwp_cond_signal(cv);
+}
+
+void
+cv_broadcast(kcondvar_t *cv)
+{
+ (void) _lwp_cond_broadcast(cv);
+}
+
+void
+cv_wait(kcondvar_t *cv, kmutex_t *mp)
+{
+ (void) cv__wait(cv, mp, 0);
+}
+
+int
+cv_wait_sig(kcondvar_t *cv, kmutex_t *mp)
+{
+ return (cv__wait(cv, mp, 1));
+}
+
+int
+cv__wait(kcondvar_t *cv, kmutex_t *mp, int sigok)
+{
+ int err;
+
+top:
+ ASSERT(mp->m_owner == _curthread());
+ mp->m_owner = _KTHREAD_INVALID;
+ err = _lwp_cond_wait(cv, &mp->m_lock);
+ mp->m_owner = _curthread();
+
+ if (err == 0)
+ return (1);
+ if (err == EINTR) {
+ if (sigok)
+ return (0);
+ goto top;
+ }
+ return (-1);
+}
+
+clock_t
+cv_timedwait(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
+{
+ clock_t delta;
+
+ delta = abstime - ddi_get_lbolt();
+ return (cv__twait(cv, mp, delta, 0));
+}
+
+clock_t
+cv_timedwait_sig(kcondvar_t *cv, kmutex_t *mp, clock_t abstime)
+{
+ clock_t delta;
+
+ delta = abstime - ddi_get_lbolt();
+ return (cv__twait(cv, mp, delta, 1));
+}
+
+clock_t
+cv_reltimedwait(kcondvar_t *cv, kmutex_t *mp, clock_t delta, time_res_t res)
+{
+ _NOTE(ARGUNUSED(res))
+
+ return (cv__twait(cv, mp, delta, 0));
+}
+
+clock_t
+cv_reltimedwait_sig(kcondvar_t *cv, kmutex_t *mp, clock_t delta,
+ time_res_t res)
+{
+ _NOTE(ARGUNUSED(res))
+
+ return (cv__twait(cv, mp, delta, 1));
+}
+
+/*
+ * Factored out implementation of all the cv_*timedwait* functions.
+ * Note that the delta passed in is relative to the (simulated)
+ * current time reported by ddi_get_lbolt(). Convert that to
+ * timespec format and keep calling _lwp_cond_reltimedwait,
+ * which (NB!) decrements that delta in-place!
+ */
+static clock_t
+cv__twait(kcondvar_t *cv, kmutex_t *mp, clock_t delta, int sigok)
+{
+ timestruc_t ts;
+ int err;
+
+ if (delta <= 0)
+ return (-1);
+
+ clock2ts(delta, &ts);
+
+top:
+ if (ts.tv_sec == 0 && ts.tv_nsec == 0)
+ return (-1);
+
+ ASSERT(mp->m_owner == _curthread());
+ mp->m_owner = _KTHREAD_INVALID;
+ err = _lwp_cond_reltimedwait(cv, &mp->m_lock, &ts);
+ mp->m_owner = _curthread();
+
+ switch (err) {
+ case 0:
+ return (1);
+ case EINTR:
+ if (sigok)
+ return (0);
+ goto top;
+ default:
+ ASSERT(0);
+ /* FALLTHROUGH */
+ case ETIME:
+ break;
+ }
+
+ return (-1);
+}
diff --git a/usr/src/lib/libfakekernel/common/copy.c b/usr/src/lib/libfakekernel/common/copy.c
new file mode 100644
index 0000000000..b1eb215b5c
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/copy.c
@@ -0,0 +1,50 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+
+int
+copyinstr(const char *src, char *dst, size_t max_len, size_t *copied)
+{
+ return (copystr(src, dst, max_len, copied));
+}
+
+int
+copystr(const char *src, char *dst, size_t max_len, size_t *outlen)
+{
+ size_t copied;
+
+ if (max_len == 0)
+ return (ENAMETOOLONG);
+
+ copied = strlcpy(dst, src, max_len) + 1;
+ if (copied >= max_len)
+ return (ENAMETOOLONG);
+
+ if (outlen != NULL)
+ *outlen = copied;
+
+ return (0);
+}
+
+void
+ovbcopy(const void *src, void *dst, size_t len)
+{
+ (void) memmove(dst, src, len);
+}
diff --git a/usr/src/lib/libfakekernel/common/cred.c b/usr/src/lib/libfakekernel/common/cred.c
new file mode 100644
index 0000000000..01baeb9f66
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/cred.c
@@ -0,0 +1,59 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/thread.h>
+#include <sys/cred.h>
+
+struct cred {
+ uint32_t pad[100];
+};
+
+cred_t cred0;
+cred_t *kcred = &cred0;
+
+cred_t *
+_curcred(void)
+{
+ /* Thread-specific data? */
+ return (&cred0);
+}
+
+/*ARGSUSED*/
+void
+crfree(cred_t *cr)
+{
+}
+
+/*ARGSUSED*/
+void
+crhold(cred_t *cr)
+{
+}
+
+/*ARGSUSED*/
+uid_t
+crgetuid(const cred_t *cr)
+{
+ return (0);
+}
+
+cred_t *
+zone_kcred(void)
+{
+ return (kcred);
+}
diff --git a/usr/src/lib/libfakekernel/common/fakekernel.h b/usr/src/lib/libfakekernel/common/fakekernel.h
new file mode 100644
index 0000000000..fc1c403f47
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/fakekernel.h
@@ -0,0 +1,35 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _FAKEKERNEL_H
+#define _FAKEKERNEL_H
+
+#include <sys/types.h>
+#include <sys/varargs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void fakekernel_init(void);
+void fakekernel_putlog(char *, size_t, int);
+void fakekernel_cprintf(const char *, va_list, int,
+ const char *, const char *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FAKEKERNEL_H */
diff --git a/usr/src/lib/libfakekernel/common/kiconv.c b/usr/src/lib/libfakekernel/common/kiconv.c
new file mode 100644
index 0000000000..7d33813eb7
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/kiconv.c
@@ -0,0 +1,57 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#include <sys/errno.h>
+#include <sys/kiconv.h>
+
+#include <errno.h>
+#include <iconv.h>
+
+
+kiconv_t
+kiconv_open(const char *tocode, const char *fromcode)
+{
+ return (iconv_open(tocode, fromcode));
+}
+
+int
+kiconv_close(kiconv_t handle)
+{
+ if (iconv_close(handle) < 0)
+ return (EBADF);
+
+ return (0);
+}
+
+size_t
+kiconv(
+ kiconv_t handle,
+ char **inbuf,
+ size_t *inbytesleft,
+ char **outbuf,
+ size_t *outbytesleft,
+ int *errno_out)
+{
+ size_t code;
+
+ code = iconv(handle, (const char **)inbuf, inbytesleft,
+ outbuf, outbytesleft);
+ *errno_out = errno;
+ return (code);
+}
diff --git a/usr/src/lib/libfakekernel/common/kmem.c b/usr/src/lib/libfakekernel/common/kmem.c
new file mode 100644
index 0000000000..82d1cfeaef
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/kmem.c
@@ -0,0 +1,151 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/kmem.h>
+
+#include <sys/debug.h>
+#include <sys/ksynch.h>
+#include <sys/systm.h>
+
+#include <umem.h>
+
+void abort(void) __NORETURN;
+
+static int
+kmem_failed_cb(void)
+{
+ abort();
+ return (UMEM_CALLBACK_RETRY);
+}
+
+#pragma init(_kmem_init)
+static int
+_kmem_init(void)
+{
+ umem_nofail_callback(kmem_failed_cb);
+ return (0);
+}
+
+static int
+kmem2umem_flags(int kmflags)
+{
+ int umflags = UMEM_NOFAIL;
+ if (kmflags & KM_NOSLEEP)
+ umflags = UMEM_DEFAULT;
+ return (umflags);
+}
+
+int
+kmem_debugging(void)
+{
+ return (0);
+}
+
+void *
+kmem_alloc(size_t size, int kmflags)
+{
+ return (umem_alloc(size, kmem2umem_flags(kmflags)));
+}
+
+void *
+kmem_zalloc(size_t size, int kmflags)
+{
+ return (umem_zalloc(size, kmem2umem_flags(kmflags)));
+}
+
+
+void
+kmem_free(void *buf, size_t size)
+{
+ umem_free(buf, size);
+}
+
+/* void *kmem_alloc_tryhard(size_t size, size_t *alloc_size, int kmflags); */
+
+kmem_cache_t *
+kmem_cache_create(
+ char *name, /* descriptive name for this cache */
+ size_t bufsize, /* size of the objects it manages */
+ size_t align, /* required object alignment */
+ int (*constructor)(void *, void *, int), /* object constructor */
+ void (*destructor)(void *, void *), /* object destructor */
+ void (*reclaim)(void *), /* memory reclaim callback */
+ void *private, /* pass-thru arg for constr/destr/reclaim */
+ vmem_t *vmp, /* vmem source for slab allocation */
+ int kcflags) /* cache creation flags */
+{
+ umem_cache_t *uc;
+ int ucflags = 0;
+
+ /* Ignore KMC_NOTOUCH - not needed for userland caches */
+ if (kcflags & KMC_NODEBUG)
+ ucflags |= UMC_NODEBUG;
+ if (kcflags & KMC_NOMAGAZINE)
+ ucflags |= UMC_NOMAGAZINE;
+ if (kcflags & KMC_NOHASH)
+ ucflags |= UMC_NOHASH;
+
+ uc = umem_cache_create(name, bufsize, align,
+ constructor, destructor, reclaim,
+ private, vmp, ucflags);
+ return ((kmem_cache_t *)uc);
+}
+
+void
+kmem_cache_destroy(kmem_cache_t *kc)
+{
+ umem_cache_destroy((umem_cache_t *)kc);
+}
+
+void *
+kmem_cache_alloc(kmem_cache_t *kc, int kmflags)
+{
+ return (umem_cache_alloc((umem_cache_t *)kc,
+ kmem2umem_flags(kmflags)));
+}
+
+void
+kmem_cache_free(kmem_cache_t *kc, void *p)
+{
+ umem_cache_free((umem_cache_t *)kc, p);
+}
+
+/* ARGSUSED */
+void
+kmem_cache_set_move(kmem_cache_t *kc,
+ kmem_cbrc_t (*fun)(void *, void *, size_t, void *))
+{
+}
+
+/* ARGSUSED */
+void
+kmem_cache_reap_now(kmem_cache_t *kc)
+{
+}
+
+/* uint64_t kmem_cache_stat(kmem_cache_t *, char *); */
+
+/* ARGSUSED */
+void
+vmem_qcache_reap(struct vmem *vmp)
+{
+}
+
+void
+strfree(char *str)
+{
+ ASSERT(str != NULL);
+ kmem_free(str, strlen(str) + 1);
+}
diff --git a/usr/src/lib/libfakekernel/common/kmisc.c b/usr/src/lib/libfakekernel/common/kmisc.c
new file mode 100644
index 0000000000..686812e9b0
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/kmisc.c
@@ -0,0 +1,81 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/thread.h>
+#include <sys/proc.h>
+#include <sys/zone.h>
+
+#include <sys/poll.h>
+
+#include <time.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <fakekernel.h>
+
+pri_t minclsyspri = 60;
+
+/* Some kernel code takes the address of this. */
+proc_t p0;
+
+proc_t *
+_curproc(void)
+{
+ return (&p0);
+}
+
+zone_t zone0 = {
+ .zone_name = "global",
+ .zone_zsched = &p0, 0
+};
+
+zone_t *
+_curzone(void)
+{
+ return (&zone0);
+}
+
+pid_t
+ddi_get_pid(void)
+{
+ return ((pid_t)getpid());
+}
+
+int
+ddi_strtoul(const char *str, char **endp, int base, unsigned long *res)
+{
+ *res = strtoul(str, endp, base);
+ return (0);
+}
+
+void
+delay(clock_t ticks)
+{
+ int msec = ticks; /* NB: hz==1000 */
+ (void) poll(0, 0, msec);
+}
+
+/*
+ * This library does not really need an "init" function, but
+ * providing one the main program can call is an easy way to
+ * make sure this library is loaded into the debugger, and
+ * gives us a way to avoid elfcheck complaints in the build.
+ */
+void
+fakekernel_init(void)
+{
+}
diff --git a/usr/src/lib/libfakekernel/common/ksocket.c b/usr/src/lib/libfakekernel/common/ksocket.c
new file mode 100644
index 0000000000..53bcf87576
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/ksocket.c
@@ -0,0 +1,535 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/cred.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <sys/ksocket.h>
+#include <sys/debug.h>
+#include <sys/kmem.h>
+#include <unistd.h>
+#include <errno.h>
+#include <umem.h>
+
+#define _KSOCKET_MAGIC 0xabcdef09
+
+#define KSOCKET_VALID(ks) (ks->kso_magic == _KSOCKET_MAGIC)
+#define KSTOSO(ks) (ks->kso_fd)
+
+#ifndef SS_CLOSING
+#define SS_CLOSING 0x00010000
+#endif
+
+/*
+ * NB: you can't cast this into a sonode like you can with a normal
+ * ksocket_t, but no correct code should ever do that anyway.
+ * The ksocket_t type is opaque to prevent exactly that.
+ */
+struct __ksocket {
+ uint32_t kso_magic;
+ uint32_t kso_count;
+ uint32_t kso_state;
+ int kso_fd;
+ kmutex_t kso_lock;
+ kcondvar_t kso_closing_cv;
+};
+
+static umem_cache_t *ksocket_cache = NULL;
+
+/*ARGSUSED*/
+static int
+_ksocket_ctor(void *buf, void *arg, int flags)
+{
+ ksocket_t sock = buf;
+
+ bzero(sock, sizeof (*sock));
+ mutex_init(&sock->kso_lock, NULL, MUTEX_DEFAULT, NULL);
+ cv_init(&sock->kso_closing_cv, NULL, CV_DEFAULT, NULL);
+ return (0);
+}
+
+/*ARGSUSED*/
+static void
+_ksocket_dtor(void *buf, void *arg)
+{
+ ksocket_t sock = buf;
+
+ mutex_destroy(&sock->kso_lock);
+ cv_destroy(&sock->kso_closing_cv);
+}
+
+#pragma init(_ksocket_init)
+int
+_ksocket_init(void)
+{
+ ksocket_cache = umem_cache_create("ksocket",
+ sizeof (struct __ksocket), 0,
+ _ksocket_ctor, _ksocket_dtor, NULL, NULL, NULL, 0);
+ VERIFY(ksocket_cache != NULL);
+ return (0);
+}
+
+#pragma fini(_ksocket_fini)
+int
+_ksocket_fini(void)
+{
+ umem_cache_destroy(ksocket_cache);
+ return (0);
+}
+
+static ksocket_t
+_ksocket_create(int fd)
+{
+ ksocket_t ks;
+
+ ks = umem_cache_alloc(ksocket_cache, 0);
+ VERIFY(ks != NULL);
+ ks->kso_magic = _KSOCKET_MAGIC;
+ ks->kso_count = 1;
+ ks->kso_fd = fd;
+ return (ks);
+}
+
+static void
+_ksocket_destroy(ksocket_t ks)
+{
+ ASSERT(ks->kso_count == 1);
+ umem_cache_free(ksocket_cache, ks);
+}
+
+int
+ksocket_socket(ksocket_t *ksp, int domain, int type, int protocol, int flags,
+ struct cred *cr)
+{
+ int fd;
+ ksocket_t ks;
+
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ ASSERT(flags == KSOCKET_SLEEP || flags == KSOCKET_NOSLEEP);
+
+ fd = socket(domain, type, protocol);
+ if (fd < 0) {
+ *ksp = NULL;
+ return (errno);
+ }
+
+ ks = _ksocket_create(fd);
+ *ksp = ks;
+ return (0);
+}
+
+/*
+ * This is marked NODIRECT so the main program linking with this library
+ * can provide its own "bind helper" function. See: fksmbd_ksock.c
+ */
+/* ARGSUSED */
+int
+ksocket_bind_helper(int fd, struct sockaddr *addr, uint_t addrlen)
+{
+ return (EACCES);
+}
+
+int
+ksocket_bind(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen,
+ struct cred *cr)
+{
+ int err = 0;
+
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ if (!KSOCKET_VALID(ks))
+ return (ENOTSOCK);
+
+ if (bind(KSTOSO(ks), addr, addrlen) != 0)
+ err = errno;
+
+ if (err == EACCES) {
+ err = ksocket_bind_helper(KSTOSO(ks), addr, addrlen);
+ }
+
+ return (err);
+}
+
+int
+ksocket_listen(ksocket_t ks, int backlog, struct cred *cr)
+{
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ if (!KSOCKET_VALID(ks))
+ return (ENOTSOCK);
+
+ if (listen(KSTOSO(ks), backlog) != 0)
+ return (errno);
+
+ return (0);
+}
+
+int
+ksocket_accept(ksocket_t ks, struct sockaddr *addr,
+ socklen_t *addrlenp, ksocket_t *nks, struct cred *cr)
+{
+ int fd;
+
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ *nks = NULL;
+
+ if (!KSOCKET_VALID(ks))
+ return (ENOTSOCK);
+
+ if (addr != NULL && addrlenp == NULL)
+ return (EFAULT);
+
+ fd = accept(KSTOSO(ks), addr, addrlenp);
+ if (fd < 0)
+ return (errno);
+
+ *nks = _ksocket_create(fd);
+
+ return (0);
+}
+
+int
+ksocket_connect(ksocket_t ks, struct sockaddr *addr, socklen_t addrlen,
+ struct cred *cr)
+{
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ if (!KSOCKET_VALID(ks))
+ return (ENOTSOCK);
+
+ if (connect(KSTOSO(ks), addr, addrlen) != 0)
+ return (errno);
+
+ return (0);
+}
+
+int
+ksocket_send(ksocket_t ks, void *msg, size_t msglen, int flags,
+ size_t *sent, struct cred *cr)
+{
+ ssize_t error;
+
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ if (!KSOCKET_VALID(ks)) {
+ if (sent != NULL)
+ *sent = 0;
+ return (ENOTSOCK);
+ }
+
+ error = send(KSTOSO(ks), msg, msglen, flags);
+ if (error < 0) {
+ if (sent != NULL)
+ *sent = 0;
+ return (errno);
+ }
+
+ if (sent != NULL)
+ *sent = (size_t)error;
+ return (0);
+}
+
+int
+ksocket_sendto(ksocket_t ks, void *msg, size_t msglen, int flags,
+ struct sockaddr *name, socklen_t namelen, size_t *sent, struct cred *cr)
+{
+ ssize_t error;
+
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ if (!KSOCKET_VALID(ks)) {
+ if (sent != NULL)
+ *sent = 0;
+ return (ENOTSOCK);
+ }
+
+ error = sendto(KSTOSO(ks), msg, msglen, flags, name, namelen);
+ if (error < 0) {
+ if (sent != NULL)
+ *sent = 0;
+ return (errno);
+ }
+
+ if (sent != NULL)
+ *sent = (size_t)error;
+ return (0);
+}
+
+int
+ksocket_sendmsg(ksocket_t ks, struct nmsghdr *msg, int flags,
+ size_t *sent, struct cred *cr)
+{
+ ssize_t error;
+
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ if (!KSOCKET_VALID(ks)) {
+ if (sent != NULL)
+ *sent = 0;
+ return (ENOTSOCK);
+ }
+
+ error = sendmsg(KSTOSO(ks), msg, flags);
+ if (error < 0) {
+ if (sent != NULL)
+ *sent = 0;
+ return (errno);
+ }
+
+ if (sent != NULL)
+ *sent = (size_t)error;
+ return (0);
+}
+
+int
+ksocket_recv(ksocket_t ks, void *msg, size_t msglen, int flags,
+ size_t *recvd, struct cred *cr)
+{
+ ssize_t error;
+
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ if (!KSOCKET_VALID(ks)) {
+ if (recvd != NULL)
+ *recvd = 0;
+ return (ENOTSOCK);
+ }
+
+ error = recv(KSTOSO(ks), msg, msglen, flags);
+ if (error < 0) {
+ if (recvd != NULL)
+ *recvd = 0;
+ return (errno);
+ }
+
+ if (recvd != NULL)
+ *recvd = (size_t)error;
+ return (0);
+}
+
+int
+ksocket_recvfrom(ksocket_t ks, void *msg, size_t msglen, int flags,
+ struct sockaddr *name, socklen_t *namelen, size_t *recvd, struct cred *cr)
+{
+ ssize_t error;
+
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ if (!KSOCKET_VALID(ks)) {
+ if (recvd != NULL)
+ *recvd = 0;
+ return (ENOTSOCK);
+ }
+
+ error = recvfrom(KSTOSO(ks), msg, msglen, flags, name, namelen);
+ if (error != 0) {
+ if (recvd != NULL)
+ *recvd = 0;
+ return (errno);
+ }
+
+ if (recvd != NULL)
+ *recvd = (ssize_t)error;
+ return (0);
+}
+
+int
+ksocket_recvmsg(ksocket_t ks, struct nmsghdr *msg, int flags, size_t *recvd,
+ struct cred *cr)
+{
+ ssize_t error;
+
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ if (!KSOCKET_VALID(ks)) {
+ if (recvd != NULL)
+ *recvd = 0;
+ return (ENOTSOCK);
+ }
+
+ error = recvmsg(KSTOSO(ks), msg, flags);
+ if (error < 0) {
+ if (recvd != NULL)
+ *recvd = 0;
+ return (errno);
+ }
+
+ if (recvd != NULL)
+ *recvd = (size_t)error;
+ return (0);
+}
+
+int
+ksocket_shutdown(ksocket_t ks, int how, struct cred *cr)
+{
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ if (!KSOCKET_VALID(ks))
+ return (ENOTSOCK);
+
+ if (shutdown(KSTOSO(ks), how) != 0)
+ return (errno);
+
+ return (0);
+}
+
+int
+ksocket_close(ksocket_t ks, struct cred *cr)
+{
+ int fd;
+
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ mutex_enter(&ks->kso_lock);
+
+ if (!KSOCKET_VALID(ks)) {
+ mutex_exit(&ks->kso_lock);
+ return (ENOTSOCK);
+ }
+
+ ks->kso_state |= SS_CLOSING;
+
+ /*
+ * The real ksocket wakes up everything.
+ * It seems the only way we can do that
+ * is to go ahead and close the FD.
+ */
+ fd = ks->kso_fd;
+ ks->kso_fd = -1;
+ (void) close(fd);
+
+ while (ks->kso_count > 1)
+ cv_wait(&ks->kso_closing_cv, &ks->kso_lock);
+
+ mutex_exit(&ks->kso_lock);
+ _ksocket_destroy(ks);
+
+ return (0);
+}
+
+int
+ksocket_getsockname(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen,
+ struct cred *cr)
+{
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ if (!KSOCKET_VALID(ks))
+ return (ENOTSOCK);
+
+ if (addrlen == NULL || (addr == NULL && *addrlen != 0))
+ return (EFAULT);
+
+ if (getsockname(KSTOSO(ks), addr, addrlen) != 0)
+ return (errno);
+
+ return (0);
+}
+
+int
+ksocket_getpeername(ksocket_t ks, struct sockaddr *addr, socklen_t *addrlen,
+ struct cred *cr)
+{
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ if (!KSOCKET_VALID(ks))
+ return (ENOTSOCK);
+
+ if (addrlen == NULL || (addr == NULL && *addrlen != 0))
+ return (EFAULT);
+
+ if (getpeername(KSTOSO(ks), addr, addrlen) != 0)
+ return (errno);
+
+ return (0);
+}
+
+int
+ksocket_setsockopt(ksocket_t ks, int level, int optname, const void *optval,
+ int optlen, struct cred *cr)
+{
+ /* All Solaris components should pass a cred for this operation. */
+ ASSERT(cr != NULL);
+
+ if (!KSOCKET_VALID(ks))
+ return (ENOTSOCK);
+
+ if (optval == NULL)
+ optlen = 0;
+
+ if (setsockopt(KSTOSO(ks), level, optname, optval, optlen) != 0)
+ return (errno);
+
+ return (0);
+}
+
+void
+ksocket_hold(ksocket_t ks)
+{
+ if (!mutex_owned(&ks->kso_lock)) {
+ mutex_enter(&ks->kso_lock);
+ ks->kso_count++;
+ mutex_exit(&ks->kso_lock);
+ } else
+ ks->kso_count++;
+}
+
+void
+ksocket_rele(ksocket_t ks)
+{
+ /*
+ * When so_count equals 1 means no thread working on this ksocket
+ */
+ VERIFY3U(ks->kso_count, >, 1);
+
+ if (!mutex_owned(&ks->kso_lock)) {
+ mutex_enter(&ks->kso_lock);
+ if (--ks->kso_count == 1)
+ cv_signal(&ks->kso_closing_cv);
+ mutex_exit(&ks->kso_lock);
+ } else {
+ if (--ks->kso_count == 1)
+ cv_signal(&ks->kso_closing_cv);
+ }
+}
diff --git a/usr/src/lib/libfakekernel/common/kstat.c b/usr/src/lib/libfakekernel/common/kstat.c
new file mode 100644
index 0000000000..ed877fd694
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/kstat.c
@@ -0,0 +1,45 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/kstat.h>
+#include <sys/systm.h>
+
+/*ARGSUSED*/
+kstat_t *
+kstat_create_zone(const char *ks_module, int ks_instance, const char *ks_name,
+ const char *ks_class, uchar_t ks_type, uint_t ks_ndata, uchar_t ks_flags,
+ zoneid_t ks_zoneid)
+{
+ return (NULL);
+}
+
+/*ARGSUSED*/
+kstat_t *
+kstat_create(const char *ks_module, int ks_instance, const char *ks_name,
+ const char *ks_class, uchar_t ks_type, uint_t ks_ndata, uchar_t ks_flags)
+{
+ return (NULL);
+}
+
+/*ARGSUSED*/
+void
+kstat_install(kstat_t *ksp)
+{}
+
+/*ARGSUSED*/
+void
+kstat_delete(kstat_t *ksp)
+{}
diff --git a/usr/src/lib/libfakekernel/common/llib-lfakekernel b/usr/src/lib/libfakekernel/common/llib-lfakekernel
new file mode 100644
index 0000000000..62015b8ff5
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/llib-lfakekernel
@@ -0,0 +1,19 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/* LINTLIBRARY */
+/* PROTOLIB1 */
+
+#include <sys/ksynch.h>
diff --git a/usr/src/lib/libfakekernel/common/mapfile-vers b/usr/src/lib/libfakekernel/common/mapfile-vers
new file mode 100644
index 0000000000..ea8b9b8ca0
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/mapfile-vers
@@ -0,0 +1,193 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
+
+#
+# MAPFILE HEADER START
+#
+# WARNING: STOP NOW. DO NOT MODIFY THIS FILE.
+# Object versioning must comply with the rules detailed in
+#
+# usr/src/lib/README.mapfiles
+#
+# You should not be making modifications here until you've read the most current
+# copy of that file. If you need help, contact a gatekeeper for guidance.
+#
+# MAPFILE HEADER END
+#
+
+$mapfile_version 2
+
+SYMBOL_VERSION SUNWprivate_1.1 {
+ global:
+
+ _curcred;
+ _curproc;
+ _curthread;
+ _curzone;
+
+ aok { FLAGS = NODIRECT };
+ boot_time;
+ cmn_err;
+ copyinstr;
+ copystr;
+
+ crfree;
+ crgetuid;
+ crhold;
+
+ cv_broadcast;
+ cv_destroy;
+ cv_init;
+ cv_reltimedwait;
+ cv_reltimedwait_sig;
+ cv_signal;
+ cv_timedwait;
+ cv_timedwait_sig;
+ cv_wait;
+ cv_wait_sig;
+
+ ddi_get_lbolt64;
+ ddi_get_lbolt;
+ ddi_get_pid;
+ ddi_strtoul;
+
+ delay;
+
+ fakekernel_cprintf { FLAGS = NODIRECT };
+ fakekernel_init;
+ fakekernel_putlog { FLAGS = NODIRECT };
+
+ gethrestime;
+ gethrestime_sec;
+ gethrtime_unscaled;
+
+ hz;
+
+ kcred;
+ kiconv;
+ kiconv_close;
+ kiconv_open;
+
+ kmem_alloc;
+ kmem_cache_alloc;
+ kmem_cache_create;
+ kmem_cache_destroy;
+ kmem_cache_free;
+ kmem_cache_reap_now;
+ kmem_cache_set_move;
+ kmem_debugging;
+ kmem_free;
+ kmem_zalloc;
+
+ kmutex_destroy;
+ kmutex_init;
+
+ ksema_destroy;
+ ksema_init;
+
+ ksocket_accept;
+ ksocket_bind;
+ ksocket_bind_helper { FLAGS = NODIRECT };
+ ksocket_close;
+ ksocket_connect;
+ ksocket_getpeername;
+ ksocket_getsockname;
+ ksocket_hold;
+ ksocket_listen;
+ ksocket_recv;
+ ksocket_recvfrom;
+ ksocket_recvmsg;
+ ksocket_rele;
+ ksocket_send;
+ ksocket_sendmsg;
+ ksocket_sendto;
+ ksocket_setsockopt;
+ ksocket_shutdown;
+ ksocket_socket;
+
+ kstat_create;
+ kstat_create_zone;
+ kstat_delete;
+ kstat_install;
+
+ msec_per_tick;
+
+ mutex_enter;
+ mutex_exit;
+ mutex_owned;
+ mutex_owner;
+ mutex_tryenter;
+
+ nsec_per_tick;
+
+ ovbcopy;
+ p0;
+ panic;
+ panicargs;
+ panicstr;
+
+ random_get_bytes;
+ random_get_pseudo_bytes;
+
+ rw_destroy;
+ rw_downgrade;
+ rw_enter;
+ rw_exit;
+ rw_init;
+ #rw_iswriter; # missing, but not currently needed
+ rw_lock_held;
+ rw_owner;
+ rw_read_held;
+ rw_tryenter;
+ rw_tryupgrade;
+ rw_write_held;
+
+ scalehrtime;
+
+ #sema_held; # call the libc version directly
+ sema_p;
+ sema_p_sig;
+ sema_tryp;
+ sema_v;
+
+ strfree;
+
+ system_taskq_fini;
+ system_taskq_init;
+ taskq_create;
+ taskq_create_proc;
+ taskq_destroy;
+ taskq_dispatch;
+ taskq_dispatch_ent;
+ taskq_member;
+ taskq_wait;
+
+ thread_join;
+
+ tick_per_msec;
+ tsignal;
+ uiomove;
+ usec_per_tick;
+ vcmn_err;
+ vmem_qcache_reap;
+ vpanic;
+ zone0;
+ zone_kcred;
+ zthread_create;
+ zthread_exit;
+
+ local:
+ *;
+};
diff --git a/usr/src/lib/libfakekernel/common/mutex.c b/usr/src/lib/libfakekernel/common/mutex.c
new file mode 100644
index 0000000000..03bfa7d2a4
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/mutex.c
@@ -0,0 +1,95 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * mutex(9f)
+ */
+
+/* This is the API we're emulating */
+#include <sys/mutex.h>
+
+#include <sys/errno.h>
+#include <sys/debug.h>
+#include <sys/thread.h>
+
+int _lwp_mutex_lock(lwp_mutex_t *);
+int _lwp_mutex_unlock(lwp_mutex_t *);
+int _lwp_mutex_trylock(lwp_mutex_t *);
+
+extern clock_t ddi_get_lbolt(void);
+extern void clock2ts(clock_t, timespec_t *);
+
+static const lwp_mutex_t default_mutex =
+ {{0, 0, 0, {USYNC_THREAD}, _MUTEX_MAGIC},
+ {{{0, 0, 0, 0, 0, 0, 0, 0}}}, 0};
+
+/* ARGSUSED */
+void
+kmutex_init(kmutex_t *mp, char *name, kmutex_type_t typ, void *arg)
+{
+ mp->m_lock = default_mutex;
+ mp->m_owner = _KTHREAD_INVALID;
+}
+
+/* ARGSUSED */
+void
+kmutex_destroy(kmutex_t *mp)
+{
+ mp->m_owner = _KTHREAD_INVALID;
+}
+
+void
+mutex_enter(kmutex_t *mp)
+{
+ VERIFY(0 == _lwp_mutex_lock(&mp->m_lock));
+ mp->m_owner = _curthread();
+}
+
+int
+mutex_tryenter(kmutex_t *mp)
+{
+ int rc;
+
+ rc = _lwp_mutex_trylock(&mp->m_lock);
+ if (rc == 0) {
+ mp->m_owner = _curthread();
+ return (1);
+ }
+ return (0);
+}
+
+void
+mutex_exit(kmutex_t *mp)
+{
+ ASSERT(mp->m_owner == _curthread());
+ mp->m_owner = _KTHREAD_INVALID;
+ (void) _lwp_mutex_unlock(&mp->m_lock);
+}
+
+/*
+ * Returns the kthread_t * of the owner.
+ */
+void *
+mutex_owner(const kmutex_t *mp)
+{
+ return (mp->m_owner);
+}
+
+int
+mutex_owned(const kmutex_t *mp)
+{
+ void *t = _curthread();
+ return (t == mp->m_owner);
+}
diff --git a/usr/src/lib/libfakekernel/common/printf.c b/usr/src/lib/libfakekernel/common/printf.c
new file mode 100644
index 0000000000..1bcef683d1
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/printf.c
@@ -0,0 +1,154 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/varargs.h>
+#include <sys/systm.h>
+#include <sys/cmn_err.h>
+#include <sys/log.h>
+
+#include <fakekernel.h>
+
+void abort(void) __NORETURN;
+
+char *volatile panicstr;
+va_list panicargs;
+char panicbuf[512];
+
+volatile int aok;
+
+static const int
+ce_flags[CE_IGNORE] = { SL_NOTE, SL_NOTE, SL_WARN, SL_FATAL };
+static const char
+ce_prefix[CE_IGNORE][10] = { "", "NOTICE: ", "WARNING: ", "" };
+static const char
+ce_suffix[CE_IGNORE][2] = { "", "\n", "\n", "" };
+
+
+/*
+ * This function is just a stub, exported NODIRECT so that
+ * comsumers like fksmbd can provide their own.
+ * (One that actually prints the messages.)
+ *
+ * It's used by fakekernel_cprintf() below.
+ * The flags are SL_... from strlog.h
+ */
+/* ARGSUSED */
+void
+fakekernel_putlog(char *msg, size_t len, int flags)
+{
+}
+
+/*
+ * fakekernel_cprintf() corresponds to os/printf.c:cprintf()
+ * This formats the message and calls fakekernel_putlog().
+ * It's exported NODIRECT to allow replacment.
+ * The flags are SL_... from strlog.h
+ */
+void
+fakekernel_cprintf(const char *fmt, va_list adx, int flags,
+ const char *prefix, const char *suffix)
+{
+ size_t bufsize = LOG_MSGSIZE;
+ char buf[LOG_MSGSIZE];
+ char *bufp = buf;
+ char *msgp, *bufend;
+ size_t len;
+
+ if (strchr("^!?", fmt[0]) != NULL) {
+ if (fmt[0] == '^')
+ flags |= SL_CONSONLY;
+ else if (fmt[0] == '!')
+ flags |= SL_LOGONLY;
+ fmt++;
+ }
+
+ bufend = bufp + bufsize;
+ msgp = bufp;
+ msgp += snprintf(msgp, bufend - msgp, "[fake_kernel] ");
+ msgp += snprintf(msgp, bufend - msgp, prefix);
+ msgp += vsnprintf(msgp, bufend - msgp, fmt, adx);
+ msgp += snprintf(msgp, bufend - msgp, suffix);
+ len = msgp - bufp;
+
+ fakekernel_putlog(bufp, len, flags);
+}
+
+/*
+ * "User-level crash dump", if you will.
+ */
+void
+vpanic(const char *fmt, va_list adx)
+{
+ va_list tmpargs;
+
+ panicstr = (char *)fmt;
+ va_copy(panicargs, adx);
+
+ va_copy(tmpargs, adx);
+ fakekernel_cprintf(fmt, tmpargs, SL_FATAL, "fatal: ", "\n");
+
+ /* Call libc`assfail() so that mdb ::status works */
+ (void) vsnprintf(panicbuf, sizeof (panicbuf), fmt, adx);
+ assfail(panicbuf, "(panic)", 0);
+
+ abort(); /* avoid "noreturn" warnings */
+}
+
+void
+panic(const char *fmt, ...)
+{
+ va_list adx;
+
+ va_start(adx, fmt);
+ vpanic(fmt, adx);
+ va_end(adx);
+}
+
+void
+vcmn_err(int ce, const char *fmt, va_list adx)
+{
+
+ if (ce == CE_PANIC)
+ vpanic(fmt, adx);
+ if (ce >= CE_IGNORE)
+ return;
+
+ fakekernel_cprintf(fmt, adx, ce_flags[ce] | SL_CONSOLE,
+ ce_prefix[ce], ce_suffix[ce]);
+}
+
+/*PRINTFLIKE2*/
+void
+cmn_err(int ce, const char *fmt, ...)
+{
+ va_list adx;
+
+ va_start(adx, fmt);
+ vcmn_err(ce, fmt, adx);
+ va_end(adx);
+}
diff --git a/usr/src/lib/libfakekernel/common/random.c b/usr/src/lib/libfakekernel/common/random.c
new file mode 100644
index 0000000000..4904deffed
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/random.c
@@ -0,0 +1,28 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <cryptoutil.h>
+
+int
+random_get_bytes(uint8_t *ptr, size_t len)
+{
+ return (pkcs11_get_random(ptr, len));
+}
+
+int
+random_get_pseudo_bytes(uint8_t *ptr, size_t len)
+{
+ return (pkcs11_get_urandom(ptr, len));
+}
diff --git a/usr/src/lib/libfakekernel/common/rwlock.c b/usr/src/lib/libfakekernel/common/rwlock.c
new file mode 100644
index 0000000000..17b4ca604d
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/rwlock.c
@@ -0,0 +1,136 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * rwlock(9f)
+ */
+
+/* This is the API we're emulating */
+#include <sys/rwlock.h>
+
+#include <sys/errno.h>
+#include <sys/debug.h>
+#include <sys/param.h>
+#include <sys/synch32.h>
+#include <sys/thread.h>
+
+/* avoiding synch.h */
+int rwlock_init(lwp_rwlock_t *, int, void *);
+int rwlock_destroy(lwp_rwlock_t *);
+int rw_rdlock(lwp_rwlock_t *);
+int rw_wrlock(lwp_rwlock_t *);
+int rw_unlock(lwp_rwlock_t *);
+int rw_tryrdlock(lwp_rwlock_t *);
+int rw_trywrlock(lwp_rwlock_t *);
+int _rw_read_held(void *);
+int _rw_write_held(void *);
+
+/*ARGSUSED*/
+void
+rw_init(krwlock_t *rwlp, char *name, krw_type_t type, void *arg)
+{
+ (void) rwlock_init(&rwlp->rw_lock, USYNC_THREAD, NULL);
+ rwlp->rw_owner = _KTHREAD_INVALID;
+}
+
+void
+rw_destroy(krwlock_t *rwlp)
+{
+ (void) rwlock_destroy(&rwlp->rw_lock);
+ rwlp->rw_owner = _KTHREAD_INVALID;
+}
+
+void
+rw_enter(krwlock_t *rwlp, krw_t rw)
+{
+ int rc;
+
+ if (rw == RW_READER) {
+ rc = rw_rdlock(&rwlp->rw_lock);
+ } else {
+ rc = rw_wrlock(&rwlp->rw_lock);
+ rwlp->rw_owner = _curthread();
+ }
+ VERIFY(rc == 0);
+}
+
+void
+rw_exit(krwlock_t *rwlp)
+{
+ if (_rw_write_held(&rwlp->rw_lock)) {
+ ASSERT(rwlp->rw_owner == _curthread());
+ rwlp->rw_owner = _KTHREAD_INVALID;
+ }
+ (void) rw_unlock(&rwlp->rw_lock);
+}
+
+int
+rw_tryenter(krwlock_t *rwlp, krw_t rw)
+{
+ int rv;
+
+ if (rw == RW_WRITER) {
+ rv = rw_trywrlock(&rwlp->rw_lock);
+ if (rv == 0)
+ rwlp->rw_owner = _curthread();
+ } else
+ rv = rw_tryrdlock(&rwlp->rw_lock);
+
+ return ((rv == 0) ? 1 : 0);
+}
+
+/*ARGSUSED*/
+int
+rw_tryupgrade(krwlock_t *rwlp)
+{
+
+ return (0);
+}
+
+void
+rw_downgrade(krwlock_t *rwlp)
+{
+ ASSERT(rwlp->rw_owner == _curthread());
+ rwlp->rw_owner = _KTHREAD_INVALID;
+ VERIFY(rw_unlock(&rwlp->rw_lock) == 0);
+ VERIFY(rw_rdlock(&rwlp->rw_lock) == 0);
+}
+
+int
+rw_read_held(krwlock_t *rwlp)
+{
+ return (_rw_read_held(rwlp));
+}
+
+int
+rw_write_held(krwlock_t *rwlp)
+{
+ return (_rw_write_held(rwlp));
+}
+
+int
+rw_lock_held(krwlock_t *rwlp)
+{
+ return (rw_read_held(rwlp) || rw_write_held(rwlp));
+}
+
+/*
+ * Return the kthread_t * of the lock owner
+ */
+void *
+rw_owner(krwlock_t *rwlp)
+{
+ return (rwlp->rw_owner);
+}
diff --git a/usr/src/lib/libfakekernel/common/sema.c b/usr/src/lib/libfakekernel/common/sema.c
new file mode 100644
index 0000000000..918351eb8d
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/sema.c
@@ -0,0 +1,107 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * semaphore(9f)
+ */
+
+/* This is the API we're emulating */
+#include <sys/semaphore.h>
+
+#include <sys/errno.h>
+#include <sys/debug.h>
+
+/* <synch.h> */
+int _lwp_sema_init(lwp_sema_t *, int);
+int _lwp_sema_wait(lwp_sema_t *);
+int _lwp_sema_trywait(lwp_sema_t *);
+int _lwp_sema_post(lwp_sema_t *);
+
+
+/* ARGSUSED */
+void
+ksema_init(ksema_t *sem, uint32_t val,
+ char *name, ksema_type_t st, void *arg)
+{
+ (void) _lwp_sema_init(sem, val);
+}
+
+/* ARGSUSED */
+void
+ksema_destroy(ksema_t *sem)
+{
+}
+
+void
+sema_p(ksema_t *sem)
+{
+ int rv;
+ do {
+ rv = _lwp_sema_wait(sem);
+ } while (rv == EINTR);
+}
+
+void
+sema_v(ksema_t *sem)
+{
+ (void) _lwp_sema_post(sem);
+}
+
+/*
+ * Return values:
+ * 1: interrupted
+ * 0: success
+ */
+int
+sema_p_sig(ksema_t *sem)
+{
+ int rv;
+ rv = _lwp_sema_wait(sem);
+ switch (rv) {
+ case 0:
+ /* rv = 0 ; success */
+ break;
+ case EINTR:
+ default:
+ rv = 1; /* interrrupted */
+ break;
+ }
+
+ return (rv);
+}
+
+/*
+ * Return values:
+ * 0: could not get semaphore
+ * 1: successful (backwards from sema_p_sig!)
+ */
+int
+sema_tryp(ksema_t *sem)
+{
+ int rv;
+ rv = _lwp_sema_trywait(sem);
+
+ switch (rv) {
+ case 0:
+ rv = 1; /* success */
+ break;
+ case EBUSY:
+ default:
+ rv = 0; /* failed */
+ break;
+ }
+
+ return (rv);
+}
diff --git a/usr/src/lib/libfakekernel/common/sys/condvar.h b/usr/src/lib/libfakekernel/common/sys/condvar.h
new file mode 100644
index 0000000000..043cc98bae
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/sys/condvar.h
@@ -0,0 +1,106 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * condvar.h:
+ *
+ * definitions for thread synchronization primitives: condition variables
+ * This is the public part of the interface to condition variables. The
+ * private (implementation-specific) part is in <arch>/sys/condvar_impl.h.
+ */
+
+#ifndef _SYS_CONDVAR_H
+#define _SYS_CONDVAR_H
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/mutex.h>
+#include <sys/synch.h> /* lwp_cond_t */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Condtion variables.
+ */
+
+typedef lwp_cond_t kcondvar_t;
+
+typedef enum {
+ CV_DEFAULT,
+ CV_DRIVER
+} kcv_type_t;
+
+
+/*
+ * Time resolution values used in cv_reltimedwait() and cv_reltimedwait_sig()
+ * to specify how accurately a relative timeout must expire - if it can be
+ * anticipated or deferred.
+ */
+typedef enum {
+ TR_NANOSEC,
+ TR_MICROSEC,
+ TR_MILLISEC,
+ TR_SEC,
+ TR_CLOCK_TICK,
+ TR_COUNT
+} time_res_t;
+
+extern time_res_t time_res[];
+
+#define TIME_RES_VALID(tr) (tr >= TR_NANOSEC && tr < TR_COUNT)
+
+/*
+ * condition variable function prototypes
+ */
+
+extern void cv_init(kcondvar_t *, char *, kcv_type_t, void *);
+extern void cv_destroy(kcondvar_t *);
+extern void cv_wait(kcondvar_t *, kmutex_t *);
+extern void cv_wait_stop(kcondvar_t *, kmutex_t *, int);
+extern clock_t cv_timedwait(kcondvar_t *, kmutex_t *, clock_t);
+extern clock_t cv_reltimedwait(kcondvar_t *, kmutex_t *, clock_t, time_res_t);
+extern int cv_wait_sig(kcondvar_t *, kmutex_t *);
+extern clock_t cv_timedwait_sig(kcondvar_t *, kmutex_t *, clock_t);
+extern int cv_timedwait_sig_hrtime(kcondvar_t *, kmutex_t *, hrtime_t);
+extern clock_t cv_reltimedwait_sig(kcondvar_t *, kmutex_t *, clock_t,
+ time_res_t);
+extern int cv_wait_sig_swap(kcondvar_t *, kmutex_t *);
+extern int cv_wait_sig_swap_core(kcondvar_t *, kmutex_t *, int *);
+extern void cv_signal(kcondvar_t *);
+extern void cv_broadcast(kcondvar_t *);
+extern int cv_waituntil_sig(kcondvar_t *, kmutex_t *, timestruc_t *, int);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_CONDVAR_H */
diff --git a/usr/src/lib/libfakekernel/common/sys/cred.h b/usr/src/lib/libfakekernel/common/sys/cred.h
new file mode 100644
index 0000000000..ecfe70baab
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/sys/cred.h
@@ -0,0 +1,85 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ *
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+/*
+ * Portions of this source code were derived from Berkeley 4.3 BSD
+ * under license from the Regents of the University of California.
+ */
+
+#ifndef _SYS_CRED_H
+#define _SYS_CRED_H
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The credential is an opaque kernel private data structure defined in
+ * <sys/cred_impl.h>.
+ */
+
+typedef struct cred cred_t;
+
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+
+cred_t *_curcred(void);
+#define CRED() (_curcred()) /* current cred_t pointer */
+
+extern int ngroups_max;
+
+/*
+ * kcred is used when you need all privileges.
+ */
+extern struct cred *kcred;
+
+extern void cred_init(void);
+extern void crhold(cred_t *);
+extern void crfree(cred_t *);
+
+extern cred_t *zone_kcred(void);
+
+extern uid_t crgetuid(const cred_t *);
+extern uid_t crgetruid(const cred_t *);
+extern uid_t crgetsuid(const cred_t *);
+extern gid_t crgetgid(const cred_t *);
+extern gid_t crgetrgid(const cred_t *);
+extern gid_t crgetsgid(const cred_t *);
+extern zoneid_t crgetzoneid(const cred_t *);
+extern projid_t crgetprojid(const cred_t *);
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_CRED_H */
diff --git a/usr/src/lib/libfakekernel/common/sys/kiconv.h b/usr/src/lib/libfakekernel/common/sys/kiconv.h
new file mode 100644
index 0000000000..a0143eb824
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/sys/kiconv.h
@@ -0,0 +1,60 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _SYS_KICONV_H
+#define _SYS_KICONV_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/types.h>
+
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+
+/*
+ * kiconv functions and their macros (from sunddi.h)
+ */
+#define KICONV_IGNORE_NULL (0x0001)
+#define KICONV_REPLACE_INVALID (0x0002)
+
+struct _iconv_info;
+typedef struct _iconv_info *kiconv_t;
+
+extern kiconv_t kiconv_open(const char *, const char *);
+extern size_t kiconv(kiconv_t, char **, size_t *, char **, size_t *, int *);
+extern int kiconv_close(kiconv_t);
+extern size_t kiconvstr(const char *, const char *, char *, size_t *, char *,
+ size_t *, int, int *);
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_KICONV_H */
diff --git a/usr/src/lib/libfakekernel/common/sys/klwp.h b/usr/src/lib/libfakekernel/common/sys/klwp.h
new file mode 100644
index 0000000000..2e0b47b586
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/sys/klwp.h
@@ -0,0 +1,80 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _SYS_KLWP_H
+#define _SYS_KLWP_H
+
+#include <sys/types.h>
+#include <sys/condvar.h>
+#include <sys/thread.h>
+#include <sys/signal.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The light-weight process object and the methods by which it
+ * is accessed.
+ */
+
+#define MAXSYSARGS 8 /* Maximum # of arguments passed to a syscall */
+
+/* lwp_eosys values */
+#define NORMALRETURN 0 /* normal return; adjusts PC, registers */
+#define JUSTRETURN 1 /* just return, leave registers alone */
+
+typedef struct _klwp *klwp_id_t;
+
+typedef struct _klwp {
+ /*
+ * linkage
+ */
+ struct _kthread *lwp_thread;
+ struct proc *lwp_procp;
+
+} klwp_t;
+
+/* lwp states */
+#define LWP_USER 0x01 /* Running in user mode */
+#define LWP_SYS 0x02 /* Running in kernel mode */
+
+#if defined(_KERNEL)
+extern volatile int lwp_default_stksize;
+extern klwp_t lwp0;
+
+/* where newly-created lwps normally start */
+extern void lwp_rtt(void);
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_KLWP_H */
diff --git a/usr/src/lib/libfakekernel/common/sys/ksynch.h b/usr/src/lib/libfakekernel/common/sys/ksynch.h
new file mode 100644
index 0000000000..9f4bfe479b
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/sys/ksynch.h
@@ -0,0 +1,48 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1991, Sun Microsystems, Inc.
+ */
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * DKI/DDI MT synchronization primitives.
+ */
+
+#ifndef _SYS_KSYNCH_H
+#define _SYS_KSYNCH_H
+
+/*
+ * Include the _real_ sys/sync.h to get the _lwp_... types
+ */
+#include <sys/synch.h>
+
+/*
+ * Lots of kernel headers we might want to use may
+ * directly include sys/t_lock.h so provide a fake
+ * that redirects to our shim.
+ */
+#include <sys/t_lock.h>
+
+#endif /* _SYS_KSYNCH_H */
diff --git a/usr/src/lib/libfakekernel/common/sys/mutex.h b/usr/src/lib/libfakekernel/common/sys/mutex.h
new file mode 100644
index 0000000000..ea1e49aea3
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/sys/mutex.h
@@ -0,0 +1,100 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _SYS_MUTEX_H
+#define _SYS_MUTEX_H
+
+#include <sys/synch.h> /* lwp_mutex_t */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Public interface to mutual exclusion locks. See mutex(9F) for details.
+ *
+ * The basic mutex type is MUTEX_ADAPTIVE, which is expected to be used
+ * in almost all of the kernel. MUTEX_SPIN provides interrupt blocking
+ * and must be used in interrupt handlers above LOCK_LEVEL. The iblock
+ * cookie argument to mutex_init() encodes the interrupt level to block.
+ * The iblock cookie must be NULL for adaptive locks.
+ *
+ * MUTEX_DEFAULT is the type usually specified (except in drivers) to
+ * mutex_init(). It is identical to MUTEX_ADAPTIVE.
+ *
+ * MUTEX_DRIVER is always used by drivers. mutex_init() converts this to
+ * either MUTEX_ADAPTIVE or MUTEX_SPIN depending on the iblock cookie.
+ *
+ * Mutex statistics can be gathered on the fly, without rebooting or
+ * recompiling the kernel, via the lockstat driver (lockstat(7D)).
+ */
+typedef enum {
+ MUTEX_ADAPTIVE = 0, /* spin if owner is running, otherwise block */
+ MUTEX_SPIN = 1, /* block interrupts and spin */
+ MUTEX_DRIVER = 4, /* driver (DDI) mutex */
+ MUTEX_DEFAULT = 6 /* kernel default mutex */
+} kmutex_type_t;
+
+struct _kmutex {
+ lwp_mutex_t m_lock;
+ void *m_owner;
+};
+typedef struct _kmutex kmutex_t;
+
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+/* See the real sys/mutex.h */
+typedef struct pad_mutex {
+ kmutex_t pad_mutex;
+#ifdef _LP64
+ char pad_pad[64 - sizeof (kmutex_t)];
+#endif
+} pad_mutex_t;
+#endif /* _KERNEL */
+
+#define MUTEX_HELD(x) (mutex_owned(x))
+#define MUTEX_NOT_HELD(x) (!mutex_owned(x) || panicstr)
+
+/*
+ * We're simulating the kernel mutex API here, and the
+ * user-level has a different signature, so rename.
+ */
+#define mutex_init kmutex_init
+#define mutex_destroy kmutex_destroy
+
+extern void kmutex_init(kmutex_t *, char *, kmutex_type_t, void *);
+extern void kmutex_destroy(kmutex_t *);
+
+extern void mutex_enter(kmutex_t *);
+extern int mutex_tryenter(kmutex_t *);
+extern void mutex_exit(kmutex_t *);
+extern int mutex_owned(const kmutex_t *);
+
+extern void *mutex_owner(const kmutex_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_MUTEX_H */
diff --git a/usr/src/lib/libfakekernel/common/sys/proc.h b/usr/src/lib/libfakekernel/common/sys/proc.h
new file mode 100644
index 0000000000..1ded4eb5a7
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/sys/proc.h
@@ -0,0 +1,125 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+#ifndef _SYS_PROC_H
+#define _SYS_PROC_H
+
+#include <sys/time.h>
+#include <sys/thread.h>
+#include <sys/cred.h>
+#include <sys/debug.h>
+#include <sys/signal.h>
+#include <sys/list.h>
+#include <sys/avl.h>
+#include <sys/refstr.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct pool;
+struct task;
+struct zone;
+
+/*
+ * One structure allocated per active process. It contains all
+ * data needed about the process while the process may be swapped
+ * out. Other per-process data (user.h) is also inside the proc structure.
+ * Lightweight-process data (lwp.h) and the kernel stack may be swapped out.
+ */
+typedef struct proc {
+
+ struct cred *p_cred; /* process credentials */
+
+ struct pid *p_pidp; /* process ID info */
+ struct pid *p_pgidp; /* process group ID info */
+
+ /*
+ * Per process lwp and kernel thread stuff
+ */
+
+ struct zone *p_zone; /* zone in which process lives */
+
+ int do_not_use[10];
+ int p_user[10]; /* (see sys/user.h) */
+} proc_t;
+
+#define PROC_T /* headers relying on proc_t are OK */
+
+/* process ID info */
+
+struct pid {
+ unsigned int pid_prinactive :1;
+ unsigned int pid_pgorphaned :1;
+ unsigned int pid_padding :6; /* used to be pid_ref, now an int */
+ unsigned int pid_prslot :24;
+ pid_t pid_id;
+ struct proc *pid_pglink;
+ struct proc *pid_pgtail;
+ struct pid *pid_link;
+ uint_t pid_ref;
+};
+
+#define p_pgrp p_pgidp->pid_id
+#define p_pid p_pidp->pid_id
+#define p_slot p_pidp->pid_prslot
+#define p_detached p_pgidp->pid_pgorphaned
+
+#define PID_HOLD(pidp) ASSERT(MUTEX_HELD(&pidlock)); \
+ ++(pidp)->pid_ref;
+#define PID_RELE(pidp) ASSERT(MUTEX_HELD(&pidlock)); \
+ (pidp)->pid_ref > 1 ? \
+ --(pidp)->pid_ref : pid_rele(pidp);
+
+/*
+ * Structure containing persistent process lock. The structure and
+ * macro allow "mutex_enter(&p->p_lock)" to continue working.
+ */
+struct plock {
+ kmutex_t pl_lock;
+};
+#define p_lock p_lockp->pl_lock
+
+extern proc_t p0; /* process 0 */
+extern struct plock p0lock; /* p0's plock */
+extern struct pid pid0; /* p0's pid */
+
+
+/*
+ * This is normally in sunddi.h but
+ * I didn't want to drag that in here.
+ */
+pid_t
+ddi_get_pid(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_PROC_H */
diff --git a/usr/src/lib/libfakekernel/common/sys/rwlock.h b/usr/src/lib/libfakekernel/common/sys/rwlock.h
new file mode 100644
index 0000000000..383c09149a
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/sys/rwlock.h
@@ -0,0 +1,84 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _SYS_RWLOCK_H
+#define _SYS_RWLOCK_H
+
+/*
+ * Public interface to readers/writer locks. See rwlock(9F) for details.
+ */
+
+#include <sys/synch.h> /* lwp_rwlock_t */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ RW_DRIVER = 2, /* driver (DDI) rwlock */
+ RW_DEFAULT = 4 /* kernel default rwlock */
+} krw_type_t;
+
+typedef enum {
+ RW_WRITER,
+ RW_READER
+} krw_t;
+
+struct _krwlock {
+ lwp_rwlock_t rw_lock;
+ void *rw_owner;
+};
+typedef struct _krwlock krwlock_t;
+
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+
+#define RW_READ_HELD(x) (rw_read_held((x)))
+#define RW_WRITE_HELD(x) (rw_write_held((x)))
+#define RW_LOCK_HELD(x) (rw_lock_held((x)))
+#define RW_ISWRITER(x) (rw_iswriter(x))
+
+extern void rw_init(krwlock_t *, char *, krw_type_t, void *);
+extern void rw_destroy(krwlock_t *);
+extern void rw_enter(krwlock_t *, krw_t);
+extern int rw_tryenter(krwlock_t *, krw_t);
+extern void rw_exit(krwlock_t *);
+extern void rw_downgrade(krwlock_t *);
+extern int rw_tryupgrade(krwlock_t *);
+extern int rw_read_held(krwlock_t *);
+extern int rw_write_held(krwlock_t *);
+extern int rw_lock_held(krwlock_t *);
+extern int rw_read_locked(krwlock_t *);
+extern int rw_iswriter(krwlock_t *);
+extern void *rw_owner(krwlock_t *);
+
+#endif /* defined(_KERNEL) */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_RWLOCK_H */
diff --git a/usr/src/lib/libfakekernel/common/sys/semaphore.h b/usr/src/lib/libfakekernel/common/sys/semaphore.h
new file mode 100644
index 0000000000..2742daf215
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/sys/semaphore.h
@@ -0,0 +1,72 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1993-1998 by Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _SYS_SEMAPHORE_H
+#define _SYS_SEMAPHORE_H
+
+/*
+ * Public interface to semaphores. See semaphore(9F) for details.
+ */
+
+#include <sys/synch.h> /* lwp_sema_t */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ SEMA_DEFAULT,
+ SEMA_DRIVER
+} ksema_type_t;
+
+typedef lwp_sema_t ksema_t;
+
+#define SEMA_HELD(x) (sema_held((x)))
+
+/*
+ * We're simulating the kernel mutex API here, and the
+ * user-level has a different signature, so rename.
+ */
+
+#define sema_init ksema_init
+#define sema_destroy ksema_destroy
+
+extern void ksema_init(ksema_t *, uint32_t, char *, ksema_type_t, void *);
+extern void ksema_destroy(ksema_t *);
+
+extern void sema_p(ksema_t *);
+extern int sema_p_sig(ksema_t *);
+extern void sema_v(ksema_t *);
+extern int sema_tryp(ksema_t *);
+extern int sema_held(ksema_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_SEMAPHORE_H */
diff --git a/usr/src/lib/libfakekernel/common/sys/t_lock.h b/usr/src/lib/libfakekernel/common/sys/t_lock.h
new file mode 100644
index 0000000000..a932a72551
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/sys/t_lock.h
@@ -0,0 +1,58 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 1991-1998 by Sun Microsystems, Inc.
+ * All rights reserved.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * t_lock.h: Prototypes for disp_locks, plus include files
+ * that describe the interfaces to kernel synch.
+ * objects.
+ */
+
+#ifndef _SYS_T_LOCK_H
+#define _SYS_T_LOCK_H
+
+/* these two are real */
+#include <sys/machlock.h>
+#include <sys/param.h>
+
+/* the rest are fake */
+#include <sys/mutex.h>
+#include <sys/rwlock.h>
+#include <sys/semaphore.h>
+#include <sys/condvar.h>
+
+/*
+ * The real sys/semaphore.h pulls in sys/thread and some headers
+ * using sys/t_lock.h rely on that, so let's pull it in here too.
+ * Note that sys/thread.h includes sys/t_lock.h too (a cycle) but
+ * that's OK thanks to the multi-include guards.
+ */
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+#include <sys/thread.h>
+#endif
+
+#endif /* _SYS_T_LOCK_H */
diff --git a/usr/src/lib/libfakekernel/common/sys/taskq_impl.h b/usr/src/lib/libfakekernel/common/sys/taskq_impl.h
new file mode 100644
index 0000000000..1920034b04
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/sys/taskq_impl.h
@@ -0,0 +1,59 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _SYS_TASKQ_IMPL_H
+#define _SYS_TASKQ_IMPL_H
+
+#include <sys/taskq.h>
+#include <sys/inttypes.h>
+#include <sys/vmem.h>
+#include <sys/list.h>
+#include <sys/kstat.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct taskq_ent {
+ struct taskq_ent *tqent_next;
+ struct taskq_ent *tqent_prev;
+ task_func_t *tqent_func;
+ void *tqent_arg;
+ uintptr_t tqent_flags;
+} taskq_ent_t;
+
+#define TQENT_FLAG_PREALLOC 0x1 /* taskq_dispatch_ent used */
+
+/* Special form of taskq dispatch that uses preallocated entries. */
+void taskq_dispatch_ent(taskq_t *, task_func_t, void *, uint_t, taskq_ent_t *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_TASKQ_IMPL_H */
diff --git a/usr/src/lib/libfakekernel/common/sys/thread.h b/usr/src/lib/libfakekernel/common/sys/thread.h
new file mode 100644
index 0000000000..6213be2807
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/sys/thread.h
@@ -0,0 +1,114 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _SYS_THREAD_H
+#define _SYS_THREAD_H
+
+#include <sys/types.h>
+#include <sys/t_lock.h>
+#include <sys/klwp.h>
+#include <sys/signal.h> /* expected by including code */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The thread object, its states, and the methods by which it
+ * is accessed.
+ */
+
+/*
+ * Values that t_state may assume. Note that t_state cannot have more
+ * than one of these flags set at a time.
+ */
+#define TS_FREE 0x00 /* Thread at loose ends */
+#define TS_SLEEP 0x01 /* Awaiting an event */
+#define TS_RUN 0x02 /* Runnable, but not yet on a processor */
+#define TS_ONPROC 0x04 /* Thread is being run on a processor */
+#define TS_ZOMB 0x08 /* Thread has died but hasn't been reaped */
+#define TS_STOPPED 0x10 /* Stopped, initial state */
+#define TS_WAIT 0x20 /* Waiting to become runnable */
+
+/* ctxop_t */
+
+/* afd_t needed by sys/file.h via sys/t_lock.h */
+typedef struct _afd_not_used afd_t;
+
+struct turnstile;
+struct panic_trap_info;
+struct upimutex;
+struct kproject;
+struct on_trap_data;
+struct waitq;
+struct _kcpc_ctx;
+struct _kcpc_set;
+
+/* Definition for kernel thread identifier type */
+typedef uint64_t kt_did_t;
+
+struct _kthread;
+typedef struct _kthread *kthread_id_t;
+
+typedef struct _kthread kthread_t;
+
+extern kthread_t *_curthread(void); /* returns thread pointer */
+#define curthread (_curthread()) /* current thread pointer */
+
+#define _KTHREAD_INVALID ((void *)(uintptr_t)-1)
+
+
+struct proc;
+extern struct proc *_curproc(void);
+#define curproc (_curproc()) /* current proc pointer */
+
+struct zone;
+extern struct zone *_curzone(void);
+#define curzone (_curzone()) /* current zone pointer */
+
+extern kthread_t *thread_create(
+ caddr_t stk,
+ size_t stksize,
+ void (*proc)(),
+ void *arg,
+ size_t len,
+ struct proc *pp,
+ int state,
+ pri_t pri);
+extern void thread_exit(void) __NORETURN;
+extern void thread_join(kt_did_t);
+
+extern kthread_t *zthread_create(caddr_t, size_t, void (*)(), void *, size_t,
+ pri_t);
+extern void zthread_exit(void) __NORETURN;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_THREAD_H */
diff --git a/usr/src/lib/libfakekernel/common/sys/user.h b/usr/src/lib/libfakekernel/common/sys/user.h
new file mode 100644
index 0000000000..f37548895c
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/sys/user.h
@@ -0,0 +1,41 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _SYS_USER_H
+#define _SYS_USER_H
+
+/*
+ * libfakekernel version of sys/user.h
+ * typically pulled in by sys/file.h
+ */
+
+#include <sys/types.h>
+#include <sys/signal.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct exdata;
+#if defined(_KERNEL) || defined(_FAKE_KERNEL) || defined(_KMEMUSER)
+typedef struct uf_info uf_info_t;
+#endif
+typedef struct user user_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_USER_H */
diff --git a/usr/src/lib/libfakekernel/common/sys/zone.h b/usr/src/lib/libfakekernel/common/sys/zone.h
new file mode 100644
index 0000000000..9a42947d3f
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/sys/zone.h
@@ -0,0 +1,101 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _SYS_ZONE_H
+#define _SYS_ZONE_H
+
+#include <sys/types.h>
+#include <sys/mutex.h>
+#include <sys/param.h>
+#include <sys/cred.h>
+#include <sys/rctl.h>
+#include <sys/ksynch.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * NOTE
+ *
+ * The contents of this file are private to the implementation of
+ * Solaris and are subject to change at any time without notice.
+ * Applications and drivers using these interfaces may fail to
+ * run on future releases.
+ */
+
+#define GLOBAL_ZONEID 0
+#define ZONENAME_MAX 64
+
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+
+#include <sys/list.h>
+
+typedef struct zone_ref {
+ struct zone *zref_zone; /* the zone to which the reference refers */
+ list_node_t zref_linkage; /* linkage for zone_t::zone_ref_list */
+} zone_ref_t;
+
+typedef struct zone {
+ char *zone_name; /* zone's configuration name */
+ zoneid_t zone_id; /* ID of zone */
+ struct proc *zone_zsched; /* Dummy kernel "zsched" process */
+ time_t zone_boot_time;
+ struct vnode *zone_rootvp; /* zone's root vnode */
+ char *zone_rootpath; /* Path to zone's root + '/' */
+ int fake_zone[10];
+} zone_t;
+
+extern zone_t zone0;
+extern zone_t *global_zone;
+extern uint_t maxzones;
+
+/*
+ * Zone-specific data (ZSD) APIs
+ */
+/*
+ * The following is what code should be initializing its zone_key_t to if it
+ * calls zone_getspecific() without necessarily knowing that zone_key_create()
+ * has been called on the key.
+ */
+#define ZONE_KEY_UNINITIALIZED 0
+
+typedef uint_t zone_key_t;
+
+extern void zone_key_create(zone_key_t *, void *(*)(zoneid_t),
+ void (*)(zoneid_t, void *), void (*)(zoneid_t, void *));
+extern int zone_key_delete(zone_key_t);
+extern void *zone_getspecific(zone_key_t, zone_t *);
+extern int zone_setspecific(zone_key_t, zone_t *, const void *);
+
+extern zoneid_t getzoneid(void);
+
+#endif /* _KERNEL || _FAKE_KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_ZONE_H */
diff --git a/usr/src/lib/libfakekernel/common/taskq.c b/usr/src/lib/libfakekernel/common/taskq.c
new file mode 100644
index 0000000000..a9320024ad
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/taskq.c
@@ -0,0 +1,380 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
+ * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/taskq_impl.h>
+
+#include <sys/class.h>
+#include <sys/debug.h>
+#include <sys/ksynch.h>
+#include <sys/kmem.h>
+#include <sys/time.h>
+#include <sys/systm.h>
+#include <sys/sysmacros.h>
+#include <sys/unistd.h>
+
+/* avoid <unistd.h> */
+extern long sysconf(int);
+
+/* avoiding <thread.h> */
+typedef unsigned int thread_t;
+typedef unsigned int thread_key_t;
+
+extern int thr_create(void *, size_t, void *(*)(void *), void *, long,
+ thread_t *);
+extern int thr_join(thread_t, thread_t *, void **);
+
+/*
+ * POSIX.1c Note:
+ * THR_BOUND is defined same as PTHREAD_SCOPE_SYSTEM in <pthread.h>
+ * THR_DETACHED is defined same as PTHREAD_CREATE_DETACHED in <pthread.h>
+ * Any changes in these definitions should be reflected in <pthread.h>
+ */
+#define THR_BOUND 0x00000001 /* = PTHREAD_SCOPE_SYSTEM */
+#define THR_NEW_LWP 0x00000002
+#define THR_DETACHED 0x00000040 /* = PTHREAD_CREATE_DETACHED */
+#define THR_SUSPENDED 0x00000080
+#define THR_DAEMON 0x00000100
+
+
+int taskq_now;
+taskq_t *system_taskq;
+
+#define TASKQ_ACTIVE 0x00010000
+
+struct taskq {
+ kmutex_t tq_lock;
+ krwlock_t tq_threadlock;
+ kcondvar_t tq_dispatch_cv;
+ kcondvar_t tq_wait_cv;
+ thread_t *tq_threadlist;
+ int tq_flags;
+ int tq_active;
+ int tq_nthreads;
+ int tq_nalloc;
+ int tq_minalloc;
+ int tq_maxalloc;
+ kcondvar_t tq_maxalloc_cv;
+ int tq_maxalloc_wait;
+ taskq_ent_t *tq_freelist;
+ taskq_ent_t tq_task;
+};
+
+static taskq_ent_t *
+task_alloc(taskq_t *tq, int tqflags)
+{
+ taskq_ent_t *t;
+ int rv;
+
+again: if ((t = tq->tq_freelist) != NULL && tq->tq_nalloc >= tq->tq_minalloc) {
+ tq->tq_freelist = t->tqent_next;
+ } else {
+ if (tq->tq_nalloc >= tq->tq_maxalloc) {
+ if (!(tqflags & KM_SLEEP))
+ return (NULL);
+
+ /*
+ * We don't want to exceed tq_maxalloc, but we can't
+ * wait for other tasks to complete (and thus free up
+ * task structures) without risking deadlock with
+ * the caller. So, we just delay for one second
+ * to throttle the allocation rate. If we have tasks
+ * complete before one second timeout expires then
+ * taskq_ent_free will signal us and we will
+ * immediately retry the allocation.
+ */
+ tq->tq_maxalloc_wait++;
+ rv = cv_timedwait(&tq->tq_maxalloc_cv,
+ &tq->tq_lock, ddi_get_lbolt() + hz);
+ tq->tq_maxalloc_wait--;
+ if (rv > 0)
+ goto again; /* signaled */
+ }
+ mutex_exit(&tq->tq_lock);
+
+ t = kmem_alloc(sizeof (taskq_ent_t), tqflags);
+
+ mutex_enter(&tq->tq_lock);
+ if (t != NULL)
+ tq->tq_nalloc++;
+ }
+ return (t);
+}
+
+static void
+task_free(taskq_t *tq, taskq_ent_t *t)
+{
+ if (tq->tq_nalloc <= tq->tq_minalloc) {
+ t->tqent_next = tq->tq_freelist;
+ tq->tq_freelist = t;
+ } else {
+ tq->tq_nalloc--;
+ mutex_exit(&tq->tq_lock);
+ kmem_free(t, sizeof (taskq_ent_t));
+ mutex_enter(&tq->tq_lock);
+ }
+
+ if (tq->tq_maxalloc_wait)
+ cv_signal(&tq->tq_maxalloc_cv);
+}
+
+taskqid_t
+taskq_dispatch(taskq_t *tq, task_func_t func, void *arg, uint_t tqflags)
+{
+ taskq_ent_t *t;
+
+ if (taskq_now) {
+ func(arg);
+ return (1);
+ }
+
+ mutex_enter(&tq->tq_lock);
+ ASSERT(tq->tq_flags & TASKQ_ACTIVE);
+ if ((t = task_alloc(tq, tqflags)) == NULL) {
+ mutex_exit(&tq->tq_lock);
+ return (0);
+ }
+ if (tqflags & TQ_FRONT) {
+ t->tqent_next = tq->tq_task.tqent_next;
+ t->tqent_prev = &tq->tq_task;
+ } else {
+ t->tqent_next = &tq->tq_task;
+ t->tqent_prev = tq->tq_task.tqent_prev;
+ }
+ t->tqent_next->tqent_prev = t;
+ t->tqent_prev->tqent_next = t;
+ t->tqent_func = func;
+ t->tqent_arg = arg;
+ t->tqent_flags = 0;
+ cv_signal(&tq->tq_dispatch_cv);
+ mutex_exit(&tq->tq_lock);
+ return (1);
+}
+
+void
+taskq_dispatch_ent(taskq_t *tq, task_func_t func, void *arg, uint_t flags,
+ taskq_ent_t *t)
+{
+ ASSERT(func != NULL);
+ ASSERT(!(tq->tq_flags & TASKQ_DYNAMIC));
+
+ /*
+ * Mark it as a prealloc'd task. This is important
+ * to ensure that we don't free it later.
+ */
+ t->tqent_flags |= TQENT_FLAG_PREALLOC;
+ /*
+ * Enqueue the task to the underlying queue.
+ */
+ mutex_enter(&tq->tq_lock);
+
+ if (flags & TQ_FRONT) {
+ t->tqent_next = tq->tq_task.tqent_next;
+ t->tqent_prev = &tq->tq_task;
+ } else {
+ t->tqent_next = &tq->tq_task;
+ t->tqent_prev = tq->tq_task.tqent_prev;
+ }
+ t->tqent_next->tqent_prev = t;
+ t->tqent_prev->tqent_next = t;
+ t->tqent_func = func;
+ t->tqent_arg = arg;
+ cv_signal(&tq->tq_dispatch_cv);
+ mutex_exit(&tq->tq_lock);
+}
+
+void
+taskq_wait(taskq_t *tq)
+{
+ mutex_enter(&tq->tq_lock);
+ while (tq->tq_task.tqent_next != &tq->tq_task || tq->tq_active != 0)
+ cv_wait(&tq->tq_wait_cv, &tq->tq_lock);
+ mutex_exit(&tq->tq_lock);
+}
+
+static void *
+taskq_thread(void *arg)
+{
+ taskq_t *tq = arg;
+ taskq_ent_t *t;
+ boolean_t prealloc;
+
+ mutex_enter(&tq->tq_lock);
+ while (tq->tq_flags & TASKQ_ACTIVE) {
+ if ((t = tq->tq_task.tqent_next) == &tq->tq_task) {
+ if (--tq->tq_active == 0)
+ cv_broadcast(&tq->tq_wait_cv);
+ cv_wait(&tq->tq_dispatch_cv, &tq->tq_lock);
+ tq->tq_active++;
+ continue;
+ }
+ t->tqent_prev->tqent_next = t->tqent_next;
+ t->tqent_next->tqent_prev = t->tqent_prev;
+ t->tqent_next = NULL;
+ t->tqent_prev = NULL;
+ prealloc = t->tqent_flags & TQENT_FLAG_PREALLOC;
+ mutex_exit(&tq->tq_lock);
+
+ rw_enter(&tq->tq_threadlock, RW_READER);
+ t->tqent_func(t->tqent_arg);
+ rw_exit(&tq->tq_threadlock);
+
+ mutex_enter(&tq->tq_lock);
+ if (!prealloc)
+ task_free(tq, t);
+ }
+ tq->tq_nthreads--;
+ cv_broadcast(&tq->tq_wait_cv);
+ mutex_exit(&tq->tq_lock);
+ return (NULL);
+}
+
+/*ARGSUSED*/
+taskq_t *
+taskq_create(const char *name, int nthr, pri_t pri, int minalloc,
+ int maxalloc, uint_t flags)
+{
+ return (taskq_create_proc(name, nthr, pri,
+ minalloc, maxalloc, NULL, flags));
+}
+
+/*ARGSUSED*/
+taskq_t *
+taskq_create_proc(const char *name, int nthreads, pri_t pri,
+ int minalloc, int maxalloc, proc_t *proc, uint_t flags)
+{
+ taskq_t *tq = kmem_zalloc(sizeof (taskq_t), KM_SLEEP);
+ int t;
+
+ if (flags & TASKQ_THREADS_CPU_PCT) {
+ int pct;
+ ASSERT3S(nthreads, >=, 0);
+ ASSERT3S(nthreads, <=, 100);
+ pct = MIN(nthreads, 100);
+ pct = MAX(pct, 0);
+
+ nthreads = (sysconf(_SC_NPROCESSORS_ONLN) * pct) / 100;
+ nthreads = MAX(nthreads, 1); /* need at least 1 thread */
+ } else {
+ ASSERT3S(nthreads, >=, 1);
+ }
+
+ rw_init(&tq->tq_threadlock, NULL, RW_DEFAULT, NULL);
+ mutex_init(&tq->tq_lock, NULL, MUTEX_DEFAULT, NULL);
+ cv_init(&tq->tq_dispatch_cv, NULL, CV_DEFAULT, NULL);
+ cv_init(&tq->tq_wait_cv, NULL, CV_DEFAULT, NULL);
+ cv_init(&tq->tq_maxalloc_cv, NULL, CV_DEFAULT, NULL);
+ tq->tq_flags = flags | TASKQ_ACTIVE;
+ tq->tq_active = nthreads;
+ tq->tq_nthreads = nthreads;
+ tq->tq_minalloc = minalloc;
+ tq->tq_maxalloc = maxalloc;
+ tq->tq_task.tqent_next = &tq->tq_task;
+ tq->tq_task.tqent_prev = &tq->tq_task;
+ tq->tq_threadlist = kmem_alloc(nthreads * sizeof (thread_t), KM_SLEEP);
+
+ if (flags & TASKQ_PREPOPULATE) {
+ mutex_enter(&tq->tq_lock);
+ while (minalloc-- > 0)
+ task_free(tq, task_alloc(tq, KM_SLEEP));
+ mutex_exit(&tq->tq_lock);
+ }
+
+ for (t = 0; t < nthreads; t++)
+ (void) thr_create(0, 0, taskq_thread,
+ tq, THR_BOUND, &tq->tq_threadlist[t]);
+
+ return (tq);
+}
+
+void
+taskq_destroy(taskq_t *tq)
+{
+ int t;
+ int nthreads = tq->tq_nthreads;
+
+ taskq_wait(tq);
+
+ mutex_enter(&tq->tq_lock);
+
+ tq->tq_flags &= ~TASKQ_ACTIVE;
+ cv_broadcast(&tq->tq_dispatch_cv);
+
+ while (tq->tq_nthreads != 0)
+ cv_wait(&tq->tq_wait_cv, &tq->tq_lock);
+
+ tq->tq_minalloc = 0;
+ while (tq->tq_nalloc != 0) {
+ ASSERT(tq->tq_freelist != NULL);
+ task_free(tq, task_alloc(tq, KM_SLEEP));
+ }
+
+ mutex_exit(&tq->tq_lock);
+
+ for (t = 0; t < nthreads; t++)
+ (void) thr_join(tq->tq_threadlist[t], NULL, NULL);
+
+ kmem_free(tq->tq_threadlist, nthreads * sizeof (thread_t));
+
+ rw_destroy(&tq->tq_threadlock);
+ mutex_destroy(&tq->tq_lock);
+ cv_destroy(&tq->tq_dispatch_cv);
+ cv_destroy(&tq->tq_wait_cv);
+ cv_destroy(&tq->tq_maxalloc_cv);
+
+ kmem_free(tq, sizeof (taskq_t));
+}
+
+int
+taskq_member(taskq_t *tq, struct _kthread *t)
+{
+ int i;
+
+ if (taskq_now)
+ return (1);
+
+ for (i = 0; i < tq->tq_nthreads; i++)
+ if (tq->tq_threadlist[i] == (thread_t)(uintptr_t)t)
+ return (1);
+
+ return (0);
+}
+
+void
+system_taskq_init(void)
+{
+ system_taskq = taskq_create("system_taskq", 64, minclsyspri, 4, 512,
+ TASKQ_DYNAMIC | TASKQ_PREPOPULATE);
+}
+
+void
+system_taskq_fini(void)
+{
+ taskq_destroy(system_taskq);
+ system_taskq = NULL; /* defensive */
+}
diff --git a/usr/src/lib/libfakekernel/common/thread.c b/usr/src/lib/libfakekernel/common/thread.c
new file mode 100644
index 0000000000..ba16f3b8d5
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/thread.c
@@ -0,0 +1,125 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/cmn_err.h>
+#include <sys/thread.h>
+#include <sys/zone.h>
+
+#define _SYNCH_H /* keep out <synch.h> */
+#include <thread.h>
+
+/*
+ * Get the current kthread_t pointer.
+ */
+kthread_t *
+_curthread(void)
+{
+ thread_t tid;
+
+ tid = thr_self();
+ return ((kthread_t *)(uintptr_t)tid);
+}
+
+/*
+ * Create a thread.
+ *
+ * thread_create() blocks for memory if necessary. It never fails.
+ */
+/* ARGSUSED */
+kthread_t *
+thread_create(
+ caddr_t stk,
+ size_t stksize,
+ void (*func)(),
+ void *arg,
+ size_t len,
+ struct proc *pp,
+ int state,
+ pri_t pri)
+{
+ void * (*thr_func)(void *);
+ thread_t newtid;
+ int thr_flags = 0;
+ int rc;
+
+ thr_flags = THR_BOUND;
+
+ switch (state) {
+ case TS_RUN:
+ case TS_ONPROC:
+ break;
+ case TS_STOPPED:
+ thr_flags |= THR_SUSPENDED;
+ break;
+ default:
+ cmn_err(CE_PANIC, "thread_create: invalid state");
+ break;
+ }
+
+ thr_func = (void *(*)(void *))func;
+ rc = thr_create(NULL, 0, thr_func, arg, thr_flags, &newtid);
+ if (rc != 0)
+ cmn_err(CE_PANIC, "thread_create failed, rc=%d", rc);
+
+ return ((void *)(uintptr_t)newtid);
+}
+
+void
+thread_exit(void)
+{
+ thr_exit(NULL);
+}
+
+void
+thread_join(kt_did_t id)
+{
+ thread_t thr_id;
+
+ thr_id = (thread_t)id;
+ (void) thr_join(thr_id, NULL, NULL);
+}
+
+void
+tsignal(kthread_t *kt, int sig)
+{
+ thread_t tid = (thread_t)(uintptr_t)kt;
+
+ (void) thr_kill(tid, sig);
+}
+
+
+/*ARGSUSED*/
+kthread_t *
+zthread_create(
+ caddr_t stk,
+ size_t stksize,
+ void (*func)(),
+ void *arg,
+ size_t len,
+ pri_t pri)
+{
+ kthread_t *t;
+
+ t = thread_create(stk, stksize, func, arg, len, NULL, TS_RUN, pri);
+
+ return (t);
+}
+
+void
+zthread_exit(void)
+{
+ thread_exit();
+ /* NOTREACHED */
+}
diff --git a/usr/src/lib/libfakekernel/common/uio.c b/usr/src/lib/libfakekernel/common/uio.c
new file mode 100644
index 0000000000..934c8900a8
--- /dev/null
+++ b/usr/src/lib/libfakekernel/common/uio.c
@@ -0,0 +1,64 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/sysmacros.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/uio.h>
+#include <sys/errno.h>
+
+/*
+ * Move "n" bytes at byte address "p"; "rw" indicates the direction
+ * of the move, and the I/O parameters are provided in "uio", which is
+ * update to reflect the data which was moved. Returns 0 on success or
+ * a non-zero errno on failure.
+ */
+int
+uiomove(void *p, size_t n, enum uio_rw rw, struct uio *uio)
+{
+ struct iovec *iov;
+ ulong_t cnt;
+
+ while (n && uio->uio_resid) {
+ iov = uio->uio_iov;
+ cnt = MIN(iov->iov_len, n);
+ if (cnt == 0L) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ continue;
+ }
+ switch (uio->uio_segflg) {
+
+ case UIO_USERSPACE:
+ case UIO_USERISPACE:
+ return (EINVAL);
+
+ case UIO_SYSSPACE:
+ if (rw == UIO_READ)
+ bcopy(p, iov->iov_base, cnt);
+ else
+ bcopy(iov->iov_base, p, cnt);
+ break;
+ }
+ iov->iov_base += cnt;
+ iov->iov_len -= cnt;
+ uio->uio_resid -= cnt;
+ uio->uio_loffset += cnt;
+ p = (caddr_t)p + cnt;
+ n -= cnt;
+ }
+ return (0);
+}
diff --git a/usr/src/lib/libfakekernel/i386/Makefile b/usr/src/lib/libfakekernel/i386/Makefile
new file mode 100644
index 0000000000..c3b3d13b05
--- /dev/null
+++ b/usr/src/lib/libfakekernel/i386/Makefile
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libfakekernel/sparc/Makefile b/usr/src/lib/libfakekernel/sparc/Makefile
new file mode 100644
index 0000000000..c3b3d13b05
--- /dev/null
+++ b/usr/src/lib/libfakekernel/sparc/Makefile
@@ -0,0 +1,31 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/libfakekernel/sparcv9/Makefile b/usr/src/lib/libfakekernel/sparcv9/Makefile
new file mode 100644
index 0000000000..e4445a2843
--- /dev/null
+++ b/usr/src/lib/libfakekernel/sparcv9/Makefile
@@ -0,0 +1,32 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License, Version 1.0 only
+# (the "License"). You may not use this file except in compliance
+# with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2003 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
+
+include ../Makefile.com
+include ../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/lib/libidmap/common/idmap.h b/usr/src/lib/libidmap/common/idmap.h
index 01dce38944..b29bf56eee 100644
--- a/usr/src/lib/libidmap/common/idmap.h
+++ b/usr/src/lib/libidmap/common/idmap.h
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -41,13 +42,24 @@
extern "C" {
#endif
+/*
+ * The ifdef's for these two accomodate duplicate definitions in
+ * lib/smbsrv/libfksmbsrv/common/sys/kidmap.h See notes there.
+ */
+
/* Status */
+#ifndef _IDMAP_STAT_TYPE
+#define _IDMAP_STAT_TYPE
typedef int32_t idmap_stat;
+#endif /* _IDMAP_STAT_TYPE */
-typedef uint32_t idmap_rid_t;
-
-/* Opaque "get-mapping" handle */
+/* Opaque get handle */
+#ifndef _IDMAP_GET_HANDLE_T
+#define _IDMAP_GET_HANDLE_T
typedef struct idmap_get_handle idmap_get_handle_t;
+#endif /* _IDMAP_GET_HANDLE_T */
+
+typedef uint32_t idmap_rid_t;
/* Logger prototype which is based on syslog */
typedef void (*idmap_logger_t)(int, const char *, ...);
diff --git a/usr/src/lib/libshare/common/libshare.h b/usr/src/lib/libshare/common/libshare.h
index 283a499a8e..6180c011f9 100644
--- a/usr/src/lib/libshare/common/libshare.h
+++ b/usr/src/lib/libshare/common/libshare.h
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -35,7 +36,7 @@ extern "C" {
#endif
#include <sys/types.h>
-#include <libnvpair.h>
+#include <sys/nvpair.h>
/*
* Basic datatypes for most functions
diff --git a/usr/src/lib/libshare/smb/smb_share_doorclnt.c b/usr/src/lib/libshare/smb/smb_share_doorclnt.c
index fdd5706f2d..7f5c19412c 100644
--- a/usr/src/lib/libshare/smb/smb_share_doorclnt.c
+++ b/usr/src/lib/libshare/smb/smb_share_doorclnt.c
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -77,8 +78,14 @@ smb_share_door_clnt_fini(void)
static int
smb_share_door_clnt_open(void)
{
+ const char *door_name;
+
if (smb_share_dfd == -1) {
- if ((smb_share_dfd = open(SMB_SHARE_DNAME, O_RDONLY)) < 0)
+ door_name = getenv("SMB_SHARE_DNAME");
+ if (door_name == NULL)
+ door_name = SMB_SHARE_DNAME;
+
+ if ((smb_share_dfd = open(door_name, O_RDONLY)) < 0)
smb_share_dfd = -1;
else
smb_share_dncall = 0;
diff --git a/usr/src/lib/smbsrv/Makefile b/usr/src/lib/smbsrv/Makefile
index c3f6eb701f..9ba411e8ce 100644
--- a/usr/src/lib/smbsrv/Makefile
+++ b/usr/src/lib/smbsrv/Makefile
@@ -20,13 +20,14 @@
#
#
-# Copyright 2011 Nexenta Systems, Inc. All rights reserved.
# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
#
include ../Makefile.lib
SUBDIRS = \
+ libfksmbsrv \
libmlsvc \
libmlrpc \
libsmb \
@@ -36,5 +37,6 @@ SUBDIRS = \
libmlrpc: libsmb
libsmbns: libsmb
libmlsvc: libsmb libmlrpc libsmbns
+libfksmbsrv: libsmb
include ./Makefile.subdirs
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/Makefile b/usr/src/lib/smbsrv/libfksmbsrv/Makefile
new file mode 100644
index 0000000000..c1d45118f3
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/Makefile
@@ -0,0 +1,28 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
+
+include ../Makefile.smbsrv
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com b/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com
new file mode 100644
index 0000000000..92afcba6ae
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com
@@ -0,0 +1,210 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+#
+
+LIBRARY = libfksmbsrv.a
+VERS = .1
+
+OBJS_LOCAL = \
+ fksmb_cred.o \
+ fksmb_fem.o \
+ fksmb_idmap.o \
+ fksmb_init.o \
+ fksmb_kdoor.o \
+ fksmb_opipe_door.o \
+ fksmb_sign_pkcs.o \
+ fake_lookup.o \
+ fake_nblk.o \
+ fake_vfs.o \
+ fake_vnode.o \
+ fake_vop.o \
+ fake_xattr.o \
+ reparse.o \
+ vncache.o
+
+# See also: $SRC/uts/common/Makefile.files
+# NB: Intentionally ommitted, compared w/ the above:
+# smb_cred, smb_fem, smb_idmap, smb_init, smb_kdoor
+#
+OBJS_FS_SMBSRV = \
+ smb_acl.o \
+ smb_alloc.o \
+ smb_close.o \
+ smb_common_open.o \
+ smb_common_transact.o \
+ smb_create.o \
+ smb_delete.o \
+ smb_directory.o \
+ smb_dispatch.o \
+ smb_echo.o \
+ smb_find.o \
+ smb_flush.o \
+ smb_fsinfo.o \
+ smb_fsops.o \
+ smb_kshare.o \
+ smb_kutil.o \
+ smb_lock.o \
+ smb_lock_byte_range.o \
+ smb_locking_andx.o \
+ smb_logoff_andx.o \
+ smb_mangle_name.o \
+ smb_mbuf_marshaling.o \
+ smb_mbuf_util.o \
+ smb_negotiate.o \
+ smb_net.o \
+ smb_node.o \
+ smb_nt_cancel.o \
+ smb_nt_create_andx.o \
+ smb_nt_transact_create.o \
+ smb_nt_transact_ioctl.o \
+ smb_nt_transact_notify_change.o \
+ smb_nt_transact_quota.o \
+ smb_nt_transact_security.o \
+ smb_odir.o \
+ smb_ofile.o \
+ smb_open_andx.o \
+ smb_opipe.o \
+ smb_oplock.o \
+ smb_pathname.o \
+ smb_print.o \
+ smb_process_exit.o \
+ smb_query_fileinfo.o \
+ smb_read.o \
+ smb_rename.o \
+ smb_sd.o \
+ smb_seek.o \
+ smb_server.o \
+ smb_session.o \
+ smb_session_setup_andx.o \
+ smb_set_fileinfo.o \
+ smb_signing.o \
+ smb_thread.o \
+ smb_tree.o \
+ smb_trans2_create_directory.o \
+ smb_trans2_dfs.o \
+ smb_trans2_find.o \
+ smb_tree_connect.o \
+ smb_unlock_byte_range.o \
+ smb_user.o \
+ smb_vfs.o \
+ smb_vops.o \
+ smb_vss.o \
+ smb_write.o
+
+# Can't just link with -lsmb because of user vs kernel API
+# i.e. can't call free with mem from kmem_alloc, which is
+# what happens if we just link with -lsmb
+OBJS_CMN_SMBSRV = \
+ smb_inet.o \
+ smb_match.o \
+ smb_msgbuf.o \
+ smb_native.o \
+ smb_netbios_util.o \
+ smb_oem.o \
+ smb_sid.o \
+ smb_string.o \
+ smb_token.o \
+ smb_token_xdr.o \
+ smb_utf8.o \
+ smb_xdr.o
+
+OBJS_MISC = \
+ acl_common.o \
+ pathname.o \
+ refstr.o \
+ xattr_common.o
+
+OBJECTS = \
+ $(OBJS_LOCAL) \
+ $(OBJS_FS_SMBSRV) \
+ $(OBJS_CMN_SMBSRV) \
+ $(OBJS_MISC)
+
+include ../../../Makefile.lib
+include ../../Makefile.lib
+
+# Force SOURCEDEBUG
+CSOURCEDEBUGFLAGS = -g
+CCSOURCEDEBUGFLAGS = -g
+STRIP_STABS = :
+
+
+# Note: need our sys includes _before_ ENVCPPFLAGS, proto etc.
+CPPFLAGS.first += -I../../../libfakekernel/common
+CPPFLAGS.first += -I../common
+
+INCS += -I$(SRC)/uts/common
+INCS += -I$(SRC)/common/smbsrv
+INCS += -I$(SRC)/common
+
+LINTCHECKFLAGS += -erroff=E_INCONS_ARG_DECL2
+LINTCHECKFLAGS += -erroff=E_INCONS_VAL_TYPE_DECL2
+LINTCHECKFLAGS += -erroff=E_INCONS_VAL_TYPE_USED2
+
+LDLIBS += $(MACH_LDLIBS)
+LDLIBS += -lfakekernel -lidmap -lcmdutils
+LDLIBS += -lavl -lnvpair -lnsl -lpkcs11 -lreparse -lc
+
+CPPFLAGS += $(INCS) -D_REENTRANT -D_FAKE_KERNEL
+CPPFLAGS += -D_FILE_OFFSET_BITS=64
+# Always want DEBUG here
+CPPFLAGS += -DDEBUG
+
+CERRWARN += -_gcc=-Wno-parentheses
+CERRWARN += -_gcc=-Wno-switch
+
+SRCS= $(OBJS_LOCAL:%.o=$(SRCDIR)/%.c) \
+ $(OBJS_FS_SMBSRV:%.o=$(SRC)/uts/common/fs/smbsrv/%.c) \
+ $(OBJS_CMN_SMBSRV:%.o=$(SRC)/common/smbsrv/%.c)
+
+all:
+
+pics/%.o: $(SRC)/uts/common/fs/smbsrv/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
+
+pics/acl_common.o: $(SRC)/common/acl/acl_common.c
+ $(COMPILE.c) -o $@ $(SRC)/common/acl/acl_common.c
+ $(POST_PROCESS_O)
+
+pics/pathname.o: $(SRC)/uts/common/fs/pathname.c
+ $(COMPILE.c) -o $@ $(SRC)/uts/common/fs/pathname.c
+ $(POST_PROCESS_O)
+
+pics/refstr.o: $(SRC)/uts/common/os/refstr.c
+ $(COMPILE.c) -o $@ $(SRC)/uts/common/os/refstr.c
+ $(POST_PROCESS_O)
+
+pics/xattr_common.o: $(SRC)/common/xattr/xattr_common.c
+ $(COMPILE.c) -o $@ $(SRC)/common/xattr/xattr_common.c
+ $(POST_PROCESS_O)
+
+# Makefile.targ has rule for $(SRC)/common/smbsrv/%.c
+
+.KEEP_STATE:
+
+include ../../Makefile.targ
+include ../../../Makefile.targ
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/amd64/Makefile b/usr/src/lib/smbsrv/libfksmbsrv/amd64/Makefile
new file mode 100644
index 0000000000..ee4c505848
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/amd64/Makefile
@@ -0,0 +1,33 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+#
+
+MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64)
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fake_lookup.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fake_lookup.c
new file mode 100644
index 0000000000..c475980dc1
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fake_lookup.c
@@ -0,0 +1,560 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/file.h>
+#include <sys/errno.h>
+#include <sys/cred.h>
+#include <sys/user.h>
+#include <sys/uio.h>
+#include <sys/vfs.h>
+#include <sys/vnode.h>
+#include <sys/pathname.h>
+#include <sys/proc.h>
+#include <sys/vtrace.h>
+#include <sys/sysmacros.h>
+#include <sys/debug.h>
+#include <sys/dirent.h>
+#include <sys/zone.h>
+#include <sys/dnlc.h>
+#include <sys/fs/snode.h>
+
+/*
+ * Starting at current directory, translate pathname pnp to end.
+ * Leave pathname of final component in pnp, return the vnode
+ * for the final component in *compvpp, and return the vnode
+ * for the parent of the final component in dirvpp.
+ *
+ * This is the central routine in pathname translation and handles
+ * multiple components in pathnames, separating them at /'s. It also
+ * implements mounted file systems and processes symbolic links.
+ *
+ * vp is the vnode where the directory search should start.
+ *
+ * Reference counts: vp must be held prior to calling this function. rootvp
+ * should only be held if rootvp != rootdir.
+ */
+int
+lookuppnvp(
+ struct pathname *pnp, /* pathname to lookup */
+ struct pathname *rpnp, /* if non-NULL, return resolved path */
+ int flags, /* follow symlinks */
+ vnode_t **dirvpp, /* ptr for parent vnode */
+ vnode_t **compvpp, /* ptr for entry vnode */
+ vnode_t *rootvp, /* rootvp */
+ vnode_t *vp, /* directory to start search at */
+ cred_t *cr) /* user's credential */
+{
+ vnode_t *cvp; /* current component vp */
+ vnode_t *tvp; /* addressable temp ptr */
+ char component[MAXNAMELEN]; /* buffer for component (incl null) */
+ int error;
+ int nlink;
+ int lookup_flags;
+ struct pathname presrvd; /* case preserved name */
+ struct pathname *pp = NULL;
+ vnode_t *startvp;
+ int must_be_directory = 0;
+ boolean_t retry_with_kcred;
+
+ nlink = 0;
+ cvp = NULL;
+ if (rpnp)
+ rpnp->pn_pathlen = 0;
+
+ lookup_flags = dirvpp ? LOOKUP_DIR : 0;
+ if (flags & FIGNORECASE) {
+ lookup_flags |= FIGNORECASE;
+ pn_alloc(&presrvd);
+ pp = &presrvd;
+ }
+
+ /*
+ * Eliminate any trailing slashes in the pathname.
+ * If there are any, we must follow all symlinks.
+ * Also, we must guarantee that the last component is a directory.
+ */
+ if (pn_fixslash(pnp)) {
+ flags |= FOLLOW;
+ must_be_directory = 1;
+ }
+
+ startvp = vp;
+next:
+ retry_with_kcred = B_FALSE;
+
+ /*
+ * Make sure we have a directory.
+ */
+ if (vp->v_type != VDIR) {
+ error = ENOTDIR;
+ goto bad;
+ }
+
+ if (rpnp && VN_CMP(vp, rootvp))
+ (void) pn_set(rpnp, "/");
+
+ /*
+ * Process the next component of the pathname.
+ */
+ if (error = pn_getcomponent(pnp, component)) {
+ goto bad;
+ }
+
+ /*
+ * Handle "..": two special cases.
+ * 1. If we're at the root directory (e.g. after chroot or
+ * zone_enter) then change ".." to "." so we can't get
+ * out of this subtree.
+ * 2. If this vnode is the root of a mounted file system,
+ * then replace it with the vnode that was mounted on
+ * so that we take the ".." in the other file system.
+ */
+ if (component[0] == '.' && component[1] == '.' && component[2] == 0) {
+checkforroot:
+ if (VN_CMP(vp, rootvp)) {
+ component[1] = '\0';
+ } else if (vp->v_flag & VROOT) {
+ vfs_t *vfsp;
+ cvp = vp;
+
+ /*
+ * While we deal with the vfs pointer from the vnode
+ * the filesystem could have been forcefully unmounted
+ * and the vnode's v_vfsp could have been invalidated
+ * by VFS_UNMOUNT. Hence, we cache v_vfsp and use it
+ * with vfs_rlock_wait/vfs_unlock.
+ * It is safe to use the v_vfsp even it is freed by
+ * VFS_UNMOUNT because vfs_rlock_wait/vfs_unlock
+ * do not dereference v_vfsp. It is just used as a
+ * magic cookie.
+ * One more corner case here is the memory getting
+ * reused for another vfs structure. In this case
+ * lookuppnvp's vfs_rlock_wait will succeed, domount's
+ * vfs_lock will fail and domount will bail out with an
+ * error (EBUSY).
+ */
+ vfsp = cvp->v_vfsp;
+
+ /*
+ * This lock is used to synchronize
+ * mounts/unmounts and lookups.
+ * Threads doing mounts/unmounts hold the
+ * writers version vfs_lock_wait().
+ */
+
+ vfs_rlock_wait(vfsp);
+
+ /*
+ * If this vnode is on a file system that
+ * has been forcibly unmounted,
+ * we can't proceed. Cancel this operation
+ * and return EIO.
+ *
+ * vfs_vnodecovered is NULL if unmounted.
+ * Currently, nfs uses VFS_UNMOUNTED to
+ * check if it's a forced-umount. Keep the
+ * same checking here as well even though it
+ * may not be needed.
+ */
+ if (((vp = cvp->v_vfsp->vfs_vnodecovered) == NULL) ||
+ (cvp->v_vfsp->vfs_flag & VFS_UNMOUNTED)) {
+ vfs_unlock(vfsp);
+ VN_RELE(cvp);
+ if (pp)
+ pn_free(pp);
+ return (EIO);
+ }
+ VN_HOLD(vp);
+ vfs_unlock(vfsp);
+ VN_RELE(cvp);
+ cvp = NULL;
+ /*
+ * Crossing mount points. For eg: We are doing
+ * a lookup of ".." for file systems root vnode
+ * mounted here, and VOP_LOOKUP() (with covered vnode)
+ * will be on underlying file systems mount point
+ * vnode. Set retry_with_kcred flag as we might end
+ * up doing VOP_LOOKUP() with kcred if required.
+ */
+ retry_with_kcred = B_TRUE;
+ goto checkforroot;
+ }
+ }
+
+ /*
+ * Perform a lookup in the current directory.
+ */
+ error = VOP_LOOKUP(vp, component, &tvp, pnp, lookup_flags,
+ rootvp, cr, NULL, NULL, pp);
+
+ /*
+ * Retry with kcred - If crossing mount points & error is EACCES.
+ *
+ * If we are crossing mount points here and doing ".." lookup,
+ * VOP_LOOKUP() might fail if the underlying file systems
+ * mount point has no execute permission. In cases like these,
+ * we retry VOP_LOOKUP() by giving as much privilage as possible
+ * by passing kcred credentials.
+ *
+ * In case of hierarchical file systems, passing kcred still may
+ * or may not work.
+ * For eg: UFS FS --> Mount NFS FS --> Again mount UFS on some
+ * directory inside NFS FS.
+ */
+ if ((error == EACCES) && retry_with_kcred)
+ error = VOP_LOOKUP(vp, component, &tvp, pnp, lookup_flags,
+ rootvp, zone_kcred(), NULL, NULL, pp);
+
+ cvp = tvp;
+ if (error) {
+ cvp = NULL;
+ /*
+ * On error, return hard error if
+ * (a) we're not at the end of the pathname yet, or
+ * (b) the caller didn't want the parent directory, or
+ * (c) we failed for some reason other than a missing entry.
+ */
+ if (pn_pathleft(pnp) || dirvpp == NULL || error != ENOENT)
+ goto bad;
+
+ pn_setlast(pnp);
+ /*
+ * We inform the caller that the desired entry must be
+ * a directory by adding a '/' to the component name.
+ */
+ if (must_be_directory && (error = pn_addslash(pnp)) != 0)
+ goto bad;
+ *dirvpp = vp;
+ if (compvpp != NULL)
+ *compvpp = NULL;
+ if (rootvp != rootdir)
+ VN_RELE(rootvp);
+ if (pp)
+ pn_free(pp);
+ return (0);
+ }
+
+ /*
+ * Traverse mount points.
+ */
+ if (vn_mountedvfs(cvp) != NULL) {
+ tvp = cvp;
+ if ((error = traverse(&tvp)) != 0) {
+ /*
+ * It is required to assign cvp here, because
+ * traverse() will return a held vnode which
+ * may different than the vnode that was passed
+ * in (even in the error case). If traverse()
+ * changes the vnode it releases the original,
+ * and holds the new one.
+ */
+ cvp = tvp;
+ goto bad;
+ }
+ cvp = tvp;
+ }
+
+ /*
+ * If we hit a symbolic link and there is more path to be
+ * translated or this operation does not wish to apply
+ * to a link, then place the contents of the link at the
+ * front of the remaining pathname.
+ */
+ if (cvp->v_type == VLNK && ((flags & FOLLOW) || pn_pathleft(pnp))) {
+ struct pathname linkpath;
+
+ if (++nlink > MAXSYMLINKS) {
+ error = ELOOP;
+ goto bad;
+ }
+ pn_alloc(&linkpath);
+ if (error = pn_getsymlink(cvp, &linkpath, cr)) {
+ pn_free(&linkpath);
+ goto bad;
+ }
+
+ if (pn_pathleft(&linkpath) == 0)
+ (void) pn_set(&linkpath, ".");
+ error = pn_insert(pnp, &linkpath, strlen(component));
+ pn_free(&linkpath);
+ if (error)
+ goto bad;
+ VN_RELE(cvp);
+ cvp = NULL;
+ if (pnp->pn_pathlen == 0) {
+ error = ENOENT;
+ goto bad;
+ }
+ if (pnp->pn_path[0] == '/') {
+ do {
+ pnp->pn_path++;
+ pnp->pn_pathlen--;
+ } while (pnp->pn_path[0] == '/');
+ VN_RELE(vp);
+ vp = rootvp;
+ VN_HOLD(vp);
+ }
+ if (pn_fixslash(pnp)) {
+ flags |= FOLLOW;
+ must_be_directory = 1;
+ }
+ goto next;
+ }
+
+ /*
+ * If rpnp is non-NULL, remember the resolved path name therein.
+ * Do not include "." components. Collapse occurrences of
+ * "previous/..", so long as "previous" is not itself "..".
+ * Exhausting rpnp results in error ENAMETOOLONG.
+ */
+ if (rpnp && strcmp(component, ".") != 0) {
+ size_t len;
+
+ if (strcmp(component, "..") == 0 &&
+ rpnp->pn_pathlen != 0 &&
+ !((rpnp->pn_pathlen > 2 &&
+ strncmp(rpnp->pn_path+rpnp->pn_pathlen-3, "/..", 3) == 0) ||
+ (rpnp->pn_pathlen == 2 &&
+ strncmp(rpnp->pn_path, "..", 2) == 0))) {
+ while (rpnp->pn_pathlen &&
+ rpnp->pn_path[rpnp->pn_pathlen-1] != '/')
+ rpnp->pn_pathlen--;
+ if (rpnp->pn_pathlen > 1)
+ rpnp->pn_pathlen--;
+ rpnp->pn_path[rpnp->pn_pathlen] = '\0';
+ } else {
+ if (rpnp->pn_pathlen != 0 &&
+ rpnp->pn_path[rpnp->pn_pathlen-1] != '/')
+ rpnp->pn_path[rpnp->pn_pathlen++] = '/';
+ if (flags & FIGNORECASE) {
+ /*
+ * Return the case-preserved name
+ * within the resolved path.
+ */
+ error = copystr(pp->pn_buf,
+ rpnp->pn_path + rpnp->pn_pathlen,
+ rpnp->pn_bufsize - rpnp->pn_pathlen, &len);
+ } else {
+ error = copystr(component,
+ rpnp->pn_path + rpnp->pn_pathlen,
+ rpnp->pn_bufsize - rpnp->pn_pathlen, &len);
+ }
+ if (error) /* copystr() returns ENAMETOOLONG */
+ goto bad;
+ rpnp->pn_pathlen += (len - 1);
+ ASSERT(rpnp->pn_bufsize > rpnp->pn_pathlen);
+ }
+ }
+
+ /*
+ * If no more components, return last directory (if wanted) and
+ * last component (if wanted).
+ */
+ if (pn_pathleft(pnp) == 0) {
+ /*
+ * If there was a trailing slash in the pathname,
+ * make sure the last component is a directory.
+ */
+ if (must_be_directory && cvp->v_type != VDIR) {
+ error = ENOTDIR;
+ goto bad;
+ }
+ if (dirvpp != NULL) {
+ /*
+ * Check that we have the real parent and not
+ * an alias of the last component.
+ */
+ if (vn_compare(vp, cvp)) {
+ pn_setlast(pnp);
+ VN_RELE(vp);
+ VN_RELE(cvp);
+ if (rootvp != rootdir)
+ VN_RELE(rootvp);
+ if (pp)
+ pn_free(pp);
+ return (EINVAL);
+ }
+ *dirvpp = vp;
+ } else
+ VN_RELE(vp);
+ if (pnp->pn_path == pnp->pn_buf)
+ (void) pn_set(pnp, ".");
+ else
+ pn_setlast(pnp);
+ if (rpnp) {
+ if (VN_CMP(cvp, rootvp))
+ (void) pn_set(rpnp, "/");
+ else if (rpnp->pn_pathlen == 0)
+ (void) pn_set(rpnp, ".");
+ }
+
+ if (compvpp != NULL)
+ *compvpp = cvp;
+ else
+ VN_RELE(cvp);
+ if (rootvp != rootdir)
+ VN_RELE(rootvp);
+ if (pp)
+ pn_free(pp);
+ return (0);
+ }
+
+ /*
+ * Skip over slashes from end of last component.
+ */
+ while (pnp->pn_path[0] == '/') {
+ pnp->pn_path++;
+ pnp->pn_pathlen--;
+ }
+
+ /*
+ * Searched through another level of directory:
+ * release previous directory handle and save new (result
+ * of lookup) as current directory.
+ */
+ VN_RELE(vp);
+ vp = cvp;
+ cvp = NULL;
+ goto next;
+
+bad:
+ /*
+ * Error. Release vnodes and return.
+ */
+ if (cvp)
+ VN_RELE(cvp);
+ /*
+ * If the error was ESTALE and the current directory to look in
+ * was the root for this lookup, the root for a mounted file
+ * system, or the starting directory for lookups, then
+ * return ENOENT instead of ESTALE. In this case, no recovery
+ * is possible by the higher level. If ESTALE was returned for
+ * some intermediate directory along the path, then recovery
+ * is potentially possible and retrying from the higher level
+ * will either correct the situation by purging stale cache
+ * entries or eventually get back to the point where no recovery
+ * is possible.
+ */
+ if (error == ESTALE &&
+ (VN_CMP(vp, rootvp) || (vp->v_flag & VROOT) || vp == startvp))
+ error = ENOENT;
+ VN_RELE(vp);
+ if (rootvp != rootdir)
+ VN_RELE(rootvp);
+ if (pp)
+ pn_free(pp);
+ return (error);
+}
+
+/*
+ * Traverse a mount point. Routine accepts a vnode pointer as a reference
+ * parameter and performs the indirection, releasing the original vnode.
+ */
+int
+traverse(vnode_t **cvpp)
+{
+ int error = 0;
+ vnode_t *cvp;
+ vnode_t *tvp;
+ vfs_t *vfsp;
+
+ cvp = *cvpp;
+
+ /*
+ * If this vnode is mounted on, then we transparently indirect
+ * to the vnode which is the root of the mounted file system.
+ * Before we do this we must check that an unmount is not in
+ * progress on this vnode.
+ */
+
+ for (;;) {
+ /*
+ * Used to try to read lock the vnode here.
+ */
+
+ /*
+ * Reached the end of the mount chain?
+ */
+ vfsp = vn_mountedvfs(cvp);
+ if (vfsp == NULL) {
+ break;
+ }
+
+ /*
+ * The read lock must be held across the call to VFS_ROOT() to
+ * prevent a concurrent unmount from destroying the vfs.
+ */
+ error = VFS_ROOT(vfsp, &tvp);
+ if (error)
+ break;
+
+ VN_RELE(cvp);
+
+ cvp = tvp;
+ }
+
+ *cvpp = cvp;
+ return (error);
+}
+
+/*
+ * Get the vnode path, relative to the passed rootvp.
+ * Our vncache always fills in v_path, so this is easy.
+ */
+/* ARGSUSED */
+int
+vnodetopath(vnode_t *vrootp, vnode_t *vp, char *buf, size_t buflen, cred_t *cr)
+{
+ int len, rvp_len = 0;
+ const char *p = vp->v_path;
+
+ if (vrootp)
+ rvp_len = strlen(vrootp->v_path);
+ len = strlen(p);
+ if (rvp_len < len)
+ p += rvp_len;
+ else
+ p = "/";
+
+ (void) strlcpy(buf, p, buflen);
+ return (0);
+}
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fake_nblk.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fake_nblk.c
new file mode 100644
index 0000000000..ea2ec317df
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fake_nblk.c
@@ -0,0 +1,173 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * Utility routines and top-level conflict detection code for NBMAND
+ * locks.
+ */
+
+#include <sys/types.h>
+#include <sys/cmn_err.h>
+#include <sys/debug.h>
+#include <sys/fcntl.h>
+#include <sys/rwlock.h>
+#include <sys/vnode.h>
+#include <sys/vfs.h>
+#include <sys/nbmlock.h>
+
+/*
+ * Enter the critical region for synchronizing I/O requests with lock/share
+ * requests. "mode" specifies whether the caller intends to update
+ * lock/share state (as opposed to just query it).
+ */
+
+void
+nbl_start_crit(vnode_t *vp, krw_t mode)
+{
+ rw_enter(&vp->v_nbllock, mode);
+}
+
+/*
+ * Leave the critical region.
+ */
+
+void
+nbl_end_crit(vnode_t *vp)
+{
+ rw_exit(&vp->v_nbllock);
+}
+
+/*
+ * Return non-zero if some thread is in the critical region.
+ * Note that this is appropriate for use in ASSERT()s only.
+ */
+
+int
+nbl_in_crit(vnode_t *vp)
+{
+ return (RW_LOCK_HELD(&vp->v_nbllock));
+}
+
+/*
+ * Returns non-zero if we need to look further for an NBMAND lock or
+ * share conflict.
+ */
+/* ARGSUSED */
+int
+nbl_need_check(vnode_t *vp)
+{
+ /*
+ * Currently we only check if NBMAND locks/shares are allowed on
+ * the filesystem. An option for the future would be to have a
+ * flag on the vnode, though the locking for that can get tricky.
+ */
+ /* (vp->v_vfsp) && (vp->v_vfsp->vfs_flag & VFS_NBMAND)) */
+ return (0);
+}
+
+/*
+ * Top-level conflict detection routine. The arguments describe the
+ * operation that is being attempted. If the operation conflicts with an
+ * existing lock or share reservation, a non-zero value is returned. If
+ * the operation is allowed, zero is returned. Note that there is an
+ * implicit argument, which is the process ID of the requester.
+ *
+ * svmand indicates that the file has System V mandatory locking enabled,
+ * so we should look at all record locks, not just NBMAND record locks.
+ * (This is to avoid a deadlock between a process making an I/O request and
+ * a process trying to release a lock. Instead of letting the first
+ * process block in the filesystem code, we flag a conflict here.)
+ */
+
+int
+nbl_conflict(vnode_t *vp,
+ nbl_op_t op, /* attempted operation */
+ u_offset_t offset, /* ignore if not I/O */
+ ssize_t length, /* ignore if not I/O */
+ int svmand, /* System V mandatory locking */
+ caller_context_t *ct) /* caller context */
+{
+ ASSERT(nbl_in_crit(vp));
+ ASSERT(op == NBL_READ || op == NBL_WRITE || op == NBL_RENAME ||
+ op == NBL_REMOVE || op == NBL_READWRITE);
+
+ if (nbl_share_conflict(vp, op, ct)) {
+ return (1);
+ }
+
+ /*
+ * If this is not an I/O request, there's no need to check against
+ * the locks on the file.
+ */
+ if (op == NBL_REMOVE || op == NBL_RENAME)
+ return (0);
+
+ return (nbl_lock_conflict(vp, op, offset, length, svmand, ct));
+}
+
+/*
+ * Determine if the given file has mode bits for System V mandatory locks.
+ * If there was an error, the errno value is returned. Otherwise, zero is
+ * returned and *svp is set appropriately (non-zero for mandatory locks,
+ * zero for no mandatory locks).
+ */
+
+int
+nbl_svmand(vnode_t *vp, cred_t *cr, int *svp)
+{
+ struct vattr va;
+ int error;
+
+ va.va_mask = AT_MODE;
+ error = VOP_GETATTR(vp, &va, 0, cr, NULL);
+ if (error != 0)
+ return (error);
+
+ *svp = MANDLOCK(vp, va.va_mode);
+ return (0);
+}
+
+/*
+ * The kernel handles this for us when we actually try I/O.
+ */
+/* ARGSUSED */
+int
+nbl_share_conflict(vnode_t *vp, nbl_op_t op, caller_context_t *ct)
+{
+ return (0);
+}
+
+/*
+ * The kernel handles this for us when we actually try I/O.
+ */
+/* ARGSUSED */
+int
+nbl_lock_conflict(vnode_t *vp, nbl_op_t op, u_offset_t offset,
+ ssize_t length, int svmand, caller_context_t *ct)
+{
+ return (0);
+}
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vfs.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vfs.c
new file mode 100644
index 0000000000..cf53ca03b2
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vfs.c
@@ -0,0 +1,244 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/t_lock.h>
+#include <sys/errno.h>
+#include <sys/cred.h>
+#include <sys/user.h>
+#include <sys/uio.h>
+#include <sys/file.h>
+#include <sys/pathname.h>
+#include <sys/vfs.h>
+#include <sys/vnode.h>
+#include <sys/stat.h>
+#include <sys/mode.h>
+#include <sys/conf.h>
+#include <sys/sysmacros.h>
+#include <sys/cmn_err.h>
+#include <sys/systm.h>
+#include <sys/kmem.h>
+#include <sys/debug.h>
+#include <sys/acl.h>
+#include <sys/nbmlock.h>
+#include <sys/fcntl.h>
+#include <sys/poll.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "vncache.h"
+
+#define VFTBITS(feature) ((feature) & 0xFFFFFFFFLL)
+
+static uint64_t vfs_features = VFSFT_XVATTR;
+
+vnode_t *rootdir = NULL; /* pointer to root inode vnode. */
+
+static struct vfs fake_rootvfs;
+struct vfs *rootvfs = NULL;
+
+int
+fksmbsrv_vfs_init(void)
+{
+ struct stat st;
+ int err, fd;
+ vnode_t *vp;
+ char *name = "/";
+
+ if (rootvfs == NULL) {
+ rootvfs = &fake_rootvfs;
+ rootvfs->vfs_mntpt = refstr_alloc(name);
+ rootvfs->vfs_fsid.val[0] = 1;
+ }
+
+ if (rootdir == NULL) {
+ if (lstat(name, &st) == -1)
+ return (errno);
+ fd = open(name, O_RDONLY, 0);
+ if (fd < 0) {
+ return (errno);
+ }
+ if (fstat(fd, &st) == -1) {
+ err = errno;
+ (void) close(fd);
+ return (err);
+ }
+ vp = vncache_enter(&st, NULL, "", fd);
+ /* extra hold for rootvp */
+ vn_hold(vp);
+ rootdir = vp;
+
+ /* VFS stuff in global zone struct. */
+ zone0.zone_rootvp = rootdir;
+ zone0.zone_rootpath = "/";
+ }
+
+ return (0);
+
+}
+
+
+/*
+ * Query a vfs for a feature.
+ * Returns 1 if feature is present, 0 if not
+ */
+/* ARGSUSED */
+int
+vfs_has_feature(vfs_t *vfsp, vfs_feature_t feature)
+{
+ int ret = 0;
+
+ if (vfs_features & VFTBITS(feature))
+ ret = 1;
+
+ return (ret);
+}
+
+/* ARGSUSED */
+struct vfs *
+getvfs(fsid_t *fsid)
+{
+ return (rootvfs);
+}
+
+vfsops_t *
+vfs_getops(vfs_t *vfsp)
+{
+ return (vfsp->vfs_op);
+}
+
+/* ARGSUSED */
+struct vfssw *
+vfs_getvfsswbyvfsops(vfsops_t *vfsops)
+{
+ return (NULL);
+}
+
+/* ARGSUSED */
+void
+vfs_unrefvfssw(struct vfssw *vswp)
+{
+}
+
+/* ARGSUSED */
+int
+fsop_root(vfs_t *vfsp, vnode_t **vpp)
+{
+ vnode_t *vp;
+
+ if ((vp = rootdir) == NULL)
+ return (ENXIO);
+
+ vn_hold(vp);
+ *vpp = vp;
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fsop_statfs(vfs_t *vfsp, statvfs64_t *sp)
+{
+ vnode_t *vp;
+ int rc;
+
+ if ((vp = rootdir) == NULL)
+ return (ENXIO);
+
+ rc = fstatvfs64(vp->v_fd, sp);
+ if (rc == -1) {
+ rc = errno;
+ }
+
+ return (rc);
+}
+
+refstr_t *
+vfs_getmntpoint(const struct vfs *vfsp)
+{
+ refstr_t *mntpt;
+
+ mntpt = vfsp->vfs_mntpt;
+ refstr_hold(mntpt);
+
+ return (mntpt);
+}
+
+/* ARGSUSED */
+void
+vfs_hold(vfs_t *vfsp)
+{
+}
+
+/* ARGSUSED */
+void
+vfs_rele(vfs_t *vfsp)
+{
+}
+
+/* ARGSUSED */
+int
+vfs_lock(vfs_t *vfsp)
+{
+ return (0);
+}
+
+/* ARGSUSED */
+int
+vfs_rlock(vfs_t *vfsp)
+{
+ return (0);
+}
+
+/* ARGSUSED */
+void
+vfs_lock_wait(vfs_t *vfsp)
+{
+}
+
+/* ARGSUSED */
+void
+vfs_rlock_wait(vfs_t *vfsp)
+{
+}
+
+/* ARGSUSED */
+void
+vfs_unlock(vfs_t *vfsp)
+{
+}
+
+
+static u_longlong_t fs_caller_id;
+u_longlong_t
+fs_new_caller_id(void)
+{
+ return (++fs_caller_id);
+}
+
+static sysid_t lm_sysid;
+sysid_t
+lm_alloc_sysidt(void)
+{
+ return (++lm_sysid);
+}
+
+/* ARGSUSED */
+void
+lm_free_sysidt(sysid_t id)
+{
+}
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vnode.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vnode.c
new file mode 100644
index 0000000000..533a40fb28
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vnode.c
@@ -0,0 +1,80 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/cmn_err.h>
+#include <sys/cred.h>
+#include <sys/debug.h>
+#include <sys/errno.h>
+#include <sys/file.h>
+#include <sys/kmem.h>
+#include <sys/t_lock.h>
+#include <sys/user.h>
+#include <sys/uio.h>
+#include <sys/pathname.h>
+#include <sys/sysmacros.h>
+#include <sys/vfs.h>
+#include <sys/vnode.h>
+
+#include <sys/acl.h>
+#include <sys/nbmlock.h>
+#include <sys/fcntl.h>
+
+/*
+ * Are vp1 and vp2 the same vnode?
+ */
+int
+vn_compare(vnode_t *vp1, vnode_t *vp2)
+{
+ vnode_t *realvp;
+
+ if (vp1 != NULL && VOP_REALVP(vp1, &realvp, NULL) == 0)
+ vp1 = realvp;
+ if (vp2 != NULL && VOP_REALVP(vp2, &realvp, NULL) == 0)
+ vp2 = realvp;
+ return (VN_CMP(vp1, vp2));
+}
+
+/* ARGSUSED */
+vfs_t *
+vn_mountedvfs(vnode_t *vp)
+{
+ return (NULL);
+}
+
+void
+xva_init(xvattr_t *xvap)
+{
+ bzero(xvap, sizeof (xvattr_t));
+ xvap->xva_mapsize = XVA_MAPSIZE;
+ xvap->xva_magic = XVA_MAGIC;
+ xvap->xva_vattr.va_mask = AT_XVATTR;
+ xvap->xva_rtnattrmapp = &(xvap->xva_rtnattrmap)[0];
+}
+
+/*
+ * If AT_XVATTR is set, returns a pointer to the embedded xoptattr_t
+ * structure. Otherwise, returns NULL.
+ */
+xoptattr_t *
+xva_getxoptattr(xvattr_t *xvap)
+{
+ xoptattr_t *xoap = NULL;
+ if (xvap->xva_vattr.va_mask & AT_XVATTR)
+ xoap = &xvap->xva_xoptattrs;
+ return (xoap);
+}
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vop.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vop.c
new file mode 100644
index 0000000000..5f14cfc896
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fake_vop.c
@@ -0,0 +1,1349 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/t_lock.h>
+#include <sys/errno.h>
+#include <sys/cred.h>
+#include <sys/user.h>
+#include <sys/uio.h>
+#include <sys/file.h>
+#include <sys/pathname.h>
+#include <sys/vfs.h>
+#include <sys/vnode.h>
+#include <sys/stat.h>
+#include <sys/mode.h>
+#include <sys/kmem.h>
+#include <sys/debug.h>
+#include <sys/atomic.h>
+#include <sys/acl.h>
+#include <sys/flock.h>
+#include <sys/nbmlock.h>
+#include <sys/fcntl.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "vncache.h"
+
+#define O_RWMASK (O_WRONLY | O_RDWR) /* == 3 */
+
+int fop_shrlock_enable = 0;
+
+int stat_to_vattr(const struct stat *, vattr_t *);
+int fop__getxvattr(vnode_t *, xvattr_t *);
+int fop__setxvattr(vnode_t *, xvattr_t *);
+
+
+/* ARGSUSED */
+int
+fop_open(
+ vnode_t **vpp,
+ int mode,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+
+ if ((*vpp)->v_type == VREG) {
+ if (mode & FREAD)
+ atomic_add_32(&((*vpp)->v_rdcnt), 1);
+ if (mode & FWRITE)
+ atomic_add_32(&((*vpp)->v_wrcnt), 1);
+ }
+
+ /* call to ->vop_open was here */
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_close(
+ vnode_t *vp,
+ int flag,
+ int count,
+ offset_t offset,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+
+ /* call to ->vop_close was here */
+
+ /*
+ * Check passed in count to handle possible dups. Vnode counts are only
+ * kept on regular files
+ */
+ if ((vp->v_type == VREG) && (count == 1)) {
+ if (flag & FREAD) {
+ ASSERT(vp->v_rdcnt > 0);
+ atomic_add_32(&(vp->v_rdcnt), -1);
+ }
+ if (flag & FWRITE) {
+ ASSERT(vp->v_wrcnt > 0);
+ atomic_add_32(&(vp->v_wrcnt), -1);
+ }
+ }
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_read(
+ vnode_t *vp,
+ uio_t *uio,
+ int ioflag,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ struct stat st;
+ struct iovec *iov;
+ ssize_t resid;
+ size_t cnt;
+ int n;
+
+ /*
+ * If that caller asks for read beyond end of file,
+ * that causes the pread call to block. (Ugh!)
+ * Get the file size and return what we can.
+ */
+ (void) fstat(vp->v_fd, &st);
+ resid = uio->uio_resid;
+ if ((uio->uio_loffset + resid) > st.st_size)
+ resid = st.st_size - uio->uio_loffset;
+
+ while (resid > 0) {
+
+ ASSERT(uio->uio_iovcnt > 0);
+ iov = uio->uio_iov;
+
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ continue;
+ }
+ cnt = iov->iov_len;
+ if (cnt > resid)
+ cnt = resid;
+
+ n = pread(vp->v_fd, iov->iov_base, cnt, uio->uio_loffset);
+ if (n < 0)
+ return (errno);
+
+ iov->iov_base += n;
+ iov->iov_len -= n;
+
+ uio->uio_resid -= n;
+ uio->uio_loffset += n;
+
+ resid -= n;
+ }
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_write(
+ vnode_t *vp,
+ uio_t *uio,
+ int ioflag,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ struct iovec *iov;
+ size_t cnt;
+ int n;
+
+ while (uio->uio_resid > 0) {
+
+ ASSERT(uio->uio_iovcnt > 0);
+ iov = uio->uio_iov;
+
+ if (iov->iov_len == 0) {
+ uio->uio_iov++;
+ uio->uio_iovcnt--;
+ continue;
+ }
+ cnt = iov->iov_len;
+ if (cnt > uio->uio_resid)
+ cnt = uio->uio_resid;
+
+ n = pwrite(vp->v_fd, iov->iov_base, iov->iov_len,
+ uio->uio_loffset);
+ if (n < 0)
+ return (errno);
+
+ iov->iov_base += n;
+ iov->iov_len -= n;
+
+ uio->uio_resid -= n;
+ uio->uio_loffset += n;
+ }
+
+ if (ioflag == FSYNC) {
+ (void) fsync(vp->v_fd);
+ }
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_ioctl(
+ vnode_t *vp,
+ int cmd,
+ intptr_t arg,
+ int flag,
+ cred_t *cr,
+ int *rvalp,
+ caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+/* ARGSUSED */
+int
+fop_setfl(
+ vnode_t *vp,
+ int oflags,
+ int nflags,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ /* allow any flags? See fs_setfl */
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_getattr(
+ vnode_t *vp,
+ vattr_t *vap,
+ int flags,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ int error;
+ struct stat st;
+
+ if (fstat(vp->v_fd, &st) == -1)
+ return (errno);
+ error = stat_to_vattr(&st, vap);
+
+ if (vap->va_mask & AT_XVATTR)
+ (void) fop__getxvattr(vp, (xvattr_t *)vap);
+
+ return (error);
+}
+
+/* ARGSUSED */
+int
+fop_setattr(
+ vnode_t *vp,
+ vattr_t *vap,
+ int flags,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ struct timeval times[2];
+
+ if (vap->va_mask & AT_SIZE) {
+ if (ftruncate(vp->v_fd, vap->va_size) == -1)
+ return (errno);
+ }
+
+ /* AT_MODE or anything else? */
+
+ if (vap->va_mask & AT_XVATTR)
+ (void) fop__setxvattr(vp, (xvattr_t *)vap);
+
+ if (vap->va_mask & (AT_ATIME | AT_MTIME)) {
+ times[0].tv_sec = 0;
+ times[0].tv_usec = UTIME_OMIT;
+ times[1].tv_sec = 0;
+ times[1].tv_usec = UTIME_OMIT;
+ if (vap->va_mask & AT_ATIME) {
+ times[0].tv_sec = vap->va_atime.tv_sec;
+ times[0].tv_usec = vap->va_atime.tv_nsec / 1000;
+ }
+ if (vap->va_mask & AT_MTIME) {
+ times[1].tv_sec = vap->va_mtime.tv_sec;
+ times[1].tv_usec = vap->va_mtime.tv_nsec / 1000;
+ }
+
+ (void) futimesat(vp->v_fd, NULL, times);
+ }
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_access(
+ vnode_t *vp,
+ int mode,
+ int flags,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_lookup(
+ vnode_t *dvp,
+ char *name,
+ vnode_t **vpp,
+ pathname_t *pnp,
+ int flags,
+ vnode_t *rdir,
+ cred_t *cr,
+ caller_context_t *ct,
+ int *deflags, /* Returned per-dirent flags */
+ pathname_t *ppnp) /* Returned case-preserved name in directory */
+{
+ int fd;
+ int omode = O_RDWR | O_NOFOLLOW;
+ vnode_t *vp;
+ struct stat st;
+
+ if (flags & LOOKUP_XATTR)
+ return (ENOENT);
+
+ /*
+ * If lookup is for "", just return dvp.
+ */
+ if (name[0] == '\0') {
+ vn_hold(dvp);
+ *vpp = dvp;
+ return (0);
+ }
+
+ if (fstatat(dvp->v_fd, name, &st, AT_SYMLINK_NOFOLLOW) == -1)
+ return (errno);
+
+ vp = vncache_lookup(&st);
+ if (vp != NULL) {
+ /* lookup gave us a hold */
+ *vpp = vp;
+ return (0);
+ }
+
+ if (S_ISDIR(st.st_mode))
+ omode = O_RDONLY | O_NOFOLLOW;
+
+again:
+ fd = openat(dvp->v_fd, name, omode, 0);
+ if (fd < 0) {
+ if ((omode & O_RWMASK) == O_RDWR) {
+ omode &= ~O_RWMASK;
+ omode |= O_RDONLY;
+ goto again;
+ }
+ return (errno);
+ }
+
+ if (fstat(fd, &st) == -1) {
+ (void) close(fd);
+ return (errno);
+ }
+
+ vp = vncache_enter(&st, dvp, name, fd);
+
+ *vpp = vp;
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_create(
+ vnode_t *dvp,
+ char *name,
+ vattr_t *vap,
+ vcexcl_t excl,
+ int mode,
+ vnode_t **vpp,
+ cred_t *cr,
+ int flags,
+ caller_context_t *ct,
+ vsecattr_t *vsecp) /* ACL to set during create */
+{
+ struct stat st;
+ vnode_t *vp;
+ int err, fd, omode;
+
+ /*
+ * If creating "", just return dvp.
+ */
+ if (name[0] == '\0') {
+ vn_hold(dvp);
+ *vpp = dvp;
+ return (0);
+ }
+
+ err = fstatat(dvp->v_fd, name, &st, AT_SYMLINK_NOFOLLOW);
+ if (err != 0)
+ err = errno;
+
+ vp = NULL;
+ if (err == 0) {
+ /* The file already exists. */
+ if (excl == EXCL)
+ return (EEXIST);
+
+ vp = vncache_lookup(&st);
+ /* vp gained a hold */
+ }
+
+ if (vp == NULL) {
+ /*
+ * Open it. (may or may not exist)
+ */
+ omode = O_RDWR | O_CREAT | O_NOFOLLOW;
+ if (excl == EXCL)
+ omode |= O_EXCL;
+ open_again:
+ fd = openat(dvp->v_fd, name, omode, mode);
+ if (fd < 0) {
+ if ((omode & O_RWMASK) == O_RDWR) {
+ omode &= ~O_RWMASK;
+ omode |= O_RDONLY;
+ goto open_again;
+ }
+ return (errno);
+ }
+ (void) fstat(fd, &st);
+
+ vp = vncache_enter(&st, dvp, name, fd);
+ /* vp has its initial hold */
+ }
+
+ /* Should have the vp now. */
+ if (vp == NULL)
+ return (EFAULT);
+
+ if (vp->v_type == VDIR && vap->va_type != VDIR) {
+ vn_rele(vp);
+ return (EISDIR);
+ }
+ if (vp->v_type != VDIR && vap->va_type == VDIR) {
+ vn_rele(vp);
+ return (ENOTDIR);
+ }
+
+ /*
+ * Truncate (if requested).
+ */
+ if ((vap->va_mask & AT_SIZE) && vap->va_size == 0) {
+ (void) ftruncate(vp->v_fd, 0);
+ }
+
+ *vpp = vp;
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_remove(
+ vnode_t *dvp,
+ char *name,
+ cred_t *cr,
+ caller_context_t *ct,
+ int flags)
+{
+
+ if (unlinkat(dvp->v_fd, name, 0))
+ return (errno);
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_link(
+ vnode_t *to_dvp,
+ vnode_t *fr_vp,
+ char *to_name,
+ cred_t *cr,
+ caller_context_t *ct,
+ int flags)
+{
+ int err;
+
+ /*
+ * Would prefer to specify "from" as the combination:
+ * (fr_vp->v_fd, NULL) but linkat does not permit it.
+ */
+ err = linkat(AT_FDCWD, fr_vp->v_path, to_dvp->v_fd, to_name,
+ AT_SYMLINK_FOLLOW);
+ if (err == -1)
+ err = errno;
+
+ return (err);
+}
+
+/* ARGSUSED */
+int
+fop_rename(
+ vnode_t *from_dvp,
+ char *from_name,
+ vnode_t *to_dvp,
+ char *to_name,
+ cred_t *cr,
+ caller_context_t *ct,
+ int flags)
+{
+ struct stat st;
+ vnode_t *vp;
+ int err;
+
+ if (fstatat(from_dvp->v_fd, from_name, &st,
+ AT_SYMLINK_NOFOLLOW) == -1)
+ return (errno);
+
+ vp = vncache_lookup(&st);
+ if (vp == NULL)
+ return (ENOENT);
+
+ err = renameat(from_dvp->v_fd, from_name, to_dvp->v_fd, to_name);
+ if (err == -1)
+ err = errno;
+ else
+ vncache_renamed(vp, to_dvp, to_name);
+
+ vn_rele(vp);
+
+ return (err);
+}
+
+/* ARGSUSED */
+int
+fop_mkdir(
+ vnode_t *dvp,
+ char *name,
+ vattr_t *vap,
+ vnode_t **vpp,
+ cred_t *cr,
+ caller_context_t *ct,
+ int flags,
+ vsecattr_t *vsecp) /* ACL to set during create */
+{
+ struct stat st;
+ int err, fd;
+
+ mode_t mode = vap->va_mode & 0777;
+
+ if (mkdirat(dvp->v_fd, name, mode) == -1)
+ return (errno);
+
+ if ((fd = openat(dvp->v_fd, name, O_RDONLY)) == -1)
+ return (errno);
+ if (fstat(fd, &st) == -1) {
+ err = errno;
+ (void) close(fd);
+ return (err);
+ }
+
+ *vpp = vncache_enter(&st, dvp, name, fd);
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_rmdir(
+ vnode_t *dvp,
+ char *name,
+ vnode_t *cdir,
+ cred_t *cr,
+ caller_context_t *ct,
+ int flags)
+{
+
+ if (unlinkat(dvp->v_fd, name, AT_REMOVEDIR) == -1)
+ return (errno);
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_readdir(
+ vnode_t *vp,
+ uio_t *uiop,
+ cred_t *cr,
+ int *eofp,
+ caller_context_t *ct,
+ int flags)
+{
+ struct iovec *iov;
+ int cnt;
+ int error = 0;
+ int fd = vp->v_fd;
+
+ if (eofp) {
+ *eofp = 0;
+ }
+
+ error = lseek(fd, uiop->uio_loffset, SEEK_SET);
+ if (error == -1)
+ return (errno);
+
+ ASSERT(uiop->uio_iovcnt > 0);
+ iov = uiop->uio_iov;
+ if (iov->iov_len < sizeof (struct dirent))
+ return (EINVAL);
+
+ /* LINTED E_BAD_PTR_CAST_ALIGN */
+ cnt = getdents(fd, (struct dirent *)(uiop->uio_iov->iov_base),
+ uiop->uio_resid);
+ if (cnt == -1)
+ return (errno);
+ if (cnt == 0) {
+ if (eofp) {
+ *eofp = 1;
+ }
+ return (ENOENT);
+ }
+
+ iov->iov_base += cnt;
+ iov->iov_len -= cnt;
+ uiop->uio_resid -= cnt;
+ uiop->uio_loffset = lseek(fd, 0LL, SEEK_CUR);
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_symlink(
+ vnode_t *dvp,
+ char *linkname,
+ vattr_t *vap,
+ char *target,
+ cred_t *cr,
+ caller_context_t *ct,
+ int flags)
+{
+ return (ENOSYS);
+}
+
+/* ARGSUSED */
+int
+fop_readlink(
+ vnode_t *vp,
+ uio_t *uiop,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+/* ARGSUSED */
+int
+fop_fsync(
+ vnode_t *vp,
+ int syncflag,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+
+ if (fsync(vp->v_fd) == -1)
+ return (errno);
+
+ return (0);
+}
+
+/* ARGSUSED */
+void
+fop_inactive(
+ vnode_t *vp,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ vncache_inactive(vp);
+}
+
+/* ARGSUSED */
+int
+fop_fid(
+ vnode_t *vp,
+ fid_t *fidp,
+ caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+/* ARGSUSED */
+int
+fop_rwlock(
+ vnode_t *vp,
+ int write_lock,
+ caller_context_t *ct)
+{
+ /* See: fs_rwlock */
+ return (-1);
+}
+
+/* ARGSUSED */
+void
+fop_rwunlock(
+ vnode_t *vp,
+ int write_lock,
+ caller_context_t *ct)
+{
+ /* See: fs_rwunlock */
+}
+
+/* ARGSUSED */
+int
+fop_seek(
+ vnode_t *vp,
+ offset_t ooff,
+ offset_t *noffp,
+ caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+/* ARGSUSED */
+int
+fop_cmp(
+ vnode_t *vp1,
+ vnode_t *vp2,
+ caller_context_t *ct)
+{
+ /* See fs_cmp */
+ return (vncache_cmp(vp1, vp2));
+}
+
+/* ARGSUSED */
+int
+fop_frlock(
+ vnode_t *vp,
+ int cmd,
+ flock64_t *bfp,
+ int flag,
+ offset_t offset,
+ struct flk_callback *flk_cbp,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ /* See fs_frlock */
+
+ switch (cmd) {
+ case F_GETLK:
+ case F_SETLK_NBMAND:
+ case F_SETLK:
+ case F_SETLKW:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ if (fcntl(vp->v_fd, cmd, bfp) == -1)
+ return (errno);
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_space(
+ vnode_t *vp,
+ int cmd,
+ flock64_t *bfp,
+ int flag,
+ offset_t offset,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ /* See fs_frlock */
+
+ switch (cmd) {
+ case F_ALLOCSP:
+ case F_FREESP:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ if (fcntl(vp->v_fd, cmd, bfp) == -1)
+ return (errno);
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_realvp(
+ vnode_t *vp,
+ vnode_t **vpp,
+ caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+/* ARGSUSED */
+int
+fop_getpage(
+ vnode_t *vp,
+ offset_t off,
+ size_t len,
+ uint_t *protp,
+ struct page **plarr,
+ size_t plsz,
+ struct seg *seg,
+ caddr_t addr,
+ enum seg_rw rw,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+/* ARGSUSED */
+int
+fop_putpage(
+ vnode_t *vp,
+ offset_t off,
+ size_t len,
+ int flags,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+/* ARGSUSED */
+int
+fop_map(
+ vnode_t *vp,
+ offset_t off,
+ struct as *as,
+ caddr_t *addrp,
+ size_t len,
+ uchar_t prot,
+ uchar_t maxprot,
+ uint_t flags,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+/* ARGSUSED */
+int
+fop_addmap(
+ vnode_t *vp,
+ offset_t off,
+ struct as *as,
+ caddr_t addr,
+ size_t len,
+ uchar_t prot,
+ uchar_t maxprot,
+ uint_t flags,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+/* ARGSUSED */
+int
+fop_delmap(
+ vnode_t *vp,
+ offset_t off,
+ struct as *as,
+ caddr_t addr,
+ size_t len,
+ uint_t prot,
+ uint_t maxprot,
+ uint_t flags,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+/* ARGSUSED */
+int
+fop_poll(
+ vnode_t *vp,
+ short events,
+ int anyyet,
+ short *reventsp,
+ struct pollhead **phpp,
+ caller_context_t *ct)
+{
+ *reventsp = 0;
+ if (events & POLLIN)
+ *reventsp |= POLLIN;
+ if (events & POLLRDNORM)
+ *reventsp |= POLLRDNORM;
+ if (events & POLLRDBAND)
+ *reventsp |= POLLRDBAND;
+ if (events & POLLOUT)
+ *reventsp |= POLLOUT;
+ if (events & POLLWRBAND)
+ *reventsp |= POLLWRBAND;
+ *phpp = NULL; /* or fake_pollhead? */
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_dump(
+ vnode_t *vp,
+ caddr_t addr,
+ offset_t lbdn,
+ offset_t dblks,
+ caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+/*
+ * See fs_pathconf
+ */
+/* ARGSUSED */
+int
+fop_pathconf(
+ vnode_t *vp,
+ int cmd,
+ ulong_t *valp,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ register ulong_t val;
+ register int error = 0;
+
+ switch (cmd) {
+
+ case _PC_LINK_MAX:
+ val = MAXLINK;
+ break;
+
+ case _PC_MAX_CANON:
+ val = MAX_CANON;
+ break;
+
+ case _PC_MAX_INPUT:
+ val = MAX_INPUT;
+ break;
+
+ case _PC_NAME_MAX:
+ val = MAXNAMELEN;
+ break;
+
+ case _PC_PATH_MAX:
+ case _PC_SYMLINK_MAX:
+ val = MAXPATHLEN;
+ break;
+
+ case _PC_PIPE_BUF:
+ val = PIPE_BUF;
+ break;
+
+ case _PC_NO_TRUNC:
+ val = (ulong_t)-1;
+ break;
+
+ case _PC_VDISABLE:
+ val = _POSIX_VDISABLE;
+ break;
+
+ case _PC_CHOWN_RESTRICTED:
+ val = 1; /* chown restricted enabled */
+ break;
+
+ case _PC_FILESIZEBITS:
+ val = (ulong_t)-1; /* large file support */
+ break;
+
+ case _PC_ACL_ENABLED:
+ val = 0;
+ break;
+
+ case _PC_CASE_BEHAVIOR:
+ val = _CASE_SENSITIVE;
+ break;
+
+ case _PC_SATTR_ENABLED:
+ case _PC_SATTR_EXISTS:
+ val = 0;
+ break;
+
+ case _PC_ACCESS_FILTERING:
+ val = 0;
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ if (error == 0)
+ *valp = val;
+ return (error);
+}
+
+/* ARGSUSED */
+int
+fop_pageio(
+ vnode_t *vp,
+ struct page *pp,
+ u_offset_t io_off,
+ size_t io_len,
+ int flags,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+/* ARGSUSED */
+int
+fop_dumpctl(
+ vnode_t *vp,
+ int action,
+ offset_t *blkp,
+ caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+/* ARGSUSED */
+void
+fop_dispose(
+ vnode_t *vp,
+ struct page *pp,
+ int flag,
+ int dn,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+}
+
+/* ARGSUSED */
+int
+fop_setsecattr(
+ vnode_t *vp,
+ vsecattr_t *vsap,
+ int flag,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+ return (0);
+}
+
+/*
+ * Fake up just enough of this so we can test get/set SDs.
+ */
+/* ARGSUSED */
+int
+fop_getsecattr(
+ vnode_t *vp,
+ vsecattr_t *vsecattr,
+ int flag,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+
+ vsecattr->vsa_aclcnt = 0;
+ vsecattr->vsa_aclentsz = 0;
+ vsecattr->vsa_aclentp = NULL;
+ vsecattr->vsa_dfaclcnt = 0; /* Default ACLs are not fabricated */
+ vsecattr->vsa_dfaclentp = NULL;
+
+ if (vsecattr->vsa_mask & (VSA_ACLCNT | VSA_ACL)) {
+ aclent_t *aclentp;
+ size_t aclsize;
+
+ aclsize = sizeof (aclent_t);
+ vsecattr->vsa_aclcnt = 1;
+ vsecattr->vsa_aclentp = kmem_zalloc(aclsize, KM_SLEEP);
+ aclentp = vsecattr->vsa_aclentp;
+
+ aclentp->a_type = OTHER_OBJ;
+ aclentp->a_perm = 0777;
+ aclentp->a_id = (gid_t)-1;
+ aclentp++;
+ } else if (vsecattr->vsa_mask & (VSA_ACECNT | VSA_ACE)) {
+ ace_t *acl;
+
+ acl = kmem_alloc(sizeof (ace_t), KM_SLEEP);
+ acl->a_who = (uint32_t)-1;
+ acl->a_type = ACE_ACCESS_ALLOWED_ACE_TYPE;
+ acl->a_flags = ACE_EVERYONE;
+ acl->a_access_mask = ACE_MODIFY_PERMS;
+
+ vsecattr->vsa_aclentp = (void *)acl;
+ vsecattr->vsa_aclcnt = 1;
+ vsecattr->vsa_aclentsz = sizeof (ace_t);
+ }
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_shrlock(
+ vnode_t *vp,
+ int cmd,
+ struct shrlock *shr,
+ int flag,
+ cred_t *cr,
+ caller_context_t *ct)
+{
+
+ switch (cmd) {
+ case F_SHARE:
+ case F_SHARE_NBMAND:
+ case F_UNSHARE:
+ break;
+ default:
+ return (EINVAL);
+ }
+
+ if (!fop_shrlock_enable)
+ return (0);
+
+ if (fcntl(vp->v_fd, cmd, shr) == -1)
+ return (errno);
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+fop_vnevent(vnode_t *vp, vnevent_t vnevent, vnode_t *dvp, char *fnm,
+ caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+/* ARGSUSED */
+int
+fop_reqzcbuf(vnode_t *vp, enum uio_rw ioflag, xuio_t *uiop, cred_t *cr,
+ caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+/* ARGSUSED */
+int
+fop_retzcbuf(vnode_t *vp, xuio_t *uiop, cred_t *cr, caller_context_t *ct)
+{
+ return (ENOSYS);
+}
+
+
+/*
+ * ***************************************************************
+ * other VOP support
+ */
+
+/*
+ * Convert stat(2) formats to vnode types and vice versa. (Knows about
+ * numerical order of S_IFMT and vnode types.)
+ */
+enum vtype iftovt_tab[] = {
+ VNON, VFIFO, VCHR, VNON, VDIR, VNON, VBLK, VNON,
+ VREG, VNON, VLNK, VNON, VSOCK, VNON, VNON, VNON
+};
+
+ushort_t vttoif_tab[] = {
+ 0, S_IFREG, S_IFDIR, S_IFBLK, S_IFCHR, S_IFLNK, S_IFIFO,
+ S_IFDOOR, 0, S_IFSOCK, S_IFPORT, 0
+};
+
+/*
+ * stat_to_vattr()
+ *
+ * Convert from a stat structure to an vattr structure
+ * Note: only set fields according to va_mask
+ */
+
+int
+stat_to_vattr(const struct stat *st, vattr_t *vap)
+{
+
+ if (vap->va_mask & AT_TYPE)
+ vap->va_type = IFTOVT(st->st_mode);
+
+ if (vap->va_mask & AT_MODE)
+ vap->va_mode = st->st_mode;
+
+ if (vap->va_mask & AT_UID)
+ vap->va_uid = st->st_uid;
+
+ if (vap->va_mask & AT_GID)
+ vap->va_gid = st->st_gid;
+
+ if (vap->va_mask & AT_FSID)
+ vap->va_fsid = st->st_dev;
+
+ if (vap->va_mask & AT_NODEID)
+ vap->va_nodeid = st->st_ino;
+
+ if (vap->va_mask & AT_NLINK)
+ vap->va_nlink = st->st_nlink;
+
+ if (vap->va_mask & AT_SIZE)
+ vap->va_size = (u_offset_t)st->st_size;
+
+ if (vap->va_mask & AT_ATIME) {
+ vap->va_atime.tv_sec = st->st_atim.tv_sec;
+ vap->va_atime.tv_nsec = st->st_atim.tv_nsec;
+ }
+
+ if (vap->va_mask & AT_MTIME) {
+ vap->va_mtime.tv_sec = st->st_mtim.tv_sec;
+ vap->va_mtime.tv_nsec = st->st_mtim.tv_nsec;
+ }
+
+ if (vap->va_mask & AT_CTIME) {
+ vap->va_ctime.tv_sec = st->st_ctim.tv_sec;
+ vap->va_ctime.tv_nsec = st->st_ctim.tv_nsec;
+ }
+
+ if (vap->va_mask & AT_RDEV)
+ vap->va_rdev = st->st_rdev;
+
+ if (vap->va_mask & AT_BLKSIZE)
+ vap->va_blksize = (uint_t)st->st_blksize;
+
+
+ if (vap->va_mask & AT_NBLOCKS)
+ vap->va_nblocks = (u_longlong_t)st->st_blocks;
+
+ if (vap->va_mask & AT_SEQ)
+ vap->va_seq = 0;
+
+ return (0);
+}
+
+/* ARGSUSED */
+void
+flk_init_callback(flk_callback_t *flk_cb,
+ callb_cpr_t *(*cb_fcn)(flk_cb_when_t, void *), void *cbdata)
+{
+}
+
+void
+vn_hold(vnode_t *vp)
+{
+ mutex_enter(&vp->v_lock);
+ vp->v_count++;
+ mutex_exit(&vp->v_lock);
+}
+
+void
+vn_rele(vnode_t *vp)
+{
+ VERIFY3U(vp->v_count, !=, 0);
+ mutex_enter(&vp->v_lock);
+ if (vp->v_count == 1) {
+ mutex_exit(&vp->v_lock);
+ vncache_inactive(vp);
+ } else {
+ vp->v_count--;
+ mutex_exit(&vp->v_lock);
+ }
+}
+
+int
+vn_has_other_opens(
+ vnode_t *vp,
+ v_mode_t mode)
+{
+
+ switch (mode) {
+ case V_WRITE:
+ if (vp->v_wrcnt > 1)
+ return (V_TRUE);
+ break;
+ case V_RDORWR:
+ if ((vp->v_rdcnt > 1) || (vp->v_wrcnt > 1))
+ return (V_TRUE);
+ break;
+ case V_RDANDWR:
+ if ((vp->v_rdcnt > 1) && (vp->v_wrcnt > 1))
+ return (V_TRUE);
+ break;
+ case V_READ:
+ if (vp->v_rdcnt > 1)
+ return (V_TRUE);
+ break;
+ }
+
+ return (V_FALSE);
+}
+
+/*
+ * vn_is_opened() checks whether a particular file is opened and
+ * whether the open is for read and/or write.
+ *
+ * Vnode counts are only kept on regular files (v_type=VREG).
+ */
+int
+vn_is_opened(
+ vnode_t *vp,
+ v_mode_t mode)
+{
+
+ ASSERT(vp != NULL);
+
+ switch (mode) {
+ case V_WRITE:
+ if (vp->v_wrcnt)
+ return (V_TRUE);
+ break;
+ case V_RDANDWR:
+ if (vp->v_rdcnt && vp->v_wrcnt)
+ return (V_TRUE);
+ break;
+ case V_RDORWR:
+ if (vp->v_rdcnt || vp->v_wrcnt)
+ return (V_TRUE);
+ break;
+ case V_READ:
+ if (vp->v_rdcnt)
+ return (V_TRUE);
+ break;
+ }
+
+ return (V_FALSE);
+}
+
+/*
+ * vn_is_mapped() checks whether a particular file is mapped and whether
+ * the file is mapped read and/or write.
+ */
+/* ARGSUSED */
+int
+vn_is_mapped(
+ vnode_t *vp,
+ v_mode_t mode)
+{
+ return (V_FALSE);
+}
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fake_xattr.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fake_xattr.c
new file mode 100644
index 0000000000..852b2e870f
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fake_xattr.c
@@ -0,0 +1,271 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/vnode.h>
+#include <sys/debug.h>
+
+#include <attr.h>
+#include <libnvpair.h>
+
+static uint64_t zero_times[2];
+
+static int
+getxva_parse_nvl(xvattr_t *xvap,
+ xoptattr_t *xoap, nvlist_t *nvl);
+
+/*
+ * See similar code to parse the nvlist in:
+ * uts/common/fs/xattr.c : xattr_file_write()
+ */
+int
+fop__getxvattr(vnode_t *vp, xvattr_t *xvap)
+{
+ nvlist_t *nvl = NULL;
+ xoptattr_t *xoap = NULL;
+ int error;
+
+ if ((xoap = xva_getxoptattr(xvap)) == NULL) {
+ return (EINVAL);
+ }
+
+ error = fgetattr(vp->v_fd, XATTR_VIEW_READWRITE, &nvl);
+ if (error == 0) {
+ error = getxva_parse_nvl(xvap, xoap, nvl);
+ nvlist_free(nvl);
+ nvl = NULL;
+ }
+
+ /*
+ * Also get the readonly attrs, but don't fail.
+ */
+ if (fgetattr(vp->v_fd, XATTR_VIEW_READONLY, &nvl) == 0) {
+ (void) getxva_parse_nvl(xvap, xoap, nvl);
+ nvlist_free(nvl);
+ }
+
+ return (error);
+}
+
+static int
+getxva_parse_nvl(xvattr_t *xvap,
+ xoptattr_t *xoap, nvlist_t *nvl)
+{
+ nvpair_t *pair = NULL;
+ int error;
+
+ while (pair = nvlist_next_nvpair(nvl, pair)) {
+ data_type_t type;
+ f_attr_t attr;
+ boolean_t value = B_FALSE;
+ uint64_t *times = zero_times;
+ uint_t nelems = 2;
+
+ /*
+ * Validate the name and type of each attribute.
+ * Log any unknown names and continue. This will
+ * help if additional attributes are added later.
+ */
+ type = nvpair_type(pair);
+ attr = name_to_attr(nvpair_name(pair));
+ if (attr == F_ATTR_INVAL)
+ continue;
+
+ /*
+ * Verify nvlist type matches required type and view is OK
+ */
+
+ if (type != attr_to_data_type(attr) ||
+ (attr_to_xattr_view(attr) == XATTR_VIEW_READONLY))
+ continue;
+
+ /*
+ * For OWNERSID/GROUPSID, just skip.
+ */
+ if ((attr == F_OWNERSID || attr == F_GROUPSID))
+ continue;
+
+ /*
+ * Retrieve data from nvpair
+ */
+ switch (type) {
+ case DATA_TYPE_BOOLEAN_VALUE:
+ if (nvpair_value_boolean_value(pair, &value)) {
+ error = EINVAL;
+ goto out;
+ }
+ break;
+
+ case DATA_TYPE_UINT64_ARRAY:
+ if (nvpair_value_uint64_array(pair, &times, &nelems)) {
+ error = EINVAL;
+ goto out;
+ }
+ if (nelems < 2)
+ continue;
+ break;
+
+ case DATA_TYPE_NVLIST:
+ continue;
+
+ case DATA_TYPE_UINT8_ARRAY:
+ continue;
+
+ default:
+ error = EINVAL;
+ goto out;
+ }
+
+ switch (attr) {
+ /*
+ * If we have several similar optional attributes to
+ * process then we should do it all together here so that
+ * xoap and the requested bitmap can be set in one place.
+ */
+ case F_READONLY:
+ XVA_SET_RTN(xvap, XAT_READONLY);
+ xoap->xoa_readonly = value;
+ break;
+
+ case F_HIDDEN:
+ XVA_SET_RTN(xvap, XAT_HIDDEN);
+ xoap->xoa_hidden = value;
+ break;
+
+ case F_SYSTEM:
+ XVA_SET_RTN(xvap, XAT_SYSTEM);
+ xoap->xoa_system = value;
+ break;
+
+ case F_ARCHIVE:
+ XVA_SET_RTN(xvap, XAT_ARCHIVE);
+ xoap->xoa_archive = value;
+ break;
+
+ case F_CRTIME:
+ XVA_SET_RTN(xvap, XAT_CREATETIME);
+ xoap->xoa_createtime.tv_sec = times[0];
+ xoap->xoa_createtime.tv_nsec = times[1];
+ break;
+
+ case F_REPARSE:
+ XVA_SET_RTN(xvap, XAT_REPARSE);
+ xoap->xoa_reparse = value;
+ break;
+
+ case F_OFFLINE:
+ XVA_SET_RTN(xvap, XAT_OFFLINE);
+ xoap->xoa_offline = value;
+ break;
+
+ case F_SPARSE:
+ XVA_SET_RTN(xvap, XAT_SPARSE);
+ xoap->xoa_sparse = value;
+ break;
+
+ default:
+ break;
+ }
+ }
+ error = 0;
+
+out:
+ return (error);
+}
+
+/*
+ * See similar code to build the nvlist in:
+ * uts/common/fs/xattr.c : xattr_fill_nvlist()
+ */
+int
+fop__setxvattr(vnode_t *vp, xvattr_t *xvap)
+{
+ uint64_t times[2];
+ nvlist_t *nvl;
+ int error;
+ xoptattr_t *xoap; /* Pointer to optional attributes */
+
+ if ((xoap = xva_getxoptattr(xvap)) == NULL)
+ return (EINVAL);
+
+ if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, KM_SLEEP))
+ return (ENOMEM);
+
+ if (XVA_ISSET_REQ(xvap, XAT_READONLY)) {
+ VERIFY(nvlist_add_boolean_value(nvl,
+ attr_to_name(F_READONLY),
+ xoap->xoa_readonly) == 0);
+ }
+
+ if (XVA_ISSET_REQ(xvap, XAT_HIDDEN)) {
+ VERIFY(nvlist_add_boolean_value(nvl,
+ attr_to_name(F_HIDDEN),
+ xoap->xoa_hidden) == 0);
+ }
+
+ if (XVA_ISSET_REQ(xvap, XAT_SYSTEM)) {
+ VERIFY(nvlist_add_boolean_value(nvl,
+ attr_to_name(F_SYSTEM),
+ xoap->xoa_system) == 0);
+ }
+
+ if (XVA_ISSET_REQ(xvap, XAT_ARCHIVE)) {
+ VERIFY(nvlist_add_boolean_value(nvl,
+ attr_to_name(F_ARCHIVE),
+ xoap->xoa_archive) == 0);
+ }
+
+ if (XVA_ISSET_REQ(xvap, XAT_CREATETIME)) {
+ times[0] = xoap->xoa_createtime.tv_sec;
+ times[1] = xoap->xoa_createtime.tv_nsec;
+ VERIFY(nvlist_add_uint64_array(nvl,
+ attr_to_name(F_CRTIME),
+ times, 2) == 0);
+ }
+
+ if (XVA_ISSET_REQ(xvap, XAT_REPARSE)) {
+ VERIFY(nvlist_add_boolean_value(nvl,
+ attr_to_name(F_REPARSE),
+ xoap->xoa_reparse) == 0);
+ }
+
+ if (XVA_ISSET_REQ(xvap, XAT_OFFLINE)) {
+ VERIFY(nvlist_add_boolean_value(nvl,
+ attr_to_name(F_OFFLINE),
+ xoap->xoa_offline) == 0);
+ }
+
+ if (XVA_ISSET_REQ(xvap, XAT_SPARSE)) {
+ VERIFY(nvlist_add_boolean_value(nvl,
+ attr_to_name(F_SPARSE),
+ xoap->xoa_sparse) == 0);
+ }
+
+ error = fsetattr(vp->v_fd, XATTR_VIEW_READWRITE, nvl);
+
+ nvlist_free(nvl);
+
+ return (error);
+}
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_cred.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_cred.c
new file mode 100644
index 0000000000..0ddd6f51bc
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_cred.c
@@ -0,0 +1,55 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/sid.h>
+#include <sys/priv_names.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <smbsrv/smb_idmap.h>
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smb_token.h>
+
+
+/*
+ * Kind of a hack here. In this user-space test implementation,
+ * we don't bother with real credential. Everything here uses
+ * the ordinary credentials of the process running this.
+ */
+cred_t *
+smb_cred_create(smb_token_t *token)
+{
+ cred_t *cr;
+ cr = (cred_t *)token; /* hack */
+ return (cr);
+}
+
+void
+smb_user_setcred(smb_user_t *user, cred_t *cr, uint32_t privileges)
+{
+ user->u_cred = cr;
+ user->u_privcred = NULL;
+ user->u_privileges = privileges;
+}
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_fem.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_fem.c
new file mode 100644
index 0000000000..16bbcb055d
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_fem.c
@@ -0,0 +1,63 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/fcntl.h>
+
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smb_fsops.h>
+
+
+/*
+ * smb_fem_init
+ */
+int
+smb_fem_init(void)
+{
+ return (0);
+}
+
+/*
+ * smb_fem_fini
+ */
+void
+smb_fem_fini(void)
+{
+}
+
+/* ARGSUSED */
+int
+smb_fem_fcn_install(smb_node_t *node)
+{
+ return (0);
+}
+
+/* ARGSUSED */
+void
+smb_fem_fcn_uninstall(smb_node_t *node)
+{
+}
+
+/* ARGSUSED */
+int
+smb_fem_oplock_install(smb_node_t *node)
+{
+ return (0);
+}
+
+/* ARGSUSED */
+void
+smb_fem_oplock_uninstall(smb_node_t *node)
+{
+}
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c
new file mode 100644
index 0000000000..4c863e0f10
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c
@@ -0,0 +1,404 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * SMB server interface to idmap
+ * (smb_idmap_get..., smb_idmap_batch_...)
+ *
+ * There are three implementations of this interface:
+ * uts/common/fs/smbsrv/smb_idmap.c (smbsrv kmod)
+ * lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c (libfksmbsrv)
+ * lib/smbsrv/libsmb/common/smb_idmap.c (libsmb)
+ *
+ * There are enough differences (relative to the code size)
+ * that it's more trouble than it's worth to merge them.
+ *
+ * This one differs from the others in that it:
+ * calls idmap interfaces (libidmap)
+ * uses kmem_... interfaces (libfakekernel)
+ * uses cmn_err instead of syslog, etc.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smb_idmap.h>
+
+static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib);
+
+/*
+ * Report an idmap error.
+ */
+void
+smb_idmap_check(const char *s, idmap_stat stat)
+{
+ if (stat != IDMAP_SUCCESS) {
+ if (s == NULL)
+ s = "smb_idmap_check";
+
+ cmn_err(CE_NOTE, "%s: %d", s, (int)stat);
+ }
+}
+
+/*
+ * smb_idmap_getsid
+ *
+ * Tries to get a mapping for the given uid/gid
+ * Allocates ->sim_domsid
+ */
+idmap_stat
+smb_idmap_getsid(uid_t id, int idtype, smb_sid_t **sid)
+{
+ smb_idmap_batch_t sib;
+ idmap_stat stat;
+
+ stat = smb_idmap_batch_create(&sib, 1, SMB_IDMAP_ID2SID);
+ if (stat != IDMAP_SUCCESS)
+ return (stat);
+
+ stat = smb_idmap_batch_getsid(sib.sib_idmaph, &sib.sib_maps[0],
+ id, idtype);
+
+ if (stat != IDMAP_SUCCESS) {
+ smb_idmap_batch_destroy(&sib);
+ return (stat);
+ }
+
+ stat = smb_idmap_batch_getmappings(&sib);
+
+ if (stat != IDMAP_SUCCESS) {
+ smb_idmap_batch_destroy(&sib);
+ return (stat);
+ }
+
+ *sid = smb_sid_dup(sib.sib_maps[0].sim_sid);
+
+ smb_idmap_batch_destroy(&sib);
+
+ return (IDMAP_SUCCESS);
+}
+
+/*
+ * smb_idmap_getid
+ *
+ * Tries to get a mapping for the given SID
+ */
+idmap_stat
+smb_idmap_getid(smb_sid_t *sid, uid_t *id, int *id_type)
+{
+ smb_idmap_batch_t sib;
+ smb_idmap_t *sim;
+ idmap_stat stat;
+
+ stat = smb_idmap_batch_create(&sib, 1, SMB_IDMAP_SID2ID);
+ if (stat != IDMAP_SUCCESS)
+ return (stat);
+
+ sim = &sib.sib_maps[0];
+ sim->sim_id = id;
+ stat = smb_idmap_batch_getid(sib.sib_idmaph, sim, sid, *id_type);
+ if (stat != IDMAP_SUCCESS) {
+ smb_idmap_batch_destroy(&sib);
+ return (stat);
+ }
+
+ stat = smb_idmap_batch_getmappings(&sib);
+
+ if (stat != IDMAP_SUCCESS) {
+ smb_idmap_batch_destroy(&sib);
+ return (stat);
+ }
+
+ *id_type = sim->sim_idtype;
+ smb_idmap_batch_destroy(&sib);
+
+ return (IDMAP_SUCCESS);
+}
+
+/*
+ * smb_idmap_batch_create
+ *
+ * Creates and initializes the context for batch ID mapping.
+ */
+idmap_stat
+smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags)
+{
+ idmap_stat stat;
+
+ if (!sib)
+ return (IDMAP_ERR_ARG);
+
+ bzero(sib, sizeof (smb_idmap_batch_t));
+ stat = idmap_get_create(&sib->sib_idmaph);
+
+ if (stat != IDMAP_SUCCESS) {
+ smb_idmap_check("idmap_get_create", stat);
+ return (stat);
+ }
+
+ sib->sib_flags = flags;
+ sib->sib_nmap = nmap;
+ sib->sib_size = nmap * sizeof (smb_idmap_t);
+ sib->sib_maps = kmem_zalloc(sib->sib_size, KM_SLEEP);
+
+ return (IDMAP_SUCCESS);
+}
+
+/*
+ * smb_idmap_batch_destroy
+ *
+ * Frees the batch ID mapping context.
+ */
+void
+smb_idmap_batch_destroy(smb_idmap_batch_t *sib)
+{
+ int i;
+
+ if (sib == NULL)
+ return;
+
+ if (sib->sib_idmaph) {
+ idmap_get_destroy(sib->sib_idmaph);
+ sib->sib_idmaph = NULL;
+ }
+
+ if (sib->sib_maps == NULL)
+ return;
+
+ if (sib->sib_flags & SMB_IDMAP_ID2SID) {
+ /*
+ * SIDs are allocated only when mapping
+ * UID/GID to SIDs
+ */
+ for (i = 0; i < sib->sib_nmap; i++) {
+ smb_sid_free(sib->sib_maps[i].sim_sid);
+ /* from strdup() in libidmap */
+ free(sib->sib_maps[i].sim_domsid);
+ }
+ }
+
+ if (sib->sib_size && sib->sib_maps) {
+ kmem_free(sib->sib_maps, sib->sib_size);
+ sib->sib_maps = NULL;
+ }
+}
+
+/*
+ * smb_idmap_batch_getid
+ *
+ * Queue a request to map the given SID to a UID or GID.
+ *
+ * sim->sim_id should point to variable that's supposed to
+ * hold the returned UID/GID. This needs to be setup by caller
+ * of this function.
+ * If requested ID type is known, it's passed as 'idtype',
+ * if it's unknown it'll be returned in sim->sim_idtype.
+ */
+idmap_stat
+smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
+ smb_sid_t *sid, int idtype)
+{
+ char sidstr[SMB_SID_STRSZ];
+ idmap_stat stat;
+ int flag = 0;
+
+ if (idmaph == NULL || sim == NULL || sid == NULL)
+ return (IDMAP_ERR_ARG);
+
+ smb_sid_tostr(sid, sidstr);
+ if (smb_sid_splitstr(sidstr, &sim->sim_rid) != 0)
+ return (IDMAP_ERR_SID);
+ sim->sim_domsid = sidstr;
+ sim->sim_idtype = idtype;
+
+ switch (idtype) {
+ case SMB_IDMAP_USER:
+ stat = idmap_get_uidbysid(idmaph, sim->sim_domsid,
+ sim->sim_rid, flag, sim->sim_id, &sim->sim_stat);
+ smb_idmap_check("idmap_get_uidbysid", stat);
+ break;
+
+ case SMB_IDMAP_GROUP:
+ stat = idmap_get_gidbysid(idmaph, sim->sim_domsid,
+ sim->sim_rid, flag, sim->sim_id, &sim->sim_stat);
+ smb_idmap_check("idmap_get_gidbysid", stat);
+ break;
+
+ case SMB_IDMAP_UNKNOWN:
+ stat = idmap_get_pidbysid(idmaph, sim->sim_domsid,
+ sim->sim_rid, flag, sim->sim_id, &sim->sim_idtype,
+ &sim->sim_stat);
+ smb_idmap_check("idmap_get_pidbysid", stat);
+ break;
+
+ default:
+ stat = IDMAP_ERR_ARG;
+ break;
+ }
+
+ /* This was copied by idmap_get_Xbysid. */
+ sim->sim_domsid = NULL;
+
+ return (stat);
+}
+
+/*
+ * smb_idmap_batch_getsid
+ *
+ * Queue a request to map the given UID/GID to a SID.
+ *
+ * sim->sim_domsid and sim->sim_rid will contain the mapping
+ * result upon successful process of the batched request.
+ * NB: sim_domsid allocated by strdup, here or in libidmap
+ */
+idmap_stat
+smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
+ uid_t id, int idtype)
+{
+ idmap_stat stat;
+ int flag = 0;
+
+ if (!idmaph || !sim)
+ return (IDMAP_ERR_ARG);
+
+ switch (idtype) {
+ case SMB_IDMAP_USER:
+ stat = idmap_get_sidbyuid(idmaph, id, flag,
+ &sim->sim_domsid, &sim->sim_rid, &sim->sim_stat);
+ smb_idmap_check("idmap_get_sidbyuid", stat);
+ break;
+
+ case SMB_IDMAP_GROUP:
+ stat = idmap_get_sidbygid(idmaph, id, flag,
+ &sim->sim_domsid, &sim->sim_rid, &sim->sim_stat);
+ smb_idmap_check("idmap_get_sidbygid", stat);
+ break;
+
+ case SMB_IDMAP_OWNERAT:
+ /* Current Owner S-1-5-32-766 */
+ sim->sim_domsid = strdup(NT_BUILTIN_DOMAIN_SIDSTR);
+ sim->sim_rid = SECURITY_CURRENT_OWNER_RID;
+ sim->sim_stat = IDMAP_SUCCESS;
+ stat = IDMAP_SUCCESS;
+ break;
+
+ case SMB_IDMAP_GROUPAT:
+ /* Current Group S-1-5-32-767 */
+ sim->sim_domsid = strdup(NT_BUILTIN_DOMAIN_SIDSTR);
+ sim->sim_rid = SECURITY_CURRENT_GROUP_RID;
+ sim->sim_stat = IDMAP_SUCCESS;
+ stat = IDMAP_SUCCESS;
+ break;
+
+ case SMB_IDMAP_EVERYONE:
+ /* Everyone S-1-1-0 */
+ sim->sim_domsid = strdup(NT_WORLD_AUTH_SIDSTR);
+ sim->sim_rid = 0;
+ sim->sim_stat = IDMAP_SUCCESS;
+ stat = IDMAP_SUCCESS;
+ break;
+
+ default:
+ return (IDMAP_ERR_ARG);
+ }
+
+ return (stat);
+}
+
+/*
+ * smb_idmap_batch_getmappings
+ *
+ * trigger ID mapping service to get the mappings for queued
+ * requests.
+ *
+ * Checks the result of all the queued requests.
+ */
+idmap_stat
+smb_idmap_batch_getmappings(smb_idmap_batch_t *sib)
+{
+ idmap_stat stat = IDMAP_SUCCESS;
+ smb_idmap_t *sim;
+ int i;
+
+ if ((stat = idmap_get_mappings(sib->sib_idmaph)) != IDMAP_SUCCESS) {
+ smb_idmap_check("idmap_get_mappings", stat);
+ return (stat);
+ }
+
+ /*
+ * Check the status for all the queued requests
+ */
+ for (i = 0, sim = sib->sib_maps; i < sib->sib_nmap; i++, sim++) {
+ if (sim->sim_stat != IDMAP_SUCCESS) {
+ if (sib->sib_flags == SMB_IDMAP_SID2ID) {
+ cmn_err(CE_NOTE, "[%d] %d (%d)",
+ sim->sim_idtype,
+ sim->sim_rid,
+ sim->sim_stat);
+ }
+ return (sim->sim_stat);
+ }
+ }
+
+ if (smb_idmap_batch_binsid(sib) != 0)
+ stat = IDMAP_ERR_OTHER;
+
+ return (stat);
+}
+
+/*
+ * smb_idmap_batch_binsid
+ *
+ * Convert sidrids to binary sids
+ *
+ * Returns 0 if successful and non-zero upon failure.
+ */
+static int
+smb_idmap_batch_binsid(smb_idmap_batch_t *sib)
+{
+ smb_sid_t *sid;
+ smb_idmap_t *sim;
+ int i;
+
+ if (sib->sib_flags & SMB_IDMAP_SID2ID)
+ /* This operation is not required */
+ return (0);
+
+ sim = sib->sib_maps;
+ for (i = 0; i < sib->sib_nmap; sim++, i++) {
+ if (sim->sim_domsid == NULL)
+ return (-1);
+
+ sid = smb_sid_fromstr(sim->sim_domsid);
+ if (sid == NULL)
+ return (-1);
+
+ sim->sim_sid = smb_sid_splice(sid, sim->sim_rid);
+ smb_sid_free(sid);
+ }
+
+ return (0);
+}
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_init.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_init.c
new file mode 100644
index 0000000000..39ab56a1dd
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_init.c
@@ -0,0 +1,217 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/ddi.h>
+#include <sys/modctl.h>
+#include <sys/cred.h>
+#include <sys/disp.h>
+#include <sys/ioccom.h>
+#include <sys/policy.h>
+#include <sys/cmn_err.h>
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smb_ioctl.h>
+
+/*
+ * *****************************************************************************
+ * ****************************** Global Variables *****************************
+ * *****************************************************************************
+ *
+ * These variables can only be changed through the /etc/system file.
+ */
+
+/*
+ * Maximum buffer size for NT: configurable based on the client environment.
+ * IR104720 Experiments with Windows 2000 indicate that we achieve better
+ * SmbWriteX performance with a buffer size of 64KB instead of the 37KB used
+ * with Windows NT4.0. Previous experiments with NT4.0 resulted in directory
+ * listing problems so this buffer size is configurable based on the end-user
+ * environment. When in doubt use 37KB.
+ *
+ * smb_raw_mode: read_raw and write_raw supported (1) or NOT supported (0).
+ */
+int smb_maxbufsize = SMB_NT_MAXBUF;
+int smb_oplock_levelII = 1;
+int smb_oplock_timeout = OPLOCK_STD_TIMEOUT;
+int smb_oplock_min_timeout = OPLOCK_MIN_TIMEOUT;
+int smb_flush_required = 1;
+int smb_dirsymlink_enable = 1;
+int smb_sign_debug = 0;
+int smb_raw_mode = 0;
+int smb_shortnames = 1;
+uint_t smb_audit_flags =
+#ifdef DEBUG
+ SMB_AUDIT_NODE;
+#else
+ 0;
+#endif
+
+/*
+ * Maximum number of simultaneous authentication, share mapping, pipe open
+ * requests to be processed.
+ */
+int smb_ssetup_threshold = 256;
+int smb_tcon_threshold = 1024;
+int smb_opipe_threshold = 1024;
+
+/*
+ * Number of milliseconds that a request will be stalled if it comes in after
+ * the maximum number of inflight operations are being proccessed.
+ */
+int smb_ssetup_timeout = (30 * 1000);
+int smb_tcon_timeout = (30 * 1000);
+int smb_opipe_timeout = (30 * 1000);
+
+int smb_threshold_debug = 0;
+
+/*
+ * Thread priorities used in smbsrv. Our threads spend most of their time
+ * blocked on various conditions. However, if the system gets heavy load,
+ * the scheduler has to choose an order to run these. We want the order:
+ * (a) timers, (b) notifications, (c) workers, (d) receivers (and etc.)
+ * where notifications are oplock and change notify work. Aside from this
+ * relative ordering, smbsrv threads should run with a priority close to
+ * that of normal user-space threads (thus minclsyspri below), just like
+ * NFS and other "file service" kinds of processing.
+ */
+int smbsrv_base_pri = MINCLSYSPRI;
+int smbsrv_listen_pri = MINCLSYSPRI;
+int smbsrv_receive_pri = MINCLSYSPRI;
+int smbsrv_worker_pri = MINCLSYSPRI + 1;
+int smbsrv_notify_pri = MINCLSYSPRI + 2;
+int smbsrv_timer_pri = MINCLSYSPRI + 5;
+
+/*
+ * These are the (open,close,ioctl) entry points into this
+ * (fake) "driver". They are declared in smb_ioctl.h
+ */
+
+static int g_init_done = 0;
+
+int fksmbsrv_vfs_init(void);
+
+int
+fksmbsrv_drv_open(void)
+{
+ int rc;
+
+ if (g_init_done == 0) {
+ if ((rc = fksmbsrv_vfs_init()) != 0) {
+ cmn_err(CE_WARN, "fksmbsrv_vfs_init, rc=%d", rc);
+ return (rc);
+ }
+ if ((rc = smb_server_g_init()) != 0) {
+ cmn_err(CE_WARN, "smb_server_g_init, rc=%d", rc);
+ return (rc);
+ }
+ g_init_done = 1;
+ }
+
+ rc = smb_server_create();
+ return (rc);
+}
+
+int
+fksmbsrv_drv_close(void)
+{
+ int rc;
+
+ rc = smb_server_delete();
+
+ if (g_init_done != 0) {
+ (void) smb_server_g_fini();
+ g_init_done = 0;
+ }
+
+ return (rc);
+}
+
+/*
+ * This is the primary entry point into this library, called by
+ * fksmbd (user-level debug version of smbsrv).
+ */
+int
+fksmbsrv_drv_ioctl(int cmd, void *varg)
+{
+ smb_ioc_t *ioc = varg;
+ int rc = 0;
+
+ switch (cmd) {
+ case SMB_IOC_CONFIG:
+ rc = smb_server_configure(&ioc->ioc_cfg);
+ break;
+ case SMB_IOC_START:
+ rc = smb_server_start(&ioc->ioc_start);
+ break;
+ case SMB_IOC_STOP:
+ rc = smb_server_stop();
+ break;
+ case SMB_IOC_EVENT:
+ rc = smb_server_notify_event(&ioc->ioc_event);
+ break;
+ case SMB_IOC_GMTOFF:
+ rc = smb_server_set_gmtoff(&ioc->ioc_gmt);
+ break;
+ case SMB_IOC_SHARE:
+ rc = smb_kshare_export_list(&ioc->ioc_share);
+ break;
+ case SMB_IOC_UNSHARE:
+ rc = smb_kshare_unexport_list(&ioc->ioc_share);
+ break;
+ case SMB_IOC_SHAREINFO:
+ rc = smb_kshare_info(&ioc->ioc_shareinfo);
+ break;
+ case SMB_IOC_NUMOPEN:
+ rc = smb_server_numopen(&ioc->ioc_opennum);
+ break;
+ case SMB_IOC_SVCENUM:
+ rc = smb_server_enum(&ioc->ioc_svcenum);
+ break;
+ case SMB_IOC_SESSION_CLOSE:
+ rc = smb_server_session_close(&ioc->ioc_session);
+ break;
+ case SMB_IOC_FILE_CLOSE:
+ rc = smb_server_file_close(&ioc->ioc_fileid);
+ break;
+ case SMB_IOC_SPOOLDOC:
+ rc = smb_server_spooldoc(&ioc->ioc_spooldoc);
+ break;
+ default:
+ rc = ENOTTY;
+ break;
+ }
+
+ return (rc);
+}
+
+/*
+ * This function intentionally does nothing. It's used only to
+ * force libfksmbsrv to load when fksmbd starts so one can set
+ * breakpoints etc. without debugger "force load" tricks.
+ */
+void
+fksmbsrv_drv_load(void)
+{
+}
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_kdoor.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_kdoor.c
new file mode 100644
index 0000000000..44c68ce2c5
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_kdoor.c
@@ -0,0 +1,275 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * "Upcall" glue for the fake (user-mode) smbsrv module.
+ */
+
+#include <sys/types.h>
+#include <sys/kmem.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/cmn_err.h>
+#include <sys/door.h>
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smb_door.h>
+
+static int smb_kdoor_encode(smb_doorarg_t *);
+static int smb_kdoor_decode(smb_doorarg_t *);
+static void smb_kdoor_sethdr(smb_doorarg_t *, uint32_t);
+static boolean_t smb_kdoor_chkhdr(smb_doorarg_t *, smb_doorhdr_t *);
+static void smb_kdoor_free(door_arg_t *);
+
+void
+smb_kdoor_init(smb_server_t *sv)
+{
+ sv->sv_kdoor_id = -1;
+ mutex_init(&sv->sv_kdoor_mutex, NULL, MUTEX_DEFAULT, NULL);
+ cv_init(&sv->sv_kdoor_cv, NULL, CV_DEFAULT, NULL);
+}
+
+void
+smb_kdoor_fini(smb_server_t *sv)
+{
+ smb_kdoor_close(sv);
+ cv_destroy(&sv->sv_kdoor_cv);
+ mutex_destroy(&sv->sv_kdoor_mutex);
+}
+
+/*
+ * In the "fake kernen", our "upcalls" don't use the
+ * real door, but just call via a function pointer.
+ * This is where we setup that pointer, which is
+ * fksmbd_door_dispatch()
+ */
+void
+fksmb_kdoor_open(smb_server_t *sv, void *varg)
+{
+ sv->sv_kdoor_hd = varg;
+}
+
+void
+smb_kdoor_close(smb_server_t *sv)
+{
+ sv->sv_kdoor_hd = NULL;
+ sv->sv_kdoor_id = -1;
+}
+
+/* ARGSUSED */
+int
+smb_kdoor_upcall(smb_server_t *sv, uint32_t cmd,
+ void *req_data, xdrproc_t req_xdr,
+ void *rsp_data, xdrproc_t rsp_xdr)
+{
+ smb_doorarg_t da;
+ fksmb_kdoor_disp_func_t *func;
+ int rc;
+
+ bzero(&da, sizeof (smb_doorarg_t));
+ da.da_opcode = cmd;
+ da.da_opname = smb_doorhdr_opname(cmd);
+ da.da_req_xdr = req_xdr;
+ da.da_rsp_xdr = rsp_xdr;
+ da.da_req_data = req_data;
+ da.da_rsp_data = rsp_data;
+
+ if ((req_data == NULL && req_xdr != NULL) ||
+ (rsp_data == NULL && rsp_xdr != NULL)) {
+ cmn_err(CE_WARN, "smb_kdoor_upcall[%s]: invalid param",
+ da.da_opname);
+ return (-1);
+ }
+
+ /* NB: no ASYNC, nor event stuff */
+
+ func = (fksmb_kdoor_disp_func_t *)(sv->sv_kdoor_hd);
+ if (func == NULL)
+ return (EFAULT);
+
+ if ((rc = smb_kdoor_encode(&da)) != 0)
+ goto out;
+
+ /*
+ * The "upcall" (just call via function pointer)
+ * i.e. see: fksmbd_door_dispatch()
+ */
+ if ((rc = (*func)(&da)) != 0)
+ goto out;
+
+ rc = smb_kdoor_decode(&da);
+out:
+ smb_kdoor_free(&da.da_arg);
+
+ return (rc);
+}
+
+/* no smb_kdoor_send, smb_kdoor_receive */
+/* no smb_kdoor_upcall_private */
+
+static int
+smb_kdoor_encode(smb_doorarg_t *da)
+{
+ XDR xdrs;
+ char *buf;
+ uint32_t len;
+
+ len = xdr_sizeof(smb_doorhdr_xdr, &da->da_hdr);
+ if (da->da_req_xdr != NULL)
+ len += xdr_sizeof(da->da_req_xdr, da->da_req_data);
+
+ smb_kdoor_sethdr(da, len);
+
+ buf = kmem_zalloc(len, KM_SLEEP);
+ xdrmem_create(&xdrs, buf, len, XDR_ENCODE);
+
+ if (!smb_doorhdr_xdr(&xdrs, &da->da_hdr)) {
+ cmn_err(CE_WARN, "smb_kdoor_encode[%s]: header encode failed",
+ da->da_opname);
+ kmem_free(buf, len);
+ xdr_destroy(&xdrs);
+ return (-1);
+ }
+
+ if (da->da_req_xdr != NULL) {
+ if (!da->da_req_xdr(&xdrs, da->da_req_data)) {
+ cmn_err(CE_WARN, "smb_kdoor_encode[%s]: encode failed",
+ da->da_opname);
+ kmem_free(buf, len);
+ xdr_destroy(&xdrs);
+ return (-1);
+ }
+ }
+
+ da->da_arg.data_ptr = buf;
+ da->da_arg.data_size = len;
+ da->da_arg.desc_ptr = NULL;
+ da->da_arg.desc_num = 0;
+ da->da_arg.rbuf = buf;
+ da->da_arg.rsize = len;
+
+ xdr_destroy(&xdrs);
+ return (0);
+}
+
+/*
+ * Decode the response in rbuf and rsize.
+ */
+static int
+smb_kdoor_decode(smb_doorarg_t *da)
+{
+ XDR xdrs;
+ smb_doorhdr_t hdr;
+ char *rbuf = da->da_arg.rbuf;
+ uint32_t rsize = da->da_arg.rsize;
+
+ if (rbuf == NULL || rsize == 0) {
+ cmn_err(CE_WARN, "smb_kdoor_decode[%s]: invalid param",
+ da->da_opname);
+ return (-1);
+ }
+
+ xdrmem_create(&xdrs, rbuf, rsize, XDR_DECODE);
+
+ if (!smb_doorhdr_xdr(&xdrs, &hdr)) {
+ cmn_err(CE_WARN, "smb_kdoor_decode[%s]: header decode failed",
+ da->da_opname);
+ xdr_destroy(&xdrs);
+ return (-1);
+ }
+
+ if (!smb_kdoor_chkhdr(da, &hdr)) {
+ xdr_destroy(&xdrs);
+ return (-1);
+ }
+
+ if (hdr.dh_datalen != 0 && da->da_rsp_xdr != NULL) {
+ if (!da->da_rsp_xdr(&xdrs, da->da_rsp_data)) {
+ cmn_err(CE_WARN, "smb_kdoor_decode[%s]: decode failed",
+ da->da_opname);
+ xdr_destroy(&xdrs);
+ return (-1);
+ }
+ }
+
+ xdr_destroy(&xdrs);
+ return (0);
+}
+
+static void
+smb_kdoor_sethdr(smb_doorarg_t *da, uint32_t datalen)
+{
+ smb_doorhdr_t *hdr = &da->da_hdr;
+
+ bzero(hdr, sizeof (smb_doorhdr_t));
+ hdr->dh_magic = SMB_DOOR_HDR_MAGIC;
+ hdr->dh_flags = da->da_flags | SMB_DF_FAKE_KERNEL;
+ hdr->dh_op = da->da_opcode;
+ /* hdr->dh_txid = 0 (not used) */
+ hdr->dh_datalen = datalen;
+ hdr->dh_door_rc = SMB_DOP_NOT_CALLED;
+}
+
+static boolean_t
+smb_kdoor_chkhdr(smb_doorarg_t *da, smb_doorhdr_t *hdr)
+{
+ if ((hdr->dh_magic != SMB_DOOR_HDR_MAGIC) ||
+ (hdr->dh_op != da->da_hdr.dh_op) ||
+ (hdr->dh_txid != da->da_hdr.dh_txid)) {
+ cmn_err(CE_WARN, "smb_kdoor_chkhdr[%s]: invalid header",
+ da->da_opname);
+ return (B_FALSE);
+ }
+
+ switch (hdr->dh_door_rc) {
+ case SMB_DOP_SUCCESS:
+ break;
+
+ /* SMB_DOP_EMPTYBUF is a "normal" error (silent). */
+ case SMB_DOP_EMPTYBUF:
+ return (B_FALSE);
+
+ default:
+ cmn_err(CE_WARN, "smb_kdoor_chkhdr[%s]: call failed: %u",
+ da->da_opname, hdr->dh_door_rc);
+ return (B_FALSE);
+ }
+
+ return (B_TRUE);
+}
+
+/*
+ * Free both the argument and result door buffers regardless of the status
+ * of the up-call. The doorfs allocates a new buffer if the result buffer
+ * passed by the client is too small.
+ */
+static void
+smb_kdoor_free(door_arg_t *arg)
+{
+ if (arg->rbuf != NULL && arg->rbuf != arg->data_ptr)
+ kmem_free(arg->rbuf, arg->rsize);
+
+ if (arg->data_ptr != NULL)
+ kmem_free(arg->data_ptr, arg->data_size);
+}
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_opipe_door.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_opipe_door.c
new file mode 100644
index 0000000000..a61ea7194c
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_opipe_door.c
@@ -0,0 +1,131 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/*
+ * This module provides the interface to NDR RPC.
+ */
+
+#include <sys/stat.h>
+#include <sys/door.h>
+#include <sys/door_data.h>
+#include <sys/uio.h>
+#include <sys/ksynch.h>
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smb_door.h>
+
+/*
+ * opipe door client (to user space door server).
+ */
+void
+smb_opipe_door_init(smb_server_t *sv)
+{
+ sv->sv_opipe_door_id = -1;
+ mutex_init(&sv->sv_opipe_door_mutex, NULL, MUTEX_DEFAULT, NULL);
+ cv_init(&sv->sv_opipe_door_cv, NULL, CV_DEFAULT, NULL);
+}
+
+void
+smb_opipe_door_fini(smb_server_t *sv)
+{
+ smb_opipe_door_close(sv);
+ cv_destroy(&sv->sv_opipe_door_cv);
+ mutex_destroy(&sv->sv_opipe_door_mutex);
+}
+
+void
+fksmb_opipe_door_open(smb_server_t *sv, void *varg)
+{
+ /* varg is the "door" dispatch function. */
+ sv->sv_opipe_door_hd = varg;
+}
+
+/*
+ * Close the (user space) door.
+ */
+void
+smb_opipe_door_close(smb_server_t *sv)
+{
+ sv->sv_opipe_door_hd = NULL;
+ sv->sv_opipe_door_id = -1;
+}
+
+
+/*
+ * opipe door call interface.
+ * Door serialization and call reference accounting is handled here.
+ */
+int
+smb_opipe_door_call(smb_opipe_t *opipe)
+{
+ smb_server_t *sv = opipe->p_server;
+ fksmb_opipe_disp_func_t *func;
+ door_arg_t da;
+ smb_doorhdr_t hdr;
+ int rc;
+
+ if (sv == NULL)
+ return (EFAULT);
+ if (smb_server_is_stopping(sv))
+ return (-1);
+
+ func = (fksmb_opipe_disp_func_t *)(sv->sv_opipe_door_hd);
+ if (func == NULL)
+ return (EFAULT);
+
+ da.data_ptr = (char *)opipe->p_doorbuf;
+ da.data_size = SMB_OPIPE_DOOR_BUFSIZE;
+ da.desc_ptr = NULL;
+ da.desc_num = 0;
+ da.rbuf = (char *)opipe->p_doorbuf;
+ da.rsize = SMB_OPIPE_DOOR_BUFSIZE;
+
+
+ /*
+ * Do the "upcall" to smbd-d. In-kernel, this is:
+ * door_ki_upcall_limited(...)
+ */
+ rc = (*func)(&da);
+ if (rc != 0)
+ return (rc);
+
+ /* Check for door_return(NULL, 0, NULL, 0) */
+ if (rc != 0 || da.data_size == 0 || da.rsize == 0)
+ return (-1);
+
+ if (smb_doorhdr_decode(&hdr, (uint8_t *)da.data_ptr, da.rsize) == -1)
+ return (-1);
+
+ if ((hdr.dh_magic != SMB_OPIPE_HDR_MAGIC) ||
+ (hdr.dh_fid != opipe->p_hdr.dh_fid) ||
+ (hdr.dh_op != opipe->p_hdr.dh_op) ||
+ (hdr.dh_door_rc != 0) ||
+ (hdr.dh_datalen > SMB_OPIPE_DOOR_BUFSIZE)) {
+ return (-1);
+ }
+
+ opipe->p_hdr.dh_datalen = hdr.dh_datalen;
+ opipe->p_hdr.dh_resid = hdr.dh_resid;
+ return (0);
+}
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_sign_pkcs.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_sign_pkcs.c
new file mode 100644
index 0000000000..91596e5d67
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_sign_pkcs.c
@@ -0,0 +1,89 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * Helper functions for SMB1 signing using PKCS#11
+ *
+ * There are two implementations of these functions:
+ * This one (for user space) and another for kernel.
+ * See: uts/common/fs/smbsrv/smb_sign_kcf.c
+ */
+
+#include <stdlib.h>
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smb_signing.h>
+#include <security/cryptoki.h>
+#include <security/pkcs11.h>
+
+/*
+ * SMB1 signing helpers:
+ * (getmech, init, update, final)
+ */
+
+int
+smb_md5_getmech(smb_sign_mech_t *mech)
+{
+ mech->mechanism = CKM_MD5;
+ mech->pParameter = NULL;
+ mech->ulParameterLen = 0;
+ return (0);
+}
+
+/*
+ * Start PKCS#11 session.
+ */
+int
+smb_md5_init(smb_sign_ctx_t *ctxp, smb_sign_mech_t *mech)
+{
+ CK_RV rv;
+
+ rv = SUNW_C_GetMechSession(mech->mechanism, ctxp);
+ if (rv != CKR_OK)
+ return (-1);
+
+ rv = C_DigestInit(*ctxp, mech);
+
+ return (rv == CKR_OK ? 0 : -1);
+}
+
+/*
+ * Digest one segment
+ */
+int
+smb_md5_update(smb_sign_ctx_t ctx, void *buf, size_t len)
+{
+ CK_RV rv;
+
+ rv = C_DigestUpdate(ctx, buf, len);
+ if (rv != CKR_OK)
+ (void) C_CloseSession(ctx);
+
+ return (rv == CKR_OK ? 0 : -1);
+}
+
+/*
+ * Get the final digest.
+ */
+int
+smb_md5_final(smb_sign_ctx_t ctx, uint8_t *digest16)
+{
+ CK_ULONG len = MD5_DIGEST_LENGTH;
+ CK_RV rv;
+
+ rv = C_DigestFinal(ctx, digest16, &len);
+ (void) C_CloseSession(ctx);
+
+ return (rv == CKR_OK ? 0 : -1);
+}
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/llib-lfksmbsrv b/usr/src/lib/smbsrv/libfksmbsrv/common/llib-lfksmbsrv
new file mode 100644
index 0000000000..d18f2c6186
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/llib-lfksmbsrv
@@ -0,0 +1,19 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*LINTLIBRARY*/
+/*PROTOLIB1*/
+
+#include <smbsrv/smb_ioctl.h>
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/mapfile-vers b/usr/src/lib/smbsrv/libfksmbsrv/common/mapfile-vers
new file mode 100644
index 0000000000..45b80291fe
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/mapfile-vers
@@ -0,0 +1,52 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+#
+#
+
+#
+# MAPFILE HEADER START
+#
+# WARNING: STOP NOW. DO NOT MODIFY THIS FILE.
+# Object versioning must comply with the rules detailed in
+#
+# usr/src/lib/README.mapfiles
+#
+# You should not be making modifications here until you've read the most current
+# copy of that file. If you need help, contact a gatekeeper for guidance.
+#
+# MAPFILE HEADER END
+#
+
+$mapfile_version 2
+
+SYMBOL_VERSION SUNWprivate {
+ global:
+ fksmbsrv_drv_close;
+ fksmbsrv_drv_ioctl;
+ fksmbsrv_drv_load;
+ fksmbsrv_drv_open;
+
+ local:
+ *;
+};
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/reparse.c b/usr/src/lib/smbsrv/libfksmbsrv/common/reparse.c
new file mode 100644
index 0000000000..c7e0d87355
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/reparse.c
@@ -0,0 +1,84 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+#include <sys/vnode.h>
+#include <sys/nvpair.h>
+#include <sys/uio.h>
+#include <sys/kmem.h>
+#include <fs/fs_subr.h>
+#include <fs/fs_reparse.h>
+
+
+/*
+ * support functions for reparse point
+ * copied from uts/common/fs/fs_subr.c
+ */
+
+/*
+ * reparse_vnode_parse
+ *
+ * Read the symlink data of a reparse point specified by the vnode
+ * and return the reparse data as name-value pair in the nvlist.
+ */
+int
+reparse_vnode_parse(vnode_t *vp, nvlist_t *nvl)
+{
+ int err;
+ char *lkdata;
+ struct uio uio;
+ struct iovec iov;
+
+ if (vp == NULL || nvl == NULL)
+ return (EINVAL);
+
+ lkdata = kmem_alloc(MAXREPARSELEN, KM_SLEEP);
+
+ /*
+ * Set up io vector to read sym link data
+ */
+ iov.iov_base = lkdata;
+ iov.iov_len = MAXREPARSELEN;
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ uio.uio_segflg = UIO_SYSSPACE;
+ uio.uio_extflg = UIO_COPY_CACHED;
+ uio.uio_loffset = (offset_t)0;
+ uio.uio_resid = MAXREPARSELEN;
+
+ if ((err = VOP_READLINK(vp, &uio, zone_kcred(), NULL)) == 0) {
+ *(lkdata + MAXREPARSELEN - uio.uio_resid) = '\0';
+ err = reparse_parse(lkdata, nvl);
+ }
+ kmem_free(lkdata, MAXREPARSELEN); /* done with lkdata */
+
+ return (err);
+}
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/sys/kidmap.h b/usr/src/lib/smbsrv/libfksmbsrv/common/sys/kidmap.h
new file mode 100644
index 0000000000..8490e7639d
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/sys/kidmap.h
@@ -0,0 +1,183 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * Windows to Solaris Identity Mapping kernel API
+ * This header defines an API to map Windows SIDs to
+ * Solaris UID and GIDs and versa visa.
+ */
+
+#ifndef _SYS_KIDMAP_H
+#define _SYS_KIDMAP_H
+
+#include <sys/idmap.h>
+#include <sys/door.h>
+#include <sys/zone.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The ifdef's for these two accomodate duplicate definitions in
+ * lib/libidmap/common/idmap.h (the real one). In this code we
+ * simulate a kernel environment in user space using the real
+ * idmap library, so need to be able to use both headers.
+ */
+
+/* Return status */
+#ifndef _IDMAP_STAT_TYPE
+#define _IDMAP_STAT_TYPE
+typedef int32_t idmap_stat;
+#endif /* _IDMAP_STAT_TYPE */
+
+/* Opaque get handle */
+#ifndef _IDMAP_GET_HANDLE_T
+#define _IDMAP_GET_HANDLE_T
+typedef struct idmap_get_handle idmap_get_handle_t;
+#endif /* _IDMAP_GET_HANDLE_T */
+
+/*
+ * In all the routines a Windows SID is handled as a
+ * string SID prefix plus a RID. For example
+ *
+ * S-1-5-5-12-34-568 will be passed as SID prefix
+ * S-1-5-5-12-34 and RID 568
+ *
+ * Certain routines returns pointers to a SID prefix string.
+ * These strings are stored internally and should not be modified
+ * or freed.
+ */
+
+
+/*
+ * The following routines are simple get ID mapping routines.
+ */
+
+
+idmap_stat
+kidmap_getuidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
+ uid_t *uid);
+
+idmap_stat
+kidmap_getgidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
+ gid_t *gid);
+
+idmap_stat
+kidmap_getpidbysid(zone_t *zone, const char *sid_prefix, uint32_t rid,
+ uid_t *pid, int *is_user);
+
+idmap_stat
+kidmap_getsidbyuid(zone_t *zone, uid_t uid, const char **sid_prefix,
+ uint32_t *rid);
+
+idmap_stat
+kidmap_getsidbygid(zone_t *zone, gid_t gid, const char **sid_prefix,
+ uint32_t *rid);
+
+
+
+/*
+ * The following routines provide a batch interface for mapping IDs.
+ */
+
+/*
+ * Create a batch "get mapping" handle for batch mappings.
+ */
+idmap_get_handle_t *
+kidmap_get_create(zone_t *zone);
+
+/*
+ * These routines queue the request to the "get mapping" handle
+ */
+
+idmap_stat
+kidmap_batch_getuidbysid(idmap_get_handle_t *get_handle,
+ const char *sid_prefix, uint32_t rid,
+ uid_t *uid, idmap_stat *stat);
+
+idmap_stat
+kidmap_batch_getgidbysid(idmap_get_handle_t *get_handle,
+ const char *sid_prefix, uint32_t rid,
+ gid_t *gid, idmap_stat *stat);
+
+idmap_stat
+kidmap_batch_getpidbysid(idmap_get_handle_t *get_handle,
+ const char *sid_prefix, uint32_t rid,
+ uid_t *pid, int *is_user, idmap_stat *stat);
+
+idmap_stat
+kidmap_batch_getsidbyuid(idmap_get_handle_t *get_handle, uid_t uid,
+ const char **sid_prefix, uint32_t *rid, idmap_stat *stat);
+
+idmap_stat
+kidmap_batch_getsidbygid(idmap_get_handle_t *get_handle, gid_t gid,
+ const char **sid_prefix, uint32_t *rid, idmap_stat *stat);
+
+/*
+ * Process the queued "get mapping" requests. The results (i.e.
+ * status and identity) will be available in the data areas
+ * provided by individual requests.
+ */
+idmap_stat
+kidmap_get_mappings(idmap_get_handle_t *get_handle);
+
+/*
+ * Destroy the "get mapping" handle
+ */
+void
+kidmap_get_destroy(idmap_get_handle_t *get_handle);
+
+#ifdef _KERNEL
+/*
+ * Functions that do the hard part of door registration/unregistration
+ * for the idmap_reg()/idmap_unreg() syscalls
+ */
+int idmap_reg_dh(zone_t *zone, door_handle_t dh);
+int idmap_unreg_dh(zone_t *zone, door_handle_t dh);
+
+/*
+ * Function needed by allocids() to ensure only the daemon that owns
+ * the door gets ephemeral IDS
+ */
+door_handle_t idmap_get_door(zone_t *zone);
+
+/*
+ * Function used by system call allocids() to purge the
+ * ID mapping cache
+ */
+void idmap_purge_cache(zone_t *zone);
+
+#endif /* _KERNEL */
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_KIDMAP_H */
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/sys/sunddi.h b/usr/src/lib/smbsrv/libfksmbsrv/common/sys/sunddi.h
new file mode 100644
index 0000000000..49e476e7a5
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/sys/sunddi.h
@@ -0,0 +1,122 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#ifndef _SYS_SUNDDI_H
+#define _SYS_SUNDDI_H
+
+/*
+ * Sun Specific DDI definitions (fakekernel version)
+ * The real sunddi.h has become a "kitchen sink" full of
+ * includes we don't want, and lots of places include it.
+ * Rather than fight that battle now, provide this one
+ * with just the str*, mem*, and kiconv* functions.
+ * Some day, re-factor: sunddi.h, systm.h
+ */
+
+#include <sys/isa_defs.h>
+#include <sys/dditypes.h>
+#include <sys/time.h>
+#include <sys/cmn_err.h>
+
+#include <sys/kmem.h>
+#include <sys/nvpair.h>
+#include <sys/thread.h>
+#include <sys/stream.h>
+
+#include <sys/u8_textprep.h>
+#include <sys/kiconv.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+
+extern char *ddi_strdup(const char *str, int flag);
+extern char *strdup(const char *str);
+extern void strfree(char *str);
+
+extern size_t strlen(const char *) __PURE;
+extern size_t strnlen(const char *, size_t) __PURE;
+extern char *strcpy(char *, const char *);
+extern char *strncpy(char *, const char *, size_t);
+
+/* Need to be consistent with <string.h> C++ definition for strchr() */
+#if __cplusplus >= 199711L
+extern const char *strchr(const char *, int);
+#else
+extern char *strchr(const char *, int);
+#endif /* __cplusplus >= 199711L */
+
+#define DDI_STRSAME(s1, s2) ((*(s1) == *(s2)) && (strcmp((s1), (s2)) == 0))
+extern int strcmp(const char *, const char *) __PURE;
+extern int strncmp(const char *, const char *, size_t) __PURE;
+extern char *strncat(char *, const char *, size_t);
+extern size_t strlcat(char *, const char *, size_t);
+extern size_t strlcpy(char *, const char *, size_t);
+extern size_t strspn(const char *, const char *);
+extern size_t strcspn(const char *, const char *);
+extern int bcmp(const void *, const void *, size_t) __PURE;
+extern int stoi(char **);
+extern void numtos(ulong_t, char *);
+extern void bcopy(const void *, void *, size_t);
+extern void bzero(void *, size_t);
+
+extern void *memcpy(void *, const void *, size_t);
+extern void *memset(void *, int, size_t);
+extern void *memmove(void *, const void *, size_t);
+extern int memcmp(const void *, const void *, size_t) __PURE;
+
+/* Need to be consistent with <string.h> C++ definition for memchr() */
+#if __cplusplus >= 199711L
+extern const void *memchr(const void *, int, size_t);
+#else
+extern void *memchr(const void *, int, size_t);
+#endif /* __cplusplus >= 199711L */
+
+extern int ddi_strtol(const char *, char **, int, long *);
+extern int ddi_strtoul(const char *, char **, int, unsigned long *);
+extern int ddi_strtoll(const char *, char **, int, longlong_t *);
+extern int ddi_strtoull(const char *, char **, int, u_longlong_t *);
+
+/*
+ * kiconv functions and their macros.
+ */
+#define KICONV_IGNORE_NULL (0x0001)
+#define KICONV_REPLACE_INVALID (0x0002)
+
+extern kiconv_t kiconv_open(const char *, const char *);
+extern size_t kiconv(kiconv_t, char **, size_t *, char **, size_t *, int *);
+extern int kiconv_close(kiconv_t);
+extern size_t kiconvstr(const char *, const char *, char *, size_t *, char *,
+ size_t *, int, int *);
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_SUNDDI_H */
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/sys/vfs_opreg.h b/usr/src/lib/smbsrv/libfksmbsrv/common/sys/vfs_opreg.h
new file mode 100644
index 0000000000..58974b8e76
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/sys/vfs_opreg.h
@@ -0,0 +1,116 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _SYS_VFS_OPREG_H
+#define _SYS_VFS_OPREG_H
+
+#include <sys/vfs.h>
+#include <sys/fem.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+
+/*
+ * The following union allows us to use C99's "designated initializer"
+ * feature so that we can have strong typechecking for the operations
+ * used in the the fs_operation_def structures.
+ */
+
+typedef union fs_func {
+ fs_generic_func_p fs_generic; /* Generic function signature */
+ int (*error)(); /* Signature of error function */
+ VFS_OPS; /* Signatures of all vfs operations (vfsops) */
+ VNODE_OPS; /* Signatures of all vnode operations (vops) */
+ FEM_OPS; /* Signatures of all FEM operations (femops) */
+ FSEM_OPS; /* Signatures of all FSEM ops (fsemops) */
+} fs_func_p;
+
+/*
+ * File systems use arrays of fs_operation_def structures to form
+ * name/value pairs of operations. These arrays get passed to:
+ *
+ * - vn_make_ops() to create vnodeops
+ * - vfs_makefsops()/vfs_setfsops() to create vfsops.
+ */
+typedef struct fs_operation_def {
+ char *name; /* name of operation (NULL at end) */
+ fs_func_p func; /* function implementing operation */
+} fs_operation_def_t;
+
+/*
+ * The operation registration mechanism uses two master tables of operations:
+ * one for vnode operations (vn_ops_table[]) and one for vfs operations
+ * (vfs_ops_table[]). These tables are arrays of fs_operation_trans_def
+ * structures. They contain all of the information necessary for the system
+ * to populate an operations structure (e.g., vnodeops, vfsops).
+ *
+ * File systems call registration routines (vfs_setfsops(), vfs_makefsops(),
+ * and vn_make_ops()) and pass in their operations specification tables
+ * (arrays of fs_operation_def structures). These routines use the master
+ * table(s) of operations to build a vnodeops or vfsops structure.
+ */
+typedef struct fs_operation_trans_def {
+ char *name; /* name of operation (NULL at end) */
+ int offset; /* byte offset within ops vector */
+ fs_generic_func_p defaultFunc; /* default function */
+ fs_generic_func_p errorFunc; /* error function */
+} fs_operation_trans_def_t;
+
+/*
+ * Generic operations vector types (used for vfs/vnode ops registration).
+ */
+
+extern int fs_default(); /* "default" function placeholder */
+extern int fs_error(); /* "error" function placeholder */
+
+int fs_build_vector(void *vector, int *unused_ops,
+ const fs_operation_trans_def_t *translation,
+ const fs_operation_def_t *operations);
+
+/*
+ * Public operations.
+ */
+
+int vn_make_ops(const char *, const struct fs_operation_def *,
+ vnodeops_t **);
+void vn_freevnodeops(vnodeops_t *);
+
+int vfs_setfsops(int, const fs_operation_def_t *, vfsops_t **);
+int vfs_makefsops(const fs_operation_def_t *, vfsops_t **);
+void vfs_freevfsops(vfsops_t *);
+int vfs_freevfsops_by_type(int);
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_VFS_OPREG_H */
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/sys/vnode.h b/usr/src/lib/smbsrv/libfksmbsrv/common/sys/vnode.h
new file mode 100644
index 0000000000..adac97b7e1
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/sys/vnode.h
@@ -0,0 +1,1438 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
+
+/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+/*
+ * University Copyright- Copyright (c) 1982, 1986, 1988
+ * The Regents of the University of California
+ * All Rights Reserved
+ *
+ * University Acknowledgment- Portions of this document are derived from
+ * software developed by the University of California, Berkeley, and its
+ * contributors.
+ */
+
+#ifndef _SYS_VNODE_H
+#define _SYS_VNODE_H
+
+#include <sys/types.h>
+#include <sys/t_lock.h>
+#include <sys/time_impl.h>
+#include <sys/cred.h>
+#include <sys/uio.h>
+#include <sys/resource.h>
+#include <vm/seg_enum.h>
+#include <sys/kstat.h>
+#include <sys/kmem.h>
+#include <sys/list.h>
+#include <sys/avl.h>
+#ifdef _KERNEL
+#include <sys/rwstlock.h>
+#include <sys/buf.h>
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Statistics for all vnode operations.
+ * All operations record number of ops (since boot/mount/zero'ed).
+ * Certain I/O operations (read, write, readdir) also record number
+ * of bytes transferred.
+ * This appears in two places in the system: one is embedded in each
+ * vfs_t. There is also an array of vopstats_t structures allocated
+ * on a per-fstype basis.
+ */
+
+#define VOPSTATS_STR "vopstats_" /* Initial string for vopstat kstats */
+
+typedef struct vopstats {
+ kstat_named_t nopen; /* VOP_OPEN */
+ kstat_named_t nclose; /* VOP_CLOSE */
+ kstat_named_t nread; /* VOP_READ */
+ kstat_named_t read_bytes;
+ kstat_named_t nwrite; /* VOP_WRITE */
+ kstat_named_t write_bytes;
+ kstat_named_t nioctl; /* VOP_IOCTL */
+ kstat_named_t nsetfl; /* VOP_SETFL */
+ kstat_named_t ngetattr; /* VOP_GETATTR */
+ kstat_named_t nsetattr; /* VOP_SETATTR */
+ kstat_named_t naccess; /* VOP_ACCESS */
+ kstat_named_t nlookup; /* VOP_LOOKUP */
+ kstat_named_t ncreate; /* VOP_CREATE */
+ kstat_named_t nremove; /* VOP_REMOVE */
+ kstat_named_t nlink; /* VOP_LINK */
+ kstat_named_t nrename; /* VOP_RENAME */
+ kstat_named_t nmkdir; /* VOP_MKDIR */
+ kstat_named_t nrmdir; /* VOP_RMDIR */
+ kstat_named_t nreaddir; /* VOP_READDIR */
+ kstat_named_t readdir_bytes;
+ kstat_named_t nsymlink; /* VOP_SYMLINK */
+ kstat_named_t nreadlink; /* VOP_READLINK */
+ kstat_named_t nfsync; /* VOP_FSYNC */
+ kstat_named_t ninactive; /* VOP_INACTIVE */
+ kstat_named_t nfid; /* VOP_FID */
+ kstat_named_t nrwlock; /* VOP_RWLOCK */
+ kstat_named_t nrwunlock; /* VOP_RWUNLOCK */
+ kstat_named_t nseek; /* VOP_SEEK */
+ kstat_named_t ncmp; /* VOP_CMP */
+ kstat_named_t nfrlock; /* VOP_FRLOCK */
+ kstat_named_t nspace; /* VOP_SPACE */
+ kstat_named_t nrealvp; /* VOP_REALVP */
+ kstat_named_t ngetpage; /* VOP_GETPAGE */
+ kstat_named_t nputpage; /* VOP_PUTPAGE */
+ kstat_named_t nmap; /* VOP_MAP */
+ kstat_named_t naddmap; /* VOP_ADDMAP */
+ kstat_named_t ndelmap; /* VOP_DELMAP */
+ kstat_named_t npoll; /* VOP_POLL */
+ kstat_named_t ndump; /* VOP_DUMP */
+ kstat_named_t npathconf; /* VOP_PATHCONF */
+ kstat_named_t npageio; /* VOP_PAGEIO */
+ kstat_named_t ndumpctl; /* VOP_DUMPCTL */
+ kstat_named_t ndispose; /* VOP_DISPOSE */
+ kstat_named_t nsetsecattr; /* VOP_SETSECATTR */
+ kstat_named_t ngetsecattr; /* VOP_GETSECATTR */
+ kstat_named_t nshrlock; /* VOP_SHRLOCK */
+ kstat_named_t nvnevent; /* VOP_VNEVENT */
+ kstat_named_t nreqzcbuf; /* VOP_REQZCBUF */
+ kstat_named_t nretzcbuf; /* VOP_RETZCBUF */
+} vopstats_t;
+
+/*
+ * The vnode is the focus of all file activity in UNIX.
+ * A vnode is allocated for each active file, each current
+ * directory, each mounted-on file, and the root.
+ *
+ * Each vnode is usually associated with a file-system-specific node (for
+ * UFS, this is the in-memory inode). Generally, a vnode and an fs-node
+ * should be created and destroyed together as a pair.
+ *
+ * If a vnode is reused for a new file, it should be reinitialized by calling
+ * either vn_reinit() or vn_recycle().
+ *
+ * vn_reinit() resets the entire vnode as if it was returned by vn_alloc().
+ * The caller is responsible for setting up the entire vnode after calling
+ * vn_reinit(). This is important when using kmem caching where the vnode is
+ * allocated by a constructor, for instance.
+ *
+ * vn_recycle() is used when the file system keeps some state around in both
+ * the vnode and the associated FS-node. In UFS, for example, the inode of
+ * a deleted file can be reused immediately. The v_data, v_vfsp, v_op, etc.
+ * remains the same but certain fields related to the previous instance need
+ * to be reset. In particular:
+ * v_femhead
+ * v_path
+ * v_rdcnt, v_wrcnt
+ * v_mmap_read, v_mmap_write
+ */
+
+/*
+ * vnode types. VNON means no type. These values are unrelated to
+ * values in on-disk inodes.
+ */
+typedef enum vtype {
+ VNON = 0,
+ VREG = 1,
+ VDIR = 2,
+ VBLK = 3,
+ VCHR = 4,
+ VLNK = 5,
+ VFIFO = 6,
+ VDOOR = 7,
+ VPROC = 8,
+ VSOCK = 9,
+ VPORT = 10,
+ VBAD = 11
+} vtype_t;
+
+/*
+ * VSD - Vnode Specific Data
+ * Used to associate additional private data with a vnode.
+ */
+struct vsd_node {
+ list_node_t vs_nodes; /* list of all VSD nodes */
+ uint_t vs_nkeys; /* entries in value array */
+ void **vs_value; /* array of value/key */
+};
+
+/*
+ * Many of the fields in the vnode are read-only once they are initialized
+ * at vnode creation time. Other fields are protected by locks.
+ *
+ * IMPORTANT: vnodes should be created ONLY by calls to vn_alloc(). They
+ * may not be embedded into the file-system specific node (inode). The
+ * size of vnodes may change.
+ *
+ * The v_lock protects:
+ * v_flag
+ * v_stream
+ * v_count
+ * v_shrlocks
+ * v_path
+ * v_vsd
+ * v_xattrdir
+ *
+ * A special lock (implemented by vn_vfswlock in vnode.c) protects:
+ * v_vfsmountedhere
+ *
+ * The global flock_lock mutex (in flock.c) protects:
+ * v_filocks
+ *
+ * IMPORTANT NOTE:
+ *
+ * The following vnode fields are considered public and may safely be
+ * accessed by file systems or other consumers:
+ *
+ * v_lock
+ * v_flag
+ * v_count
+ * v_data
+ * v_vfsp
+ * v_stream
+ * v_type
+ * v_rdev
+ *
+ * ALL OTHER FIELDS SHOULD BE ACCESSED ONLY BY THE OWNER OF THAT FIELD.
+ * In particular, file systems should not access other fields; they may
+ * change or even be removed. The functionality which was once provided
+ * by these fields is available through vn_* functions.
+ */
+
+struct fem_head; /* from fem.h */
+
+typedef struct vnode {
+ kmutex_t v_lock; /* protects vnode fields */
+ uint_t v_flag; /* vnode flags (see below) */
+ uint_t v_count; /* reference count */
+ void *v_data; /* private data for fs */
+ struct vfs *v_vfsp; /* ptr to containing VFS */
+ struct stdata *v_stream; /* associated stream */
+ enum vtype v_type; /* vnode type */
+ dev_t v_rdev; /* device (VCHR, VBLK) */
+
+ /* PRIVATE FIELDS BELOW - DO NOT USE */
+
+ krwlock_t v_nbllock; /* sync for NBMAND locks */
+ char *v_path; /* cached path */
+ uint_t v_rdcnt; /* open for read count (VREG only) */
+ uint_t v_wrcnt; /* open for write count (VREG only) */
+ struct vnode *v_xattrdir; /* unnamed extended attr dir (GFS) */
+
+ /* Private to the fake vnode impl. */
+
+ int v_fd;
+ dev_t v_st_dev;
+ ino_t v_st_ino;
+ avl_node_t v_avl_node;
+} vnode_t;
+
+#define IS_DEVVP(vp) \
+ ((vp)->v_type == VCHR || (vp)->v_type == VBLK || (vp)->v_type == VFIFO)
+
+#define VNODE_ALIGN 64
+/* Count of low-order 0 bits in a vnode *, based on size and alignment. */
+#if defined(_LP64)
+#define VNODE_ALIGN_LOG2 8
+#else
+#define VNODE_ALIGN_LOG2 7
+#endif
+
+/*
+ * vnode flags.
+ */
+#define VROOT 0x01 /* root of its file system */
+#define VNOCACHE 0x02 /* don't keep cache pages on vnode */
+#define VNOMAP 0x04 /* file cannot be mapped/faulted */
+#define VDUP 0x08 /* file should be dup'ed rather then opened */
+#define VNOSWAP 0x10 /* file cannot be used as virtual swap device */
+#define VNOMOUNT 0x20 /* file cannot be covered by mount */
+#define VISSWAP 0x40 /* vnode is being used for swap */
+#define VSWAPLIKE 0x80 /* vnode acts like swap (but may not be) */
+
+#define IS_SWAPVP(vp) (((vp)->v_flag & (VISSWAP | VSWAPLIKE)) != 0)
+
+#if defined(_KERNEL)
+typedef struct vn_vfslocks_entry {
+ rwstlock_t ve_lock;
+ void *ve_vpvfs;
+ struct vn_vfslocks_entry *ve_next;
+ uint32_t ve_refcnt;
+ char pad[64 - sizeof (rwstlock_t) - 2 * sizeof (void *) - \
+ sizeof (uint32_t)];
+} vn_vfslocks_entry_t;
+#endif /* _KERNEL */
+
+/*
+ * The following two flags are used to lock the v_vfsmountedhere field
+ */
+#define VVFSLOCK 0x100
+#define VVFSWAIT 0x200
+
+/*
+ * Used to serialize VM operations on a vnode
+ */
+#define VVMLOCK 0x400
+
+/*
+ * Tell vn_open() not to fail a directory open for writing but
+ * to go ahead and call VOP_OPEN() to let the filesystem check.
+ */
+#define VDIROPEN 0x800
+
+/*
+ * Flag to let the VM system know that this file is most likely a binary
+ * or shared library since it has been mmap()ed EXEC at some time.
+ */
+#define VVMEXEC 0x1000
+
+#define VPXFS 0x2000 /* clustering: global fs proxy vnode */
+
+#define IS_PXFSVP(vp) ((vp)->v_flag & VPXFS)
+
+#define V_XATTRDIR 0x4000 /* attribute unnamed directory */
+
+#define IS_XATTRDIR(vp) ((vp)->v_flag & V_XATTRDIR)
+
+#define V_LOCALITY 0x8000 /* whether locality aware */
+
+/*
+ * Flag that indicates the VM should maintain the v_pages list with all modified
+ * pages on one end and unmodified pages at the other. This makes finding dirty
+ * pages to write back to disk much faster at the expense of taking a minor
+ * fault on the first store instruction which touches a writable page.
+ */
+#define VMODSORT (0x10000)
+#define IS_VMODSORT(vp) \
+ (pvn_vmodsort_supported != 0 && ((vp)->v_flag & VMODSORT) != 0)
+
+#define VISSWAPFS 0x20000 /* vnode is being used for swapfs */
+
+/*
+ * The mdb memstat command assumes that IS_SWAPFSVP only uses the
+ * vnode's v_flag field. If this changes, cache the additional
+ * fields in mdb; see vn_get in mdb/common/modules/genunix/memory.c
+ */
+#define IS_SWAPFSVP(vp) (((vp)->v_flag & VISSWAPFS) != 0)
+
+#define V_SYSATTR 0x40000 /* vnode is a GFS system attribute */
+
+/*
+ * Vnode attributes. A bit-mask is supplied as part of the
+ * structure to indicate the attributes the caller wants to
+ * set (setattr) or extract (getattr).
+ */
+
+/*
+ * Note that va_nodeid and va_nblocks are 64bit data type.
+ * We support large files over NFSV3. With Solaris client and
+ * Server that generates 64bit ino's and sizes these fields
+ * will overflow if they are 32 bit sizes.
+ */
+
+typedef struct vattr {
+ uint_t va_mask; /* bit-mask of attributes */
+ vtype_t va_type; /* vnode type (for create) */
+ mode_t va_mode; /* file access mode */
+ uid_t va_uid; /* owner user id */
+ gid_t va_gid; /* owner group id */
+ dev_t va_fsid; /* file system id (dev for now) */
+ u_longlong_t va_nodeid; /* node id */
+ nlink_t va_nlink; /* number of references to file */
+ u_offset_t va_size; /* file size in bytes */
+ timestruc_t va_atime; /* time of last access */
+ timestruc_t va_mtime; /* time of last modification */
+ timestruc_t va_ctime; /* time of last status change */
+ dev_t va_rdev; /* device the file represents */
+ uint_t va_blksize; /* fundamental block size */
+ u_longlong_t va_nblocks; /* # of blocks allocated */
+ uint_t va_seq; /* sequence number */
+} vattr_t;
+
+#define AV_SCANSTAMP_SZ 32 /* length of anti-virus scanstamp */
+
+/*
+ * Structure of all optional attributes.
+ */
+typedef struct xoptattr {
+ timestruc_t xoa_createtime; /* Create time of file */
+ uint8_t xoa_archive;
+ uint8_t xoa_system;
+ uint8_t xoa_readonly;
+ uint8_t xoa_hidden;
+ uint8_t xoa_nounlink;
+ uint8_t xoa_immutable;
+ uint8_t xoa_appendonly;
+ uint8_t xoa_nodump;
+ uint8_t xoa_opaque;
+ uint8_t xoa_av_quarantined;
+ uint8_t xoa_av_modified;
+ uint8_t xoa_av_scanstamp[AV_SCANSTAMP_SZ];
+ uint8_t xoa_reparse;
+ uint64_t xoa_generation;
+ uint8_t xoa_offline;
+ uint8_t xoa_sparse;
+} xoptattr_t;
+
+/*
+ * The xvattr structure is really a variable length structure that
+ * is made up of:
+ * - The classic vattr_t (xva_vattr)
+ * - a 32 bit quantity (xva_mapsize) that specifies the size of the
+ * attribute bitmaps in 32 bit words.
+ * - A pointer to the returned attribute bitmap (needed because the
+ * previous element, the requested attribute bitmap) is variable lenth.
+ * - The requested attribute bitmap, which is an array of 32 bit words.
+ * Callers use the XVA_SET_REQ() macro to set the bits corresponding to
+ * the attributes that are being requested.
+ * - The returned attribute bitmap, which is an array of 32 bit words.
+ * File systems that support optional attributes use the XVA_SET_RTN()
+ * macro to set the bits corresponding to the attributes that are being
+ * returned.
+ * - The xoptattr_t structure which contains the attribute values
+ *
+ * xva_mapsize determines how many words in the attribute bitmaps.
+ * Immediately following the attribute bitmaps is the xoptattr_t.
+ * xva_getxoptattr() is used to get the pointer to the xoptattr_t
+ * section.
+ */
+
+#define XVA_MAPSIZE 3 /* Size of attr bitmaps */
+#define XVA_MAGIC 0x78766174 /* Magic # for verification */
+
+/*
+ * The xvattr structure is an extensible structure which permits optional
+ * attributes to be requested/returned. File systems may or may not support
+ * optional attributes. They do so at their own discretion but if they do
+ * support optional attributes, they must register the VFSFT_XVATTR feature
+ * so that the optional attributes can be set/retrived.
+ *
+ * The fields of the xvattr structure are:
+ *
+ * xva_vattr - The first element of an xvattr is a legacy vattr structure
+ * which includes the common attributes. If AT_XVATTR is set in the va_mask
+ * then the entire structure is treated as an xvattr. If AT_XVATTR is not
+ * set, then only the xva_vattr structure can be used.
+ *
+ * xva_magic - 0x78766174 (hex for "xvat"). Magic number for verification.
+ *
+ * xva_mapsize - Size of requested and returned attribute bitmaps.
+ *
+ * xva_rtnattrmapp - Pointer to xva_rtnattrmap[]. We need this since the
+ * size of the array before it, xva_reqattrmap[], could change which means
+ * the location of xva_rtnattrmap[] could change. This will allow unbundled
+ * file systems to find the location of xva_rtnattrmap[] when the sizes change.
+ *
+ * xva_reqattrmap[] - Array of requested attributes. Attributes are
+ * represented by a specific bit in a specific element of the attribute
+ * map array. Callers set the bits corresponding to the attributes
+ * that the caller wants to get/set.
+ *
+ * xva_rtnattrmap[] - Array of attributes that the file system was able to
+ * process. Not all file systems support all optional attributes. This map
+ * informs the caller which attributes the underlying file system was able
+ * to set/get. (Same structure as the requested attributes array in terms
+ * of each attribute corresponding to specific bits and array elements.)
+ *
+ * xva_xoptattrs - Structure containing values of optional attributes.
+ * These values are only valid if the corresponding bits in xva_reqattrmap
+ * are set and the underlying file system supports those attributes.
+ */
+typedef struct xvattr {
+ vattr_t xva_vattr; /* Embedded vattr structure */
+ uint32_t xva_magic; /* Magic Number */
+ uint32_t xva_mapsize; /* Size of attr bitmap (32-bit words) */
+ uint32_t *xva_rtnattrmapp; /* Ptr to xva_rtnattrmap[] */
+ uint32_t xva_reqattrmap[XVA_MAPSIZE]; /* Requested attrs */
+ uint32_t xva_rtnattrmap[XVA_MAPSIZE]; /* Returned attrs */
+ xoptattr_t xva_xoptattrs; /* Optional attributes */
+} xvattr_t;
+
+#ifdef _SYSCALL32
+/*
+ * For bigtypes time_t changed to 64 bit on the 64-bit kernel.
+ * Define an old version for user/kernel interface
+ */
+
+#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
+#pragma pack(4)
+#endif
+
+typedef struct vattr32 {
+ uint32_t va_mask; /* bit-mask of attributes */
+ vtype_t va_type; /* vnode type (for create) */
+ mode32_t va_mode; /* file access mode */
+ uid32_t va_uid; /* owner user id */
+ gid32_t va_gid; /* owner group id */
+ dev32_t va_fsid; /* file system id (dev for now) */
+ u_longlong_t va_nodeid; /* node id */
+ nlink_t va_nlink; /* number of references to file */
+ u_offset_t va_size; /* file size in bytes */
+ timestruc32_t va_atime; /* time of last access */
+ timestruc32_t va_mtime; /* time of last modification */
+ timestruc32_t va_ctime; /* time of last status change */
+ dev32_t va_rdev; /* device the file represents */
+ uint32_t va_blksize; /* fundamental block size */
+ u_longlong_t va_nblocks; /* # of blocks allocated */
+ uint32_t va_seq; /* sequence number */
+} vattr32_t;
+
+#if _LONG_LONG_ALIGNMENT == 8 && _LONG_LONG_ALIGNMENT_32 == 4
+#pragma pack()
+#endif
+
+#else /* not _SYSCALL32 */
+#define vattr32 vattr
+typedef vattr_t vattr32_t;
+#endif /* _SYSCALL32 */
+
+/*
+ * Attributes of interest to the caller of setattr or getattr.
+ */
+#define AT_TYPE 0x00001
+#define AT_MODE 0x00002
+#define AT_UID 0x00004
+#define AT_GID 0x00008
+#define AT_FSID 0x00010
+#define AT_NODEID 0x00020
+#define AT_NLINK 0x00040
+#define AT_SIZE 0x00080
+#define AT_ATIME 0x00100
+#define AT_MTIME 0x00200
+#define AT_CTIME 0x00400
+#define AT_RDEV 0x00800
+#define AT_BLKSIZE 0x01000
+#define AT_NBLOCKS 0x02000
+/* 0x04000 */ /* unused */
+#define AT_SEQ 0x08000
+/*
+ * If AT_XVATTR is set then there are additional bits to process in
+ * the xvattr_t's attribute bitmap. If this is not set then the bitmap
+ * MUST be ignored. Note that this bit must be set/cleared explicitly.
+ * That is, setting AT_ALL will NOT set AT_XVATTR.
+ */
+#define AT_XVATTR 0x10000
+
+#define AT_ALL (AT_TYPE|AT_MODE|AT_UID|AT_GID|AT_FSID|AT_NODEID|\
+ AT_NLINK|AT_SIZE|AT_ATIME|AT_MTIME|AT_CTIME|\
+ AT_RDEV|AT_BLKSIZE|AT_NBLOCKS|AT_SEQ)
+
+#define AT_STAT (AT_MODE|AT_UID|AT_GID|AT_FSID|AT_NODEID|AT_NLINK|\
+ AT_SIZE|AT_ATIME|AT_MTIME|AT_CTIME|AT_RDEV|AT_TYPE)
+
+#define AT_TIMES (AT_ATIME|AT_MTIME|AT_CTIME)
+
+#define AT_NOSET (AT_NLINK|AT_RDEV|AT_FSID|AT_NODEID|AT_TYPE|\
+ AT_BLKSIZE|AT_NBLOCKS|AT_SEQ)
+
+/*
+ * Attribute bits used in the extensible attribute's (xva's) attribute
+ * bitmaps. Note that the bitmaps are made up of a variable length number
+ * of 32-bit words. The convention is to use XAT{n}_{attrname} where "n"
+ * is the element in the bitmap (starting at 1). This convention is for
+ * the convenience of the maintainer to keep track of which element each
+ * attribute belongs to.
+ *
+ * NOTE THAT CONSUMERS MUST *NOT* USE THE XATn_* DEFINES DIRECTLY. CONSUMERS
+ * MUST USE THE XAT_* DEFINES.
+ */
+#define XAT0_INDEX 0LL /* Index into bitmap for XAT0 attrs */
+#define XAT0_CREATETIME 0x00000001 /* Create time of file */
+#define XAT0_ARCHIVE 0x00000002 /* Archive */
+#define XAT0_SYSTEM 0x00000004 /* System */
+#define XAT0_READONLY 0x00000008 /* Readonly */
+#define XAT0_HIDDEN 0x00000010 /* Hidden */
+#define XAT0_NOUNLINK 0x00000020 /* Nounlink */
+#define XAT0_IMMUTABLE 0x00000040 /* immutable */
+#define XAT0_APPENDONLY 0x00000080 /* appendonly */
+#define XAT0_NODUMP 0x00000100 /* nodump */
+#define XAT0_OPAQUE 0x00000200 /* opaque */
+#define XAT0_AV_QUARANTINED 0x00000400 /* anti-virus quarantine */
+#define XAT0_AV_MODIFIED 0x00000800 /* anti-virus modified */
+#define XAT0_AV_SCANSTAMP 0x00001000 /* anti-virus scanstamp */
+#define XAT0_REPARSE 0x00002000 /* FS reparse point */
+#define XAT0_GEN 0x00004000 /* object generation number */
+#define XAT0_OFFLINE 0x00008000 /* offline */
+#define XAT0_SPARSE 0x00010000 /* sparse */
+
+#define XAT0_ALL_ATTRS (XAT0_CREATETIME|XAT0_ARCHIVE|XAT0_SYSTEM| \
+ XAT0_READONLY|XAT0_HIDDEN|XAT0_NOUNLINK|XAT0_IMMUTABLE|XAT0_APPENDONLY| \
+ XAT0_NODUMP|XAT0_OPAQUE|XAT0_AV_QUARANTINED| XAT0_AV_MODIFIED| \
+ XAT0_AV_SCANSTAMP|XAT0_REPARSE|XATO_GEN|XAT0_OFFLINE|XAT0_SPARSE)
+
+/* Support for XAT_* optional attributes */
+#define XVA_MASK 0xffffffff /* Used to mask off 32 bits */
+#define XVA_SHFT 32 /* Used to shift index */
+
+/*
+ * Used to pry out the index and attribute bits from the XAT_* attributes
+ * defined below. Note that we're masking things down to 32 bits then
+ * casting to uint32_t.
+ */
+#define XVA_INDEX(attr) ((uint32_t)(((attr) >> XVA_SHFT) & XVA_MASK))
+#define XVA_ATTRBIT(attr) ((uint32_t)((attr) & XVA_MASK))
+
+/*
+ * The following defines present a "flat namespace" so that consumers don't
+ * need to keep track of which element belongs to which bitmap entry.
+ *
+ * NOTE THAT THESE MUST NEVER BE OR-ed TOGETHER
+ */
+#define XAT_CREATETIME ((XAT0_INDEX << XVA_SHFT) | XAT0_CREATETIME)
+#define XAT_ARCHIVE ((XAT0_INDEX << XVA_SHFT) | XAT0_ARCHIVE)
+#define XAT_SYSTEM ((XAT0_INDEX << XVA_SHFT) | XAT0_SYSTEM)
+#define XAT_READONLY ((XAT0_INDEX << XVA_SHFT) | XAT0_READONLY)
+#define XAT_HIDDEN ((XAT0_INDEX << XVA_SHFT) | XAT0_HIDDEN)
+#define XAT_NOUNLINK ((XAT0_INDEX << XVA_SHFT) | XAT0_NOUNLINK)
+#define XAT_IMMUTABLE ((XAT0_INDEX << XVA_SHFT) | XAT0_IMMUTABLE)
+#define XAT_APPENDONLY ((XAT0_INDEX << XVA_SHFT) | XAT0_APPENDONLY)
+#define XAT_NODUMP ((XAT0_INDEX << XVA_SHFT) | XAT0_NODUMP)
+#define XAT_OPAQUE ((XAT0_INDEX << XVA_SHFT) | XAT0_OPAQUE)
+#define XAT_AV_QUARANTINED ((XAT0_INDEX << XVA_SHFT) | XAT0_AV_QUARANTINED)
+#define XAT_AV_MODIFIED ((XAT0_INDEX << XVA_SHFT) | XAT0_AV_MODIFIED)
+#define XAT_AV_SCANSTAMP ((XAT0_INDEX << XVA_SHFT) | XAT0_AV_SCANSTAMP)
+#define XAT_REPARSE ((XAT0_INDEX << XVA_SHFT) | XAT0_REPARSE)
+#define XAT_GEN ((XAT0_INDEX << XVA_SHFT) | XAT0_GEN)
+#define XAT_OFFLINE ((XAT0_INDEX << XVA_SHFT) | XAT0_OFFLINE)
+#define XAT_SPARSE ((XAT0_INDEX << XVA_SHFT) | XAT0_SPARSE)
+
+/*
+ * The returned attribute map array (xva_rtnattrmap[]) is located past the
+ * requested attribute map array (xva_reqattrmap[]). Its location changes
+ * when the array sizes change. We use a separate pointer in a known location
+ * (xva_rtnattrmapp) to hold the location of xva_rtnattrmap[]. This is
+ * set in xva_init()
+ */
+#define XVA_RTNATTRMAP(xvap) ((xvap)->xva_rtnattrmapp)
+
+/*
+ * XVA_SET_REQ() sets an attribute bit in the proper element in the bitmap
+ * of requested attributes (xva_reqattrmap[]).
+ */
+#define XVA_SET_REQ(xvap, attr) \
+ ASSERT((xvap)->xva_vattr.va_mask | AT_XVATTR); \
+ ASSERT((xvap)->xva_magic == XVA_MAGIC); \
+ (xvap)->xva_reqattrmap[XVA_INDEX(attr)] |= XVA_ATTRBIT(attr)
+/*
+ * XVA_CLR_REQ() clears an attribute bit in the proper element in the bitmap
+ * of requested attributes (xva_reqattrmap[]).
+ */
+#define XVA_CLR_REQ(xvap, attr) \
+ ASSERT((xvap)->xva_vattr.va_mask | AT_XVATTR); \
+ ASSERT((xvap)->xva_magic == XVA_MAGIC); \
+ (xvap)->xva_reqattrmap[XVA_INDEX(attr)] &= ~XVA_ATTRBIT(attr)
+
+/*
+ * XVA_SET_RTN() sets an attribute bit in the proper element in the bitmap
+ * of returned attributes (xva_rtnattrmap[]).
+ */
+#define XVA_SET_RTN(xvap, attr) \
+ ASSERT((xvap)->xva_vattr.va_mask | AT_XVATTR); \
+ ASSERT((xvap)->xva_magic == XVA_MAGIC); \
+ (XVA_RTNATTRMAP(xvap))[XVA_INDEX(attr)] |= XVA_ATTRBIT(attr)
+
+/*
+ * XVA_ISSET_REQ() checks the requested attribute bitmap (xva_reqattrmap[])
+ * to see of the corresponding attribute bit is set. If so, returns non-zero.
+ */
+#define XVA_ISSET_REQ(xvap, attr) \
+ ((((xvap)->xva_vattr.va_mask | AT_XVATTR) && \
+ ((xvap)->xva_magic == XVA_MAGIC) && \
+ ((xvap)->xva_mapsize > XVA_INDEX(attr))) ? \
+ ((xvap)->xva_reqattrmap[XVA_INDEX(attr)] & XVA_ATTRBIT(attr)) : 0)
+
+/*
+ * XVA_ISSET_RTN() checks the returned attribute bitmap (xva_rtnattrmap[])
+ * to see of the corresponding attribute bit is set. If so, returns non-zero.
+ */
+#define XVA_ISSET_RTN(xvap, attr) \
+ ((((xvap)->xva_vattr.va_mask | AT_XVATTR) && \
+ ((xvap)->xva_magic == XVA_MAGIC) && \
+ ((xvap)->xva_mapsize > XVA_INDEX(attr))) ? \
+ ((XVA_RTNATTRMAP(xvap))[XVA_INDEX(attr)] & XVA_ATTRBIT(attr)) : 0)
+
+/*
+ * Modes. Some values same as S_xxx entries from stat.h for convenience.
+ */
+#define VSUID 04000 /* set user id on execution */
+#define VSGID 02000 /* set group id on execution */
+#define VSVTX 01000 /* save swapped text even after use */
+
+/*
+ * Permissions.
+ */
+#define VREAD 00400
+#define VWRITE 00200
+#define VEXEC 00100
+
+#define MODEMASK 07777 /* mode bits plus permission bits */
+#define PERMMASK 00777 /* permission bits */
+
+/*
+ * VOP_ACCESS flags
+ */
+#define V_ACE_MASK 0x1 /* mask represents NFSv4 ACE permissions */
+#define V_APPEND 0x2 /* want to do append only check */
+
+/*
+ * Check whether mandatory file locking is enabled.
+ */
+
+#define MANDMODE(mode) (((mode) & (VSGID|(VEXEC>>3))) == VSGID)
+#define MANDLOCK(vp, mode) ((vp)->v_type == VREG && MANDMODE(mode))
+
+/*
+ * Flags for vnode operations.
+ */
+enum rm { RMFILE, RMDIRECTORY }; /* rm or rmdir (remove) */
+enum symfollow { NO_FOLLOW, FOLLOW }; /* follow symlinks (or not) */
+enum vcexcl { NONEXCL, EXCL }; /* (non)excl create */
+enum create { CRCREAT, CRMKNOD, CRMKDIR }; /* reason for create */
+
+typedef enum rm rm_t;
+typedef enum symfollow symfollow_t;
+typedef enum vcexcl vcexcl_t;
+typedef enum create create_t;
+
+/* Vnode Events - Used by VOP_VNEVENT */
+typedef enum vnevent {
+ VE_SUPPORT = 0, /* Query */
+ VE_RENAME_SRC = 1, /* Rename, with vnode as source */
+ VE_RENAME_DEST = 2, /* Rename, with vnode as target/destination */
+ VE_REMOVE = 3, /* Remove of vnode's name */
+ VE_RMDIR = 4, /* Remove of directory vnode's name */
+ VE_CREATE = 5, /* Create with vnode's name which exists */
+ VE_LINK = 6, /* Link with vnode's name as source */
+ VE_RENAME_DEST_DIR = 7, /* Rename with vnode as target dir */
+ VE_MOUNTEDOVER = 8, /* File or Filesystem got mounted over vnode */
+ VE_TRUNCATE = 9 /* Truncate */
+} vnevent_t;
+
+/*
+ * Values for checking vnode open and map counts
+ */
+enum v_mode { V_READ, V_WRITE, V_RDORWR, V_RDANDWR };
+
+typedef enum v_mode v_mode_t;
+
+#define V_TRUE 1
+#define V_FALSE 0
+
+/*
+ * Structure used on VOP_GETSECATTR and VOP_SETSECATTR operations
+ */
+
+typedef struct vsecattr {
+ uint_t vsa_mask; /* See below */
+ int vsa_aclcnt; /* ACL entry count */
+ void *vsa_aclentp; /* pointer to ACL entries */
+ int vsa_dfaclcnt; /* default ACL entry count */
+ void *vsa_dfaclentp; /* pointer to default ACL entries */
+ size_t vsa_aclentsz; /* ACE size in bytes of vsa_aclentp */
+ uint_t vsa_aclflags; /* ACE ACL flags */
+} vsecattr_t;
+
+/* vsa_mask values */
+#define VSA_ACL 0x0001
+#define VSA_ACLCNT 0x0002
+#define VSA_DFACL 0x0004
+#define VSA_DFACLCNT 0x0008
+#define VSA_ACE 0x0010
+#define VSA_ACECNT 0x0020
+#define VSA_ACE_ALLTYPES 0x0040
+#define VSA_ACE_ACLFLAGS 0x0080 /* get/set ACE ACL flags */
+
+/*
+ * Structure used by various vnode operations to determine
+ * the context (pid, host, identity) of a caller.
+ *
+ * The cc_caller_id is used to identify one or more callers who invoke
+ * operations, possibly on behalf of others. For example, the NFS
+ * server could have it's own cc_caller_id which can be detected by
+ * vnode/vfs operations or (FEM) monitors on those operations. New
+ * caller IDs are generated by fs_new_caller_id().
+ */
+typedef struct caller_context {
+ pid_t cc_pid; /* Process ID of the caller */
+ int cc_sysid; /* System ID, used for remote calls */
+ u_longlong_t cc_caller_id; /* Identifier for (set of) caller(s) */
+ ulong_t cc_flags;
+} caller_context_t;
+
+/*
+ * Flags for caller context. The caller sets CC_DONTBLOCK if it does not
+ * want to block inside of a FEM monitor. The monitor will set CC_WOULDBLOCK
+ * and return EAGAIN if the operation would have blocked.
+ */
+#define CC_WOULDBLOCK 0x01
+#define CC_DONTBLOCK 0x02
+
+/*
+ * Structure tags for function prototypes, defined elsewhere.
+ */
+struct pathname;
+struct fid;
+struct flock64;
+struct flk_callback;
+struct shrlock;
+struct page;
+struct seg;
+struct as;
+struct pollhead;
+struct taskq;
+
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+
+/*
+ * VNODE_OPS defines all the vnode operations. It is used to define
+ * the vnodeops structure (below) and the fs_func_p union (vfs_opreg.h).
+ */
+#define VNODE_OPS \
+ int (*vop_open)(vnode_t **, int, cred_t *, \
+ caller_context_t *); \
+ int (*vop_close)(vnode_t *, int, int, offset_t, cred_t *, \
+ caller_context_t *); \
+ int (*vop_read)(vnode_t *, uio_t *, int, cred_t *, \
+ caller_context_t *); \
+ int (*vop_write)(vnode_t *, uio_t *, int, cred_t *, \
+ caller_context_t *); \
+ int (*vop_ioctl)(vnode_t *, int, intptr_t, int, cred_t *, \
+ int *, caller_context_t *); \
+ int (*vop_setfl)(vnode_t *, int, int, cred_t *, \
+ caller_context_t *); \
+ int (*vop_getattr)(vnode_t *, vattr_t *, int, cred_t *, \
+ caller_context_t *); \
+ int (*vop_setattr)(vnode_t *, vattr_t *, int, cred_t *, \
+ caller_context_t *); \
+ int (*vop_access)(vnode_t *, int, int, cred_t *, \
+ caller_context_t *); \
+ int (*vop_lookup)(vnode_t *, char *, vnode_t **, \
+ struct pathname *, \
+ int, vnode_t *, cred_t *, \
+ caller_context_t *, int *, \
+ struct pathname *); \
+ int (*vop_create)(vnode_t *, char *, vattr_t *, vcexcl_t, \
+ int, vnode_t **, cred_t *, int, \
+ caller_context_t *, vsecattr_t *); \
+ int (*vop_remove)(vnode_t *, char *, cred_t *, \
+ caller_context_t *, int); \
+ int (*vop_link)(vnode_t *, vnode_t *, char *, cred_t *, \
+ caller_context_t *, int); \
+ int (*vop_rename)(vnode_t *, char *, vnode_t *, char *, \
+ cred_t *, caller_context_t *, int); \
+ int (*vop_mkdir)(vnode_t *, char *, vattr_t *, vnode_t **, \
+ cred_t *, caller_context_t *, int, \
+ vsecattr_t *); \
+ int (*vop_rmdir)(vnode_t *, char *, vnode_t *, cred_t *, \
+ caller_context_t *, int); \
+ int (*vop_readdir)(vnode_t *, uio_t *, cred_t *, int *, \
+ caller_context_t *, int); \
+ int (*vop_symlink)(vnode_t *, char *, vattr_t *, char *, \
+ cred_t *, caller_context_t *, int); \
+ int (*vop_readlink)(vnode_t *, uio_t *, cred_t *, \
+ caller_context_t *); \
+ int (*vop_fsync)(vnode_t *, int, cred_t *, \
+ caller_context_t *); \
+ void (*vop_inactive)(vnode_t *, cred_t *, \
+ caller_context_t *); \
+ int (*vop_fid)(vnode_t *, struct fid *, \
+ caller_context_t *); \
+ int (*vop_rwlock)(vnode_t *, int, caller_context_t *); \
+ void (*vop_rwunlock)(vnode_t *, int, caller_context_t *); \
+ int (*vop_seek)(vnode_t *, offset_t, offset_t *, \
+ caller_context_t *); \
+ int (*vop_cmp)(vnode_t *, vnode_t *, caller_context_t *); \
+ int (*vop_frlock)(vnode_t *, int, struct flock64 *, \
+ int, offset_t, \
+ struct flk_callback *, cred_t *, \
+ caller_context_t *); \
+ int (*vop_space)(vnode_t *, int, struct flock64 *, \
+ int, offset_t, \
+ cred_t *, caller_context_t *); \
+ int (*vop_realvp)(vnode_t *, vnode_t **, \
+ caller_context_t *); \
+ int (*vop_getpage)(vnode_t *, offset_t, size_t, uint_t *, \
+ struct page **, size_t, struct seg *, \
+ caddr_t, enum seg_rw, cred_t *, \
+ caller_context_t *); \
+ int (*vop_putpage)(vnode_t *, offset_t, size_t, \
+ int, cred_t *, caller_context_t *); \
+ int (*vop_map)(vnode_t *, offset_t, struct as *, \
+ caddr_t *, size_t, \
+ uchar_t, uchar_t, uint_t, cred_t *, \
+ caller_context_t *); \
+ int (*vop_addmap)(vnode_t *, offset_t, struct as *, \
+ caddr_t, size_t, \
+ uchar_t, uchar_t, uint_t, cred_t *, \
+ caller_context_t *); \
+ int (*vop_delmap)(vnode_t *, offset_t, struct as *, \
+ caddr_t, size_t, \
+ uint_t, uint_t, uint_t, cred_t *, \
+ caller_context_t *); \
+ int (*vop_poll)(vnode_t *, short, int, short *, \
+ struct pollhead **, \
+ caller_context_t *); \
+ int (*vop_dump)(vnode_t *, caddr_t, offset_t, offset_t, \
+ caller_context_t *); \
+ int (*vop_pathconf)(vnode_t *, int, ulong_t *, cred_t *, \
+ caller_context_t *); \
+ int (*vop_pageio)(vnode_t *, struct page *, \
+ u_offset_t, size_t, int, cred_t *, \
+ caller_context_t *); \
+ int (*vop_dumpctl)(vnode_t *, int, offset_t *, \
+ caller_context_t *); \
+ void (*vop_dispose)(vnode_t *, struct page *, \
+ int, int, cred_t *, \
+ caller_context_t *); \
+ int (*vop_setsecattr)(vnode_t *, vsecattr_t *, \
+ int, cred_t *, caller_context_t *); \
+ int (*vop_getsecattr)(vnode_t *, vsecattr_t *, \
+ int, cred_t *, caller_context_t *); \
+ int (*vop_shrlock)(vnode_t *, int, struct shrlock *, \
+ int, cred_t *, caller_context_t *); \
+ int (*vop_vnevent)(vnode_t *, vnevent_t, vnode_t *, \
+ char *, caller_context_t *); \
+ int (*vop_reqzcbuf)(vnode_t *, enum uio_rw, xuio_t *, \
+ cred_t *, caller_context_t *); \
+ int (*vop_retzcbuf)(vnode_t *, xuio_t *, cred_t *, \
+ caller_context_t *)
+ /* NB: No ";" */
+
+/*
+ * Operations on vnodes. Note: File systems must never operate directly
+ * on a 'vnodeops' structure -- it WILL change in future releases! They
+ * must use vn_make_ops() to create the structure.
+ */
+typedef struct vnodeops {
+ const char *vnop_name;
+ VNODE_OPS; /* Signatures of all vnode operations (vops) */
+} vnodeops_t;
+
+typedef int (*fs_generic_func_p) (); /* Generic vop/vfsop/femop/fsemop ptr */
+
+extern int fop_open(vnode_t **, int, cred_t *, caller_context_t *);
+extern int fop_close(vnode_t *, int, int, offset_t, cred_t *,
+ caller_context_t *);
+extern int fop_read(vnode_t *, uio_t *, int, cred_t *, caller_context_t *);
+extern int fop_write(vnode_t *, uio_t *, int, cred_t *,
+ caller_context_t *);
+extern int fop_ioctl(vnode_t *, int, intptr_t, int, cred_t *, int *,
+ caller_context_t *);
+extern int fop_setfl(vnode_t *, int, int, cred_t *, caller_context_t *);
+extern int fop_getattr(vnode_t *, vattr_t *, int, cred_t *,
+ caller_context_t *);
+extern int fop_setattr(vnode_t *, vattr_t *, int, cred_t *,
+ caller_context_t *);
+extern int fop_access(vnode_t *, int, int, cred_t *, caller_context_t *);
+extern int fop_lookup(vnode_t *, char *, vnode_t **, struct pathname *,
+ int, vnode_t *, cred_t *, caller_context_t *,
+ int *, struct pathname *);
+extern int fop_create(vnode_t *, char *, vattr_t *, vcexcl_t, int,
+ vnode_t **, cred_t *, int, caller_context_t *,
+ vsecattr_t *);
+extern int fop_remove(vnode_t *vp, char *, cred_t *, caller_context_t *,
+ int);
+extern int fop_link(vnode_t *, vnode_t *, char *, cred_t *,
+ caller_context_t *, int);
+extern int fop_rename(vnode_t *, char *, vnode_t *, char *, cred_t *,
+ caller_context_t *, int);
+extern int fop_mkdir(vnode_t *, char *, vattr_t *, vnode_t **, cred_t *,
+ caller_context_t *, int, vsecattr_t *);
+extern int fop_rmdir(vnode_t *, char *, vnode_t *, cred_t *,
+ caller_context_t *, int);
+extern int fop_readdir(vnode_t *, uio_t *, cred_t *, int *,
+ caller_context_t *, int);
+extern int fop_symlink(vnode_t *, char *, vattr_t *, char *, cred_t *,
+ caller_context_t *, int);
+extern int fop_readlink(vnode_t *, uio_t *, cred_t *, caller_context_t *);
+extern int fop_fsync(vnode_t *, int, cred_t *, caller_context_t *);
+extern void fop_inactive(vnode_t *, cred_t *, caller_context_t *);
+extern int fop_fid(vnode_t *, struct fid *, caller_context_t *);
+extern int fop_rwlock(vnode_t *, int, caller_context_t *);
+extern void fop_rwunlock(vnode_t *, int, caller_context_t *);
+extern int fop_seek(vnode_t *, offset_t, offset_t *, caller_context_t *);
+extern int fop_cmp(vnode_t *, vnode_t *, caller_context_t *);
+extern int fop_frlock(vnode_t *, int, struct flock64 *, int, offset_t,
+ struct flk_callback *, cred_t *,
+ caller_context_t *);
+extern int fop_space(vnode_t *, int, struct flock64 *, int, offset_t,
+ cred_t *, caller_context_t *);
+extern int fop_realvp(vnode_t *, vnode_t **, caller_context_t *);
+extern int fop_getpage(vnode_t *, offset_t, size_t, uint_t *,
+ struct page **, size_t, struct seg *,
+ caddr_t, enum seg_rw, cred_t *,
+ caller_context_t *);
+extern int fop_putpage(vnode_t *, offset_t, size_t, int, cred_t *,
+ caller_context_t *);
+extern int fop_map(vnode_t *, offset_t, struct as *, caddr_t *, size_t,
+ uchar_t, uchar_t, uint_t, cred_t *cr,
+ caller_context_t *);
+extern int fop_addmap(vnode_t *, offset_t, struct as *, caddr_t, size_t,
+ uchar_t, uchar_t, uint_t, cred_t *,
+ caller_context_t *);
+extern int fop_delmap(vnode_t *, offset_t, struct as *, caddr_t, size_t,
+ uint_t, uint_t, uint_t, cred_t *,
+ caller_context_t *);
+extern int fop_poll(vnode_t *, short, int, short *, struct pollhead **,
+ caller_context_t *);
+extern int fop_dump(vnode_t *, caddr_t, offset_t, offset_t,
+ caller_context_t *);
+extern int fop_pathconf(vnode_t *, int, ulong_t *, cred_t *,
+ caller_context_t *);
+extern int fop_pageio(vnode_t *, struct page *, u_offset_t, size_t, int,
+ cred_t *, caller_context_t *);
+extern int fop_dumpctl(vnode_t *, int, offset_t *, caller_context_t *);
+extern void fop_dispose(vnode_t *, struct page *, int, int, cred_t *,
+ caller_context_t *);
+extern int fop_setsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
+ caller_context_t *);
+extern int fop_getsecattr(vnode_t *, vsecattr_t *, int, cred_t *,
+ caller_context_t *);
+extern int fop_shrlock(vnode_t *, int, struct shrlock *, int, cred_t *,
+ caller_context_t *);
+extern int fop_vnevent(vnode_t *, vnevent_t, vnode_t *, char *,
+ caller_context_t *);
+extern int fop_reqzcbuf(vnode_t *, enum uio_rw, xuio_t *, cred_t *,
+ caller_context_t *);
+extern int fop_retzcbuf(vnode_t *, xuio_t *, cred_t *, caller_context_t *);
+
+#endif /* _KERNEL */
+
+#define VOP_OPEN(vpp, mode, cr, ct) \
+ fop_open(vpp, mode, cr, ct)
+#define VOP_CLOSE(vp, f, c, o, cr, ct) \
+ fop_close(vp, f, c, o, cr, ct)
+#define VOP_READ(vp, uiop, iof, cr, ct) \
+ fop_read(vp, uiop, iof, cr, ct)
+#define VOP_WRITE(vp, uiop, iof, cr, ct) \
+ fop_write(vp, uiop, iof, cr, ct)
+#define VOP_IOCTL(vp, cmd, a, f, cr, rvp, ct) \
+ fop_ioctl(vp, cmd, a, f, cr, rvp, ct)
+#define VOP_SETFL(vp, f, a, cr, ct) \
+ fop_setfl(vp, f, a, cr, ct)
+#define VOP_GETATTR(vp, vap, f, cr, ct) \
+ fop_getattr(vp, vap, f, cr, ct)
+#define VOP_SETATTR(vp, vap, f, cr, ct) \
+ fop_setattr(vp, vap, f, cr, ct)
+#define VOP_ACCESS(vp, mode, f, cr, ct) \
+ fop_access(vp, mode, f, cr, ct)
+#define VOP_LOOKUP(vp, cp, vpp, pnp, f, rdir, cr, ct, defp, rpnp) \
+ fop_lookup(vp, cp, vpp, pnp, f, rdir, cr, ct, defp, rpnp)
+#define VOP_CREATE(dvp, p, vap, ex, mode, vpp, cr, flag, ct, vsap) \
+ fop_create(dvp, p, vap, ex, mode, vpp, cr, flag, ct, vsap)
+#define VOP_REMOVE(dvp, p, cr, ct, f) \
+ fop_remove(dvp, p, cr, ct, f)
+#define VOP_LINK(tdvp, fvp, p, cr, ct, f) \
+ fop_link(tdvp, fvp, p, cr, ct, f)
+#define VOP_RENAME(fvp, fnm, tdvp, tnm, cr, ct, f) \
+ fop_rename(fvp, fnm, tdvp, tnm, cr, ct, f)
+#define VOP_MKDIR(dp, p, vap, vpp, cr, ct, f, vsap) \
+ fop_mkdir(dp, p, vap, vpp, cr, ct, f, vsap)
+#define VOP_RMDIR(dp, p, cdir, cr, ct, f) \
+ fop_rmdir(dp, p, cdir, cr, ct, f)
+#define VOP_READDIR(vp, uiop, cr, eofp, ct, f) \
+ fop_readdir(vp, uiop, cr, eofp, ct, f)
+#define VOP_SYMLINK(dvp, lnm, vap, tnm, cr, ct, f) \
+ fop_symlink(dvp, lnm, vap, tnm, cr, ct, f)
+#define VOP_READLINK(vp, uiop, cr, ct) \
+ fop_readlink(vp, uiop, cr, ct)
+#define VOP_FSYNC(vp, syncflag, cr, ct) \
+ fop_fsync(vp, syncflag, cr, ct)
+#define VOP_INACTIVE(vp, cr, ct) \
+ fop_inactive(vp, cr, ct)
+#define VOP_FID(vp, fidp, ct) \
+ fop_fid(vp, fidp, ct)
+#define VOP_RWLOCK(vp, w, ct) \
+ fop_rwlock(vp, w, ct)
+#define VOP_RWUNLOCK(vp, w, ct) \
+ fop_rwunlock(vp, w, ct)
+#define VOP_SEEK(vp, ooff, noffp, ct) \
+ fop_seek(vp, ooff, noffp, ct)
+#define VOP_CMP(vp1, vp2, ct) \
+ fop_cmp(vp1, vp2, ct)
+#define VOP_FRLOCK(vp, cmd, a, f, o, cb, cr, ct) \
+ fop_frlock(vp, cmd, a, f, o, cb, cr, ct)
+#define VOP_SPACE(vp, cmd, a, f, o, cr, ct) \
+ fop_space(vp, cmd, a, f, o, cr, ct)
+#define VOP_REALVP(vp1, vp2, ct) \
+ fop_realvp(vp1, vp2, ct)
+#define VOP_GETPAGE(vp, of, sz, pr, pl, ps, sg, a, rw, cr, ct) \
+ fop_getpage(vp, of, sz, pr, pl, ps, sg, a, rw, cr, ct)
+#define VOP_PUTPAGE(vp, of, sz, fl, cr, ct) \
+ fop_putpage(vp, of, sz, fl, cr, ct)
+#define VOP_MAP(vp, of, as, a, sz, p, mp, fl, cr, ct) \
+ fop_map(vp, of, as, a, sz, p, mp, fl, cr, ct)
+#define VOP_ADDMAP(vp, of, as, a, sz, p, mp, fl, cr, ct) \
+ fop_addmap(vp, of, as, a, sz, p, mp, fl, cr, ct)
+#define VOP_DELMAP(vp, of, as, a, sz, p, mp, fl, cr, ct) \
+ fop_delmap(vp, of, as, a, sz, p, mp, fl, cr, ct)
+#define VOP_POLL(vp, events, anyyet, reventsp, phpp, ct) \
+ fop_poll(vp, events, anyyet, reventsp, phpp, ct)
+#define VOP_DUMP(vp, addr, bn, count, ct) \
+ fop_dump(vp, addr, bn, count, ct)
+#define VOP_PATHCONF(vp, cmd, valp, cr, ct) \
+ fop_pathconf(vp, cmd, valp, cr, ct)
+#define VOP_PAGEIO(vp, pp, io_off, io_len, flags, cr, ct) \
+ fop_pageio(vp, pp, io_off, io_len, flags, cr, ct)
+#define VOP_DUMPCTL(vp, action, blkp, ct) \
+ fop_dumpctl(vp, action, blkp, ct)
+#define VOP_DISPOSE(vp, pp, flag, dn, cr, ct) \
+ fop_dispose(vp, pp, flag, dn, cr, ct)
+#define VOP_GETSECATTR(vp, vsap, f, cr, ct) \
+ fop_getsecattr(vp, vsap, f, cr, ct)
+#define VOP_SETSECATTR(vp, vsap, f, cr, ct) \
+ fop_setsecattr(vp, vsap, f, cr, ct)
+#define VOP_SHRLOCK(vp, cmd, shr, f, cr, ct) \
+ fop_shrlock(vp, cmd, shr, f, cr, ct)
+#define VOP_VNEVENT(vp, vnevent, dvp, fnm, ct) \
+ fop_vnevent(vp, vnevent, dvp, fnm, ct)
+#define VOP_REQZCBUF(vp, rwflag, xuiop, cr, ct) \
+ fop_reqzcbuf(vp, rwflag, xuiop, cr, ct)
+#define VOP_RETZCBUF(vp, xuiop, cr, ct) \
+ fop_retzcbuf(vp, xuiop, cr, ct)
+
+#define VOPNAME_OPEN "open"
+#define VOPNAME_CLOSE "close"
+#define VOPNAME_READ "read"
+#define VOPNAME_WRITE "write"
+#define VOPNAME_IOCTL "ioctl"
+#define VOPNAME_SETFL "setfl"
+#define VOPNAME_GETATTR "getattr"
+#define VOPNAME_SETATTR "setattr"
+#define VOPNAME_ACCESS "access"
+#define VOPNAME_LOOKUP "lookup"
+#define VOPNAME_CREATE "create"
+#define VOPNAME_REMOVE "remove"
+#define VOPNAME_LINK "link"
+#define VOPNAME_RENAME "rename"
+#define VOPNAME_MKDIR "mkdir"
+#define VOPNAME_RMDIR "rmdir"
+#define VOPNAME_READDIR "readdir"
+#define VOPNAME_SYMLINK "symlink"
+#define VOPNAME_READLINK "readlink"
+#define VOPNAME_FSYNC "fsync"
+#define VOPNAME_INACTIVE "inactive"
+#define VOPNAME_FID "fid"
+#define VOPNAME_RWLOCK "rwlock"
+#define VOPNAME_RWUNLOCK "rwunlock"
+#define VOPNAME_SEEK "seek"
+#define VOPNAME_CMP "cmp"
+#define VOPNAME_FRLOCK "frlock"
+#define VOPNAME_SPACE "space"
+#define VOPNAME_REALVP "realvp"
+#define VOPNAME_GETPAGE "getpage"
+#define VOPNAME_PUTPAGE "putpage"
+#define VOPNAME_MAP "map"
+#define VOPNAME_ADDMAP "addmap"
+#define VOPNAME_DELMAP "delmap"
+#define VOPNAME_POLL "poll"
+#define VOPNAME_DUMP "dump"
+#define VOPNAME_PATHCONF "pathconf"
+#define VOPNAME_PAGEIO "pageio"
+#define VOPNAME_DUMPCTL "dumpctl"
+#define VOPNAME_DISPOSE "dispose"
+#define VOPNAME_GETSECATTR "getsecattr"
+#define VOPNAME_SETSECATTR "setsecattr"
+#define VOPNAME_SHRLOCK "shrlock"
+#define VOPNAME_VNEVENT "vnevent"
+#define VOPNAME_REQZCBUF "reqzcbuf"
+#define VOPNAME_RETZCBUF "retzcbuf"
+
+/*
+ * Flags for VOP_LOOKUP
+ *
+ * Defined in file.h, but also possible, FIGNORECASE and FSEARCH
+ *
+ */
+#define LOOKUP_DIR 0x01 /* want parent dir vp */
+#define LOOKUP_XATTR 0x02 /* lookup up extended attr dir */
+#define CREATE_XATTR_DIR 0x04 /* Create extended attr dir */
+#define LOOKUP_HAVE_SYSATTR_DIR 0x08 /* Already created virtual GFS dir */
+
+/*
+ * Flags for VOP_READDIR
+ */
+#define V_RDDIR_ENTFLAGS 0x01 /* request dirent flags */
+#define V_RDDIR_ACCFILTER 0x02 /* filter out inaccessible dirents */
+
+/*
+ * Flags for VOP_RWLOCK/VOP_RWUNLOCK
+ * VOP_RWLOCK will return the flag that was actually set, or -1 if none.
+ */
+#define V_WRITELOCK_TRUE (1) /* Request write-lock on the vnode */
+#define V_WRITELOCK_FALSE (0) /* Request read-lock on the vnode */
+
+/*
+ * Flags for VOP_DUMPCTL
+ */
+#define DUMP_ALLOC 0
+#define DUMP_FREE 1
+#define DUMP_SCAN 2
+
+/*
+ * Public vnode manipulation functions.
+ */
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+
+vnode_t *vn_alloc(int);
+void vn_reinit(vnode_t *);
+void vn_recycle(vnode_t *);
+void vn_free(vnode_t *);
+
+int vn_is_readonly(vnode_t *);
+int vn_is_opened(vnode_t *, v_mode_t);
+int vn_is_mapped(vnode_t *, v_mode_t);
+int vn_has_other_opens(vnode_t *, v_mode_t);
+void vn_open_upgrade(vnode_t *, int);
+void vn_open_downgrade(vnode_t *, int);
+
+int vn_can_change_zones(vnode_t *vp);
+
+int vn_has_flocks(vnode_t *);
+int vn_has_mandatory_locks(vnode_t *, int);
+int vn_has_cached_data(vnode_t *);
+
+void vn_setops(vnode_t *, vnodeops_t *);
+vnodeops_t *vn_getops(vnode_t *);
+int vn_matchops(vnode_t *, vnodeops_t *);
+int vn_matchopval(vnode_t *, char *, fs_generic_func_p);
+int vn_ismntpt(vnode_t *);
+
+struct vfs *vn_mountedvfs(vnode_t *);
+
+int vn_in_dnlc(vnode_t *);
+
+void vn_create_cache(void);
+void vn_destroy_cache(void);
+
+void vn_freevnodeops(vnodeops_t *);
+
+int vn_open(char *pnamep, enum uio_seg seg, int filemode, int createmode,
+ struct vnode **vpp, enum create crwhy, mode_t umask);
+int vn_openat(char *pnamep, enum uio_seg seg, int filemode, int createmode,
+ struct vnode **vpp, enum create crwhy,
+ mode_t umask, struct vnode *startvp, int fd);
+int vn_create(char *pnamep, enum uio_seg seg, struct vattr *vap,
+ enum vcexcl excl, int mode, struct vnode **vpp,
+ enum create why, int flag, mode_t umask);
+int vn_createat(char *pnamep, enum uio_seg seg, struct vattr *vap,
+ enum vcexcl excl, int mode, struct vnode **vpp,
+ enum create why, int flag, mode_t umask, struct vnode *startvp);
+int vn_rdwr(enum uio_rw rw, struct vnode *vp, caddr_t base, ssize_t len,
+ offset_t offset, enum uio_seg seg, int ioflag, rlim64_t ulimit,
+ cred_t *cr, ssize_t *residp);
+
+void vn_hold(struct vnode *vp);
+void vn_rele(struct vnode *vp);
+void vn_rele_async(struct vnode *vp, struct taskq *taskq);
+void vn_rele_dnlc(struct vnode *vp);
+void vn_rele_stream(struct vnode *vp);
+int vn_link(char *from, char *to, enum uio_seg seg);
+int vn_linkat(vnode_t *fstartvp, char *from, enum symfollow follow,
+ vnode_t *tstartvp, char *to, enum uio_seg seg);
+int vn_rename(char *from, char *to, enum uio_seg seg);
+int vn_renameat(vnode_t *fdvp, char *fname, vnode_t *tdvp, char *tname,
+ enum uio_seg seg);
+int vn_remove(char *fnamep, enum uio_seg seg, enum rm dirflag);
+int vn_removeat(vnode_t *startvp, char *fnamep, enum uio_seg seg,
+ enum rm dirflag);
+int vn_compare(vnode_t *vp1, vnode_t *vp2);
+int vn_vfswlock(struct vnode *vp);
+int vn_vfswlock_wait(struct vnode *vp);
+int vn_vfsrlock(struct vnode *vp);
+int vn_vfsrlock_wait(struct vnode *vp);
+void vn_vfsunlock(struct vnode *vp);
+int vn_vfswlock_held(struct vnode *vp);
+vnode_t *specvp(struct vnode *vp, dev_t dev, vtype_t type, struct cred *cr);
+vnode_t *makespecvp(dev_t dev, vtype_t type);
+
+#if defined(_KERNEL)
+vn_vfslocks_entry_t *vn_vfslocks_getlock(void *);
+void vn_vfslocks_rele(vn_vfslocks_entry_t *);
+#endif
+
+boolean_t vn_is_reparse(vnode_t *, cred_t *, caller_context_t *);
+
+void vn_copypath(struct vnode *src, struct vnode *dst);
+void vn_setpath_str(struct vnode *vp, const char *str, size_t len);
+void vn_setpath(vnode_t *rootvp, struct vnode *startvp, struct vnode *vp,
+ const char *path, size_t plen);
+void vn_renamepath(vnode_t *dvp, vnode_t *vp, const char *nm, size_t len);
+
+/* Vnode event notification */
+void vnevent_rename_src(vnode_t *, vnode_t *, char *, caller_context_t *);
+void vnevent_rename_dest(vnode_t *, vnode_t *, char *, caller_context_t *);
+void vnevent_remove(vnode_t *, vnode_t *, char *, caller_context_t *);
+void vnevent_rmdir(vnode_t *, vnode_t *, char *, caller_context_t *);
+void vnevent_create(vnode_t *, caller_context_t *);
+void vnevent_link(vnode_t *, caller_context_t *);
+void vnevent_rename_dest_dir(vnode_t *, caller_context_t *ct);
+void vnevent_mountedover(vnode_t *, caller_context_t *);
+void vnevent_truncate(vnode_t *, caller_context_t *);
+int vnevent_support(vnode_t *, caller_context_t *);
+
+/* Vnode specific data */
+void vsd_create(uint_t *, void (*)(void *));
+void vsd_destroy(uint_t *);
+void *vsd_get(vnode_t *, uint_t);
+int vsd_set(vnode_t *, uint_t, void *);
+void vsd_free(vnode_t *);
+
+/*
+ * Extensible vnode attribute (xva) routines:
+ * xva_init() initializes an xvattr_t (zero struct, init mapsize, set AT_XATTR)
+ * xva_getxoptattr() returns a ponter to the xoptattr_t section of xvattr_t
+ */
+void xva_init(xvattr_t *);
+xoptattr_t *xva_getxoptattr(xvattr_t *); /* Get ptr to xoptattr_t */
+
+void xattr_init(void); /* Initialize vnodeops for xattrs */
+
+/* GFS tunnel for xattrs */
+int xattr_dir_lookup(vnode_t *, vnode_t **, int, cred_t *);
+
+/* Reparse Point */
+void reparse_point_init(void);
+
+/* Context identification */
+u_longlong_t fs_new_caller_id();
+
+int vn_vmpss_usepageio(vnode_t *);
+
+/*
+ * Needed for use of IS_VMODSORT() in kernel.
+ */
+extern uint_t pvn_vmodsort_supported;
+
+#define VN_HOLD(vp) { \
+ vn_hold(vp); \
+}
+
+#define VN_RELE(vp) { \
+ vn_rele(vp); \
+}
+
+#define VN_RELE_ASYNC(vp, taskq) { \
+ vn_rele_async(vp, taskq); \
+}
+
+#define VN_SET_VFS_TYPE_DEV(vp, vfsp, type, dev) { \
+ (vp)->v_vfsp = (vfsp); \
+ (vp)->v_type = (type); \
+ (vp)->v_rdev = (dev); \
+}
+
+/*
+ * Compare two vnodes for equality. In general this macro should be used
+ * in preference to calling VOP_CMP directly.
+ */
+#if defined(_FAKE_KERNEL)
+#define VN_CMP(VP1, VP2) \
+ (((VP1) == (VP2)) ? 1 : VOP_CMP(VP1, VP2, NULL))
+#else
+#define VN_CMP(VP1, VP2) ((VP1) == (VP2) ? 1 : \
+ ((VP1) && (VP2) && (vn_getops(VP1) == vn_getops(VP2)) ? \
+ VOP_CMP(VP1, VP2, NULL) : 0))
+#endif
+
+/*
+ * Some well-known global vnodes used by the VM system to name pages.
+ */
+extern struct vnode kvps[];
+
+typedef enum {
+ KV_KVP, /* vnode for all segkmem pages */
+ KV_ZVP, /* vnode for all ZFS pages */
+#if defined(__sparc)
+ KV_MPVP, /* vnode for all page_t meta-pages */
+ KV_PROMVP, /* vnode for all PROM pages */
+#endif /* __sparc */
+ KV_MAX /* total number of vnodes in kvps[] */
+} kvps_index_t;
+
+#define VN_ISKAS(vp) ((vp) >= &kvps[0] && (vp) < &kvps[KV_MAX])
+
+#endif /* _KERNEL */
+
+/*
+ * Flags to VOP_SETATTR/VOP_GETATTR.
+ */
+#define ATTR_UTIME 0x01 /* non-default utime(2) request */
+#define ATTR_EXEC 0x02 /* invocation from exec(2) */
+#define ATTR_COMM 0x04 /* yield common vp attributes */
+#define ATTR_HINT 0x08 /* information returned will be `hint' */
+#define ATTR_REAL 0x10 /* yield attributes of the real vp */
+#define ATTR_NOACLCHECK 0x20 /* Don't check ACL when checking permissions */
+#define ATTR_TRIGGER 0x40 /* Mount first if vnode is a trigger mount */
+/*
+ * Generally useful macros.
+ */
+#define VBSIZE(vp) ((vp)->v_vfsp->vfs_bsize)
+
+#define VTOZONE(vp) ((vp)->v_vfsp->vfs_zone)
+
+#define NULLVP ((struct vnode *)0)
+#define NULLVPP ((struct vnode **)0)
+
+#ifdef _KERNEL
+
+/*
+ * Structure used while handling asynchronous VOP_PUTPAGE operations.
+ */
+struct async_reqs {
+ struct async_reqs *a_next; /* pointer to next arg struct */
+ struct vnode *a_vp; /* vnode pointer */
+ u_offset_t a_off; /* offset in file */
+ uint_t a_len; /* size of i/o request */
+ int a_flags; /* flags to indicate operation type */
+ struct cred *a_cred; /* cred pointer */
+ ushort_t a_prealloced; /* set if struct is pre-allocated */
+};
+
+/*
+ * VN_DISPOSE() -- given a page pointer, safely invoke VOP_DISPOSE().
+ * Note that there is no guarantee that the page passed in will be
+ * freed. If that is required, then a check after calling VN_DISPOSE would
+ * be necessary to ensure the page was freed.
+ */
+#define VN_DISPOSE(pp, flag, dn, cr) { \
+ if ((pp)->p_vnode != NULL && !VN_ISKAS((pp)->p_vnode)) \
+ VOP_DISPOSE((pp)->p_vnode, (pp), (flag), (dn), (cr), NULL); \
+ else if ((flag) == B_FREE) \
+ page_free((pp), (dn)); \
+ else \
+ page_destroy((pp), (dn)); \
+ }
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_VNODE_H */
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/vncache.c b/usr/src/lib/smbsrv/libfksmbsrv/common/vncache.c
new file mode 100644
index 0000000000..7349abef2f
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/vncache.c
@@ -0,0 +1,322 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/cmn_err.h>
+#include <sys/cred.h>
+#include <sys/debug.h>
+#include <sys/errno.h>
+#include <sys/t_lock.h>
+#include <sys/user.h>
+#include <sys/uio.h>
+#include <sys/file.h>
+#include <sys/pathname.h>
+#include <sys/sysmacros.h>
+#include <sys/vfs.h>
+#include <sys/vnode.h>
+#include <sys/avl.h>
+#include <sys/stat.h>
+#include <sys/mode.h>
+
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "vncache.h"
+
+kmem_cache_t *vn_cache;
+
+/*
+ * You can dump this AVL tree with mdb, i.e.
+ * vncache_avl ::walk avl |::print -s1 vnode_t
+ */
+avl_tree_t vncache_avl;
+kmutex_t vncache_lock;
+
+/*
+ * Vnode cache.
+ */
+
+/* ARGSUSED */
+static int
+vn_cache_constructor(void *buf, void *cdrarg, int kmflags)
+{
+ struct vnode *vp;
+
+ vp = buf;
+ bzero(vp, sizeof (*vp));
+
+ mutex_init(&vp->v_lock, NULL, MUTEX_DEFAULT, NULL);
+ vp->v_fd = -1;
+
+ return (0);
+}
+
+/* ARGSUSED */
+static void
+vn_cache_destructor(void *buf, void *cdrarg)
+{
+ struct vnode *vp;
+
+ vp = buf;
+
+ mutex_destroy(&vp->v_lock);
+}
+
+/*
+ * Used by file systems when fs-specific nodes (e.g., ufs inodes) are
+ * cached by the file system and vnodes remain associated.
+ */
+void
+vn_recycle(vnode_t *vp)
+{
+
+ ASSERT(vp->v_fd == -1);
+
+ vp->v_rdcnt = 0;
+ vp->v_wrcnt = 0;
+
+ if (vp->v_path) {
+ strfree(vp->v_path);
+ vp->v_path = NULL;
+ }
+}
+
+
+/*
+ * Used to reset the vnode fields including those that are directly accessible
+ * as well as those which require an accessor function.
+ *
+ * Does not initialize:
+ * synchronization objects: v_lock, v_vsd_lock, v_nbllock, v_cv
+ * v_data (since FS-nodes and vnodes point to each other and should
+ * be updated simultaneously)
+ * v_op (in case someone needs to make a VOP call on this object)
+ */
+void
+vn_reinit(vnode_t *vp)
+{
+ vp->v_count = 1;
+ vp->v_vfsp = NULL;
+ vp->v_stream = NULL;
+ vp->v_flag = 0;
+ vp->v_type = VNON;
+ vp->v_rdev = NODEV;
+
+ vn_recycle(vp);
+}
+
+vnode_t *
+vn_alloc(int kmflag)
+{
+ vnode_t *vp;
+
+ vp = kmem_cache_alloc(vn_cache, kmflag);
+
+ if (vp != NULL) {
+ vn_reinit(vp);
+ }
+
+ return (vp);
+}
+
+void
+vn_free(vnode_t *vp)
+{
+
+ /*
+ * Some file systems call vn_free() with v_count of zero,
+ * some with v_count of 1. In any case, the value should
+ * never be anything else.
+ */
+ ASSERT((vp->v_count == 0) || (vp->v_count == 1));
+ if (vp->v_path != NULL) {
+ strfree(vp->v_path);
+ vp->v_path = NULL;
+ }
+ ASSERT(vp->v_fd != -1);
+ (void) close(vp->v_fd);
+ vp->v_fd = -1;
+
+ kmem_cache_free(vn_cache, vp);
+}
+
+int
+vncache_cmp(const void *v1, const void *v2)
+{
+ const vnode_t *vp1, *vp2;
+
+ vp1 = v1;
+ vp2 = v2;
+
+ if (vp1->v_st_dev < vp2->v_st_dev)
+ return (-1);
+ if (vp1->v_st_dev > vp2->v_st_dev)
+ return (+1);
+ if (vp1->v_st_ino < vp2->v_st_ino)
+ return (-1);
+ if (vp1->v_st_ino > vp2->v_st_ino)
+ return (+1);
+
+ return (0);
+}
+
+vnode_t *
+vncache_lookup(struct stat *st)
+{
+ vnode_t tmp_vn;
+ vnode_t *vp;
+
+ tmp_vn.v_st_dev = st->st_dev;
+ tmp_vn.v_st_ino = st->st_ino;
+
+ mutex_enter(&vncache_lock);
+ vp = avl_find(&vncache_avl, &tmp_vn, NULL);
+ if (vp != NULL)
+ vn_hold(vp);
+ mutex_exit(&vncache_lock);
+
+ return (vp);
+}
+
+vnode_t *
+vncache_enter(struct stat *st, vnode_t *dvp, char *name, int fd)
+{
+ vnode_t *old_vp;
+ vnode_t *new_vp;
+ vfs_t *vfs;
+ char *vpath;
+ avl_index_t where;
+ int len;
+
+ /*
+ * Fill in v_path
+ * Note: fsop_root() calls with dvp=NULL
+ */
+ len = strlen(name) + 1;
+ if (dvp == NULL) {
+ vpath = kmem_alloc(len, KM_SLEEP);
+ (void) strlcpy(vpath, name, len);
+ vfs = rootvfs;
+ } else {
+ /* add to length for parent path + "/" */
+ len += (strlen(dvp->v_path) + 1);
+ vpath = kmem_alloc(len, KM_SLEEP);
+ (void) snprintf(vpath, len, "%s/%s", dvp->v_path, name);
+ vfs = dvp->v_vfsp;
+ }
+
+ new_vp = vn_alloc(KM_SLEEP);
+ new_vp->v_path = vpath;
+ new_vp->v_fd = fd;
+ new_vp->v_st_dev = st->st_dev;
+ new_vp->v_st_ino = st->st_ino;
+ new_vp->v_vfsp = vfs;
+ new_vp->v_type = IFTOVT(st->st_mode);
+
+ mutex_enter(&vncache_lock);
+ old_vp = avl_find(&vncache_avl, new_vp, &where);
+ if (old_vp != NULL)
+ vn_hold(old_vp);
+ else
+ avl_insert(&vncache_avl, new_vp, where);
+ mutex_exit(&vncache_lock);
+
+ /* If we lost the race, free new_vp */
+ if (old_vp != NULL) {
+ vn_free(new_vp);
+ return (old_vp);
+ }
+
+ return (new_vp);
+}
+
+/*
+ * Called after a successful rename to update v_path
+ */
+void
+vncache_renamed(vnode_t *vp, vnode_t *to_dvp, char *to_name)
+{
+ char *vpath;
+ char *ovpath;
+ int len;
+
+ len = strlen(to_name) + 1;
+ /* add to length for parent path + "/" */
+ len += (strlen(to_dvp->v_path) + 1);
+ vpath = kmem_alloc(len, KM_SLEEP);
+ (void) snprintf(vpath, len, "%s/%s", to_dvp->v_path, to_name);
+
+ mutex_enter(&vncache_lock);
+ ovpath = vp->v_path;
+ vp->v_path = vpath;
+ mutex_exit(&vncache_lock);
+
+ strfree(ovpath);
+}
+
+/*
+ * Last reference to this vnode is (possibly) going away.
+ * This is normally called by vn_rele() when v_count==1.
+ * Note that due to lock order concerns, we have to take
+ * the vncache_lock (for the avl tree) and then recheck
+ * v_count, which might have gained a ref during the time
+ * we did not hold vp->v_lock.
+ */
+void
+vncache_inactive(vnode_t *vp)
+{
+ uint_t count;
+
+ mutex_enter(&vncache_lock);
+ mutex_enter(&vp->v_lock);
+
+ if ((count = vp->v_count) <= 1) {
+ /* This is (still) the last ref. */
+ avl_remove(&vncache_avl, vp);
+ }
+
+ mutex_exit(&vp->v_lock);
+ mutex_exit(&vncache_lock);
+
+ if (count <= 1) {
+ vn_free(vp);
+ }
+}
+
+#pragma init(vncache_init)
+int
+vncache_init(void)
+{
+ vn_cache = kmem_cache_create("vn_cache", sizeof (struct vnode),
+ VNODE_ALIGN, vn_cache_constructor, vn_cache_destructor, NULL, NULL,
+ NULL, 0);
+ avl_create(&vncache_avl,
+ vncache_cmp,
+ sizeof (vnode_t),
+ offsetof(vnode_t, v_avl_node));
+ mutex_init(&vncache_lock, NULL, MUTEX_DEFAULT, NULL);
+ return (0);
+}
+
+#pragma fini(vncache_fini)
+void
+vncache_fini(void)
+{
+ mutex_destroy(&vncache_lock);
+ avl_destroy(&vncache_avl);
+ kmem_cache_destroy(vn_cache);
+}
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/vncache.h b/usr/src/lib/smbsrv/libfksmbsrv/common/vncache.h
new file mode 100644
index 0000000000..885aa5244b
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/common/vncache.h
@@ -0,0 +1,37 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _VNCACHE_H
+#define _VNCACHE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct stat;
+vnode_t *vncache_lookup(struct stat *);
+vnode_t *vncache_enter(struct stat *, vnode_t *, char *, int);
+void vncache_renamed(vnode_t *, vnode_t *, char *);
+void vncache_inactive(vnode_t *);
+int vncache_cmp(const void *, const void *);
+
+int vncache_init(void);
+void vncache_fini(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _VNCACHE_H */
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/i386/Makefile b/usr/src/lib/smbsrv/libfksmbsrv/i386/Makefile
new file mode 100644
index 0000000000..600e5596ba
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/i386/Makefile
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/sparc/Makefile b/usr/src/lib/smbsrv/libfksmbsrv/sparc/Makefile
new file mode 100644
index 0000000000..600e5596ba
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/sparc/Makefile
@@ -0,0 +1,30 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT)
diff --git a/usr/src/lib/smbsrv/libfksmbsrv/sparcv9/Makefile b/usr/src/lib/smbsrv/libfksmbsrv/sparcv9/Makefile
new file mode 100644
index 0000000000..5760fd3b1e
--- /dev/null
+++ b/usr/src/lib/smbsrv/libfksmbsrv/sparcv9/Makefile
@@ -0,0 +1,35 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+#
+
+MACH_LDLIBS += -L$(ROOT)/usr/lib/smbsrv/$(MACH64)
+
+include ../Makefile.com
+include ../../../Makefile.lib.64
+
+sparcv9_C_PICFLAGS= $(sparcv9_C_BIGPICFLAGS)
+
+install: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64)
diff --git a/usr/src/lib/smbsrv/libmlsvc/Makefile.com b/usr/src/lib/smbsrv/libmlsvc/Makefile.com
index f00731b1c0..151a1e8337 100644
--- a/usr/src/lib/smbsrv/libmlsvc/Makefile.com
+++ b/usr/src/lib/smbsrv/libmlsvc/Makefile.com
@@ -19,8 +19,8 @@
# CDDL HEADER END
#
#
-# Copyright 2012 Nexenta Systems, Inc. All rights reserved.
# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
#
LIBRARY = libmlsvc.a
@@ -87,6 +87,7 @@ LDLIBS += -lmlrpc -lsmb -lsmbns -lshare -lsmbfs -lresolv -lnsl -lpkcs11 \
-lscf -lcmdutils -lsec -lavl -lnvpair -luutil -luuid -lgen -lzfs -lc
CPPFLAGS += $(INCS) -D_REENTRANT
+CPPFLAGS += -Dsyslog=smb_syslog
$(ENABLE_SMB_PRINTING) CPPFLAGS += -DHAVE_CUPS
CERRWARN += -_gcc=-Wno-unused-function
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c
index 45973ab820..18d5bd18b0 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/mlsvc_util.c
@@ -35,6 +35,7 @@
#include <stdlib.h>
#include <sys/time.h>
#include <sys/systm.h>
+#include <note.h>
#include <syslog.h>
#include <smbsrv/libsmb.h>
diff --git a/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c b/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c
index 5accb7cc75..5c1bba93cf 100644
--- a/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c
+++ b/usr/src/lib/smbsrv/libmlsvc/common/spoolss_svc.c
@@ -29,6 +29,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/utsname.h>
+#include <sys/atomic.h>
#include <unistd.h>
#include <stdlib.h>
#include <strings.h>
diff --git a/usr/src/lib/smbsrv/libsmb/Makefile.com b/usr/src/lib/smbsrv/libsmb/Makefile.com
index bc371d4807..0c972a66f0 100644
--- a/usr/src/lib/smbsrv/libsmb/Makefile.com
+++ b/usr/src/lib/smbsrv/libsmb/Makefile.com
@@ -20,7 +20,7 @@
#
#
# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
#
LIBRARY= libsmb.a
@@ -29,7 +29,6 @@ VERS= .1
OBJS_SHARED = \
smb_door_legacy.o \
smb_inet.o \
- smb_match.o \
smb_msgbuf.o \
smb_native.o \
smb_oem.o \
@@ -64,6 +63,7 @@ OBJS_COMMON = \
smb_scfutil.o \
smb_sd.o \
smb_status_tbl.o \
+ smb_syslog.o \
smb_util.o \
smb_wksids.o
@@ -75,12 +75,14 @@ include ../../Makefile.lib
INCS += -I$(SRC)/common/smbsrv
LINTCHECKFLAGS += -erroff=E_INCONS_ARG_DECL2
+LINTCHECKFLAGS += -erroff=E_BAD_FORMAT_STR2
LDLIBS += $(MACH_LDLIBS)
LDLIBS += -lscf -lmd -luuid -lpkcs11 -lcryptoutil
LDLIBS += -lsec -lidmap -lnsl -lsocket -lresolv
LDLIBS += -lreparse -lnvpair -lcmdutils -lavl -lc
CPPFLAGS += $(INCS) -D_REENTRANT
+CPPFLAGS += -Dsyslog=smb_syslog
CERRWARN += -_gcc=-Wno-uninitialized
CERRWARN += -_gcc=-Wno-char-subscripts
CERRWARN += -_gcc=-Wno-switch
diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h
index 36a63e719b..7c5f88976a 100644
--- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h
+++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h
@@ -35,15 +35,14 @@ extern "C" {
#include <sys/list.h>
#include <sys/avl.h>
#include <arpa/inet.h>
-#include <net/if.h>
-#include <inet/tcp.h>
-#include <uuid/uuid.h>
+#include <net/if.h> /* LIFNAMSIZ */
#include <netdb.h>
#include <stdlib.h>
#include <libscf.h>
#include <libshare.h>
#include <uuid/uuid.h>
#include <synch.h>
+#include <stdarg.h>
#include <smbsrv/string.h>
#include <smbsrv/smb_idmap.h>
@@ -191,6 +190,7 @@ extern int smb_config_setnum(smb_cfg_id_t, int64_t);
extern int smb_config_setbool(smb_cfg_id_t, boolean_t);
extern boolean_t smb_config_get_ads_enable(void);
+extern int smb_config_get_debug(void);
extern uint8_t smb_config_get_fg_flag(void);
extern char *smb_config_get_localsid(void);
extern int smb_config_secmode_fromstr(char *);
@@ -292,6 +292,8 @@ void smb_tracef(const char *fmt, ...);
const char *xlate_nt_status(unsigned int);
+void libsmb_redirect_syslog(__FILE_TAG *fp, int priority);
+
/*
* Authentication
*/
@@ -995,37 +997,9 @@ int smb_reparse_svcget(const char *, const char *, char **);
uint32_t smb_get_txid(void);
-#define SMB_LOG_LINE_SZ 256
-
-typedef uint32_t smb_log_hdl_t;
-
-typedef struct smb_log_item {
- list_node_t li_lnd;
- char li_msg[SMB_LOG_LINE_SZ];
-} smb_log_item_t;
-
-typedef struct smb_log {
- smb_log_hdl_t l_handle;
- int l_cnt;
- int l_max_cnt;
- mutex_t l_mtx;
- list_t l_list;
- char l_file[MAXPATHLEN];
-} smb_log_t;
-
-typedef struct smb_loglist_item {
- list_node_t lli_lnd;
- smb_log_t lli_log;
-} smb_loglist_item_t;
-
-typedef struct smb_loglist {
- mutex_t ll_mtx;
- list_t ll_list;
-} smb_loglist_t;
-
-smb_log_hdl_t smb_log_create(int, char *);
-void smb_log(smb_log_hdl_t, int, const char *, ...);
-void smb_log_dumpall(void);
+void smb_syslog(int, const char *, ...);
+void smb_vsyslog(int, const char *, va_list ap);
+char *smb_syslog_fmt_m(char *, int, const char *, int);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
index 4d2fc95e9b..3570d05ba4 100644
--- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
+++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers
@@ -19,7 +19,7 @@
#
#
# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
-# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
#
#
@@ -99,6 +99,7 @@ SYMBOL_VERSION SUNWprivate {
smb_common_encode;
smb_config_get;
smb_config_get_ads_enable;
+ smb_config_get_debug;
smb_config_get_execinfo;
smb_config_get_fg_flag;
smb_config_get_localsid;
@@ -217,7 +218,7 @@ SYMBOL_VERSION SUNWprivate {
smb_isupper;
smb_isstrlwr;
smb_isstrupr;
- smb_kmod_bind;
+ smb_kmod_bind { FLAGS = NODIRECT };
smb_kmod_enum;
smb_kmod_enum_init;
smb_kmod_enum_fini;
@@ -225,15 +226,16 @@ SYMBOL_VERSION SUNWprivate {
smb_kmod_file_close;
smb_kmod_get_open_num;
smb_kmod_get_spool_doc;
- smb_kmod_isbound;
+ smb_kmod_ioctl { FLAGS = NODIRECT };
+ smb_kmod_isbound { FLAGS = NODIRECT };
smb_kmod_session_close;
smb_kmod_setcfg;
smb_kmod_setgmtoff;
smb_kmod_share;
smb_kmod_shareinfo;
- smb_kmod_start;
- smb_kmod_stop;
- smb_kmod_unbind;
+ smb_kmod_start { FLAGS = NODIRECT };
+ smb_kmod_stop { FLAGS = NODIRECT };
+ smb_kmod_unbind { FLAGS = NODIRECT };
smb_kmod_unshare;
smb_join;
smb_lgrp_add;
@@ -258,11 +260,9 @@ SYMBOL_VERSION SUNWprivate {
smb_lgrp_stop;
smb_lgrp_strerror;
smb_load_kconfig;
- smb_log;
- smb_log_create;
- smb_log_dumpall;
smb_logon_decode;
smb_logon_free;
+ smb_logon_xdr;
smb_lookup_name;
smb_lookup_sid;
smb_mac_chk;
@@ -270,7 +270,6 @@ SYMBOL_VERSION SUNWprivate {
smb_mac_inc_seqnum;
smb_mac_init;
smb_mac_sign;
- smb_match;
smb_match_netlogon_seqnum;
smb_mbstos;
smb_mbstowcs;
@@ -300,6 +299,7 @@ SYMBOL_VERSION SUNWprivate {
smb_netfileinfo_encode;
smb_netuserinfo_decode;
smb_netuserinfo_encode;
+ smb_netuserinfo_xdr;
smb_nic_addhost;
smb_nic_delhost;
smb_nic_is_local;
@@ -383,17 +383,21 @@ SYMBOL_VERSION SUNWprivate {
smb_string_xdr;
smb_strlwr;
smb_strupr;
+ smb_syslog { FLAGS = NODIRECT };
+ smb_syslog_fmt_m;
smb_tolower;
smb_toupper;
smb_token_encode;
smb_token_query_privilege;
smb_token_valid;
+ smb_token_xdr;
smb_tonetbiosname;
- smb_trace;
- smb_tracef;
+ smb_trace { FLAGS = NODIRECT };
+ smb_tracef { FLAGS = NODIRECT };
smb_unc_free;
smb_unc_init;
smb_update_netlogon_seqnum;
+ smb_vsyslog { FLAGS = NODIRECT };
smb_wcequiv_strlen;
smb_wcstombs;
smb_wctomb;
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c
index 94d36e6c3b..08ab3376be 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_cfg.c
@@ -135,7 +135,7 @@ static smb_cfg_param_t smb_cfg_table[] =
{SMB_CI_UNMAP, "unmap", SCF_TYPE_ASTRING, SMB_CF_EXEC},
{SMB_CI_DISPOSITION, "disposition", SCF_TYPE_ASTRING, SMB_CF_EXEC},
{SMB_CI_DFS_STDROOT_NUM, "dfs_stdroot_num", SCF_TYPE_INTEGER, 0},
- {SMB_CI_TRAVERSE_MOUNTS, "traverse_mounts", SCF_TYPE_BOOLEAN, 0}
+ {SMB_CI_TRAVERSE_MOUNTS, "traverse_mounts", SCF_TYPE_BOOLEAN, 0},
/* SMB_CI_MAX */
};
@@ -712,6 +712,36 @@ smb_config_set(smb_cfg_id_t id, char *value)
return (SMBD_SMF_INVALID_ARG);
}
+
+int
+smb_config_get_debug()
+{
+ int64_t val64;
+ int val = 0; /* default */
+ smb_scfhandle_t *handle = NULL;
+
+ handle = smb_smf_scf_init(SMBD_FMRI_PREFIX);
+ if (handle == NULL) {
+ return (val);
+ }
+
+ if (smb_smf_create_service_pgroup(handle,
+ SMBD_PG_NAME) != SMBD_SMF_OK) {
+ smb_smf_scf_fini(handle);
+ return (val);
+ }
+
+ if (smb_smf_get_integer_property(handle, "debug", &val64) != 0) {
+ smb_smf_scf_fini(handle);
+ return (val);
+ }
+ val = (int)val64;
+
+ smb_smf_scf_fini(handle);
+
+ return (val);
+}
+
uint8_t
smb_config_get_fg_flag()
{
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c b/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c
index 23e4d311e1..97b4bef60e 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_doorclnt.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#include <assert.h>
@@ -124,8 +125,11 @@ smb_join(smb_joininfo_t *jdi)
&status, xdr_uint32_t);
if (rc != 0) {
+ /*
+ * This usually means the SMB service is not running.
+ */
syslog(LOG_DEBUG, "smb_join: %m");
- status = NT_STATUS_INTERNAL_ERROR;
+ status = NT_STATUS_SERVER_DISABLED;
}
return (status);
@@ -260,6 +264,7 @@ smb_door_call(uint32_t cmd, void *req_data, xdrproc_t req_xdr,
smb_doorarg_t da;
int fd;
int rc;
+ char *door_name;
bzero(&da, sizeof (smb_doorarg_t));
da.da_opcode = cmd;
@@ -276,7 +281,11 @@ smb_door_call(uint32_t cmd, void *req_data, xdrproc_t req_xdr,
return (-1);
}
- if ((fd = open(SMBD_DOOR_NAME, O_RDONLY)) < 0) {
+ door_name = getenv("SMBD_DOOR_NAME");
+ if (door_name == NULL)
+ door_name = SMBD_DOOR_NAME;
+
+ if ((fd = open(door_name, O_RDONLY)) < 0) {
syslog(LOG_DEBUG, "smb_door_call[%s]: %m", da.da_opname);
return (-1);
}
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c b/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c
index 07d0edacd9..9edcbea2f9 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c
@@ -20,7 +20,24 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * SMB server interface to idmap
+ * (smb_idmap_get..., smb_idmap_batch_...)
+ *
+ * There are three implementations of this interface:
+ * uts/common/fs/smbsrv/smb_idmap.c (smbsrv kmod)
+ * lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c (libfksmbsrv)
+ * lib/smbsrv/libsmb/common/smb_idmap.c (libsmb)
+ *
+ * There are enough differences (relative to the code size)
+ * that it's more trouble than it's worth to merge them.
+ *
+ * This one differs from the others in that it:
+ * calls idmap interfaces (libidmap)
+ * domain SIDs returned are allocated
*/
#include <syslog.h>
@@ -47,6 +64,7 @@ smb_idmap_check(const char *s, idmap_stat stat)
* smb_idmap_getsid
*
* Tries to get a mapping for the given uid/gid
+ * Allocates ->sim_domsid
*/
idmap_stat
smb_idmap_getsid(uid_t id, int idtype, smb_sid_t **sid)
@@ -203,20 +221,17 @@ smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
smb_sid_t *sid, int idtype)
{
char sidstr[SMB_SID_STRSZ];
- smb_sid_t *tmpsid;
idmap_stat stat;
int flag = 0;
if (idmaph == NULL || sim == NULL || sid == NULL)
return (IDMAP_ERR_ARG);
- if ((tmpsid = smb_sid_split(sid, &sim->sim_rid)) == NULL)
- return (IDMAP_ERR_MEMORY);
-
- smb_sid_tostr(tmpsid, sidstr);
+ smb_sid_tostr(sid, sidstr);
+ if (smb_sid_splitstr(sidstr, &sim->sim_rid) != 0)
+ return (IDMAP_ERR_SID);
sim->sim_domsid = sidstr;
sim->sim_idtype = idtype;
- smb_sid_free(tmpsid);
switch (idtype) {
case SMB_IDMAP_USER:
@@ -239,9 +254,13 @@ smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
break;
default:
- return (IDMAP_ERR_ARG);
+ stat = IDMAP_ERR_ARG;
+ break;
}
+ /* This was copied by idmap_get_Xbysid. */
+ sim->sim_domsid = NULL;
+
return (stat);
}
@@ -252,6 +271,7 @@ smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
*
* sim->sim_domsid and sim->sim_rid will contain the mapping
* result upon successful process of the batched request.
+ * NB: sim_domsid allocated by strdup, here or in libidmap
*/
idmap_stat
smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
@@ -374,7 +394,7 @@ smb_idmap_batch_binsid(smb_idmap_batch_t *sib)
return (-1);
sim->sim_sid = smb_sid_splice(sid, sim->sim_rid);
- free(sid);
+ smb_sid_free(sid);
}
return (0);
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_info.c b/usr/src/lib/smbsrv/libsmb/common/smb_info.c
index b8251b185b..ea6707951e 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_info.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_info.c
@@ -516,11 +516,17 @@ smb_tracef(const char *fmt, ...)
/*
* Temporary fbt for dtrace until user space sdt enabled.
+ *
+ * This function is designed to be used with dtrace, i.e. see:
+ * usr/src/cmd/smbsrv/dtrace/smbd-all.d
+ *
+ * Outside of dtrace, the messages passed to this function usually
+ * lack sufficient context to be useful, so we don't log them.
*/
+/* ARGSUSED */
void
smb_trace(const char *s)
{
- syslog(LOG_DEBUG, "%s", s);
}
/*
@@ -577,14 +583,14 @@ smb_get_nameservers(smb_inaddr_t *ips, int sz)
if (i >= sz)
break;
ips[i].a_family = AF_INET;
- bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv4, INADDRSZ);
+ bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv4, NS_INADDRSZ);
if (inet_ntop(AF_INET, &ips[i].a_ipv4, ipstr,
INET_ADDRSTRLEN)) {
syslog(LOG_DEBUG, "Found %s name server\n", ipstr);
continue;
}
ips[i].a_family = AF_INET6;
- bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv6, IPV6_ADDR_LEN);
+ bcopy(&set[i].sin.sin_addr, &ips[i].a_ipv6, NS_IN6ADDRSZ);
if (inet_ntop(AF_INET6, &ips[i].a_ipv6, ipstr,
INET6_ADDRSTRLEN)) {
syslog(LOG_DEBUG, "Found %s name server\n", ipstr);
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c b/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c
index 474137ff5e..145d8da21c 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_kmod.c
@@ -39,13 +39,12 @@
#include <smbsrv/smb_xdr.h>
#include <smbsrv/smbinfo.h>
#include <smbsrv/smb_ioctl.h>
-#include <smbsrv/smb_ioctl.h>
#include <smbsrv/libsmb.h>
#define SMBDRV_DEVICE_PATH "/dev/smbsrv"
#define SMB_IOC_DATA_SIZE (256 * 1024)
-static int smb_kmod_ioctl(int, smb_ioc_header_t *, uint32_t);
+int smb_kmod_ioctl(int, smb_ioc_header_t *, uint32_t);
int smbdrv_fd = -1;
@@ -444,7 +443,11 @@ smb_kmod_unbind(void)
}
}
-static int
+/*
+ * Note: The user-space smbd-d provides it own version of this function
+ * which directly calls the "kernel" module code (in user space).
+ */
+int
smb_kmod_ioctl(int cmd, smb_ioc_header_t *ioc, uint32_t len)
{
int rc = EINVAL;
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_nic.c b/usr/src/lib/smbsrv/libsmb/common/smb_nic.c
index e9a1521f75..30be231e2f 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_nic.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_nic.c
@@ -21,6 +21,8 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <stdio.h>
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_sam.c b/usr/src/lib/smbsrv/libsmb/common/smb_sam.c
index 7016f5a878..e236b56724 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_sam.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_sam.c
@@ -19,9 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <strings.h>
@@ -571,3 +572,35 @@ smb_lwka_lookup_sid(smb_sid_t *sid)
return (NULL);
}
+
+/*
+ * smb_sid_islocal
+ *
+ * Check a SID to see if it belongs to the local domain.
+ */
+boolean_t
+smb_sid_islocal(smb_sid_t *sid)
+{
+ smb_domain_t di;
+ boolean_t islocal = B_FALSE;
+
+ if (smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di))
+ islocal = smb_sid_indomain(di.di_binsid, sid);
+
+ return (islocal);
+}
+
+void
+smb_ids_free(smb_ids_t *ids)
+{
+ smb_id_t *id;
+ int i;
+
+ if ((ids != NULL) && (ids->i_ids != NULL)) {
+ id = ids->i_ids;
+ for (i = 0; i < ids->i_cnt; i++, id++)
+ smb_sid_free(id->i_sid);
+
+ free(ids->i_ids);
+ }
+}
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c b/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c
index 94071ee488..ac35bbd7f7 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_scfutil.c
@@ -21,10 +21,10 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
-#pragma ident "@(#)smb_scfutil.c 1.5 08/07/30 SMI"
-
/* helper functions for using libscf with CIFS */
#include <libscf.h>
@@ -49,12 +49,10 @@
static void
smb_smf_scf_log_error(char *msg)
{
- if (!msg) {
- syslog(LOG_ERR, " SMBD SMF problem: %s\n",
- scf_strerror(scf_error()));
- } else { /*LINTED E_SEC_PRINTF_E_VAR_FMT*/
- syslog(LOG_ERR, msg, scf_strerror(scf_error()));
- }
+ if (msg == NULL)
+ msg = "SMBD SMF problem";
+
+ syslog(LOG_ERR, " %s: %s", msg, scf_strerror(scf_error()));
}
/*
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_syslog.c b/usr/src/lib/smbsrv/libsmb/common/smb_syslog.c
new file mode 100644
index 0000000000..b085627a83
--- /dev/null
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_syslog.c
@@ -0,0 +1,69 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <string.h>
+#include <syslog.h>
+#include <smbsrv/libsmb.h>
+
+/*
+ * This is exported NODIRECT so that smbd can provide it's own.
+ */
+void
+smb_vsyslog(int pri, const char *fmt, va_list ap)
+{
+ vsyslog(pri, fmt, ap);
+}
+
+/*
+ * This is exported NODIRECT so that fksmbd can provide it's own.
+ */
+void
+smb_syslog(int pri, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ smb_vsyslog(pri, fmt, ap);
+ va_end(ap);
+}
+
+/*
+ * Helper for smb_vsyslog(). Does %m substitutions.
+ */
+char *
+smb_syslog_fmt_m(char *buf, int buflen, const char *str, int err)
+{
+ char *bp = buf;
+ const char *sp = str;
+ const char *endp = buf + buflen - 1;
+
+ while ((*bp = *sp) != '\0' && bp != endp) {
+ if ((*sp++ == '%') && (*sp == 'm')) {
+ sp++;
+ if (strerror_r(err, bp, endp - bp) == 0)
+ bp += strlen(bp);
+ } else {
+ bp++;
+ }
+ }
+ *bp = '\0';
+
+ return (buf);
+}
diff --git a/usr/src/lib/smbsrv/libsmb/common/smb_util.c b/usr/src/lib/smbsrv/libsmb/common/smb_util.c
index 91bf0a7b00..53ad11a91c 100644
--- a/usr/src/lib/smbsrv/libsmb/common/smb_util.c
+++ b/usr/src/lib/smbsrv/libsmb/common/smb_util.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#include <ctype.h>
@@ -49,42 +49,12 @@
#define SMB_LIB_ALT "/usr/lib/smbsrv/libsmbex.so"
-#define SMB_TIMEBUF_SZ 16
-#define SMB_TRACEBUF_SZ 200
-
-#define SMB_LOG_FILE_FMT "/var/smb/%s_log.txt"
-
-typedef struct smb_log_pri {
- char *lp_name;
- int lp_value;
-} smb_log_pri_t;
-
-static smb_log_pri_t smb_log_pri[] = {
- "panic", LOG_EMERG,
- "emerg", LOG_EMERG,
- "alert", LOG_ALERT,
- "crit", LOG_CRIT,
- "error", LOG_ERR,
- "err", LOG_ERR,
- "warn", LOG_WARNING,
- "warning", LOG_WARNING,
- "notice", LOG_NOTICE,
- "info", LOG_INFO,
- "debug", LOG_DEBUG
-};
-
-static void smb_log_trace(int, const char *);
-static smb_log_t *smb_log_get(smb_log_hdl_t);
-static void smb_log_dump(smb_log_t *);
-
static boolean_t smb_netgroup_match(struct nd_hostservlist *, char *, int);
extern int __multi_innetgr();
extern int __netdir_getbyaddr_nosrv(struct netconfig *,
struct nd_hostservlist **, struct netbuf *);
-static smb_loglist_t smb_loglist;
-
#define C2H(c) "0123456789ABCDEF"[(c)]
#define H2C(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \
((c) >= 'a' && (c) <= 'f') ? ((c) - 'a' + 10) : \
@@ -1111,189 +1081,3 @@ smb_get_txid(void)
return (txid_ret);
}
-
-/*
- * Creates a log object and inserts it into a list of logs.
- */
-smb_log_hdl_t
-smb_log_create(int max_cnt, char *name)
-{
- smb_loglist_item_t *log_node;
- smb_log_t *log = NULL;
- smb_log_hdl_t handle = 0;
-
- if (max_cnt <= 0 || name == NULL)
- return (0);
-
- (void) mutex_lock(&smb_loglist.ll_mtx);
-
- log_node = malloc(sizeof (smb_loglist_item_t));
-
- if (log_node != NULL) {
- log = &log_node->lli_log;
-
- bzero(log, sizeof (smb_log_t));
-
- handle = log->l_handle = smb_get_txid();
- log->l_max_cnt = max_cnt;
- (void) snprintf(log->l_file, sizeof (log->l_file),
- SMB_LOG_FILE_FMT, name);
-
- list_create(&log->l_list, sizeof (smb_log_item_t),
- offsetof(smb_log_item_t, li_lnd));
-
- if (smb_loglist.ll_list.list_size == 0)
- list_create(&smb_loglist.ll_list,
- sizeof (smb_loglist_item_t),
- offsetof(smb_loglist_item_t, lli_lnd));
-
- list_insert_tail(&smb_loglist.ll_list, log_node);
- }
-
- (void) mutex_unlock(&smb_loglist.ll_mtx);
-
- return (handle);
-}
-
-/*
- * Keep the most recent log entries, based on max count.
- * If the priority is LOG_ERR or higher then the entire log is
- * dumped to a file.
- *
- * The date format for each message is the same as a syslog entry.
- *
- * The log is also added to syslog via smb_log_trace().
- */
-void
-smb_log(smb_log_hdl_t hdl, int priority, const char *fmt, ...)
-{
- va_list ap;
- smb_log_t *log;
- smb_log_item_t *msg;
- time_t now;
- struct tm *tm;
- char timebuf[SMB_TIMEBUF_SZ];
- char buf[SMB_TRACEBUF_SZ];
- char netbiosname[NETBIOS_NAME_SZ];
- char *pri_name;
- int i;
-
- va_start(ap, fmt);
- (void) vsnprintf(buf, SMB_TRACEBUF_SZ, fmt, ap);
- va_end(ap);
-
- priority &= LOG_PRIMASK;
- smb_log_trace(priority, buf);
-
- if ((log = smb_log_get(hdl)) == NULL)
- return;
-
- (void) mutex_lock(&log->l_mtx);
-
- (void) time(&now);
- tm = localtime(&now);
- (void) strftime(timebuf, SMB_TIMEBUF_SZ, "%b %d %H:%M:%S", tm);
-
- if (smb_getnetbiosname(netbiosname, NETBIOS_NAME_SZ) != 0)
- (void) strlcpy(netbiosname, "unknown", NETBIOS_NAME_SZ);
-
- if (log->l_cnt == log->l_max_cnt) {
- msg = list_head(&log->l_list);
- list_remove(&log->l_list, msg);
- } else {
- if ((msg = malloc(sizeof (smb_log_item_t))) == NULL) {
- (void) mutex_unlock(&log->l_mtx);
- return;
- }
- log->l_cnt++;
- }
-
- pri_name = "info";
- for (i = 0; i < sizeof (smb_log_pri) / sizeof (smb_log_pri[0]); i++) {
- if (priority == smb_log_pri[i].lp_value) {
- pri_name = smb_log_pri[i].lp_name;
- break;
- }
- }
-
- (void) snprintf(msg->li_msg, SMB_LOG_LINE_SZ,
- "%s %s smb[%d]: [ID 0 daemon.%s] %s",
- timebuf, netbiosname, getpid(), pri_name, buf);
- list_insert_tail(&log->l_list, msg);
-
- if (priority <= LOG_ERR)
- smb_log_dump(log);
-
- (void) mutex_unlock(&log->l_mtx);
-}
-
-/*
- * Dumps all the logs in the log list.
- */
-void
-smb_log_dumpall()
-{
- smb_loglist_item_t *log_node;
-
- (void) mutex_lock(&smb_loglist.ll_mtx);
-
- log_node = list_head(&smb_loglist.ll_list);
-
- while (log_node != NULL) {
- smb_log_dump(&log_node->lli_log);
- log_node = list_next(&smb_loglist.ll_list, log_node);
- }
-
- (void) mutex_unlock(&smb_loglist.ll_mtx);
-}
-
-static void
-smb_log_trace(int priority, const char *s)
-{
- syslog(priority, "%s", s);
-}
-
-static smb_log_t *
-smb_log_get(smb_log_hdl_t hdl)
-{
- smb_loglist_item_t *log_node;
- smb_log_t *log;
-
- (void) mutex_lock(&smb_loglist.ll_mtx);
-
- log_node = list_head(&smb_loglist.ll_list);
-
- while (log_node != NULL) {
- if (log_node->lli_log.l_handle == hdl) {
- log = &log_node->lli_log;
- (void) mutex_unlock(&smb_loglist.ll_mtx);
- return (log);
- }
- log_node = list_next(&smb_loglist.ll_list, log_node);
- }
-
- (void) mutex_unlock(&smb_loglist.ll_mtx);
- return (NULL);
-}
-
-/*
- * Dumps the log to a file.
- */
-static void
-smb_log_dump(smb_log_t *log)
-{
- smb_log_item_t *msg;
- FILE *fp;
-
- if ((fp = fopen(log->l_file, "w")) == NULL)
- return;
-
- msg = list_head(&log->l_list);
-
- while (msg != NULL) {
- (void) fprintf(fp, "%s\n", msg->li_msg);
- msg = list_next(&log->l_list, msg);
- }
-
- (void) fclose(fp);
-}
diff --git a/usr/src/lib/smbsrv/libsmbns/Makefile.com b/usr/src/lib/smbsrv/libsmbns/Makefile.com
index d148e11d65..31d30cb358 100644
--- a/usr/src/lib/smbsrv/libsmbns/Makefile.com
+++ b/usr/src/lib/smbsrv/libsmbns/Makefile.com
@@ -19,6 +19,7 @@
# CDDL HEADER END
#
# Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
#
LIBRARY= libsmbns.a
@@ -50,6 +51,7 @@ SRCS= $(OBJS_COMMON:%.o=$(SRCDIR)/%.c) \
LDLIBS += $(MACH_LDLIBS)
LDLIBS += -lsmb -lgss -lcmdutils -lldap -lresolv -lnsl -lsocket -lc
CPPFLAGS += -D_REENTRANT
+CPPFLAGS += -Dsyslog=smb_syslog
CERRWARN += -_gcc=-Wno-unused-function
CERRWARN += -_gcc=-Wno-uninitialized
diff --git a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c
index bcdfb8dbbf..c88ab69cec 100644
--- a/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c
+++ b/usr/src/lib/smbsrv/libsmbns/common/smbns_ads.c
@@ -553,18 +553,18 @@ smb_ads_decode_host_ip(int addit_cnt, int ans_cnt, uchar_t **ptr,
/* LINTED: E_CONSTANT_CONDITION */
NS_GET16(size, *ptr);
- if (size == INADDRSZ) {
+ if (size == NS_INADDRSZ) {
/* LINTED: E_CONSTANT_CONDITION */
NS_GET32(ipaddr.a_ipv4, *ptr);
ipaddr.a_ipv4 = htonl(ipaddr.a_ipv4);
ipaddr.a_family = AF_INET;
- } else if (size == IN6ADDRSZ) {
+ } else if (size == NS_IN6ADDRSZ) {
#ifdef BIG_ENDIAN
- bcopy(*ptr, &ipaddr.a_ipv6, IN6ADDRSZ);
+ bcopy(*ptr, &ipaddr.a_ipv6, NS_IN6ADDRSZ);
#else
- for (i = 0; i < IN6ADDRSZ; i++)
+ for (i = 0; i < NS_IN6ADDRSZ; i++)
(uint8_t *)(ipaddr.a_ipv6)
- [IN6ADDRSZ-1-i] = *(*ptr+i);
+ [NS_IN6ADDRSZ-1-i] = *(*ptr+i);
#endif
ipaddr.a_family = AF_INET6;
*ptr += size;
@@ -800,14 +800,14 @@ smb_ads_getipnodebyname(smb_ads_host_info_t *hentry)
case AF_INET6:
h = getipnodebyname(hentry->name, hentry->ipaddr.a_family,
AI_DEFAULT, &error);
- if (h == NULL || h->h_length != IPV6_ADDR_LEN)
+ if (h == NULL || h->h_length != NS_IN6ADDRSZ)
return (-1);
break;
case AF_INET:
h = getipnodebyname(hentry->name, hentry->ipaddr.a_family,
0, &error);
- if (h == NULL || h->h_length != INADDRSZ)
+ if (h == NULL || h->h_length != NS_INADDRSZ)
return (-1);
break;
diff --git a/usr/src/tools/quick/make-smbsrv b/usr/src/tools/quick/make-smbsrv
index 87666bbcdf..3eca17ff83 100755
--- a/usr/src/tools/quick/make-smbsrv
+++ b/usr/src/tools/quick/make-smbsrv
@@ -11,7 +11,7 @@
#
#
-# Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+# Copyright 2014 Nexenta Systems, Inc. All rights reserved.
#
# Use distributed make (dmake) by default.
@@ -101,6 +101,7 @@ for lib in \
libcmdutils \
libcryptoutil \
libdevid \
+ libfakekernel \
libidmap \
libpam \
libsec \
@@ -131,17 +132,33 @@ do_kern() {
################################################################
-do_libs() {
+# Note lib1 builds prerequisite libraries not delivered by the
+# tar file we create below. To accelerate clean/install, we
+# skip these on clean (but still nuke them for clobber)
+
+do_lib1() {
for lib in \
libavl \
libcmdutils \
- libsmbfs \
libsqlite \
libuutil
do
(cd $SRC/lib/$lib && $make $1)
done
+}
+
+# lib2 builds stuff we include in the tar file,
+# or that we don't mind rebuilding after clean.
+
+do_lib2() {
+
+for lib in \
+ libfakekernel \
+ libsmbfs
+do
+ (cd $SRC/lib/$lib && $make $1)
+done
(cd $SRC/lib/libshare && $make $1 PLUGINS=smb)
(cd $SRC/lib/smbsrv && $make $1)
@@ -190,6 +207,16 @@ do
$make $1 KMDB_LINKTEST_ENABLE= )
(cd $SRC/cmd/mdb/$x/$a/smbsrv &&
$make $1 KMDB_LINKTEST_ENABLE= )
+ (cd $SRC/cmd/mdb/$x/$a/libfksmbsrv &&
+ $make $1 KMDB_LINKTEST_ENABLE= )
+
+# We build these libraries (to the proto area), so we need to
+# build the mdb modules too so mdb will load them.
+ (cd $SRC/cmd/mdb/$x/$a/libcmdutils &&
+ $make $1 )
+ (cd $SRC/cmd/mdb/$x/$a/libavl &&
+ $make $1 )
+
done
(cd $SRC/cmd/Adm/sun && $make $1)
@@ -265,28 +292,31 @@ set -x
for arg
do
case "$arg" in
- build|install)
- arg=install
+ install)
build_tools
set -e
do_hdrs $arg
do_kern $arg
- do_libs $arg
+ do_lib1 $arg
+ do_lib2 $arg
do_cmds $arg
;;
lint)
do_kern $arg
- do_libs $arg
+ do_lib1 $arg
+ do_lib2 $arg
do_cmds $arg
;;
clean)
+ # intentionally skip: lib1, hdrs, tools
do_cmds $arg
- do_libs $arg
+ do_lib2 $arg
do_kern $arg
;;
clobber)
do_cmds $arg
- do_libs $arg
+ do_lib2 $arg
+ do_lib1 $arg
do_kern $arg
do_hdrs $arg
clobber_tools
@@ -298,7 +328,7 @@ do
do_tar
;;
*)
- echo "Usage: $0 {build|lint|clean|clobber|tags|tar}";
+ echo "Usage: $0 {install|lint|clean|clobber|tags|tar}";
exit 1;
;;
esac
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index 8477310f0a..ca912c05dd 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -1195,10 +1195,11 @@ SMBSRV_OBJS += $(SMBSRV_SHARED_OBJS) \
smb_flush.o \
smb_fsinfo.o \
smb_fsops.o \
+ smb_idmap.o \
smb_init.o \
smb_kdoor.o \
smb_kshare.o \
- smb_kutil.o \
+ smb_kutil.o \
smb_lock.o \
smb_lock_byte_range.o \
smb_locking_andx.o \
@@ -1209,17 +1210,18 @@ SMBSRV_OBJS += $(SMBSRV_SHARED_OBJS) \
smb_negotiate.o \
smb_net.o \
smb_node.o \
- smb_nt_cancel.o \
+ smb_nt_cancel.o \
smb_nt_create_andx.o \
- smb_nt_transact_create.o \
+ smb_nt_transact_create.o \
smb_nt_transact_ioctl.o \
smb_nt_transact_notify_change.o \
smb_nt_transact_quota.o \
smb_nt_transact_security.o \
- smb_odir.o \
+ smb_odir.o \
smb_ofile.o \
smb_open_andx.o \
smb_opipe.o \
+ smb_opipe_door.o \
smb_oplock.o \
smb_pathname.o \
smb_print.o \
@@ -1233,8 +1235,10 @@ SMBSRV_OBJS += $(SMBSRV_SHARED_OBJS) \
smb_session.o \
smb_session_setup_andx.o \
smb_set_fileinfo.o \
+ smb_sign_kcf.o \
smb_signing.o \
- smb_tree.o \
+ smb_thread.o \
+ smb_tree.o \
smb_trans2_create_directory.o \
smb_trans2_dfs.o \
smb_trans2_find.o \
diff --git a/usr/src/uts/common/fs/fs_reparse.h b/usr/src/uts/common/fs/fs_reparse.h
index a3bb086a25..68f7c5603f 100644
--- a/usr/src/uts/common/fs/fs_reparse.h
+++ b/usr/src/uts/common/fs/fs_reparse.h
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _FS_REPARSE_H
@@ -32,7 +34,7 @@ extern "C" {
#include <sys/types.h>
#include <sys/param.h>
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#include <sys/time.h>
#include <sys/nvpair.h>
#else
diff --git a/usr/src/uts/common/fs/smbsrv/smb_acl.c b/usr/src/uts/common/fs/smbsrv/smb_acl.c
index d42a76d314..a241fd6fd7 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_acl.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_acl.c
@@ -19,9 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/sid.h>
@@ -73,11 +74,13 @@
* owner: full access
* SYSTEM: full access
*/
+#ifdef _KERNEL
static const ace_t const default_dacl[DEFAULT_DACL_ACENUM] = {
{ (uid_t)-1, ACE_ALL_PERMS, 0, ACE_ACCESS_ALLOWED_ACE_TYPE },
{ IDMAP_WK_LOCAL_SYSTEM_GID, ACE_ALL_PERMS, ACE_IDENTIFIER_GROUP,
ACE_ACCESS_ALLOWED_ACE_TYPE }
};
+#endif /* _KERNEL */
/*
* Note:
@@ -89,9 +92,11 @@ static const ace_t const default_dacl[DEFAULT_DACL_ACENUM] = {
static idmap_stat smb_fsacl_getsids(smb_idmap_batch_t *, acl_t *);
static acl_t *smb_fsacl_null_empty(boolean_t);
+#ifdef _KERNEL
static int smb_fsacl_inheritable(acl_t *, int);
-
static void smb_ace_inherit(ace_t *, ace_t *, int, uid_t, gid_t);
+#endif /* _KERNEL */
+
static boolean_t smb_ace_isvalid(smb_ace_t *, int);
static uint16_t smb_ace_len(smb_ace_t *);
static uint32_t smb_ace_mask_g2s(uint32_t);
@@ -469,7 +474,7 @@ smb_fsacl_getsids(smb_idmap_batch_t *sib, acl_t *zacl)
ace_t *zace;
idmap_stat idm_stat;
smb_idmap_t *sim;
- uid_t id;
+ uid_t id = (uid_t)-1;
int i, idtype;
sim = sib->sib_maps;
@@ -610,8 +615,8 @@ void
smb_fsacl_split(acl_t *zacl, acl_t **dacl, acl_t **sacl, int which_acl)
{
ace_t *zace;
- ace_t *access_ace;
- ace_t *audit_ace;
+ ace_t *access_ace = NULL;
+ ace_t *audit_ace = NULL;
int naccess, naudit;
int get_dacl, get_sacl;
int i;
@@ -704,6 +709,7 @@ smb_fsacl_split(acl_t *zacl, acl_t **dacl, acl_t **sacl, int which_acl)
* which the generic information has been mapped.
*/
+#ifdef _KERNEL
/*
* smb_fsacl_inherit
*
@@ -831,6 +837,7 @@ smb_fsacl_inherit(acl_t *dir_zacl, int is_dir, int which_acl, cred_t *cr)
return (new_zacl);
}
+#endif /* _KERNEL */
/*
* smb_fsacl_from_vsa
@@ -1007,6 +1014,7 @@ smb_fsacl_to_vsa(acl_t *acl_info, vsecattr_t *vsecattr, int *aclbsize)
return (error);
}
+#ifdef _KERNEL
/*
* smb_fsacl_inheritable
*
@@ -1087,6 +1095,7 @@ smb_fsacl_inheritable(acl_t *zacl, int is_dir)
return (num_inheritable);
}
+#endif /* _KERNEL */
/*
@@ -1176,6 +1185,7 @@ smb_ace_len(smb_ace_t *ace)
smb_sid_len(ace->se_sid));
}
+#ifdef _KERNEL
static void
smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir, uid_t uid, gid_t gid)
{
@@ -1206,6 +1216,7 @@ smb_ace_inherit(ace_t *dir_zace, ace_t *zace, int is_dir, uid_t uid, gid_t gid)
zace->a_flags &= ~ACE_INHERIT_FLAGS;
}
}
+#endif /* _KERNEL */
/*
* smb_ace_mask_g2s
diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_open.c b/usr/src/uts/common/fs/smbsrv/smb_common_open.c
index e4b202d328..6e217c51ed 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_common_open.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_open.c
@@ -39,6 +39,7 @@
#include <smbsrv/smbinfo.h>
volatile uint32_t smb_fids = 0;
+#define SMB_UNIQ_FID() atomic_inc_32_nv(&smb_fids)
static uint32_t smb_open_subr(smb_request_t *);
extern uint32_t smb_is_executable(char *);
@@ -437,9 +438,10 @@ smb_open_subr(smb_request_t *sr)
op->fqi.fq_dnode = cur_node->n_dnode;
smb_node_ref(op->fqi.fq_dnode);
} else {
- if (rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
+ rc = smb_pathname_reduce(sr, sr->user_cr, pn->pn_path,
sr->tid_tree->t_snode, cur_node, &op->fqi.fq_dnode,
- op->fqi.fq_last_comp)) {
+ op->fqi.fq_last_comp);
+ if (rc != 0) {
smbsr_errno(sr, rc);
return (sr->smb_error.status);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c
index c8a9ec9093..47607b4bb9 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c
@@ -1569,7 +1569,8 @@ smb_trans2_dispatch(smb_request_t *sr, smb_xa_t *xa)
{
int rc, pos;
int total_bytes, n_setup, n_param, n_data;
- int param_off, param_pad, data_off, data_pad;
+ int param_off, param_pad, data_off;
+ uint16_t data_pad;
uint16_t opcode;
uint16_t nt_unknown_secret = 0x0100;
char *fmt;
@@ -1730,7 +1731,6 @@ smb_trans2_dispatch(smb_request_t *sr, smb_xa_t *xa)
/* Param off from hdr start */
data_off = param_off + n_param + data_pad;
fmt = "bww2.wwwwwwb.Cw#.C#.C";
- /*LINTED E_ASSIGN_NARROW_CONV*/
nt_unknown_secret = data_pad;
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_delete.c b/usr/src/uts/common/fs/smbsrv/smb_delete.c
index 3bca7e6202..96435a0b81 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_delete.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_delete.c
@@ -24,10 +24,12 @@
* Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
+#include <sys/sunddi.h>
+#include <sys/nbmlock.h>
+
#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_fsops.h>
#include <smbsrv/smbinfo.h>
-#include <sys/nbmlock.h>
static int smb_delete_check_path(smb_request_t *);
static int smb_delete_single_file(smb_request_t *, smb_error_t *);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c
index 9b65e5cafd..e2488c244f 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c
@@ -583,12 +583,9 @@ smb_dispatch_request(struct smb_request *sr)
sr->smb_mid);
sr->first_smb_com = sr->smb_com;
- /*
- * Verify SMB signature if signing is enabled, dialect is NT LM 0.12,
- * signing was negotiated and authentication has occurred.
- */
- if (session->signing.flags & SMB_SIGNING_ENABLED) {
- if (smb_sign_check_request(sr) != 0) {
+ if ((session->signing.flags & SMB_SIGNING_CHECK) != 0) {
+ if ((sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) == 0 ||
+ smb_sign_check_request(sr) != 0) {
smbsr_error(sr, NT_STATUS_ACCESS_DENIED,
ERRDOS, ERROR_ACCESS_DENIED);
disconnect = B_TRUE;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_fem.c b/usr/src/uts/common/fs/smbsrv/smb_fem.c
index 98d13aa6b3..41c74756cf 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_fem.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_fem.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <smbsrv/smb_kproto.h>
@@ -235,7 +235,7 @@ smb_fem_fcn_create(
error = vnext_create(arg, name, vap, excl, mode, vpp, cr, flag,
ct, vsecp);
- if (error == 0)
+ if (error == 0 && ct != &smb_ct)
smb_node_notify_change(dnode, FILE_ACTION_ADDED, name);
return (error);
@@ -269,7 +269,7 @@ smb_fem_fcn_remove(
error = vnext_remove(arg, name, cr, ct, flags);
- if (error == 0)
+ if (error == 0 && ct != &smb_ct)
smb_node_notify_change(dnode, FILE_ACTION_REMOVED, name);
return (error);
@@ -294,18 +294,19 @@ smb_fem_fcn_rename(
error = vnext_rename(arg, snm, tdvp, tnm, cr, ct, flags);
- if (error != 0)
- return (error);
-
- /*
- * Note that renames in the same directory are normally
- * delivered in {old,new} pairs, and clients expect them
- * in that order, if both events are delivered.
- */
- smb_node_notify_change(dnode, FILE_ACTION_RENAMED_OLD_NAME, snm);
- smb_node_notify_change(dnode, FILE_ACTION_RENAMED_NEW_NAME, tnm);
+ if (error == 0 && ct != &smb_ct) {
+ /*
+ * Note that renames in the same directory are normally
+ * delivered in {old,new} pairs, and clients expect them
+ * in that order, if both events are delivered.
+ */
+ smb_node_notify_change(dnode,
+ FILE_ACTION_RENAMED_OLD_NAME, snm);
+ smb_node_notify_change(dnode,
+ FILE_ACTION_RENAMED_NEW_NAME, tnm);
+ }
- return (0);
+ return (error);
}
static int
@@ -328,7 +329,7 @@ smb_fem_fcn_mkdir(
error = vnext_mkdir(arg, name, vap, vpp, cr, ct, flags, vsecp);
- if (error == 0)
+ if (error == 0 && ct != &smb_ct)
smb_node_notify_change(dnode, FILE_ACTION_ADDED, name);
return (error);
@@ -352,7 +353,7 @@ smb_fem_fcn_rmdir(
error = vnext_rmdir(arg, name, cdir, cr, ct, flags);
- if (error == 0)
+ if (error == 0 && ct != &smb_ct)
smb_node_notify_change(dnode, FILE_ACTION_REMOVED, name);
return (error);
@@ -376,7 +377,7 @@ smb_fem_fcn_link(
error = vnext_link(arg, svp, tnm, cr, ct, flags);
- if (error == 0)
+ if (error == 0 && ct != &smb_ct)
smb_node_notify_change(dnode, FILE_ACTION_ADDED, tnm);
return (error);
@@ -401,7 +402,7 @@ smb_fem_fcn_symlink(
error = vnext_symlink(arg, linkname, vap, target, cr, ct, flags);
- if (error == 0)
+ if (error == 0 && ct != &smb_ct)
smb_node_notify_change(dnode, FILE_ACTION_ADDED, linkname);
return (error);
@@ -421,17 +422,19 @@ smb_fem_oplock_open(
cred_t *cr,
caller_context_t *ct)
{
- int rc;
uint32_t flags;
+ int rc = 0;
- if (mode & (FWRITE|FTRUNC))
- flags = SMB_OPLOCK_BREAK_TO_NONE;
- else
- flags = SMB_OPLOCK_BREAK_TO_LEVEL_II;
-
- rc = smb_fem_oplock_break(arg, ct, flags);
+ if (ct != &smb_ct) {
+ if (mode & (FWRITE|FTRUNC))
+ flags = SMB_OPLOCK_BREAK_TO_NONE;
+ else
+ flags = SMB_OPLOCK_BREAK_TO_LEVEL_II;
+ rc = smb_fem_oplock_break(arg, ct, flags);
+ }
if (rc == 0)
rc = vnext_open(arg, mode, cr, ct);
+
return (rc);
}
@@ -448,11 +451,15 @@ smb_fem_oplock_read(
cred_t *cr,
caller_context_t *ct)
{
- int rc;
+ int rc = 0;
- rc = smb_fem_oplock_break(arg, ct, SMB_OPLOCK_BREAK_TO_LEVEL_II);
+ if (ct != &smb_ct) {
+ rc = smb_fem_oplock_break(arg, ct,
+ SMB_OPLOCK_BREAK_TO_LEVEL_II);
+ }
if (rc == 0)
rc = vnext_read(arg, uiop, ioflag, cr, ct);
+
return (rc);
}
@@ -469,11 +476,13 @@ smb_fem_oplock_write(
cred_t *cr,
caller_context_t *ct)
{
- int rc;
+ int rc = 0;
- rc = smb_fem_oplock_break(arg, ct, SMB_OPLOCK_BREAK_TO_NONE);
+ if (ct != &smb_ct)
+ rc = smb_fem_oplock_break(arg, ct, SMB_OPLOCK_BREAK_TO_NONE);
if (rc == 0)
rc = vnext_write(arg, uiop, ioflag, cr, ct);
+
return (rc);
}
@@ -487,7 +496,7 @@ smb_fem_oplock_setattr(
{
int rc = 0;
- if (vap->va_mask & AT_SIZE)
+ if (ct != &smb_ct && (vap->va_mask & AT_SIZE) != 0)
rc = smb_fem_oplock_break(arg, ct, SMB_OPLOCK_BREAK_TO_NONE);
if (rc == 0)
rc = vnext_setattr(arg, vap, flags, cr, ct);
@@ -500,15 +509,16 @@ smb_fem_oplock_rwlock(
int write_lock,
caller_context_t *ct)
{
- int rc;
uint32_t flags;
+ int rc = 0;
- if (write_lock)
- flags = SMB_OPLOCK_BREAK_TO_NONE;
- else
- flags = SMB_OPLOCK_BREAK_TO_LEVEL_II;
-
- rc = smb_fem_oplock_break(arg, ct, flags);
+ if (ct != &smb_ct) {
+ if (write_lock)
+ flags = SMB_OPLOCK_BREAK_TO_NONE;
+ else
+ flags = SMB_OPLOCK_BREAK_TO_LEVEL_II;
+ rc = smb_fem_oplock_break(arg, ct, flags);
+ }
if (rc == 0)
rc = vnext_rwlock(arg, write_lock, ct);
@@ -525,9 +535,10 @@ smb_fem_oplock_space(
cred_t *cr,
caller_context_t *ct)
{
- int rc;
+ int rc = 0;
- rc = smb_fem_oplock_break(arg, ct, SMB_OPLOCK_BREAK_TO_NONE);
+ if (ct != &smb_ct)
+ rc = smb_fem_oplock_break(arg, ct, SMB_OPLOCK_BREAK_TO_NONE);
if (rc == 0)
rc = vnext_space(arg, cmd, bfp, flag, offset, cr, ct);
return (rc);
@@ -555,28 +566,31 @@ smb_fem_oplock_vnevent(
char *name,
caller_context_t *ct)
{
- int rc;
uint32_t flags;
-
- switch (vnevent) {
- case VE_REMOVE:
- case VE_RENAME_DEST:
- flags = SMB_OPLOCK_BREAK_TO_NONE | SMB_OPLOCK_BREAK_BATCH;
- rc = smb_fem_oplock_break(arg, ct, flags);
- break;
- case VE_RENAME_SRC:
- flags = SMB_OPLOCK_BREAK_TO_LEVEL_II | SMB_OPLOCK_BREAK_BATCH;
- rc = smb_fem_oplock_break(arg, ct, flags);
- break;
- default:
- rc = 0;
- break;
+ int rc = 0;
+
+ if (ct != &smb_ct) {
+ switch (vnevent) {
+ case VE_REMOVE:
+ case VE_RENAME_DEST:
+ flags = SMB_OPLOCK_BREAK_TO_NONE |
+ SMB_OPLOCK_BREAK_BATCH;
+ rc = smb_fem_oplock_break(arg, ct, flags);
+ break;
+ case VE_RENAME_SRC:
+ flags = SMB_OPLOCK_BREAK_TO_LEVEL_II |
+ SMB_OPLOCK_BREAK_BATCH;
+ rc = smb_fem_oplock_break(arg, ct, flags);
+ break;
+ default:
+ rc = 0;
+ break;
+ }
}
+ if (rc == 0)
+ rc = vnext_vnevent(arg, vnevent, dvp, name, ct);
- if (rc != 0)
- return (rc);
-
- return (vnext_vnevent(arg, vnevent, dvp, name, ct));
+ return (rc);
}
static int
@@ -588,8 +602,7 @@ smb_fem_oplock_break(femarg_t *arg, caller_context_t *ct, uint32_t flags)
node = (smb_node_t *)((arg)->fa_fnode->fn_available);
SMB_NODE_VALID(node);
- if (ct && (ct->cc_caller_id == smb_ct.cc_caller_id))
- return (0);
+ ASSERT(ct != &smb_ct);
if (ct && (ct->cc_flags & CC_DONTBLOCK)) {
flags |= SMB_OPLOCK_BREAK_NOWAIT;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsops.c b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
index d63de75843..c1d96faa43 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_fsops.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_fsops.c
@@ -40,10 +40,11 @@ static int smb_fsop_create_stream(smb_request_t *, cred_t *, smb_node_t *,
static int smb_fsop_create_file(smb_request_t *, cred_t *, smb_node_t *,
char *, int, smb_attr_t *, smb_node_t **);
+#ifdef _KERNEL
static int smb_fsop_create_with_sd(smb_request_t *, cred_t *, smb_node_t *,
char *, smb_attr_t *, smb_node_t **, smb_fssd_t *);
-
static int smb_fsop_sdinherit(smb_request_t *, smb_node_t *, smb_fssd_t *);
+#endif /* _KERNEL */
/*
* The smb_fsop_* functions have knowledge of CIFS semantics.
@@ -116,6 +117,7 @@ smb_fsop_close(smb_node_t *node, int mode, cred_t *cred)
smb_vop_close(node->vp, mode, cred);
}
+#ifdef _KERNEL
static int
smb_fsop_create_with_sd(smb_request_t *sr, cred_t *cr,
smb_node_t *dnode, char *name,
@@ -262,6 +264,7 @@ smb_fsop_create_with_sd(smb_request_t *sr, cred_t *cr,
return (rc);
}
+#endif /* _KERNEL */
/*
* smb_fsop_create
@@ -442,10 +445,12 @@ smb_fsop_create_file(smb_request_t *sr, cred_t *cr,
{
smb_arg_open_t *op = &sr->sr_open;
vnode_t *vp;
+ int rc;
+
+#ifdef _KERNEL
smb_fssd_t fs_sd;
uint32_t secinfo;
uint32_t status;
- int rc = 0;
if (op->sd) {
/*
@@ -477,7 +482,9 @@ smb_fsop_create_file(smb_request_t *sr, cred_t *cr,
}
smb_fssd_term(&fs_sd);
- } else {
+ } else
+#endif /* _KERNEL */
+ {
/*
* No incoming SD and filesystem is not ZFS
* let the filesystem handles the inheritance.
@@ -498,7 +505,7 @@ smb_fsop_create_file(smb_request_t *sr, cred_t *cr,
}
if (rc == 0)
- smb_node_notify_parents(dnode);
+ smb_node_notify_change(dnode, FILE_ACTION_ADDED, name);
return (rc);
}
@@ -529,10 +536,14 @@ smb_fsop_mkdir(
char *longname;
vnode_t *vp;
int flags = 0;
+ int rc;
+
+#ifdef _KERNEL
smb_fssd_t fs_sd;
uint32_t secinfo;
uint32_t status;
- int rc;
+#endif /* _KERNEL */
+
ASSERT(cr);
ASSERT(dnode);
ASSERT(dnode->n_magic == SMB_NODE_MAGIC);
@@ -581,6 +592,7 @@ smb_fsop_mkdir(
if (SMB_TREE_IS_CASEINSENSITIVE(sr))
flags = SMB_IGNORE_CASE;
+#ifdef _KERNEL
if (op->sd) {
/*
* SD sent by client in Windows format. Needs to be
@@ -612,7 +624,9 @@ smb_fsop_mkdir(
smb_fssd_term(&fs_sd);
- } else {
+ } else
+#endif /* _KERNEL */
+ {
rc = smb_vop_mkdir(dnode->vp, name, attr, &vp, flags, cr,
NULL);
@@ -628,7 +642,7 @@ smb_fsop_mkdir(
}
if (rc == 0)
- smb_node_notify_parents(dnode);
+ smb_node_notify_change(dnode, FILE_ACTION_ADDED, name);
return (rc);
}
@@ -749,12 +763,12 @@ smb_fsop_remove(
rc = smb_vop_remove(dnode->vp, longname,
flags, cr);
}
-
- if (rc == 0)
- smb_node_notify_parents(dnode);
-
kmem_free(longname, MAXNAMELEN);
}
+ if (rc == 0) {
+ smb_node_notify_change(dnode,
+ FILE_ACTION_REMOVED, name);
+ }
}
kmem_free(fname, MAXNAMELEN);
@@ -894,7 +908,7 @@ smb_fsop_rmdir(
}
if (rc == 0)
- smb_node_notify_parents(dnode);
+ smb_node_notify_change(dnode, FILE_ACTION_REMOVED, name);
return (rc);
}
@@ -1025,8 +1039,8 @@ smb_fsop_link(smb_request_t *sr, cred_t *cr, smb_node_t *from_fnode,
rc = smb_vop_link(to_dnode->vp, from_fnode->vp, to_name, flags, cr);
- if ((rc == 0) && from_fnode->n_dnode)
- smb_node_notify_parents(from_fnode->n_dnode);
+ if (rc == 0)
+ smb_node_notify_change(to_dnode, FILE_ACTION_ADDED, to_name);
return (rc);
}
@@ -1161,8 +1175,19 @@ smb_fsop_rename(
}
VN_RELE(from_vp);
- if (rc == 0)
- smb_node_notify_parents(from_dnode);
+ if (rc == 0) {
+ if (from_dnode == to_dnode) {
+ smb_node_notify_change(from_dnode,
+ FILE_ACTION_RENAMED_OLD_NAME, from_name);
+ smb_node_notify_change(to_dnode,
+ FILE_ACTION_RENAMED_NEW_NAME, to_name);
+ } else {
+ smb_node_notify_change(from_dnode,
+ FILE_ACTION_REMOVED, from_name);
+ smb_node_notify_change(to_dnode,
+ FILE_ACTION_ADDED, to_name);
+ }
+ }
/* XXX: unlock */
@@ -2337,6 +2362,7 @@ smb_fsop_sdwrite(smb_request_t *sr, cred_t *cr, smb_node_t *snode,
return (error);
}
+#ifdef _KERNEL
/*
* smb_fsop_sdinherit
*
@@ -2404,6 +2430,7 @@ smb_fsop_sdinherit(smb_request_t *sr, smb_node_t *dnode, smb_fssd_t *fs_sd)
return (0);
}
+#endif /* _KERNEL */
/*
* smb_fsop_eaccess
diff --git a/usr/src/uts/common/fs/smbsrv/smb_idmap.c b/usr/src/uts/common/fs/smbsrv/smb_idmap.c
new file mode 100644
index 0000000000..654a4fa018
--- /dev/null
+++ b/usr/src/uts/common/fs/smbsrv/smb_idmap.c
@@ -0,0 +1,411 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * SMB server interface to idmap
+ * (smb_idmap_get..., smb_idmap_batch_...)
+ *
+ * There are three implementations of this interface:
+ * uts/common/fs/smbsrv/smb_idmap.c (smbsrv kmod)
+ * lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c (libfksmbsrv)
+ * lib/smbsrv/libsmb/common/smb_idmap.c (libsmb)
+ *
+ * There are enough differences (relative to the code size)
+ * that it's more trouble than it's worth to merge them.
+ *
+ * This one differs from the others in that it:
+ * calls kernel (kidmap_...) interfaces
+ * domain SIDs are shared, not strdup'ed
+ */
+
+/*
+ * SMB ID mapping
+ *
+ * Solaris ID mapping service (aka Winchester) works with domain SIDs
+ * and RIDs where domain SIDs are in string format. CIFS service works
+ * with binary SIDs understandable by CIFS clients. A layer of SMB ID
+ * mapping functions are implemeted to hide the SID conversion details
+ * and also hide the handling of array of batch mapping requests.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/tzfile.h>
+#include <sys/atomic.h>
+#include <sys/kidmap.h>
+#include <sys/time.h>
+#include <sys/spl.h>
+#include <sys/random.h>
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smb_fsops.h>
+#include <smbsrv/smbinfo.h>
+#include <smbsrv/smb_xdr.h>
+#include <smbsrv/smb_vops.h>
+#include <smbsrv/smb_idmap.h>
+
+#include <sys/sid.h>
+#include <sys/priv_names.h>
+
+static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib);
+
+/*
+ * smb_idmap_getsid
+ *
+ * Maps the given Solaris ID to a Windows SID using the
+ * simple mapping API.
+ */
+idmap_stat
+smb_idmap_getsid(uid_t id, int idtype, smb_sid_t **sid)
+{
+ smb_idmap_t sim;
+
+ switch (idtype) {
+ case SMB_IDMAP_USER:
+ sim.sim_stat = kidmap_getsidbyuid(global_zone, id,
+ (const char **)&sim.sim_domsid, &sim.sim_rid);
+ break;
+
+ case SMB_IDMAP_GROUP:
+ sim.sim_stat = kidmap_getsidbygid(global_zone, id,
+ (const char **)&sim.sim_domsid, &sim.sim_rid);
+ break;
+
+ case SMB_IDMAP_EVERYONE:
+ /* Everyone S-1-1-0 */
+ sim.sim_domsid = "S-1-1";
+ sim.sim_rid = 0;
+ sim.sim_stat = IDMAP_SUCCESS;
+ break;
+
+ default:
+ ASSERT(0);
+ return (IDMAP_ERR_ARG);
+ }
+
+ if (sim.sim_stat != IDMAP_SUCCESS)
+ return (sim.sim_stat);
+
+ if (sim.sim_domsid == NULL)
+ return (IDMAP_ERR_NOMAPPING);
+
+ sim.sim_sid = smb_sid_fromstr(sim.sim_domsid);
+ if (sim.sim_sid == NULL)
+ return (IDMAP_ERR_INTERNAL);
+
+ *sid = smb_sid_splice(sim.sim_sid, sim.sim_rid);
+ smb_sid_free(sim.sim_sid);
+ if (*sid == NULL)
+ sim.sim_stat = IDMAP_ERR_INTERNAL;
+
+ return (sim.sim_stat);
+}
+
+/*
+ * smb_idmap_getid
+ *
+ * Maps the given Windows SID to a Unix ID using the
+ * simple mapping API.
+ */
+idmap_stat
+smb_idmap_getid(smb_sid_t *sid, uid_t *id, int *idtype)
+{
+ smb_idmap_t sim;
+ char sidstr[SMB_SID_STRSZ];
+
+ smb_sid_tostr(sid, sidstr);
+ if (smb_sid_splitstr(sidstr, &sim.sim_rid) != 0)
+ return (IDMAP_ERR_SID);
+ sim.sim_domsid = sidstr;
+ sim.sim_id = id;
+
+ switch (*idtype) {
+ case SMB_IDMAP_USER:
+ sim.sim_stat = kidmap_getuidbysid(global_zone, sim.sim_domsid,
+ sim.sim_rid, sim.sim_id);
+ break;
+
+ case SMB_IDMAP_GROUP:
+ sim.sim_stat = kidmap_getgidbysid(global_zone, sim.sim_domsid,
+ sim.sim_rid, sim.sim_id);
+ break;
+
+ case SMB_IDMAP_UNKNOWN:
+ sim.sim_stat = kidmap_getpidbysid(global_zone, sim.sim_domsid,
+ sim.sim_rid, sim.sim_id, &sim.sim_idtype);
+ break;
+
+ default:
+ ASSERT(0);
+ return (IDMAP_ERR_ARG);
+ }
+
+ *idtype = sim.sim_idtype;
+
+ return (sim.sim_stat);
+}
+
+/*
+ * smb_idmap_batch_create
+ *
+ * Creates and initializes the context for batch ID mapping.
+ */
+idmap_stat
+smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags)
+{
+ ASSERT(sib);
+
+ bzero(sib, sizeof (smb_idmap_batch_t));
+
+ sib->sib_idmaph = kidmap_get_create(global_zone);
+
+ sib->sib_flags = flags;
+ sib->sib_nmap = nmap;
+ sib->sib_size = nmap * sizeof (smb_idmap_t);
+ sib->sib_maps = kmem_zalloc(sib->sib_size, KM_SLEEP);
+
+ return (IDMAP_SUCCESS);
+}
+
+/*
+ * smb_idmap_batch_destroy
+ *
+ * Frees the batch ID mapping context.
+ * If ID mapping is Solaris -> Windows it frees memories
+ * allocated for binary SIDs.
+ */
+void
+smb_idmap_batch_destroy(smb_idmap_batch_t *sib)
+{
+ char *domsid;
+ int i;
+
+ ASSERT(sib);
+ ASSERT(sib->sib_maps);
+
+ if (sib->sib_idmaph)
+ kidmap_get_destroy(sib->sib_idmaph);
+
+ if (sib->sib_flags & SMB_IDMAP_ID2SID) {
+ /*
+ * SIDs are allocated only when mapping
+ * UID/GID to SIDs
+ */
+ for (i = 0; i < sib->sib_nmap; i++)
+ smb_sid_free(sib->sib_maps[i].sim_sid);
+ } else if (sib->sib_flags & SMB_IDMAP_SID2ID) {
+ /*
+ * SID prefixes are allocated only when mapping
+ * SIDs to UID/GID
+ */
+ for (i = 0; i < sib->sib_nmap; i++) {
+ domsid = sib->sib_maps[i].sim_domsid;
+ if (domsid)
+ smb_mem_free(domsid);
+ }
+ }
+
+ if (sib->sib_size && sib->sib_maps)
+ kmem_free(sib->sib_maps, sib->sib_size);
+}
+
+/*
+ * smb_idmap_batch_getid
+ *
+ * Queue a request to map the given SID to a UID or GID.
+ *
+ * sim->sim_id should point to variable that's supposed to
+ * hold the returned UID/GID. This needs to be setup by caller
+ * of this function.
+ *
+ * If requested ID type is known, it's passed as 'idtype',
+ * if it's unknown it'll be returned in sim->sim_idtype.
+ */
+idmap_stat
+smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
+ smb_sid_t *sid, int idtype)
+{
+ char strsid[SMB_SID_STRSZ];
+ idmap_stat idm_stat;
+
+ ASSERT(idmaph);
+ ASSERT(sim);
+ ASSERT(sid);
+
+ smb_sid_tostr(sid, strsid);
+ if (smb_sid_splitstr(strsid, &sim->sim_rid) != 0)
+ return (IDMAP_ERR_SID);
+ sim->sim_domsid = smb_mem_strdup(strsid);
+
+ switch (idtype) {
+ case SMB_IDMAP_USER:
+ idm_stat = kidmap_batch_getuidbysid(idmaph, sim->sim_domsid,
+ sim->sim_rid, sim->sim_id, &sim->sim_stat);
+ break;
+
+ case SMB_IDMAP_GROUP:
+ idm_stat = kidmap_batch_getgidbysid(idmaph, sim->sim_domsid,
+ sim->sim_rid, sim->sim_id, &sim->sim_stat);
+ break;
+
+ case SMB_IDMAP_UNKNOWN:
+ idm_stat = kidmap_batch_getpidbysid(idmaph, sim->sim_domsid,
+ sim->sim_rid, sim->sim_id, &sim->sim_idtype,
+ &sim->sim_stat);
+ break;
+
+ default:
+ ASSERT(0);
+ return (IDMAP_ERR_ARG);
+ }
+
+ return (idm_stat);
+}
+
+/*
+ * smb_idmap_batch_getsid
+ *
+ * Queue a request to map the given UID/GID to a SID.
+ *
+ * sim->sim_domsid and sim->sim_rid will contain the mapping
+ * result upon successful process of the batched request.
+ */
+idmap_stat
+smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
+ uid_t id, int idtype)
+{
+ idmap_stat idm_stat;
+
+ switch (idtype) {
+ case SMB_IDMAP_USER:
+ idm_stat = kidmap_batch_getsidbyuid(idmaph, id,
+ (const char **)&sim->sim_domsid, &sim->sim_rid,
+ &sim->sim_stat);
+ break;
+
+ case SMB_IDMAP_GROUP:
+ idm_stat = kidmap_batch_getsidbygid(idmaph, id,
+ (const char **)&sim->sim_domsid, &sim->sim_rid,
+ &sim->sim_stat);
+ break;
+
+ case SMB_IDMAP_OWNERAT:
+ /* Current Owner S-1-5-32-766 */
+ sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR;
+ sim->sim_rid = SECURITY_CURRENT_OWNER_RID;
+ sim->sim_stat = IDMAP_SUCCESS;
+ idm_stat = IDMAP_SUCCESS;
+ break;
+
+ case SMB_IDMAP_GROUPAT:
+ /* Current Group S-1-5-32-767 */
+ sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR;
+ sim->sim_rid = SECURITY_CURRENT_GROUP_RID;
+ sim->sim_stat = IDMAP_SUCCESS;
+ idm_stat = IDMAP_SUCCESS;
+ break;
+
+ case SMB_IDMAP_EVERYONE:
+ /* Everyone S-1-1-0 */
+ sim->sim_domsid = NT_WORLD_AUTH_SIDSTR;
+ sim->sim_rid = 0;
+ sim->sim_stat = IDMAP_SUCCESS;
+ idm_stat = IDMAP_SUCCESS;
+ break;
+
+ default:
+ ASSERT(0);
+ return (IDMAP_ERR_ARG);
+ }
+
+ return (idm_stat);
+}
+
+/*
+ * smb_idmap_batch_getmappings
+ *
+ * trigger ID mapping service to get the mappings for queued
+ * requests.
+ *
+ * Checks the result of all the queued requests.
+ * If this is a Solaris -> Windows mapping it generates
+ * binary SIDs from returned (domsid, rid) pairs.
+ */
+idmap_stat
+smb_idmap_batch_getmappings(smb_idmap_batch_t *sib)
+{
+ idmap_stat idm_stat = IDMAP_SUCCESS;
+ int i;
+
+ idm_stat = kidmap_get_mappings(sib->sib_idmaph);
+ if (idm_stat != IDMAP_SUCCESS)
+ return (idm_stat);
+
+ /*
+ * Check the status for all the queued requests
+ */
+ for (i = 0; i < sib->sib_nmap; i++) {
+ if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS)
+ return (sib->sib_maps[i].sim_stat);
+ }
+
+ if (smb_idmap_batch_binsid(sib) != 0)
+ idm_stat = IDMAP_ERR_OTHER;
+
+ return (idm_stat);
+}
+
+/*
+ * smb_idmap_batch_binsid
+ *
+ * Convert sidrids to binary sids
+ *
+ * Returns 0 if successful and non-zero upon failure.
+ */
+static int
+smb_idmap_batch_binsid(smb_idmap_batch_t *sib)
+{
+ smb_sid_t *sid;
+ smb_idmap_t *sim;
+ int i;
+
+ if (sib->sib_flags & SMB_IDMAP_SID2ID)
+ /* This operation is not required */
+ return (0);
+
+ sim = sib->sib_maps;
+ for (i = 0; i < sib->sib_nmap; sim++, i++) {
+ ASSERT(sim->sim_domsid);
+ if (sim->sim_domsid == NULL)
+ return (1);
+
+ if ((sid = smb_sid_fromstr(sim->sim_domsid)) == NULL)
+ return (1);
+
+ sim->sim_sid = smb_sid_splice(sid, sim->sim_rid);
+ smb_sid_free(sid);
+ }
+
+ return (0);
+}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_init.c b/usr/src/uts/common/fs/smbsrv/smb_init.c
index 323bd65089..90619f8b4d 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_init.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_init.c
@@ -19,11 +19,12 @@
* CDDL HEADER END
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/types.h>
+#include <sys/conf.h>
#include <sys/ddi.h>
#include <sys/modctl.h>
#include <sys/cred.h>
@@ -34,6 +35,10 @@
#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_ioctl.h>
+#ifdef _FAKE_KERNEL
+#error "See libfksmbsrv"
+#endif /* _FAKE_KERNEL */
+
static int smb_drv_open(dev_t *, int, int, cred_t *);
static int smb_drv_close(dev_t, int, int, cred_t *);
static int smb_drv_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_kdoor.c b/usr/src/uts/common/fs/smbsrv/smb_kdoor.c
index f14a54a6cc..3b39ad1db2 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_kdoor.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_kdoor.c
@@ -19,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/types.h>
@@ -32,6 +32,10 @@
#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_door.h>
+#ifdef _FAKE_KERNEL
+#error "See libfksmbsrv"
+#endif /* _FAKE_KERNEL */
+
static int smb_kdoor_send(smb_server_t *, smb_doorarg_t *);
static int smb_kdoor_receive(smb_server_t *, smb_doorarg_t *);
static int smb_kdoor_upcall_private(smb_server_t *, smb_doorarg_t *);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_kshare.c b/usr/src/uts/common/fs/smbsrv/smb_kshare.c
index 68a2e8587c..53e900d0ed 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_kshare.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_kshare.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <smbsrv/smb_door.h>
@@ -54,7 +54,9 @@ static void smb_kshare_csc_flags(smb_kshare_t *, const char *);
static boolean_t smb_export_isready(smb_server_t *);
+#ifdef _KERNEL
static int smb_kshare_chk_dsrv_status(int, smb_dr_ctx_t *);
+#endif /* _KERNEL */
static const smb_avl_nops_t smb_kshare_avlops = {
smb_kshare_cmp,
@@ -63,6 +65,7 @@ static const smb_avl_nops_t smb_kshare_avlops = {
smb_kshare_destroy
};
+#ifdef _KERNEL
/*
* This function is not MultiThread safe. The caller has to make sure only one
* thread calls this function.
@@ -115,7 +118,8 @@ smb_kshare_upcall(door_handle_t dhdl, void *arg, boolean_t add_share)
switch (opcode) {
case SMB_SHROP_ADD:
lmshare = kmem_alloc(sizeof (smb_share_t), KM_SLEEP);
- if (error = xcopyin(arg, lmshare, sizeof (smb_share_t))) {
+ error = xcopyin(arg, lmshare, sizeof (smb_share_t));
+ if (error != 0) {
kmem_free(lmshare, sizeof (smb_share_t));
kmem_free(buf, SMB_SHARE_DSIZE);
return (error);
@@ -125,7 +129,8 @@ smb_kshare_upcall(door_handle_t dhdl, void *arg, boolean_t add_share)
case SMB_SHROP_DELETE:
str = kmem_alloc(MAXPATHLEN, KM_SLEEP);
- if (error = copyinstr(arg, str, MAXPATHLEN, NULL)) {
+ error = copyinstr(arg, str, MAXPATHLEN, NULL);
+ if (error != 0) {
kmem_free(str, MAXPATHLEN);
kmem_free(buf, SMB_SHARE_DSIZE);
return (error);
@@ -177,6 +182,7 @@ smb_kshare_upcall(door_handle_t dhdl, void *arg, boolean_t add_share)
return ((rc == NERR_DuplicateShare && add_share) ? 0 : rc);
}
+#endif /* _KERNEL */
/*
* Executes map and unmap command for shares.
@@ -1197,6 +1203,7 @@ smb_export_isready(smb_server_t *sv)
return (ready);
}
+#ifdef _KERNEL
/*
* Return 0 upon success. Otherwise > 0
*/
@@ -1221,3 +1228,4 @@ smb_kshare_chk_dsrv_status(int opcode, smb_dr_ctx_t *dec_ctx)
ASSERT(0);
return (EINVAL);
}
+#endif /* _KERNEL */
diff --git a/usr/src/uts/common/fs/smbsrv/smb_kutil.c b/usr/src/uts/common/fs/smbsrv/smb_kutil.c
index b9564035eb..a31865f298 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_kutil.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_kutil.c
@@ -21,17 +21,15 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/tzfile.h>
#include <sys/atomic.h>
-#include <sys/kidmap.h>
#include <sys/time.h>
#include <sys/spl.h>
-#include <sys/cpuvar.h>
#include <sys/random.h>
#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_fsops.h>
@@ -45,8 +43,6 @@
static kmem_cache_t *smb_dtor_cache = NULL;
-static boolean_t smb_thread_continue_timedwait_locked(smb_thread_t *, int);
-
static boolean_t smb_avl_hold(smb_avl_t *);
static void smb_avl_rele(smb_avl_t *);
@@ -759,260 +755,7 @@ smb_slist_exit(smb_slist_t *sl)
mutex_exit(&sl->sl_mutex);
}
-/*
- * smb_thread_entry_point
- *
- * Common entry point for all the threads created through smb_thread_start.
- * The state of the thread is set to "running" at the beginning and moved to
- * "exiting" just before calling thread_exit(). The condition variable is
- * also signaled.
- */
-static void
-smb_thread_entry_point(
- smb_thread_t *thread)
-{
- ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
- mutex_enter(&thread->sth_mtx);
- ASSERT(thread->sth_state == SMB_THREAD_STATE_STARTING);
- thread->sth_th = curthread;
- thread->sth_did = thread->sth_th->t_did;
-
- if (!thread->sth_kill) {
- thread->sth_state = SMB_THREAD_STATE_RUNNING;
- cv_signal(&thread->sth_cv);
- mutex_exit(&thread->sth_mtx);
- thread->sth_ep(thread, thread->sth_ep_arg);
- mutex_enter(&thread->sth_mtx);
- }
- thread->sth_th = NULL;
- thread->sth_state = SMB_THREAD_STATE_EXITING;
- cv_broadcast(&thread->sth_cv);
- mutex_exit(&thread->sth_mtx);
- zthread_exit();
-}
-
-/*
- * smb_thread_init
- */
-void
-smb_thread_init(
- smb_thread_t *thread,
- char *name,
- smb_thread_ep_t ep,
- void *ep_arg,
- pri_t pri)
-{
- ASSERT(thread->sth_magic != SMB_THREAD_MAGIC);
-
- bzero(thread, sizeof (*thread));
-
- (void) strlcpy(thread->sth_name, name, sizeof (thread->sth_name));
- thread->sth_ep = ep;
- thread->sth_ep_arg = ep_arg;
- thread->sth_state = SMB_THREAD_STATE_EXITED;
- thread->sth_pri = pri;
- mutex_init(&thread->sth_mtx, NULL, MUTEX_DEFAULT, NULL);
- cv_init(&thread->sth_cv, NULL, CV_DEFAULT, NULL);
- thread->sth_magic = SMB_THREAD_MAGIC;
-}
-
-/*
- * smb_thread_destroy
- */
-void
-smb_thread_destroy(
- smb_thread_t *thread)
-{
- ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
- ASSERT(thread->sth_state == SMB_THREAD_STATE_EXITED);
- thread->sth_magic = 0;
- mutex_destroy(&thread->sth_mtx);
- cv_destroy(&thread->sth_cv);
-}
-
-/*
- * smb_thread_start
- *
- * This function starts a thread with the parameters provided. It waits until
- * the state of the thread has been moved to running.
- */
-/*ARGSUSED*/
-int
-smb_thread_start(
- smb_thread_t *thread)
-{
- int rc = 0;
- kthread_t *tmpthread;
-
- ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
-
- mutex_enter(&thread->sth_mtx);
- switch (thread->sth_state) {
- case SMB_THREAD_STATE_EXITED:
- thread->sth_state = SMB_THREAD_STATE_STARTING;
- mutex_exit(&thread->sth_mtx);
- tmpthread = zthread_create(NULL, 0, smb_thread_entry_point,
- thread, 0, thread->sth_pri);
- ASSERT(tmpthread != NULL);
- mutex_enter(&thread->sth_mtx);
- while (thread->sth_state == SMB_THREAD_STATE_STARTING)
- cv_wait(&thread->sth_cv, &thread->sth_mtx);
- if (thread->sth_state != SMB_THREAD_STATE_RUNNING)
- rc = -1;
- break;
- default:
- ASSERT(0);
- rc = -1;
- break;
- }
- mutex_exit(&thread->sth_mtx);
- return (rc);
-}
-
-/*
- * smb_thread_stop
- *
- * This function signals a thread to kill itself and waits until the "exiting"
- * state has been reached.
- */
-void
-smb_thread_stop(smb_thread_t *thread)
-{
- ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
-
- mutex_enter(&thread->sth_mtx);
- switch (thread->sth_state) {
- case SMB_THREAD_STATE_RUNNING:
- case SMB_THREAD_STATE_STARTING:
- if (!thread->sth_kill) {
- thread->sth_kill = B_TRUE;
- cv_broadcast(&thread->sth_cv);
- while (thread->sth_state != SMB_THREAD_STATE_EXITING)
- cv_wait(&thread->sth_cv, &thread->sth_mtx);
- mutex_exit(&thread->sth_mtx);
- thread_join(thread->sth_did);
- mutex_enter(&thread->sth_mtx);
- thread->sth_state = SMB_THREAD_STATE_EXITED;
- thread->sth_did = 0;
- thread->sth_kill = B_FALSE;
- cv_broadcast(&thread->sth_cv);
- break;
- }
- /*FALLTHRU*/
-
- case SMB_THREAD_STATE_EXITING:
- if (thread->sth_kill) {
- while (thread->sth_state != SMB_THREAD_STATE_EXITED)
- cv_wait(&thread->sth_cv, &thread->sth_mtx);
- } else {
- thread->sth_state = SMB_THREAD_STATE_EXITED;
- thread->sth_did = 0;
- }
- break;
-
- case SMB_THREAD_STATE_EXITED:
- break;
-
- default:
- ASSERT(0);
- break;
- }
- mutex_exit(&thread->sth_mtx);
-}
-
-/*
- * smb_thread_signal
- *
- * This function signals a thread.
- */
-void
-smb_thread_signal(smb_thread_t *thread)
-{
- ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
-
- mutex_enter(&thread->sth_mtx);
- switch (thread->sth_state) {
- case SMB_THREAD_STATE_RUNNING:
- cv_signal(&thread->sth_cv);
- break;
-
- default:
- break;
- }
- mutex_exit(&thread->sth_mtx);
-}
-
-boolean_t
-smb_thread_continue(smb_thread_t *thread)
-{
- boolean_t result;
-
- ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
-
- mutex_enter(&thread->sth_mtx);
- result = smb_thread_continue_timedwait_locked(thread, 0);
- mutex_exit(&thread->sth_mtx);
-
- return (result);
-}
-
-boolean_t
-smb_thread_continue_nowait(smb_thread_t *thread)
-{
- boolean_t result;
-
- ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
-
- mutex_enter(&thread->sth_mtx);
- /*
- * Setting ticks=-1 requests a non-blocking check. We will
- * still block if the thread is in "suspend" state.
- */
- result = smb_thread_continue_timedwait_locked(thread, -1);
- mutex_exit(&thread->sth_mtx);
-
- return (result);
-}
-
-boolean_t
-smb_thread_continue_timedwait(smb_thread_t *thread, int seconds)
-{
- boolean_t result;
-
- ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
-
- mutex_enter(&thread->sth_mtx);
- result = smb_thread_continue_timedwait_locked(thread,
- SEC_TO_TICK(seconds));
- mutex_exit(&thread->sth_mtx);
-
- return (result);
-}
-
-/*
- * smb_thread_continue_timedwait_locked
- *
- * Internal only. Ticks==-1 means don't block, Ticks == 0 means wait
- * indefinitely
- */
-static boolean_t
-smb_thread_continue_timedwait_locked(smb_thread_t *thread, int ticks)
-{
- boolean_t result;
-
- /* -1 means don't block */
- if (ticks != -1 && !thread->sth_kill) {
- if (ticks == 0) {
- cv_wait(&thread->sth_cv, &thread->sth_mtx);
- } else {
- (void) cv_reltimedwait(&thread->sth_cv,
- &thread->sth_mtx, (clock_t)ticks, TR_CLOCK_TICK);
- }
- }
- result = (thread->sth_kill == 0);
-
- return (result);
-}
+/* smb_thread_... moved to smb_thread.c */
/*
* smb_rwx_init
@@ -1117,8 +860,8 @@ smb_rwx_rwwait(
smb_rwx_t *rwx,
clock_t timeout)
{
- int rc;
krw_t mode;
+ int rc = 1;
mutex_enter(&rwx->rwx_mutex);
rwx->rwx_waiting = B_TRUE;
@@ -1136,7 +879,6 @@ smb_rwx_rwwait(
mutex_enter(&rwx->rwx_mutex);
if (rwx->rwx_waiting) {
if (timeout == -1) {
- rc = 1;
cv_wait(&rwx->rwx_cv, &rwx->rwx_mutex);
} else {
rc = cv_reltimedwait(&rwx->rwx_cv, &rwx->rwx_mutex,
@@ -1149,361 +891,7 @@ smb_rwx_rwwait(
return (rc);
}
-/*
- * SMB ID mapping
- *
- * Solaris ID mapping service (aka Winchester) works with domain SIDs
- * and RIDs where domain SIDs are in string format. CIFS service works
- * with binary SIDs understandable by CIFS clients. A layer of SMB ID
- * mapping functions are implemeted to hide the SID conversion details
- * and also hide the handling of array of batch mapping requests.
- *
- * IMPORTANT NOTE The Winchester API requires a zone. Because CIFS server
- * currently only runs in the global zone the global zone is specified.
- * This needs to be fixed when the CIFS server supports zones.
- */
-
-static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib);
-
-/*
- * smb_idmap_getid
- *
- * Maps the given Windows SID to a Solaris ID using the
- * simple mapping API.
- */
-idmap_stat
-smb_idmap_getid(smb_sid_t *sid, uid_t *id, int *idtype)
-{
- smb_idmap_t sim;
- char sidstr[SMB_SID_STRSZ];
-
- smb_sid_tostr(sid, sidstr);
- if (smb_sid_splitstr(sidstr, &sim.sim_rid) != 0)
- return (IDMAP_ERR_SID);
- sim.sim_domsid = sidstr;
- sim.sim_id = id;
-
- switch (*idtype) {
- case SMB_IDMAP_USER:
- sim.sim_stat = kidmap_getuidbysid(global_zone, sim.sim_domsid,
- sim.sim_rid, sim.sim_id);
- break;
-
- case SMB_IDMAP_GROUP:
- sim.sim_stat = kidmap_getgidbysid(global_zone, sim.sim_domsid,
- sim.sim_rid, sim.sim_id);
- break;
-
- case SMB_IDMAP_UNKNOWN:
- sim.sim_stat = kidmap_getpidbysid(global_zone, sim.sim_domsid,
- sim.sim_rid, sim.sim_id, &sim.sim_idtype);
- break;
-
- default:
- ASSERT(0);
- return (IDMAP_ERR_ARG);
- }
-
- *idtype = sim.sim_idtype;
-
- return (sim.sim_stat);
-}
-
-/*
- * smb_idmap_getsid
- *
- * Maps the given Solaris ID to a Windows SID using the
- * simple mapping API.
- */
-idmap_stat
-smb_idmap_getsid(uid_t id, int idtype, smb_sid_t **sid)
-{
- smb_idmap_t sim;
-
- switch (idtype) {
- case SMB_IDMAP_USER:
- sim.sim_stat = kidmap_getsidbyuid(global_zone, id,
- (const char **)&sim.sim_domsid, &sim.sim_rid);
- break;
-
- case SMB_IDMAP_GROUP:
- sim.sim_stat = kidmap_getsidbygid(global_zone, id,
- (const char **)&sim.sim_domsid, &sim.sim_rid);
- break;
-
- case SMB_IDMAP_EVERYONE:
- /* Everyone S-1-1-0 */
- sim.sim_domsid = "S-1-1";
- sim.sim_rid = 0;
- sim.sim_stat = IDMAP_SUCCESS;
- break;
-
- default:
- ASSERT(0);
- return (IDMAP_ERR_ARG);
- }
-
- if (sim.sim_stat != IDMAP_SUCCESS)
- return (sim.sim_stat);
-
- if (sim.sim_domsid == NULL)
- return (IDMAP_ERR_NOMAPPING);
-
- sim.sim_sid = smb_sid_fromstr(sim.sim_domsid);
- if (sim.sim_sid == NULL)
- return (IDMAP_ERR_INTERNAL);
-
- *sid = smb_sid_splice(sim.sim_sid, sim.sim_rid);
- smb_sid_free(sim.sim_sid);
- if (*sid == NULL)
- sim.sim_stat = IDMAP_ERR_INTERNAL;
-
- return (sim.sim_stat);
-}
-
-/*
- * smb_idmap_batch_create
- *
- * Creates and initializes the context for batch ID mapping.
- */
-idmap_stat
-smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags)
-{
- ASSERT(sib);
-
- bzero(sib, sizeof (smb_idmap_batch_t));
-
- sib->sib_idmaph = kidmap_get_create(global_zone);
-
- sib->sib_flags = flags;
- sib->sib_nmap = nmap;
- sib->sib_size = nmap * sizeof (smb_idmap_t);
- sib->sib_maps = kmem_zalloc(sib->sib_size, KM_SLEEP);
-
- return (IDMAP_SUCCESS);
-}
-
-/*
- * smb_idmap_batch_destroy
- *
- * Frees the batch ID mapping context.
- * If ID mapping is Solaris -> Windows it frees memories
- * allocated for binary SIDs.
- */
-void
-smb_idmap_batch_destroy(smb_idmap_batch_t *sib)
-{
- char *domsid;
- int i;
-
- ASSERT(sib);
- ASSERT(sib->sib_maps);
-
- if (sib->sib_idmaph)
- kidmap_get_destroy(sib->sib_idmaph);
-
- if (sib->sib_flags & SMB_IDMAP_ID2SID) {
- /*
- * SIDs are allocated only when mapping
- * UID/GID to SIDs
- */
- for (i = 0; i < sib->sib_nmap; i++)
- smb_sid_free(sib->sib_maps[i].sim_sid);
- } else if (sib->sib_flags & SMB_IDMAP_SID2ID) {
- /*
- * SID prefixes are allocated only when mapping
- * SIDs to UID/GID
- */
- for (i = 0; i < sib->sib_nmap; i++) {
- domsid = sib->sib_maps[i].sim_domsid;
- if (domsid)
- smb_mem_free(domsid);
- }
- }
-
- if (sib->sib_size && sib->sib_maps)
- kmem_free(sib->sib_maps, sib->sib_size);
-}
-
-/*
- * smb_idmap_batch_getid
- *
- * Queue a request to map the given SID to a UID or GID.
- *
- * sim->sim_id should point to variable that's supposed to
- * hold the returned UID/GID. This needs to be setup by caller
- * of this function.
- *
- * If requested ID type is known, it's passed as 'idtype',
- * if it's unknown it'll be returned in sim->sim_idtype.
- */
-idmap_stat
-smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
- smb_sid_t *sid, int idtype)
-{
- char strsid[SMB_SID_STRSZ];
- idmap_stat idm_stat;
-
- ASSERT(idmaph);
- ASSERT(sim);
- ASSERT(sid);
-
- smb_sid_tostr(sid, strsid);
- if (smb_sid_splitstr(strsid, &sim->sim_rid) != 0)
- return (IDMAP_ERR_SID);
- sim->sim_domsid = smb_mem_strdup(strsid);
-
- switch (idtype) {
- case SMB_IDMAP_USER:
- idm_stat = kidmap_batch_getuidbysid(idmaph, sim->sim_domsid,
- sim->sim_rid, sim->sim_id, &sim->sim_stat);
- break;
-
- case SMB_IDMAP_GROUP:
- idm_stat = kidmap_batch_getgidbysid(idmaph, sim->sim_domsid,
- sim->sim_rid, sim->sim_id, &sim->sim_stat);
- break;
-
- case SMB_IDMAP_UNKNOWN:
- idm_stat = kidmap_batch_getpidbysid(idmaph, sim->sim_domsid,
- sim->sim_rid, sim->sim_id, &sim->sim_idtype,
- &sim->sim_stat);
- break;
-
- default:
- ASSERT(0);
- return (IDMAP_ERR_ARG);
- }
-
- return (idm_stat);
-}
-
-/*
- * smb_idmap_batch_getsid
- *
- * Queue a request to map the given UID/GID to a SID.
- *
- * sim->sim_domsid and sim->sim_rid will contain the mapping
- * result upon successful process of the batched request.
- */
-idmap_stat
-smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
- uid_t id, int idtype)
-{
- idmap_stat idm_stat;
-
- switch (idtype) {
- case SMB_IDMAP_USER:
- idm_stat = kidmap_batch_getsidbyuid(idmaph, id,
- (const char **)&sim->sim_domsid, &sim->sim_rid,
- &sim->sim_stat);
- break;
-
- case SMB_IDMAP_GROUP:
- idm_stat = kidmap_batch_getsidbygid(idmaph, id,
- (const char **)&sim->sim_domsid, &sim->sim_rid,
- &sim->sim_stat);
- break;
-
- case SMB_IDMAP_OWNERAT:
- /* Current Owner S-1-5-32-766 */
- sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR;
- sim->sim_rid = SECURITY_CURRENT_OWNER_RID;
- sim->sim_stat = IDMAP_SUCCESS;
- idm_stat = IDMAP_SUCCESS;
- break;
-
- case SMB_IDMAP_GROUPAT:
- /* Current Group S-1-5-32-767 */
- sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR;
- sim->sim_rid = SECURITY_CURRENT_GROUP_RID;
- sim->sim_stat = IDMAP_SUCCESS;
- idm_stat = IDMAP_SUCCESS;
- break;
-
- case SMB_IDMAP_EVERYONE:
- /* Everyone S-1-1-0 */
- sim->sim_domsid = NT_WORLD_AUTH_SIDSTR;
- sim->sim_rid = 0;
- sim->sim_stat = IDMAP_SUCCESS;
- idm_stat = IDMAP_SUCCESS;
- break;
-
- default:
- ASSERT(0);
- return (IDMAP_ERR_ARG);
- }
-
- return (idm_stat);
-}
-
-/*
- * smb_idmap_batch_binsid
- *
- * Convert sidrids to binary sids
- *
- * Returns 0 if successful and non-zero upon failure.
- */
-static int
-smb_idmap_batch_binsid(smb_idmap_batch_t *sib)
-{
- smb_sid_t *sid;
- smb_idmap_t *sim;
- int i;
-
- if (sib->sib_flags & SMB_IDMAP_SID2ID)
- /* This operation is not required */
- return (0);
-
- sim = sib->sib_maps;
- for (i = 0; i < sib->sib_nmap; sim++, i++) {
- ASSERT(sim->sim_domsid);
- if (sim->sim_domsid == NULL)
- return (1);
-
- if ((sid = smb_sid_fromstr(sim->sim_domsid)) == NULL)
- return (1);
-
- sim->sim_sid = smb_sid_splice(sid, sim->sim_rid);
- smb_sid_free(sid);
- }
-
- return (0);
-}
-
-/*
- * smb_idmap_batch_getmappings
- *
- * trigger ID mapping service to get the mappings for queued
- * requests.
- *
- * Checks the result of all the queued requests.
- * If this is a Solaris -> Windows mapping it generates
- * binary SIDs from returned (domsid, rid) pairs.
- */
-idmap_stat
-smb_idmap_batch_getmappings(smb_idmap_batch_t *sib)
-{
- idmap_stat idm_stat = IDMAP_SUCCESS;
- int i;
-
- idm_stat = kidmap_get_mappings(sib->sib_idmaph);
- if (idm_stat != IDMAP_SUCCESS)
- return (idm_stat);
-
- /*
- * Check the status for all the queued requests
- */
- for (i = 0; i < sib->sib_nmap; i++) {
- if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS)
- return (sib->sib_maps[i].sim_stat);
- }
-
- if (smb_idmap_batch_binsid(sib) != 0)
- idm_stat = IDMAP_ERR_OTHER;
-
- return (idm_stat);
-}
+/* smb_idmap_... moved to smb_idmap.c */
uint64_t
smb_time_unix_to_nt(timestruc_t *unix_time)
diff --git a/usr/src/uts/common/fs/smbsrv/smb_lock.c b/usr/src/uts/common/fs/smbsrv/smb_lock.c
index e9cc41ae02..d86dd76604 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_lock.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_lock.c
@@ -595,7 +595,7 @@ smb_lock_range_lckrules(
static clock_t
smb_lock_wait(smb_request_t *sr, smb_lock_t *b_lock, smb_lock_t *c_lock)
{
- clock_t rc;
+ clock_t rc = 0;
ASSERT(sr->sr_awaiting == NULL);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_mangle_name.c b/usr/src/uts/common/fs/smbsrv/smb_mangle_name.c
index db19fb84c6..7555441f01 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_mangle_name.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_mangle_name.c
@@ -19,14 +19,15 @@
* CDDL HEADER END
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/types.h>
#include <sys/param.h>
#include <sys/sunddi.h>
#include <sys/errno.h>
+#include <sys/extdirent.h>
#include <smbsrv/string.h>
#include <smbsrv/smb_vops.h>
#include <smbsrv/smb_kproto.h>
@@ -375,13 +376,13 @@ smb_unmangle(smb_node_t *dnode, char *name, char *namebuf,
char shortname[SMB_SHORTNAMELEN];
vnode_t *vp;
union {
- char *bufptr;
- edirent_t *edp;
- dirent64_t *dp;
+ char *u_bufptr;
+ edirent_t *u_edp;
+ dirent64_t *u_dp;
} u;
-#define bufptr u.bufptr
-#define edp u.edp
-#define dp u.dp
+#define bufptr u.u_bufptr
+#define edp u.u_edp
+#define dp u.u_dp
if (dnode == NULL || name == NULL || namebuf == NULL || buflen == 0)
return (EINVAL);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_negotiate.c b/usr/src/uts/common/fs/smbsrv/smb_negotiate.c
index b22ff8e8f1..46bd2964ad 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_negotiate.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_negotiate.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -186,8 +186,6 @@
* ERRSRV/ERRerror
*/
#include <sys/types.h>
-#include <sys/strsubr.h>
-#include <sys/socketvar.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <smbsrv/smb_kproto.h>
diff --git a/usr/src/uts/common/fs/smbsrv/smb_net.c b/usr/src/uts/common/fs/smbsrv/smb_net.c
index d112688a45..9f63846537 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_net.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_net.c
@@ -19,23 +19,22 @@
* CDDL HEADER END
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/types.h>
#include <sys/param.h>
-#include <sys/cpuvar.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/time.h>
#include <sys/varargs.h>
#include <sys/modctl.h>
#include <sys/pathname.h>
-#include <sys/fs/snode.h>
-#include <sys/fs/dv_node.h>
#include <sys/vnode.h>
+#include <sys/socket.h>
#include <sys/ksocket.h>
#undef mem_free /* XXX Remove this after we convert everything to kmem_alloc */
diff --git a/usr/src/uts/common/fs/smbsrv/smb_node.c b/usr/src/uts/common/fs/smbsrv/smb_node.c
index 95411528f2..8ff046cb5d 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_node.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_node.c
@@ -1191,7 +1191,7 @@ smb_node_free(smb_node_t *node)
VERIFY(node->n_oplock.ol_count == 0);
VERIFY(node->n_oplock.ol_xthread == NULL);
VERIFY(node->n_oplock.ol_fem == B_FALSE);
- VERIFY(mutex_owner(&node->n_mutex) == NULL);
+ VERIFY(MUTEX_NOT_HELD(&node->n_mutex));
VERIFY(!RW_LOCK_HELD(&node->n_lock));
VN_RELE(node->vp);
kmem_cache_free(smb_node_cache, node);
@@ -1284,6 +1284,7 @@ smb_node_destroy_audit_buf(smb_node_t *node)
static void
smb_node_audit(smb_node_t *node)
{
+#ifdef _KERNEL
smb_audit_buf_node_t *abn;
smb_audit_record_node_t *anr;
@@ -1297,6 +1298,9 @@ smb_node_audit(smb_node_t *node)
anr->anr_depth = getpcstack(anr->anr_stack,
SMB_AUDIT_STACK_DEPTH);
}
+#else /* _KERNEL */
+ _NOTE(ARGUNUSED(node))
+#endif /* _KERNEL */
}
static smb_llist_t *
@@ -1722,6 +1726,10 @@ smb_node_getattr(smb_request_t *sr, smb_node_t *node, cred_t *cr,
}
+#ifndef _KERNEL
+extern int reparse_vnode_parse(vnode_t *vp, nvlist_t *nvl);
+#endif /* _KERNEL */
+
/*
* Check to see if the node represents a reparse point.
* If yes, whether the reparse point contains a DFS link.
diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c
index dcfa469617..54dd589b7c 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_create.c
@@ -250,8 +250,7 @@ smb_nt_transact_create(smb_request_t *sr, smb_xa_t *xa)
ERRDOS, ERROR_INVALID_FUNCTION);
goto errout;
}
- if (rc == 0)
- return (SDRC_SUCCESS);
+ return (SDRC_SUCCESS);
errout:
smb_ofile_close(of, 0);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_opipe.c b/usr/src/uts/common/fs/smbsrv/smb_opipe.c
index 41f1149e87..116cdc6e3b 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_opipe.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_opipe.c
@@ -40,6 +40,7 @@
((OPIPE)->p_hdr.dh_fid))
extern volatile uint32_t smb_fids;
+#define SMB_UNIQ_FID() atomic_inc_32_nv(&smb_fids)
static int smb_opipe_do_open(smb_request_t *, smb_opipe_t *);
static char *smb_opipe_lookup(const char *);
@@ -48,8 +49,6 @@ static int smb_opipe_exec(smb_opipe_t *);
static void smb_opipe_enter(smb_opipe_t *);
static void smb_opipe_exit(smb_opipe_t *);
-static int smb_opipe_door_call(smb_opipe_t *);
-static int smb_opipe_door_upcall(smb_opipe_t *);
smb_opipe_t *
smb_opipe_alloc(smb_server_t *sv)
@@ -541,148 +540,3 @@ smb_opipe_exit(smb_opipe_t *opipe)
cv_signal(&opipe->p_cv);
mutex_exit(&opipe->p_mutex);
}
-
-/*
- * opipe door client (to user space door server).
- */
-void
-smb_opipe_door_init(smb_server_t *sv)
-{
- sv->sv_opipe_door_id = -1;
- mutex_init(&sv->sv_opipe_door_mutex, NULL, MUTEX_DEFAULT, NULL);
- cv_init(&sv->sv_opipe_door_cv, NULL, CV_DEFAULT, NULL);
-}
-
-void
-smb_opipe_door_fini(smb_server_t *sv)
-{
- smb_opipe_door_close(sv);
- cv_destroy(&sv->sv_opipe_door_cv);
- mutex_destroy(&sv->sv_opipe_door_mutex);
-}
-
-/*
- * Open the (user space) door. If the door is already open,
- * close it first because the door-id has probably changed.
- */
-int
-smb_opipe_door_open(smb_server_t *sv, int door_id)
-{
- smb_opipe_door_close(sv);
-
- mutex_enter(&sv->sv_opipe_door_mutex);
- sv->sv_opipe_door_ncall = 0;
-
- if (sv->sv_opipe_door_hd == NULL) {
- sv->sv_opipe_door_id = door_id;
- sv->sv_opipe_door_hd = door_ki_lookup(door_id);
- }
-
- mutex_exit(&sv->sv_opipe_door_mutex);
- return ((sv->sv_opipe_door_hd == NULL) ? -1 : 0);
-}
-
-/*
- * Close the (user space) door.
- */
-void
-smb_opipe_door_close(smb_server_t *sv)
-{
- mutex_enter(&sv->sv_opipe_door_mutex);
-
- if (sv->sv_opipe_door_hd != NULL) {
- while (sv->sv_opipe_door_ncall > 0)
- cv_wait(&sv->sv_opipe_door_cv,
- &sv->sv_opipe_door_mutex);
-
- door_ki_rele(sv->sv_opipe_door_hd);
- sv->sv_opipe_door_hd = NULL;
- }
-
- mutex_exit(&sv->sv_opipe_door_mutex);
-}
-
-/*
- * opipe door call interface.
- * Door serialization and call reference accounting is handled here.
- */
-static int
-smb_opipe_door_call(smb_opipe_t *opipe)
-{
- int rc;
- smb_server_t *sv = opipe->p_server;
-
- mutex_enter(&sv->sv_opipe_door_mutex);
-
- if (sv->sv_opipe_door_hd == NULL) {
- mutex_exit(&sv->sv_opipe_door_mutex);
-
- if (smb_opipe_door_open(sv, sv->sv_opipe_door_id) != 0)
- return (-1);
-
- mutex_enter(&sv->sv_opipe_door_mutex);
- }
-
- sv->sv_opipe_door_ncall++;
- mutex_exit(&sv->sv_opipe_door_mutex);
-
- rc = smb_opipe_door_upcall(opipe);
-
- mutex_enter(&sv->sv_opipe_door_mutex);
- if ((--sv->sv_opipe_door_ncall) == 0)
- cv_signal(&sv->sv_opipe_door_cv);
- mutex_exit(&sv->sv_opipe_door_mutex);
- return (rc);
-}
-
-/*
- * Door upcall wrapper - handles data marshalling.
- * This function should only be called by smb_opipe_door_call.
- */
-static int
-smb_opipe_door_upcall(smb_opipe_t *opipe)
-{
- smb_server_t *sv = opipe->p_server;
- door_arg_t da;
- smb_doorhdr_t hdr;
- int i;
- int rc;
-
- da.data_ptr = (char *)opipe->p_doorbuf;
- da.data_size = SMB_OPIPE_DOOR_BUFSIZE;
- da.desc_ptr = NULL;
- da.desc_num = 0;
- da.rbuf = (char *)opipe->p_doorbuf;
- da.rsize = SMB_OPIPE_DOOR_BUFSIZE;
-
- for (i = 0; i < 3; ++i) {
- if (smb_server_is_stopping(sv))
- return (-1);
-
- if ((rc = door_ki_upcall_limited(sv->sv_opipe_door_hd,
- &da, NULL, SIZE_MAX, 0)) == 0)
- break;
-
- if (rc != EAGAIN && rc != EINTR)
- return (-1);
- }
-
- /* Check for door_return(NULL, 0, NULL, 0) */
- if (rc != 0 || da.data_size == 0 || da.rsize == 0)
- return (-1);
-
- if (smb_doorhdr_decode(&hdr, (uint8_t *)da.data_ptr, da.rsize) == -1)
- return (-1);
-
- if ((hdr.dh_magic != SMB_OPIPE_HDR_MAGIC) ||
- (hdr.dh_fid != opipe->p_hdr.dh_fid) ||
- (hdr.dh_op != opipe->p_hdr.dh_op) ||
- (hdr.dh_door_rc != 0) ||
- (hdr.dh_datalen > SMB_OPIPE_DOOR_BUFSIZE)) {
- return (-1);
- }
-
- opipe->p_hdr.dh_datalen = hdr.dh_datalen;
- opipe->p_hdr.dh_resid = hdr.dh_resid;
- return (0);
-}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_opipe_door.c b/usr/src/uts/common/fs/smbsrv/smb_opipe_door.c
new file mode 100644
index 0000000000..6dc1b8c007
--- /dev/null
+++ b/usr/src/uts/common/fs/smbsrv/smb_opipe_door.c
@@ -0,0 +1,188 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/*
+ * This module provides the interface to the opipe door.
+ * (used by the NDR RPC services).
+ */
+
+#include <sys/stat.h>
+#include <sys/door.h>
+#include <sys/door_data.h>
+#include <sys/uio.h>
+#include <sys/ksynch.h>
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smb_xdr.h>
+
+#ifdef _FAKE_KERNEL
+#error "See libfksmbsrv"
+#endif /* _FAKE_KERNEL */
+
+static int smb_opipe_door_upcall(smb_opipe_t *);
+
+/*
+ * opipe door client (to user space door server).
+ */
+void
+smb_opipe_door_init(smb_server_t *sv)
+{
+ sv->sv_opipe_door_id = -1;
+ mutex_init(&sv->sv_opipe_door_mutex, NULL, MUTEX_DEFAULT, NULL);
+ cv_init(&sv->sv_opipe_door_cv, NULL, CV_DEFAULT, NULL);
+}
+
+void
+smb_opipe_door_fini(smb_server_t *sv)
+{
+ smb_opipe_door_close(sv);
+ cv_destroy(&sv->sv_opipe_door_cv);
+ mutex_destroy(&sv->sv_opipe_door_mutex);
+}
+
+/*
+ * Open the (user space) door. If the door is already open,
+ * close it first because the door-id has probably changed.
+ */
+int
+smb_opipe_door_open(smb_server_t *sv, int door_id)
+{
+ smb_opipe_door_close(sv);
+
+ mutex_enter(&sv->sv_opipe_door_mutex);
+ sv->sv_opipe_door_ncall = 0;
+
+ if (sv->sv_opipe_door_hd == NULL) {
+ sv->sv_opipe_door_id = door_id;
+ sv->sv_opipe_door_hd = door_ki_lookup(door_id);
+ }
+
+ mutex_exit(&sv->sv_opipe_door_mutex);
+ return ((sv->sv_opipe_door_hd == NULL) ? -1 : 0);
+}
+
+/*
+ * Close the (user space) door.
+ */
+void
+smb_opipe_door_close(smb_server_t *sv)
+{
+ mutex_enter(&sv->sv_opipe_door_mutex);
+
+ if (sv->sv_opipe_door_hd != NULL) {
+ while (sv->sv_opipe_door_ncall > 0)
+ cv_wait(&sv->sv_opipe_door_cv,
+ &sv->sv_opipe_door_mutex);
+
+ door_ki_rele(sv->sv_opipe_door_hd);
+ sv->sv_opipe_door_hd = NULL;
+ }
+
+ mutex_exit(&sv->sv_opipe_door_mutex);
+}
+
+/*
+ * opipe door call interface.
+ * Door serialization and call reference accounting is handled here.
+ */
+int
+smb_opipe_door_call(smb_opipe_t *opipe)
+{
+ int rc;
+ smb_server_t *sv = opipe->p_server;
+
+ mutex_enter(&sv->sv_opipe_door_mutex);
+
+ if (sv->sv_opipe_door_hd == NULL) {
+ mutex_exit(&sv->sv_opipe_door_mutex);
+
+ if (smb_opipe_door_open(sv, sv->sv_opipe_door_id) != 0)
+ return (-1);
+
+ mutex_enter(&sv->sv_opipe_door_mutex);
+ }
+
+ sv->sv_opipe_door_ncall++;
+ mutex_exit(&sv->sv_opipe_door_mutex);
+
+ rc = smb_opipe_door_upcall(opipe);
+
+ mutex_enter(&sv->sv_opipe_door_mutex);
+ if ((--sv->sv_opipe_door_ncall) == 0)
+ cv_signal(&sv->sv_opipe_door_cv);
+ mutex_exit(&sv->sv_opipe_door_mutex);
+ return (rc);
+}
+
+/*
+ * Door upcall wrapper - handles data marshalling.
+ * This function should only be called by smb_opipe_door_call.
+ */
+static int
+smb_opipe_door_upcall(smb_opipe_t *opipe)
+{
+ smb_server_t *sv = opipe->p_server;
+ door_arg_t da;
+ smb_doorhdr_t hdr;
+ int i;
+ int rc;
+
+ da.data_ptr = (char *)opipe->p_doorbuf;
+ da.data_size = SMB_OPIPE_DOOR_BUFSIZE;
+ da.desc_ptr = NULL;
+ da.desc_num = 0;
+ da.rbuf = (char *)opipe->p_doorbuf;
+ da.rsize = SMB_OPIPE_DOOR_BUFSIZE;
+
+ for (i = 0; i < 3; ++i) {
+ if (smb_server_is_stopping(sv))
+ return (-1);
+
+ if ((rc = door_ki_upcall_limited(sv->sv_opipe_door_hd,
+ &da, NULL, SIZE_MAX, 0)) == 0)
+ break;
+
+ if (rc != EAGAIN && rc != EINTR)
+ return (-1);
+ }
+
+ /* Check for door_return(NULL, 0, NULL, 0) */
+ if (rc != 0 || da.data_size == 0 || da.rsize == 0)
+ return (-1);
+
+ if (smb_doorhdr_decode(&hdr, (uint8_t *)da.data_ptr, da.rsize) == -1)
+ return (-1);
+
+ if ((hdr.dh_magic != SMB_OPIPE_HDR_MAGIC) ||
+ (hdr.dh_fid != opipe->p_hdr.dh_fid) ||
+ (hdr.dh_op != opipe->p_hdr.dh_op) ||
+ (hdr.dh_door_rc != 0) ||
+ (hdr.dh_datalen > SMB_OPIPE_DOOR_BUFSIZE)) {
+ return (-1);
+ }
+
+ opipe->p_hdr.dh_datalen = hdr.dh_datalen;
+ opipe->p_hdr.dh_resid = hdr.dh_resid;
+ return (0);
+}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_oplock.c b/usr/src/uts/common/fs/smbsrv/smb_oplock.c
index bde986db44..b2d77a0be4 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_oplock.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_oplock.c
@@ -41,7 +41,6 @@
#include <smbsrv/smb_kproto.h>
#include <sys/nbmlock.h>
-#include <inet/tcp.h>
#define SMB_OPLOCK_IS_EXCLUSIVE(level) \
(((level) == SMB_OPLOCK_EXCLUSIVE) || \
diff --git a/usr/src/uts/common/fs/smbsrv/smb_rename.c b/usr/src/uts/common/fs/smbsrv/smb_rename.c
index 8f7cad3553..2ea687f1ef 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_rename.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_rename.c
@@ -320,8 +320,9 @@ smb_trans2_rename(smb_request_t *sr, smb_node_t *node, char *fname, int flags)
static int
smb_common_rename(smb_request_t *sr, smb_fqi_t *src_fqi, smb_fqi_t *dst_fqi)
{
- smb_node_t *src_fnode, *src_dnode, *dst_fnode, *dst_dnode;
- smb_node_t *tnode;
+ smb_node_t *src_fnode, *src_dnode, *dst_dnode;
+ smb_node_t *dst_fnode = 0;
+ smb_node_t *tnode = 0;
int rc, count;
DWORD status;
char *new_name, *path;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_server.c b/usr/src/uts/common/fs/smbsrv/smb_server.c
index 1fb0887458..2ac120c137 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_server.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_server.c
@@ -201,10 +201,8 @@
* enforced in user space.
*/
-#include <sys/strsubr.h>
#include <sys/cmn_err.h>
#include <sys/priv.h>
-#include <sys/socketvar.h>
#include <sys/zone.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
@@ -303,7 +301,6 @@ smb_server_g_init(void)
smb_mbc_init(); /* smb_mbc_cache */
smb_net_init(); /* smb_txr_cache */
smb_node_init(); /* smb_node_cache, lists */
- smb_sign_g_init();
smb_cache_request = kmem_cache_create("smb_request_cache",
sizeof (smb_request_t), 8, NULL, NULL, NULL, NULL, NULL, 0);
@@ -401,7 +398,7 @@ smb_server_create(void)
sv->sv_magic = SMB_SERVER_MAGIC;
sv->sv_state = SMB_SERVER_STATE_CREATED;
sv->sv_zid = zid;
- sv->sv_pid = curproc->p_pid;
+ sv->sv_pid = ddi_get_pid();
mutex_init(&sv->sv_mutex, NULL, MUTEX_DEFAULT, NULL);
cv_init(&sv->sv_cv, NULL, CV_DEFAULT, NULL);
@@ -592,6 +589,10 @@ smb_server_start(smb_ioc_start_t *ioc)
if ((rc = smb_kshare_start(sv)) != 0)
break;
+ /*
+ * NB: the proc passed here has to be a "system" one.
+ * Normally that's p0, or the NGZ eqivalent.
+ */
sv->sv_worker_pool = taskq_create_proc("smb_workers",
sv->sv_cfg.skc_maxworkers, smbsrv_worker_pri,
sv->sv_cfg.skc_maxworkers, INT_MAX,
@@ -609,6 +610,7 @@ smb_server_start(smb_ioc_start_t *ioc)
break;
}
+#ifdef _KERNEL
ASSERT(sv->sv_lmshrd == NULL);
sv->sv_lmshrd = smb_kshare_door_init(ioc->lmshrd);
if (sv->sv_lmshrd == NULL)
@@ -621,6 +623,12 @@ smb_server_start(smb_ioc_start_t *ioc)
cmn_err(CE_WARN, "Cannot open opipe door");
break;
}
+#else /* _KERNEL */
+ /* Fake kernel does not use the kshare_door */
+ fksmb_kdoor_open(sv, ioc->udoor_func);
+ fksmb_opipe_door_open(sv, ioc->opipe_func);
+#endif /* _KERNEL */
+
if (rc = smb_thread_start(&sv->si_thread_timers))
break;
@@ -989,7 +997,7 @@ smb_server_sharevp(smb_server_t *sv, const char *shr_path, vnode_t **vp)
return (0);
}
-
+#ifdef _KERNEL
/*
* This is a special interface that will be utilized by ZFS to cause a share to
* be added/removed.
@@ -1020,6 +1028,7 @@ smb_server_share(void *arg, boolean_t add_share)
return (rc);
}
+#endif /* _KERNEL */
int
smb_server_unshare(const char *sharename)
@@ -1220,7 +1229,11 @@ smb_server_timers(smb_thread_t *thread, void *arg)
ASSERT(sv != NULL);
- while (smb_thread_continue_timedwait(thread, 1 /* Seconds */)) {
+ /*
+ * This just kills old inactive sessions. No urgency.
+ * The session code expects one call per minute.
+ */
+ while (smb_thread_continue_timedwait(thread, 60 /* Seconds */)) {
smb_session_timers(&sv->sv_nbt_daemon.ld_session_list);
smb_session_timers(&sv->sv_tcp_daemon.ld_session_list);
}
@@ -1402,8 +1415,11 @@ smb_server_shutdown(smb_server_t *sv)
smb_opipe_door_close(sv);
smb_kdoor_close(sv);
+#ifdef _KERNEL
smb_kshare_door_fini(sv->sv_lmshrd);
+#endif /* _KERNEL */
sv->sv_lmshrd = NULL;
+
smb_export_stop(sv);
if (sv->sv_session != NULL) {
diff --git a/usr/src/uts/common/fs/smbsrv/smb_session.c b/usr/src/uts/common/fs/smbsrv/smb_session.c
index 9069269ed5..0ce893970d 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_session.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_session.c
@@ -20,23 +20,28 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
+
#include <sys/atomic.h>
-#include <sys/strsubr.h>
#include <sys/synch.h>
#include <sys/types.h>
-#include <sys/socketvar.h>
#include <sys/sdt.h>
#include <sys/random.h>
#include <smbsrv/netbios.h>
#include <smbsrv/smb_kproto.h>
#include <smbsrv/string.h>
-#include <inet/tcp.h>
+#include <netinet/tcp.h>
+
+#define SMB_NEW_KID() atomic_inc_64_nv(&smb_kids)
static volatile uint64_t smb_kids;
-uint32_t smb_keep_alive = SSN_KEEP_ALIVE_TIMEOUT;
+/*
+ * We track the keepalive in minutes, but this constant
+ * specifies it in seconds, so convert to minutes.
+ */
+uint32_t smb_keep_alive = SMB_PI_KEEP_ALIVE_MIN / 60;
static void smb_session_cancel(smb_session_t *);
static int smb_session_message(smb_session_t *);
@@ -75,6 +80,12 @@ smb_session_correct_keep_alive_values(smb_llist_t *ll, uint32_t new_keep_alive)
{
smb_session_t *sn;
+ /*
+ * Caller specifies seconds, but we track in minutes, so
+ * convert to minutes (rounded up).
+ */
+ new_keep_alive = (new_keep_alive + 59) / 60;
+
if (new_keep_alive == smb_keep_alive)
return;
/*
@@ -415,7 +426,7 @@ smb_request_cancel(smb_request_t *sr)
void
smb_session_receiver(smb_session_t *session)
{
- int rc;
+ int rc = 0;
SMB_SESSION_VALID(session);
@@ -698,6 +709,9 @@ smb_session_delete(smb_session_t *session)
session->s_magic = 0;
+ if (session->sign_fini != NULL)
+ session->sign_fini(session);
+
smb_rwx_destroy(&session->s_lock);
smb_net_txl_destructor(&session->s_txlst);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c b/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c
index c1dd328bdd..7eabad7513 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_session_setup_andx.c
@@ -19,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/types.h>
@@ -32,14 +32,13 @@
#include <smbsrv/smb_kproto.h>
#include <smbsrv/smb_token.h>
-static int smb_authenticate(smb_request_t *, smb_arg_sessionsetup_t *,
- smb_session_key_t **);
-static int smb_authenticate_core(smb_request_t *, smb_arg_sessionsetup_t *,
- smb_session_key_t **);
-static cred_t *smb_cred_create(smb_token_t *);
+static int smb_authenticate(smb_request_t *, smb_arg_sessionsetup_t *);
+static int smb_authenticate_core(smb_request_t *, smb_arg_sessionsetup_t *);
+static uint32_t smb_priv_xlate(smb_token_t *);
+#ifdef _KERNEL
static void smb_cred_set_sid(smb_id_t *id, ksid_t *ksid);
static ksidlist_t *smb_cred_set_sidlist(smb_ids_t *token_grps);
-static uint32_t smb_priv_xlate(smb_token_t *);
+#endif /* _KERNEL */
/*
* In NTLM 0.12, the padding between the Native OS and Native LM is a bit
@@ -63,6 +62,7 @@ smb_pre_session_setup_andx(smb_request_t *sr)
smb_arg_sessionsetup_t *sinfo;
char *native_os;
char *native_lm;
+ uint32_t junk_sesskey;
uint16_t maxbufsize;
uint16_t vcnumber;
int rc = 0;
@@ -74,7 +74,7 @@ smb_pre_session_setup_andx(smb_request_t *sr)
rc = smbsr_decode_vwv(sr, "b.wwwwlww4.l", &sr->andx_com,
&sr->andx_off, &maxbufsize,
&sinfo->ssi_maxmpxcount, &vcnumber,
- &sinfo->ssi_sesskey, &sinfo->ssi_cipwlen,
+ &junk_sesskey, &sinfo->ssi_cipwlen,
&sinfo->ssi_cspwlen, &sinfo->ssi_capabilities);
if (rc != 0)
goto pre_session_setup_andx_done;
@@ -110,7 +110,7 @@ smb_pre_session_setup_andx(smb_request_t *sr)
rc = smbsr_decode_vwv(sr, "b.wwwwlw4.", &sr->andx_com,
&sr->andx_off, &maxbufsize,
&sinfo->ssi_maxmpxcount, &vcnumber,
- &sinfo->ssi_sesskey, &sinfo->ssi_cipwlen);
+ &junk_sesskey, &sinfo->ssi_cipwlen);
if (rc != 0)
goto pre_session_setup_andx_done;
@@ -174,11 +174,9 @@ smb_sdrc_t
smb_com_session_setup_andx(smb_request_t *sr)
{
smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
- smb_session_key_t *session_key = NULL;
- char ipaddr_buf[INET6_ADDRSTRLEN];
int rc;
- if (smb_authenticate(sr, sinfo, &session_key) != 0)
+ if (smb_authenticate(sr, sinfo) != 0)
return (SDRC_ERROR);
if (sr->session->native_lm == NATIVE_LM_WIN2000)
@@ -190,25 +188,6 @@ smb_com_session_setup_andx(smb_request_t *sr)
sr->session->capabilities = sinfo->ssi_capabilities;
- if (!(sr->session->signing.flags & SMB_SIGNING_ENABLED) &&
- (sr->session->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) &&
- (sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) &&
- session_key)
- smb_sign_init(sr, session_key, (char *)sinfo->ssi_cspwd,
- sinfo->ssi_cspwlen);
-
- if (!(sr->smb_flg2 & SMB_FLAGS2_SMB_SECURITY_SIGNATURE) &&
- (sr->sr_cfg->skc_signing_required)) {
- (void) smb_inet_ntop(&sr->session->ipaddr, ipaddr_buf,
- SMB_IPSTRLEN(sr->session->ipaddr.a_family));
- cmn_err(CE_NOTE,
- "SmbSessonSetupX: client %s does not support signing",
- ipaddr_buf);
- smbsr_error(sr, NT_STATUS_LOGON_FAILURE,
- ERRDOS, ERROR_LOGON_FAILURE);
- return (SDRC_ERROR);
- }
-
rc = smbsr_encode_result(sr, 3, VAR_BCC, "bb.www%uuu",
3,
sr->andx_com,
@@ -224,8 +203,7 @@ smb_com_session_setup_andx(smb_request_t *sr)
}
static int
-smb_authenticate(smb_request_t *sr, smb_arg_sessionsetup_t *sinfo,
- smb_session_key_t **session_key)
+smb_authenticate(smb_request_t *sr, smb_arg_sessionsetup_t *sinfo)
{
int rc;
smb_server_t *sv = sr->sr_server;
@@ -235,7 +213,7 @@ smb_authenticate(smb_request_t *sr, smb_arg_sessionsetup_t *sinfo,
return (-1);
}
- rc = smb_authenticate_core(sr, sinfo, session_key);
+ rc = smb_authenticate_core(sr, sinfo);
smb_threshold_exit(&sv->sv_ssetup_ct);
return (rc);
}
@@ -249,8 +227,7 @@ smb_authenticate(smb_request_t *sr, smb_arg_sessionsetup_t *sinfo,
* generate a cred and new user based on the token.
*/
static int
-smb_authenticate_core(smb_request_t *sr, smb_arg_sessionsetup_t *sinfo,
- smb_session_key_t **session_key)
+smb_authenticate_core(smb_request_t *sr, smb_arg_sessionsetup_t *sinfo)
{
char *hostname = sr->sr_cfg->skc_hostname;
int security = sr->sr_cfg->skc_secmode;
@@ -349,12 +326,6 @@ smb_authenticate_core(smb_request_t *sr, smb_arg_sessionsetup_t *sinfo,
}
}
- if (token->tkn_session_key) {
- *session_key = smb_srm_zalloc(sr, sizeof (smb_session_key_t));
- bcopy(token->tkn_session_key, *session_key,
- sizeof (smb_session_key_t));
- }
-
if ((cr = smb_cred_create(token)) == NULL) {
smb_token_free(token);
smbsr_error(sr, 0, ERRDOS, ERROR_INVALID_HANDLE);
@@ -366,8 +337,15 @@ smb_authenticate_core(smb_request_t *sr, smb_arg_sessionsetup_t *sinfo,
user = smb_user_login(sr->session, cr,
token->tkn_domain_name, token->tkn_account_name,
token->tkn_flags, privileges, token->tkn_audit_sid);
-
crfree(cr);
+
+ /*
+ * Save the session key, and (maybe) enable signing,
+ * but only for real logon (not ANON or GUEST).
+ */
+ if ((token->tkn_flags & (SMB_ATF_GUEST | SMB_ATF_ANON)) == 0)
+ (void) smb_sign_begin(sr, token);
+
smb_token_free(token);
if (user == NULL) {
@@ -382,6 +360,7 @@ smb_authenticate_core(smb_request_t *sr, smb_arg_sessionsetup_t *sinfo,
return (0);
}
+#ifdef _KERNEL
/*
* Allocate a Solaris cred and initialize it based on the access token.
*
@@ -392,7 +371,7 @@ smb_authenticate_core(smb_request_t *sr, smb_arg_sessionsetup_t *sinfo,
* obtained, the cred gid is set to whatever Solaris group is mapped
* to the token's primary group.
*/
-static cred_t *
+cred_t *
smb_cred_create(smb_token_t *token)
{
ksid_t ksid;
@@ -497,6 +476,7 @@ smb_cred_set_sidlist(smb_ids_t *token_grps)
return (lp);
}
+#endif /* _KERNEL */
/*
* Convert access token privileges to local definitions.
diff --git a/usr/src/uts/common/fs/smbsrv/smb_sign_kcf.c b/usr/src/uts/common/fs/smbsrv/smb_sign_kcf.c
new file mode 100644
index 0000000000..45b7f31d4d
--- /dev/null
+++ b/usr/src/uts/common/fs/smbsrv/smb_sign_kcf.c
@@ -0,0 +1,99 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
+/*
+ * Helper functions for SMB1 signing using the
+ * Kernel Cryptographic Framework (KCF)
+ *
+ * There are two implementations of these functions:
+ * This one (for kernel) and another for user space:
+ * See: lib/smbsrv/libfksmbsrv/common/fksmb_sign_pkcs.c
+ */
+
+#include <sys/types.h>
+#include <sys/kmem.h>
+#include <sys/crypto/api.h>
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smb_signing.h>
+
+/*
+ * SMB1 signing helpers:
+ * (getmech, init, update, final)
+ */
+
+int
+smb_md5_getmech(smb_sign_mech_t *mech)
+{
+ crypto_mech_type_t t;
+
+ t = crypto_mech2id(SUN_CKM_MD5);
+ if (t == CRYPTO_MECH_INVALID)
+ return (-1);
+ mech->cm_type = t;
+ return (0);
+}
+
+/*
+ * Start the KCF session, load the key
+ */
+int
+smb_md5_init(smb_sign_ctx_t *ctxp, smb_sign_mech_t *mech)
+{
+ int rv;
+
+ rv = crypto_digest_init(mech, ctxp, NULL);
+
+ return (rv == CRYPTO_SUCCESS ? 0 : -1);
+}
+
+/*
+ * Digest one segment
+ */
+int
+smb_md5_update(smb_sign_ctx_t ctx, void *buf, size_t len)
+{
+ crypto_data_t data;
+ int rv;
+
+ bzero(&data, sizeof (data));
+ data.cd_format = CRYPTO_DATA_RAW;
+ data.cd_length = len;
+ data.cd_raw.iov_base = buf;
+ data.cd_raw.iov_len = len;
+
+ rv = crypto_digest_update(ctx, &data, 0);
+
+ return (rv == CRYPTO_SUCCESS ? 0 : -1);
+}
+
+/*
+ * Get the final digest.
+ */
+int
+smb_md5_final(smb_sign_ctx_t ctx, uint8_t *digest16)
+{
+ crypto_data_t out;
+ int rv;
+
+ bzero(&out, sizeof (out));
+ out.cd_format = CRYPTO_DATA_RAW;
+ out.cd_length = MD5_DIGEST_LENGTH;
+ out.cd_raw.iov_len = MD5_DIGEST_LENGTH;
+ out.cd_raw.iov_base = (void *)digest16;
+
+ rv = crypto_digest_final(ctx, &out, 0);
+
+ return (rv == CRYPTO_SUCCESS ? 0 : -1);
+}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_signing.c b/usr/src/uts/common/fs/smbsrv/smb_signing.c
index ce622edc9d..c1cd826e32 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_signing.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_signing.c
@@ -19,8 +19,8 @@
* CDDL HEADER END
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
*/
/*
* These routines provide the SMB MAC signing for the SMB server.
@@ -40,12 +40,20 @@
#include <sys/uio.h>
#include <smbsrv/smb_kproto.h>
-#include <smbsrv/msgbuf.h>
-#include <sys/crypto/api.h>
+#include <smbsrv/smb_signing.h>
+#include <sys/isa_defs.h>
+#include <sys/byteorder.h>
-#define SMBAUTH_SESSION_KEY_SZ 16
+#define SSN_KEY_LEN 16
#define SMB_SIG_SIZE 8
#define SMB_SIG_OFFS 14
+#define SMB_HDRLEN 32
+
+#ifdef _LITTLE_ENDIAN
+#define htolel(x) ((uint32_t)(x))
+#else
+#define htolel(x) BSWAP_32(x)
+#endif
int
smb_sign_calc(struct mbuf_chain *mbc,
@@ -54,28 +62,7 @@ smb_sign_calc(struct mbuf_chain *mbc,
unsigned char *mac_sign);
#ifdef DEBUG
-void smb_sign_find_seqnum(
- uint32_t seqnum,
- struct smb_sign *sign,
- struct mbuf_chain *command,
- unsigned char *mac_sig,
- unsigned char *sr_sig,
- boolean_t *found);
-#define SMB_CHECK_SEQNUM(seqnum, sign, command, mac_sig, sr_sig, found) \
-{ \
- if (smb_sign_debug) \
- smb_sign_find_seqnum(seqnum, sign, \
- command, mac_sig, sr_sig, found); \
-}
-#else
-#define SMB_CHECK_SEQNUM(seqnum, sign, command, mac_sig, sr_sig, found) \
- { \
- *found = 0; \
- }
-#endif
-
-#ifdef DEBUG
-void
+static void
smb_sign_find_seqnum(
uint32_t seqnum,
struct smb_sign *sign,
@@ -105,57 +92,95 @@ int i;
}
#endif
-/* This holds the MD5 mechanism */
-static crypto_mechanism_t crypto_mech = {CRYPTO_MECHANISM_INVALID, 0, 0};
-
-void
-smb_sign_g_init(void)
+/*
+ * Called during session destroy.
+ */
+static void
+smb_sign_fini(smb_session_t *s)
{
- /*
- * Initialise the crypto mechanism to MD5 if it not
- * already initialised.
- */
- if (crypto_mech.cm_type == CRYPTO_MECHANISM_INVALID) {
- crypto_mech.cm_type = crypto_mech2id(SUN_CKM_MD5);
+ smb_sign_mech_t *mech;
+
+ if ((mech = s->signing.mech) != NULL) {
+ kmem_free(mech, sizeof (*mech));
+ s->signing.mech = NULL;
}
}
/*
- * smb_sign_init
+ * smb_sign_begin
*
* Intializes MAC key based on the user session key and
* NTLM response and store it in the signing structure.
+ * This is what begins SMB signing.
*/
-void
-smb_sign_init(smb_request_t *sr, smb_session_key_t *session_key,
- char *resp, int resp_len)
+int
+smb_sign_begin(smb_request_t *sr, smb_token_t *token)
{
- struct smb_sign *sign = &sr->session->signing;
+ smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup;
+ smb_session_t *session = sr->session;
+ struct smb_sign *sign = &session->signing;
+ smb_sign_mech_t *mech;
+ int rc;
- if (crypto_mech.cm_type == CRYPTO_MECHANISM_INVALID) {
- /*
- * There is no MD5 crypto mechanism
- * so turn off signing
- */
- sr->sr_cfg->skc_signing_enable = 0;
- sr->session->secmode &=
- (~NEGOTIATE_SECURITY_SIGNATURES_ENABLED);
- cmn_err(CE_WARN,
- "SmbSignInit: signing disabled (no MD5)");
- return;
+ /*
+ * Session-level initialization (once per session)
+ */
+ smb_rwx_rwenter(&session->s_lock, RW_WRITER);
+
+ /*
+ * Signing may already have been setup by a prior logon,
+ * in which case we're done here.
+ */
+ if (sign->mackey != NULL) {
+ smb_rwx_rwexit(&session->s_lock);
+ return (0);
}
- /* MAC key = concat (SessKey, NTLMResponse) */
+ /*
+ * Get the mech handle
+ */
+ if (sign->mech == NULL) {
+ mech = kmem_zalloc(sizeof (*mech), KM_SLEEP);
+ rc = smb_md5_getmech(mech);
+ if (rc != 0) {
+ kmem_free(mech, sizeof (*mech));
+ smb_rwx_rwexit(&session->s_lock);
+ return (rc);
+ }
+ sign->mech = mech;
+ session->sign_fini = smb_sign_fini;
+ }
- bcopy(session_key, sign->mackey, sizeof (smb_session_key_t));
- bcopy(resp, &(sign->mackey[sizeof (smb_session_key_t)]),
- resp_len);
- sign->mackey_len = sizeof (smb_session_key_t) + resp_len;
+ /*
+ * Compute and store the signing (MAC) key.
+ *
+ * With extended security, the MAC key is the same as the
+ * session key (and we'll have sinfo->ssi_cspwlen == 0).
+ * With non-extended security, it's the concatenation of
+ * the session key and the "NT response" we received.
+ * (NB: no extended security yet)
+ */
+ sign->mackey_len = SSN_KEY_LEN + sinfo->ssi_cspwlen;
+ sign->mackey = kmem_alloc(sign->mackey_len, KM_SLEEP);
+ bcopy(token->tkn_session_key, sign->mackey, SSN_KEY_LEN);
+ if (sinfo->ssi_cspwlen > 0) {
+ bcopy(sinfo->ssi_cspwd, sign->mackey + SSN_KEY_LEN,
+ sinfo->ssi_cspwlen);
+ }
- sr->session->signing.seqnum = 0;
+ session->signing.seqnum = 0;
sr->sr_seqnum = 2;
sr->reply_seqnum = 1;
- sign->flags = SMB_SIGNING_ENABLED;
+ sign->flags = 0;
+
+ if (session->secmode & NEGOTIATE_SECURITY_SIGNATURES_ENABLED) {
+ sign->flags |= SMB_SIGNING_ENABLED;
+ if (session->secmode & NEGOTIATE_SECURITY_SIGNATURES_REQUIRED)
+ sign->flags |= SMB_SIGNING_CHECK;
+ }
+
+ smb_rwx_rwexit(&session->s_lock);
+ return (0);
}
/*
@@ -179,7 +204,7 @@ smb_sign_init(smb_request_t *sr, smb_session_key_t *session_key,
*
* SMBMsg is the SMB message containing the sequence number.
*
- * Return 0 if success else -1
+ * Return 0 if success
*
*/
int
@@ -188,130 +213,87 @@ smb_sign_calc(struct mbuf_chain *mbc,
uint32_t seqnum,
unsigned char *mac_sign)
{
- uint32_t seq_buf[2] = {0, 0};
- unsigned char mac[16];
+ smb_sign_ctx_t ctx = 0;
+ uchar_t digest[MD5_DIGEST_LENGTH];
+ uchar_t *hdrp;
struct mbuf *mbuf = mbc->chain;
int offset = mbc->chain_offset;
int size;
- int status;
-
- crypto_data_t data;
- crypto_data_t digest;
- crypto_context_t crypto_ctx;
+ int rc;
- data.cd_format = CRYPTO_DATA_RAW;
- data.cd_offset = 0;
- data.cd_length = (size_t)-1;
- data.cd_miscdata = 0;
+ /*
+ * This union is a little bit of trickery to:
+ * (1) get the sequence number int aligned, and
+ * (2) reduce the number of digest calls, at the
+ * cost of a copying 32 bytes instead of 8.
+ * Both sides of this union are 2+32 bytes.
+ */
+ union {
+ struct {
+ uint8_t skip[2]; /* not used - just alignment */
+ uint8_t raw[SMB_HDRLEN]; /* header length (32) */
+ } r;
+ struct {
+ uint8_t skip[2]; /* not used - just alignment */
+ uint8_t hdr[SMB_SIG_OFFS]; /* sig. offset (14) */
+ uint32_t sig[2]; /* MAC signature, aligned! */
+ uint16_t ids[5]; /* pad, Tid, Pid, Uid, Mid */
+ } s;
+ } smbhdr;
+
+ if (sign->mech == NULL || sign->mackey == NULL)
+ return (-1);
- digest.cd_format = CRYPTO_DATA_RAW;
- digest.cd_offset = 0;
- digest.cd_length = (size_t)-1;
- digest.cd_miscdata = 0;
- digest.cd_raw.iov_base = (char *)mac;
- digest.cd_raw.iov_len = sizeof (mac);
+ if ((rc = smb_md5_init(&ctx, sign->mech)) != 0)
+ return (rc);
- status = crypto_digest_init(&crypto_mech, &crypto_ctx, 0);
- if (status != CRYPTO_SUCCESS)
- goto error;
+ /* Digest the MAC Key */
+ rc = smb_md5_update(ctx, sign->mackey, sign->mackey_len);
+ if (rc != 0)
+ return (rc);
/*
- * Put the sequence number into the first 4 bytes
- * of the signature field in little endian format.
- * We are using a buffer to represent the signature
- * rather than modifying the SMB message.
+ * Make an aligned copy of the SMB header,
+ * fill in the sequence number, and digest.
*/
-#ifdef __sparc
- {
- uint32_t temp;
- ((uint8_t *)&temp)[0] = ((uint8_t *)&seqnum)[3];
- ((uint8_t *)&temp)[1] = ((uint8_t *)&seqnum)[2];
- ((uint8_t *)&temp)[2] = ((uint8_t *)&seqnum)[1];
- ((uint8_t *)&temp)[3] = ((uint8_t *)&seqnum)[0];
-
- seq_buf[0] = temp;
- }
-#else
- seq_buf[0] = seqnum;
-#endif
+ hdrp = (unsigned char *)&smbhdr.r.raw;
+ size = SMB_HDRLEN;
+ if (smb_mbc_peek(mbc, offset, "#c", size, hdrp) != 0)
+ return (-1);
+ smbhdr.s.sig[0] = htolel(seqnum);
+ smbhdr.s.sig[1] = 0;
- /* Digest the MACKey */
- data.cd_raw.iov_base = (char *)sign->mackey;
- data.cd_raw.iov_len = sign->mackey_len;
- data.cd_length = sign->mackey_len;
- status = crypto_digest_update(crypto_ctx, &data, 0);
- if (status != CRYPTO_SUCCESS)
- goto error;
+ rc = smb_md5_update(ctx, &smbhdr.r.raw, size);
+ if (rc != 0)
+ return (rc);
- /* Find start of data in chain */
- while (offset >= mbuf->m_len) {
+ /*
+ * Digest the rest of the SMB packet, starting at the data
+ * just after the SMB header.
+ */
+ offset += size;
+ while (mbuf != NULL && (offset >= mbuf->m_len)) {
offset -= mbuf->m_len;
mbuf = mbuf->m_next;
}
-
- /* Digest the SMB packet up to the signature field */
- size = SMB_SIG_OFFS;
- while (size >= mbuf->m_len - offset) {
- data.cd_raw.iov_base = &mbuf->m_data[offset];
- data.cd_raw.iov_len = mbuf->m_len - offset;
- data.cd_length = mbuf->m_len - offset;
- status = crypto_digest_update(crypto_ctx, &data, 0);
- if (status != CRYPTO_SUCCESS)
- goto error;
-
- size -= mbuf->m_len - offset;
- mbuf = mbuf->m_next;
+ if (mbuf != NULL && (size = (mbuf->m_len - offset)) > 0) {
+ rc = smb_md5_update(ctx, &mbuf->m_data[offset], size);
+ if (rc != 0)
+ return (rc);
offset = 0;
- }
- if (size > 0) {
- data.cd_raw.iov_base = &mbuf->m_data[offset];
- data.cd_raw.iov_len = size;
- data.cd_length = size;
- status = crypto_digest_update(crypto_ctx, &data, 0);
- if (status != CRYPTO_SUCCESS)
- goto error;
- offset += size;
- }
-
- /*
- * Digest in the seq_buf instead of the signature
- * which has the sequence number
- */
-
- data.cd_raw.iov_base = (char *)seq_buf;
- data.cd_raw.iov_len = SMB_SIG_SIZE;
- data.cd_length = SMB_SIG_SIZE;
- status = crypto_digest_update(crypto_ctx, &data, 0);
- if (status != CRYPTO_SUCCESS)
- goto error;
-
- /* Find the end of the signature field */
- offset += SMB_SIG_SIZE;
- while (offset >= mbuf->m_len) {
- offset -= mbuf->m_len;
mbuf = mbuf->m_next;
}
- /* Digest the rest of the SMB packet */
- while (mbuf) {
- data.cd_raw.iov_base = &mbuf->m_data[offset];
- data.cd_raw.iov_len = mbuf->m_len - offset;
- data.cd_length = mbuf->m_len - offset;
- status = crypto_digest_update(crypto_ctx, &data, 0);
- if (status != CRYPTO_SUCCESS)
- goto error;
+ while (mbuf != NULL) {
+ rc = smb_md5_update(ctx, mbuf->m_data, mbuf->m_len);
+ if (rc != 0)
+ return (rc);
mbuf = mbuf->m_next;
- offset = 0;
}
- digest.cd_length = SMBAUTH_SESSION_KEY_SZ;
- status = crypto_digest_final(crypto_ctx, &digest, 0);
- if (status != CRYPTO_SUCCESS)
- goto error;
- bcopy(mac, mac_sign, SMB_SIG_SIZE);
- return (0);
-error:
- cmn_err(CE_WARN, "SmbSignCalc: crypto error %d", status);
- return (-1);
+ rc = smb_md5_final(ctx, digest);
+ if (rc == 0)
+ bcopy(digest, mac_sign, SMB_SIG_SIZE);
+ return (rc);
}
@@ -361,8 +343,14 @@ smb_sign_check_request(smb_request_t *sr)
/*
* check nearby sequence numbers in debug mode
*/
- SMB_CHECK_SEQNUM(sr->sr_seqnum, sign, &command,
- mac_sig, sr->smb_sig, &found);
+#ifdef DEBUG
+ if (smb_sign_debug)
+ smb_sign_find_seqnum(sr->sr_seqnum, sign,
+ &command, mac_sig, sr->smb_sig, &found);
+ else
+#endif
+ found = B_FALSE;
+
if (found == B_FALSE)
rtn = -1;
}
@@ -418,10 +406,6 @@ smb_sign_reply(smb_request_t *sr, struct mbuf_chain *reply)
struct mbuf_chain resp;
struct smb_sign *sign = &sr->session->signing;
unsigned char signature[SMB_SIG_SIZE];
- struct mbuf *mbuf;
- int size = SMB_SIG_SIZE;
- unsigned char *sig_ptr = signature;
- int offset = 0;
if (reply)
resp = *reply;
@@ -430,7 +414,6 @@ smb_sign_reply(smb_request_t *sr, struct mbuf_chain *reply)
/* Reset offset to start of reply */
resp.chain_offset = 0;
- mbuf = resp.chain;
/*
* Calculate MAC signature
@@ -442,24 +425,7 @@ smb_sign_reply(smb_request_t *sr, struct mbuf_chain *reply)
/*
* Put signature in the response
- *
- * First find start of signature in chain (offset + signature offset)
*/
- offset += SMB_SIG_OFFS;
- while (offset >= mbuf->m_len) {
- offset -= mbuf->m_len;
- mbuf = mbuf->m_next;
- }
-
- while (size >= mbuf->m_len - offset) {
- (void) memcpy(&mbuf->m_data[offset],
- sig_ptr, mbuf->m_len - offset);
- offset = 0;
- sig_ptr += mbuf->m_len - offset;
- size -= mbuf->m_len - offset;
- mbuf = mbuf->m_next;
- }
- if (size > 0) {
- (void) memcpy(&mbuf->m_data[offset], sig_ptr, size);
- }
+ (void) smb_mbc_poke(&resp, SMB_SIG_OFFS, "#c",
+ SMB_SIG_SIZE, signature);
}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_thread.c b/usr/src/uts/common/fs/smbsrv/smb_thread.c
new file mode 100644
index 0000000000..1907baa7dc
--- /dev/null
+++ b/usr/src/uts/common/fs/smbsrv/smb_thread.c
@@ -0,0 +1,313 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/tzfile.h>
+#include <sys/atomic.h>
+#include <sys/kidmap.h>
+#include <sys/time.h>
+#include <sys/spl.h>
+#include <sys/random.h>
+#include <smbsrv/smb_kproto.h>
+#include <smbsrv/smb_fsops.h>
+#include <smbsrv/smbinfo.h>
+#include <smbsrv/smb_xdr.h>
+#include <smbsrv/smb_vops.h>
+#include <smbsrv/smb_idmap.h>
+
+#include <sys/sid.h>
+#include <sys/priv_names.h>
+
+#ifdef _FAKE_KERNEL
+#define THR_TO_DID(t) ((kt_did_t)(uintptr_t)t)
+#else
+#define THR_TO_DID(t) (t->t_did)
+#endif
+
+static boolean_t smb_thread_continue_timedwait_locked(smb_thread_t *, int);
+
+/*
+ * smb_thread_entry_point
+ *
+ * Common entry point for all the threads created through smb_thread_start.
+ * The state of the thread is set to "running" at the beginning and moved to
+ * "exiting" just before calling thread_exit(). The condition variable is
+ * also signaled.
+ */
+static void
+smb_thread_entry_point(
+ smb_thread_t *thread)
+{
+ ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
+ mutex_enter(&thread->sth_mtx);
+ ASSERT(thread->sth_state == SMB_THREAD_STATE_STARTING);
+
+ if (!thread->sth_kill) {
+ thread->sth_state = SMB_THREAD_STATE_RUNNING;
+ cv_signal(&thread->sth_cv);
+ mutex_exit(&thread->sth_mtx);
+
+ /* Run the real thread entry point. */
+ thread->sth_ep(thread, thread->sth_ep_arg);
+
+ mutex_enter(&thread->sth_mtx);
+ }
+ /*
+ * It's tempting to clear sth_did here too, but don't.
+ * That's needed in thread_join().
+ */
+ thread->sth_th = NULL;
+ thread->sth_state = SMB_THREAD_STATE_EXITING;
+ cv_broadcast(&thread->sth_cv);
+ mutex_exit(&thread->sth_mtx);
+ zthread_exit();
+}
+
+/*
+ * smb_thread_init
+ */
+void
+smb_thread_init(
+ smb_thread_t *thread,
+ char *name,
+ smb_thread_ep_t ep,
+ void *ep_arg,
+ pri_t pri)
+{
+ ASSERT(thread->sth_magic != SMB_THREAD_MAGIC);
+
+ bzero(thread, sizeof (*thread));
+
+ (void) strlcpy(thread->sth_name, name, sizeof (thread->sth_name));
+ thread->sth_ep = ep;
+ thread->sth_ep_arg = ep_arg;
+ thread->sth_state = SMB_THREAD_STATE_EXITED;
+ thread->sth_pri = pri;
+ mutex_init(&thread->sth_mtx, NULL, MUTEX_DEFAULT, NULL);
+ cv_init(&thread->sth_cv, NULL, CV_DEFAULT, NULL);
+ thread->sth_magic = SMB_THREAD_MAGIC;
+}
+
+/*
+ * smb_thread_destroy
+ */
+void
+smb_thread_destroy(
+ smb_thread_t *thread)
+{
+ ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
+ ASSERT(thread->sth_state == SMB_THREAD_STATE_EXITED);
+ thread->sth_magic = 0;
+ mutex_destroy(&thread->sth_mtx);
+ cv_destroy(&thread->sth_cv);
+}
+
+/*
+ * smb_thread_start
+ *
+ * This function starts a thread with the parameters provided. It waits until
+ * the state of the thread has been moved to running.
+ */
+/*ARGSUSED*/
+int
+smb_thread_start(
+ smb_thread_t *thread)
+{
+ int rc = 0;
+ kthread_t *tmpthread;
+
+ ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
+
+ mutex_enter(&thread->sth_mtx);
+ switch (thread->sth_state) {
+ case SMB_THREAD_STATE_EXITED:
+ thread->sth_state = SMB_THREAD_STATE_STARTING;
+ mutex_exit(&thread->sth_mtx);
+ tmpthread = zthread_create(NULL, 0, smb_thread_entry_point,
+ thread, 0, thread->sth_pri);
+ ASSERT(tmpthread != NULL);
+ mutex_enter(&thread->sth_mtx);
+ thread->sth_th = tmpthread;
+ thread->sth_did = THR_TO_DID(tmpthread);
+ while (thread->sth_state == SMB_THREAD_STATE_STARTING)
+ cv_wait(&thread->sth_cv, &thread->sth_mtx);
+ if (thread->sth_state != SMB_THREAD_STATE_RUNNING)
+ rc = -1;
+ break;
+ default:
+ ASSERT(0);
+ rc = -1;
+ break;
+ }
+ mutex_exit(&thread->sth_mtx);
+ return (rc);
+}
+
+/*
+ * smb_thread_stop
+ *
+ * This function signals a thread to kill itself and waits until the "exiting"
+ * state has been reached.
+ */
+void
+smb_thread_stop(smb_thread_t *thread)
+{
+ ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
+
+ mutex_enter(&thread->sth_mtx);
+ switch (thread->sth_state) {
+ case SMB_THREAD_STATE_RUNNING:
+ case SMB_THREAD_STATE_STARTING:
+ if (!thread->sth_kill) {
+ thread->sth_kill = B_TRUE;
+ cv_broadcast(&thread->sth_cv);
+ while (thread->sth_state != SMB_THREAD_STATE_EXITING)
+ cv_wait(&thread->sth_cv, &thread->sth_mtx);
+ mutex_exit(&thread->sth_mtx);
+ thread_join(thread->sth_did);
+ mutex_enter(&thread->sth_mtx);
+ thread->sth_state = SMB_THREAD_STATE_EXITED;
+ thread->sth_did = 0;
+ thread->sth_kill = B_FALSE;
+ cv_broadcast(&thread->sth_cv);
+ break;
+ }
+ /* FALLTHROUGH */
+
+ case SMB_THREAD_STATE_EXITING:
+ if (thread->sth_kill) {
+ while (thread->sth_state != SMB_THREAD_STATE_EXITED)
+ cv_wait(&thread->sth_cv, &thread->sth_mtx);
+ } else {
+ thread->sth_state = SMB_THREAD_STATE_EXITED;
+ thread->sth_did = 0;
+ }
+ break;
+
+ case SMB_THREAD_STATE_EXITED:
+ break;
+
+ default:
+ ASSERT(0);
+ break;
+ }
+ mutex_exit(&thread->sth_mtx);
+}
+
+/*
+ * smb_thread_signal
+ *
+ * This function signals a thread.
+ */
+void
+smb_thread_signal(smb_thread_t *thread)
+{
+ ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
+
+ mutex_enter(&thread->sth_mtx);
+ switch (thread->sth_state) {
+ case SMB_THREAD_STATE_RUNNING:
+ cv_signal(&thread->sth_cv);
+ break;
+
+ default:
+ break;
+ }
+ mutex_exit(&thread->sth_mtx);
+}
+
+boolean_t
+smb_thread_continue(smb_thread_t *thread)
+{
+ boolean_t result;
+
+ ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
+
+ mutex_enter(&thread->sth_mtx);
+ result = smb_thread_continue_timedwait_locked(thread, 0);
+ mutex_exit(&thread->sth_mtx);
+
+ return (result);
+}
+
+boolean_t
+smb_thread_continue_nowait(smb_thread_t *thread)
+{
+ boolean_t result;
+
+ ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
+
+ mutex_enter(&thread->sth_mtx);
+ /*
+ * Setting ticks=-1 requests a non-blocking check. We will
+ * still block if the thread is in "suspend" state.
+ */
+ result = smb_thread_continue_timedwait_locked(thread, -1);
+ mutex_exit(&thread->sth_mtx);
+
+ return (result);
+}
+
+boolean_t
+smb_thread_continue_timedwait(smb_thread_t *thread, int seconds)
+{
+ boolean_t result;
+
+ ASSERT(thread->sth_magic == SMB_THREAD_MAGIC);
+
+ mutex_enter(&thread->sth_mtx);
+ result = smb_thread_continue_timedwait_locked(thread,
+ SEC_TO_TICK(seconds));
+ mutex_exit(&thread->sth_mtx);
+
+ return (result);
+}
+
+/*
+ * smb_thread_continue_timedwait_locked
+ *
+ * Internal only. Ticks==-1 means don't block, Ticks == 0 means wait
+ * indefinitely
+ */
+static boolean_t
+smb_thread_continue_timedwait_locked(smb_thread_t *thread, int ticks)
+{
+ boolean_t result;
+
+ /* -1 means don't block */
+ if (ticks != -1 && !thread->sth_kill) {
+ if (ticks == 0) {
+ cv_wait(&thread->sth_cv, &thread->sth_mtx);
+ } else {
+ (void) cv_reltimedwait(&thread->sth_cv,
+ &thread->sth_mtx, (clock_t)ticks, TR_CLOCK_TICK);
+ }
+ }
+ result = (thread->sth_kill == 0);
+
+ return (result);
+}
diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_dfs.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_dfs.c
index c8e4fadd7b..337490a836 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_dfs.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_dfs.c
@@ -19,9 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <smbsrv/smb_kproto.h>
@@ -211,7 +212,7 @@ static dfs_reftype_t
smb_dfs_get_reftype(const char *path)
{
smb_unc_t unc;
- dfs_reftype_t reftype;
+ dfs_reftype_t reftype = 0;
if (*path == '\0')
return (DFS_REFERRAL_DOMAIN);
diff --git a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
index d0d60cea5d..7fa91a0576 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c
@@ -19,9 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
@@ -535,10 +536,10 @@ static int
smb_trans2_find_entries(smb_request_t *sr, smb_xa_t *xa, smb_odir_t *od,
smb_find_args_t *args)
{
- int rc;
- uint16_t count, maxcount;
smb_fileinfo_t fileinfo;
smb_odir_resume_t odir_resume;
+ uint16_t count, maxcount;
+ int rc = -1;
if ((maxcount = args->fa_maxcount) == 0)
maxcount = 1;
diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree.c b/usr/src/uts/common/fs/smbsrv/smb_tree.c
index 419f05d4e7..7ee4544475 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_tree.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_tree.c
@@ -21,7 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -538,7 +538,7 @@ smb_tree_acl_access(smb_request_t *sr, const smb_kshare_t *si, vnode_t *pathvp)
size = sizeof (SHARES_DIR) + strlen(si->shr_name) + 1;
sharepath = smb_srm_alloc(sr, size);
- (void) sprintf(sharepath, "%s%s", SHARES_DIR, si->shr_name);
+ (void) snprintf(sharepath, size, "%s%s", SHARES_DIR, si->shr_name);
pn_alloc(&pnp);
(void) pn_set(&pnp, sharepath);
@@ -1094,7 +1094,7 @@ smb_tree_get_volname(vfs_t *vfsp, smb_tree_t *tree)
vfs_mntpoint = vfs_getmntpoint(vfsp);
- s = vfs_mntpoint->rs_string;
+ s = refstr_value(vfs_mntpoint);
s += strspn(s, "/");
(void) strlcpy(tree->t_volume, s, SMB_VOLNAMELEN);
@@ -1115,6 +1115,7 @@ static void
smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree)
{
smb_session_t *ssn = tree->t_session;
+ struct vfssw *vswp;
typedef struct smb_mtype {
char *mt_name;
@@ -1162,7 +1163,13 @@ smb_tree_get_flags(const smb_kshare_t *si, vfs_t *vfsp, smb_tree_t *tree)
if (vfsp->vfs_flag & VFS_XATTR)
flags |= SMB_TREE_STREAMS;
- name = vfssw[vfsp->vfs_fstype].vsw_name;
+ vswp = vfs_getvfsswbyvfsops(vfs_getops(vfsp));
+ if (vswp != NULL) {
+ name = vswp->vsw_name;
+ vfs_unrefvfssw(vswp);
+ } else {
+ name = "?";
+ }
for (i = 0; i < sizeof (smb_mtype) / sizeof (smb_mtype[0]); ++i) {
mtype = &smb_mtype[i];
diff --git a/usr/src/uts/common/fs/smbsrv/smb_user.c b/usr/src/uts/common/fs/smbsrv/smb_user.c
index 6b0c614466..017e3771ed 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_user.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_user.c
@@ -20,7 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -171,10 +171,10 @@
static boolean_t smb_user_is_logged_in(smb_user_t *);
static int smb_user_enum_private(smb_user_t *, smb_svcenum_t *);
-static void smb_user_setcred(smb_user_t *, cred_t *, uint32_t);
static void smb_user_nonauth_logon(smb_user_t *);
static void smb_user_auth_logoff(smb_user_t *);
+
/*
* Create a new user.
*/
@@ -366,12 +366,14 @@ smb_user_release(
boolean_t
smb_user_is_admin(smb_user_t *user)
{
+#ifdef _KERNEL
char sidstr[SMB_SID_STRSZ];
ksidlist_t *ksidlist;
ksid_t ksid1;
ksid_t *ksid2;
- boolean_t rc = B_FALSE;
int i;
+#endif /* _KERNEL */
+ boolean_t rc = B_FALSE;
ASSERT(user);
ASSERT(user->u_cred);
@@ -379,6 +381,7 @@ smb_user_is_admin(smb_user_t *user)
if (SMB_USER_IS_ADMIN(user))
return (B_TRUE);
+#ifdef _KERNEL
bzero(&ksid1, sizeof (ksid_t));
(void) strlcpy(sidstr, ADMINISTRATORS_SID, SMB_SID_STRSZ);
ASSERT(smb_sid_splitstr(sidstr, &ksid1.ks_rid) == 0);
@@ -407,6 +410,7 @@ smb_user_is_admin(smb_user_t *user)
} while (i++ < ksidlist->ksl_nsid);
ksid_rele(&ksid1);
+#endif /* _KERNEL */
return (rc);
}
@@ -533,13 +537,14 @@ smb_user_getprivcred(smb_user_t *user)
return ((user->u_privcred)? user->u_privcred : user->u_cred);
}
+#ifdef _KERNEL
/*
* Assign the user cred and privileges.
*
* If the user has backup and/or restore privleges, dup the cred
* and add those privileges to this new privileged cred.
*/
-static void
+void
smb_user_setcred(smb_user_t *user, cred_t *cr, uint32_t privileges)
{
cred_t *privcred = NULL;
@@ -569,6 +574,7 @@ smb_user_setcred(smb_user_t *user, cred_t *cr, uint32_t privileges)
user->u_privcred = privcred;
user->u_privileges = privileges;
}
+#endif /* _KERNEL */
/*
* Private function to support smb_user_enum.
diff --git a/usr/src/uts/common/fs/smbsrv/smb_vfs.c b/usr/src/uts/common/fs/smbsrv/smb_vfs.c
index 8af3417787..ae631e4ffa 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_vfs.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_vfs.c
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#include <sys/vfs.h>
@@ -95,7 +96,7 @@ smb_vfs_rele(smb_export_t *se, vfs_t *vfsp)
smb_llist_enter(&se->e_vfs_list, RW_WRITER);
smb_vfs = smb_vfs_find(se, vfsp);
- DTRACE_PROBE1(smb_vfs_release, smb_vfs_t *, smb_vfs)
+ DTRACE_PROBE1(smb_vfs_release, smb_vfs_t *, smb_vfs);
if (smb_vfs) {
ASSERT(smb_vfs->sv_refcnt);
if (--smb_vfs->sv_refcnt == 0) {
diff --git a/usr/src/uts/common/fs/smbsrv/smb_vops.c b/usr/src/uts/common/fs/smbsrv/smb_vops.c
index 91bf0083c1..f847053adc 100644
--- a/usr/src/uts/common/fs/smbsrv/smb_vops.c
+++ b/usr/src/uts/common/fs/smbsrv/smb_vops.c
@@ -1045,8 +1045,8 @@ smb_vop_stream_lookup(
*/
solaris_stream_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
- (void) sprintf(solaris_stream_name, "%s%s", SMB_STREAM_PREFIX,
- stream_name);
+ (void) snprintf(solaris_stream_name, MAXNAMELEN,
+ "%s%s", SMB_STREAM_PREFIX, stream_name);
/*
* "name" will hold the on-disk name returned from smb_vop_lookup
@@ -1085,8 +1085,8 @@ smb_vop_stream_create(vnode_t *fvp, char *stream_name, smb_attr_t *attr,
*/
solaris_stream_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
- (void) sprintf(solaris_stream_name, "%s%s", SMB_STREAM_PREFIX,
- stream_name);
+ (void) snprintf(solaris_stream_name, MAXNAMELEN,
+ "%s%s", SMB_STREAM_PREFIX, stream_name);
if ((error = smb_vop_create(*xattrdirvpp, solaris_stream_name, attr,
vpp, flags, cr, NULL)) != 0)
@@ -1113,8 +1113,8 @@ smb_vop_stream_remove(vnode_t *vp, char *stream_name, int flags, cred_t *cr)
*/
solaris_stream_name = kmem_alloc(MAXNAMELEN, KM_SLEEP);
- (void) sprintf(solaris_stream_name, "%s%s", SMB_STREAM_PREFIX,
- stream_name);
+ (void) snprintf(solaris_stream_name, MAXNAMELEN,
+ "%s%s", SMB_STREAM_PREFIX, stream_name);
/* XXX might have to use kcred */
error = smb_vop_remove(xattrdirvp, solaris_stream_name, flags, cr);
diff --git a/usr/src/uts/common/fs/sockfs/nl7c.c b/usr/src/uts/common/fs/sockfs/nl7c.c
index 51ca4f1116..88584eda68 100644
--- a/usr/src/uts/common/fs/sockfs/nl7c.c
+++ b/usr/src/uts/common/fs/sockfs/nl7c.c
@@ -287,21 +287,6 @@ atou(const char *p)
}
/*
- * strdup(), yet another strdup() in the kernel.
- */
-
-static char *
-strdup(char *s)
-{
- int len = strlen(s) + 1;
- char *ret = kmem_alloc(len, KM_SLEEP);
-
- bcopy(s, ret, len);
-
- return (ret);
-}
-
-/*
* Inet ASCII to binary.
*
* Note, it's assumed that *s is a valid zero byte terminated string, and
diff --git a/usr/src/uts/common/nfs/lm.h b/usr/src/uts/common/nfs/lm.h
index fa467faa4b..0328a9686c 100644
--- a/usr/src/uts/common/nfs/lm.h
+++ b/usr/src/uts/common/nfs/lm.h
@@ -23,9 +23,8 @@
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _NFS_LM_H
@@ -43,9 +42,9 @@ extern "C" {
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/vnode.h>
-#include <rpc/rpc.h>
+#include <rpc/xdr.h>
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
/*
* Common interfaces.
@@ -77,6 +76,8 @@ struct exportinfo;
* Struct used to represent a host.
*/
struct lm_sysid;
+struct knetconfig;
+struct netbuf;
/*
* Given a knetconfig and network address, returns a reference to the
diff --git a/usr/src/uts/common/rpc/xdr.h b/usr/src/uts/common/rpc/xdr.h
index 3db775893c..ebdd448d48 100644
--- a/usr/src/uts/common/rpc/xdr.h
+++ b/usr/src/uts/common/rpc/xdr.h
@@ -20,6 +20,8 @@
*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
@@ -39,12 +41,11 @@
#include <sys/byteorder.h> /* For all ntoh* and hton*() kind of macros */
#include <rpc/types.h> /* For all ntoh* and hton*() kind of macros */
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
#include <stdio.h> /* defines FILE *, used in ANSI C function prototypes */
-#endif
-#ifdef _KERNEL
+#else /* _KERNEL */
#include <sys/stream.h>
-#endif
+#endif /* _KERNEL */
#ifdef __cplusplus
extern "C" {
@@ -557,7 +558,7 @@ typedef struct xdr_bytesrec xdr_bytesrec;
* These are the public routines for the various implementations of
* xdr streams.
*/
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
#ifdef __STDC__
extern void xdrmem_create(XDR *, const caddr_t, const uint_t, const enum
xdr_op);
diff --git a/usr/src/uts/common/smbsrv/alloc.h b/usr/src/uts/common/smbsrv/alloc.h
index 3a2ca86368..c1e93b88d6 100644
--- a/usr/src/uts/common/smbsrv/alloc.h
+++ b/usr/src/uts/common/smbsrv/alloc.h
@@ -21,6 +21,8 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SMBSRV_ALLOC_H
@@ -52,9 +54,8 @@ extern "C" {
*/
#include <sys/types.h>
-#include <sys/sysmacros.h>
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
#include <stdlib.h>
#include <string.h>
diff --git a/usr/src/uts/common/smbsrv/ndr.h b/usr/src/uts/common/smbsrv/ndr.h
index e3f48fdca8..3652c2e0b7 100644
--- a/usr/src/uts/common/smbsrv/ndr.h
+++ b/usr/src/uts/common/smbsrv/ndr.h
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SMBSRV_NDR_H
@@ -38,7 +40,9 @@
* ogspecs@opengroup.org
*/
-#ifndef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+#error "not used in kernel code"
+#else /* _KERNEL */
#include <sys/types.h>
#include <sys/uio.h>
#include <syslog.h>
@@ -47,7 +51,7 @@
#include <smbsrv/wintypes.h>
#include <smbsrv/ndl/rpcpdu.ndl>
#include <smbsrv/string.h>
-#endif
+#endif /* _KERNEL */
#ifdef __cplusplus
extern "C" {
diff --git a/usr/src/uts/common/smbsrv/smb.h b/usr/src/uts/common/smbsrv/smb.h
index 59e056a52e..100691582b 100644
--- a/usr/src/uts/common/smbsrv/smb.h
+++ b/usr/src/uts/common/smbsrv/smb.h
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SMBSRV_SMB_H
@@ -30,9 +31,7 @@
/*
* SMB definitions and interfaces, mostly defined in the SMB and CIFS specs.
*/
-#ifdef _KERNEL
#include <sys/types.h>
-#endif
#include <smbsrv/string.h>
#include <smbsrv/msgbuf.h>
diff --git a/usr/src/uts/common/smbsrv/smb_door.h b/usr/src/uts/common/smbsrv/smb_door.h
index d1e68603d2..909f0778bf 100644
--- a/usr/src/uts/common/smbsrv/smb_door.h
+++ b/usr/src/uts/common/smbsrv/smb_door.h
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SMBSRV_SMB_DOOR_H
@@ -93,12 +94,18 @@ typedef struct smb_doorarg {
#define SMB_DOP_ENCODE_ERROR 3
#define SMB_DOP_EMPTYBUF 4
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
char *smb_common_encode(void *, xdrproc_t, size_t *);
int smb_common_decode(char *, size_t, xdrproc_t, void *);
char *smb_string_encode(char *, size_t *);
int smb_string_decode(smb_string_t *, char *, size_t);
-#endif /* _KERNEL */
+#endif /* !_KERNEL */
+
+/* libfksmbsrv "kdoor" callback to smbd-d */
+typedef int fksmb_kdoor_disp_func_t(smb_doorarg_t *);
+
+/* libfksmbsrv "opipe" callback to smbd-d */
+typedef int fksmb_opipe_disp_func_t(door_arg_t *);
/*
* Legacy door interface
diff --git a/usr/src/uts/common/smbsrv/smb_idmap.h b/usr/src/uts/common/smbsrv/smb_idmap.h
index d69af220eb..08115827fb 100644
--- a/usr/src/uts/common/smbsrv/smb_idmap.h
+++ b/usr/src/uts/common/smbsrv/smb_idmap.h
@@ -21,12 +21,14 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SMB_IDMAP_H
#define _SMB_IDMAP_H
-#ifdef _KERNEL
+#if defined(_KERNEL) /* intentionally not || defined(_FAKE_KERNEL) */
#include <sys/kidmap.h>
#else
#include <idmap.h>
diff --git a/usr/src/uts/common/smbsrv/smb_inet.h b/usr/src/uts/common/smbsrv/smb_inet.h
index ff4734be3e..59e9e13fab 100644
--- a/usr/src/uts/common/smbsrv/smb_inet.h
+++ b/usr/src/uts/common/smbsrv/smb_inet.h
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/*
@@ -34,10 +36,6 @@
extern "C" {
#endif
-#ifndef _KERNEL
-#include <inet/tcp.h>
-#include <arpa/inet.h>
-#endif /* !_KERNEL */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
diff --git a/usr/src/uts/common/smbsrv/smb_ioctl.h b/usr/src/uts/common/smbsrv/smb_ioctl.h
index 7716cedc04..e620a2b762 100644
--- a/usr/src/uts/common/smbsrv/smb_ioctl.h
+++ b/usr/src/uts/common/smbsrv/smb_ioctl.h
@@ -89,6 +89,10 @@ typedef struct smb_ioc_start {
int opipe;
int lmshrd;
int udoor;
+ /* These are used only by libfksmbsrv */
+ void *opipe_func;
+ void *lmshr_func;
+ void *udoor_func;
} smb_ioc_start_t;
typedef struct smb_ioc_event {
@@ -186,6 +190,12 @@ typedef union smb_ioc {
uint32_t smb_crc_gen(uint8_t *, size_t);
+/* fksmbd (init,open,close,ioctl) calls into libfksmbsrv */
+int fksmbsrv_drv_open(void);
+int fksmbsrv_drv_close(void);
+int fksmbsrv_drv_ioctl(int cmd, void *arg);
+void fksmbsrv_drv_load(void);
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/common/smbsrv/smb_kproto.h b/usr/src/uts/common/smbsrv/smb_kproto.h
index 8f454fd1b7..879b21cdba 100644
--- a/usr/src/uts/common/smbsrv/smb_kproto.h
+++ b/usr/src/uts/common/smbsrv/smb_kproto.h
@@ -38,13 +38,14 @@ extern "C" {
#include <sys/types.h>
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/debug.h>
+#include <sys/kmem.h>
#include <sys/socket.h>
-#include <sys/strsubr.h>
-#include <sys/socketvar.h>
#include <sys/ksocket.h>
#include <sys/cred.h>
#include <sys/nbmlock.h>
#include <sys/sunddi.h>
+#include <sys/atomic.h>
#include <smbsrv/smb.h>
#include <smbsrv/string.h>
#include <smbsrv/smb_vops.h>
@@ -53,6 +54,24 @@ extern "C" {
#include <smbsrv/smb_ktypes.h>
#include <smbsrv/smb_ioctl.h>
+/*
+ * DTrace SDT probes have different signatures in userland than they do in
+ * kernel. If they're being used in kernel code, re-define them out of
+ * existence for their counterparts in libfksmbsrv
+ */
+#ifndef _KERNEL
+#undef DTRACE_SMB_1
+#define DTRACE_SMB_1(a, b, c) ((void)c)
+#undef DTRACE_SMB_2
+#define DTRACE_SMB_2(a, b, c, d, e) ((void)c, (void)e)
+#undef DTRACE_PROBE1
+#define DTRACE_PROBE1(a, b, c) ((void)c)
+#undef DTRACE_PROBE2
+#define DTRACE_PROBE2(a, b, c, d, e) ((void)c, (void)e)
+#undef DTRACE_PROBE3
+#define DTRACE_PROBE3(a, b, c, d, e, f, g) ((void)c, (void)e, (void)g)
+#endif /* _KERNEL */
+
extern int smb_maxbufsize;
extern int smb_flush_required;
extern int smb_dirsymlink_enable;
@@ -368,6 +387,8 @@ void smb_opipe_door_init(smb_server_t *);
void smb_opipe_door_fini(smb_server_t *);
int smb_opipe_door_open(smb_server_t *, int);
void smb_opipe_door_close(smb_server_t *);
+int smb_opipe_door_call(smb_opipe_t *);
+void fksmb_opipe_door_open(smb_server_t *, void *);
void smb_kdoor_init(smb_server_t *);
void smb_kdoor_fini(smb_server_t *);
@@ -375,6 +396,7 @@ int smb_kdoor_open(smb_server_t *, int);
void smb_kdoor_close(smb_server_t *);
int smb_kdoor_upcall(smb_server_t *, uint32_t,
void *, xdrproc_t, void *, xdrproc_t);
+void fksmb_kdoor_open(smb_server_t *, void *);
/*
* SMB server functions (file smb_server.c)
@@ -521,8 +543,7 @@ int smb_try_grow(smb_request_t *sr, int64_t new_size);
unsigned short smb_worker_getnum();
/* SMB signing routines smb_signing.c */
-void smb_sign_g_init(void);
-void smb_sign_init(smb_request_t *, smb_session_key_t *, char *, int);
+int smb_sign_begin(smb_request_t *, smb_token_t *);
int smb_sign_check_request(smb_request_t *);
int smb_sign_check_secondary(smb_request_t *, unsigned int);
void smb_sign_reply(smb_request_t *, mbuf_chain_t *);
@@ -650,6 +671,8 @@ void smb_user_netinfo_init(smb_user_t *, smb_netuserinfo_t *);
void smb_user_netinfo_fini(smb_netuserinfo_t *);
int smb_user_netinfo_encode(smb_user_t *, uint8_t *, size_t, uint32_t *);
smb_token_t *smb_get_token(smb_session_t *, smb_logon_t *);
+cred_t *smb_cred_create(smb_token_t *);
+void smb_user_setcred(smb_user_t *, cred_t *, uint32_t);
/*
* SMB tree functions (file smb_tree.c)
@@ -824,9 +847,12 @@ char *smb_srm_strdup(smb_request_t *, const char *);
void smb_export_start(smb_server_t *);
void smb_export_stop(smb_server_t *);
-door_handle_t smb_kshare_door_init(int);
-void smb_kshare_door_fini(door_handle_t);
-int smb_kshare_upcall(door_handle_t, void *, boolean_t);
+#ifdef _KERNEL
+struct __door_handle;
+struct __door_handle *smb_kshare_door_init(int);
+void smb_kshare_door_fini(struct __door_handle *);
+int smb_kshare_upcall(struct __door_handle *, void *, boolean_t);
+#endif /* _KERNEL */
void smb_kshare_g_init(void);
void smb_kshare_g_fini(void);
diff --git a/usr/src/uts/common/smbsrv/smb_ktypes.h b/usr/src/uts/common/smbsrv/smb_ktypes.h
index c3d8b6c214..74e2b9f437 100644
--- a/usr/src/uts/common/smbsrv/smb_ktypes.h
+++ b/usr/src/uts/common/smbsrv/smb_ktypes.h
@@ -49,8 +49,6 @@ extern "C" {
#include <netinet/in.h>
#include <sys/ksocket.h>
#include <sys/fem.h>
-#include <sys/door.h>
-#include <sys/extdirent.h>
#include <smbsrv/smb.h>
#include <smbsrv/smbinfo.h>
#include <smbsrv/mbuf.h>
@@ -60,6 +58,9 @@ extern "C" {
#include <smbsrv/smb_vops.h>
#include <smbsrv/smb_kstat.h>
+struct __door_handle; /* <sys/door.h> */
+struct edirent; /* <sys/extdirent.h> */
+
struct smb_disp_entry;
struct smb_request;
struct smb_server;
@@ -250,7 +251,8 @@ typedef enum smb_thread_state {
SMB_THREAD_STATE_STARTING = 0,
SMB_THREAD_STATE_RUNNING,
SMB_THREAD_STATE_EXITING,
- SMB_THREAD_STATE_EXITED
+ SMB_THREAD_STATE_EXITED,
+ SMB_THREAD_STATE_FAILED
} smb_thread_state_t;
struct _smb_thread;
@@ -707,7 +709,6 @@ typedef struct smb_arg_sessionsetup {
uint8_t *ssi_cspwd;
uint16_t ssi_maxmpxcount;
uint32_t ssi_capabilities;
- uint32_t ssi_sesskey;
boolean_t ssi_guest;
} smb_arg_sessionsetup_t;
@@ -759,13 +760,12 @@ typedef struct tcon {
* local_ipaddr: the local IP address used to connect to the server.
*/
-#define SMB_MAC_KEYSZ 512
-
struct smb_sign {
- unsigned int seqnum;
- unsigned int mackey_len;
unsigned int flags;
- unsigned char mackey[SMB_MAC_KEYSZ];
+ uint32_t seqnum;
+ uint_t mackey_len;
+ uint8_t *mackey;
+ void *mech; /* mechanism info */
};
#define SMB_SIGNING_ENABLED 1
@@ -913,6 +913,7 @@ typedef struct smb_session {
uint32_t capabilities;
struct smb_sign signing;
+ void (*sign_fini)(struct smb_session *);
ksocket_t sock;
@@ -1286,8 +1287,8 @@ typedef struct smb_odir {
uint64_t d_offset;
union {
char *u_bufptr;
- edirent_t *u_edp;
- dirent64_t *u_dp;
+ struct edirent *u_edp;
+ struct dirent64 *u_dp;
} d_u;
uint32_t d_last_cookie;
uint32_t d_cookies[SMB_MAX_SEARCH];
@@ -1849,17 +1850,17 @@ typedef struct smb_server {
smb_session_t *sv_session;
struct smb_export sv_export;
- door_handle_t sv_lmshrd;
+ struct __door_handle *sv_lmshrd;
/* Internal door for up-calls to smbd */
- door_handle_t sv_kdoor_hd;
+ struct __door_handle *sv_kdoor_hd;
int sv_kdoor_id; /* init -1 */
uint64_t sv_kdoor_ncall;
kmutex_t sv_kdoor_mutex;
kcondvar_t sv_kdoor_cv;
/* RPC pipes (client side) */
- door_handle_t sv_opipe_door_hd;
+ struct __door_handle *sv_opipe_door_hd;
int sv_opipe_door_id;
uint64_t sv_opipe_door_ncall;
kmutex_t sv_opipe_door_mutex;
@@ -1936,9 +1937,6 @@ typedef struct smb_spoolfid {
#define SMB_INFO_USER_LEVEL_SECURITY 0x40000000
#define SMB_INFO_ENCRYPT_PASSWORDS 0x80000000
-#define SMB_NEW_KID() atomic_inc_64_nv(&smb_kids)
-#define SMB_UNIQ_FID() atomic_inc_32_nv(&smb_fids)
-
#define SMB_IS_STREAM(node) ((node)->n_unode)
typedef struct smb_tsd {
diff --git a/usr/src/uts/common/smbsrv/smb_share.h b/usr/src/uts/common/smbsrv/smb_share.h
index 6a66853dfc..2ca97856c0 100644
--- a/usr/src/uts/common/smbsrv/smb_share.h
+++ b/usr/src/uts/common/smbsrv/smb_share.h
@@ -21,6 +21,7 @@
/*
* Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SMB_SHARE_H
@@ -33,7 +34,7 @@
#include <smbsrv/wintypes.h>
#include <smb/lmerr.h>
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
#include <libshare.h>
#endif
@@ -228,7 +229,7 @@ typedef struct smb_shr_execinfo {
* will return -1.
*/
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
/*
* CIFS share management functions exported by libmlsvc
@@ -271,7 +272,7 @@ uint32_t smb_share_rename(char *, char *);
uint32_t smb_share_create(smb_share_t *);
uint32_t smb_share_modify(smb_share_t *);
-#endif
+#endif /* _KERNEL */
#ifdef __cplusplus
}
diff --git a/usr/src/uts/common/smbsrv/smb_signing.h b/usr/src/uts/common/smbsrv/smb_signing.h
new file mode 100644
index 0000000000..1b1694a99d
--- /dev/null
+++ b/usr/src/uts/common/smbsrv/smb_signing.h
@@ -0,0 +1,50 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
+ */
+
+#ifndef _SMB_SIGNING_H_
+#define _SMB_SIGNING_H_
+
+#ifdef _KERNEL
+#include <sys/crypto/api.h>
+#else
+#include <security/cryptoki.h>
+#include <security/pkcs11.h>
+#endif
+
+#define MD5_DIGEST_LENGTH 16 /* MD5 digest length in bytes */
+
+#ifdef _KERNEL
+/* KCF variant */
+typedef crypto_mechanism_t smb_sign_mech_t;
+typedef crypto_context_t smb_sign_ctx_t;
+#else /* _KERNEL */
+/* PKCS11 variant */
+typedef CK_MECHANISM smb_sign_mech_t;
+typedef CK_SESSION_HANDLE smb_sign_ctx_t;
+#endif /* _KERNEL */
+
+/*
+ * SMB1 signing routines used in smb_signing.c
+ * Two implementations of these (kernel/user) in:
+ * uts/common/fs/smbsrv/smb_sign_kcf.c
+ * lib/smbsrv/libfksmbsrv/common/fksmb_sign_pkcs.c
+ */
+
+int smb_md5_getmech(smb_sign_mech_t *);
+int smb_md5_init(smb_sign_ctx_t *, smb_sign_mech_t *);
+int smb_md5_update(smb_sign_ctx_t, void *, size_t);
+int smb_md5_final(smb_sign_ctx_t, uint8_t *);
+
+#endif /* _SMB_SIGNING_H_ */
diff --git a/usr/src/uts/common/smbsrv/smb_token.h b/usr/src/uts/common/smbsrv/smb_token.h
index a210244f24..99541ad670 100644
--- a/usr/src/uts/common/smbsrv/smb_token.h
+++ b/usr/src/uts/common/smbsrv/smb_token.h
@@ -21,6 +21,8 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SMB_TOKEN_H
@@ -29,7 +31,6 @@
#include <smbsrv/netrauth.h>
#include <smbsrv/smb_privilege.h>
#include <smbsrv/smb_sid.h>
-#include <smbsrv/smb_xdr.h>
#ifdef __cplusplus
extern "C" {
@@ -44,6 +45,12 @@ typedef struct smb_session_key {
uint8_t data[16];
} smb_session_key_t;
+/* 32-bit opaque buffer (non-null terminated strings) */
+typedef struct smb_buf32 {
+ uint32_t len;
+ uint8_t *val;
+} smb_buf32_t;
+
/*
* Access Token
*
@@ -118,10 +125,12 @@ typedef struct smb_logon {
uint32_t lg_status; /* filled in user space */
} smb_logon_t;
-bool_t smb_logon_xdr();
-bool_t smb_token_xdr();
+int smb_logon_xdr();
+int smb_token_xdr();
-#ifndef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+void smb_token_free(smb_token_t *);
+#else /* _KERNEL */
smb_token_t *smb_logon(smb_logon_t *);
void smb_logon_abort(void);
void smb_token_destroy(smb_token_t *);
@@ -129,8 +138,6 @@ uint8_t *smb_token_encode(smb_token_t *, uint32_t *);
void smb_token_log(smb_token_t *);
smb_logon_t *smb_logon_decode(uint8_t *, uint32_t);
void smb_logon_free(smb_logon_t *);
-#else /* _KERNEL */
-void smb_token_free(smb_token_t *);
#endif /* _KERNEL */
int smb_token_query_privilege(smb_token_t *token, int priv_id);
@@ -140,5 +147,4 @@ boolean_t smb_token_valid(smb_token_t *);
}
#endif
-
#endif /* _SMB_TOKEN_H */
diff --git a/usr/src/uts/common/smbsrv/smb_xdr.h b/usr/src/uts/common/smbsrv/smb_xdr.h
index 34c140fc6b..8990884b19 100644
--- a/usr/src/uts/common/smbsrv/smb_xdr.h
+++ b/usr/src/uts/common/smbsrv/smb_xdr.h
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SMBSRV_SMB_XDR_H
@@ -32,6 +33,7 @@ extern "C" {
#include <rpc/xdr.h>
#include <sys/param.h>
#include <sys/avl.h>
+#include <sys/list.h>
#include <smbsrv/wintypes.h>
#include <smbsrv/smb_sid.h>
#include <smbsrv/smbinfo.h>
@@ -41,11 +43,14 @@ extern "C" {
#include <smbsrv/smb_dfs.h>
#include <smbsrv/wintypes.h>
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+#include <sys/sysmacros.h>
#define xdr_int8_t xdr_char
#define xdr_uint8_t xdr_u_char
#define xdr_int16_t xdr_short
#define xdr_uint16_t xdr_u_short
+#else /* _KERNEL */
+#include <stddef.h> /* offsetof */
#endif /* _KERNEL */
/* null-terminated string */
@@ -53,11 +58,7 @@ typedef struct smb_string {
char *buf;
} smb_string_t;
-/* 32-bit opaque buffer (non-null terminated strings) */
-typedef struct smb_buf32 {
- uint32_t len;
- uint8_t *val;
-} smb_buf32_t;
+struct smb_buf32;
#define SMB_OPIPE_HDR_MAGIC 0x4F484452 /* OHDR */
#define SMB_OPIPE_DOOR_BUFSIZE (30 * 1024)
@@ -83,6 +84,7 @@ typedef enum {
#define SMB_DF_ASYNC 0x00000001 /* Asynchronous call */
#define SMB_DF_SYSSPACE 0x00000002 /* Called from the kernel */
#define SMB_DF_USERSPACE 0x00000004 /* Called from user space */
+#define SMB_DF_FAKE_KERNEL 0x00000008 /* Called from fake kernel */
/*
* Header for door calls. The op codes and return codes are defined
@@ -173,7 +175,7 @@ typedef struct smb_netsvc {
} smb_netsvc_t;
-bool_t smb_buf32_xdr(XDR *, smb_buf32_t *);
+bool_t smb_buf32_xdr(XDR *, struct smb_buf32 *);
bool_t smb_string_xdr(XDR *, smb_string_t *);
bool_t smb_inaddr_xdr(XDR *, smb_inaddr_t *);
diff --git a/usr/src/uts/common/sys/acl.h b/usr/src/uts/common/sys/acl.h
index 2a92319408..079c4f473f 100644
--- a/usr/src/uts/common/sys/acl.h
+++ b/usr/src/uts/common/sys/acl.h
@@ -23,6 +23,8 @@
*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SYS_ACL_H
@@ -118,8 +120,6 @@ typedef struct acl_info acl_t;
#define ACL_FLAGS_ALL (ACL_AUTO_INHERIT|ACL_PROTECTED| \
ACL_DEFAULTED)
-#ifdef _KERNEL
-
/*
* These are only applicable in a CIFS context.
*/
@@ -139,6 +139,8 @@ typedef struct acl_info acl_t;
#define ACE_ALL_TYPES 0x001F
+#ifdef _KERNEL
+
typedef struct ace_object {
uid_t a_who; /* uid or gid */
uint32_t a_access_mask; /* read,write,... */
diff --git a/usr/src/uts/common/sys/class.h b/usr/src/uts/common/sys/class.h
index 8487942ea2..82258d4357 100644
--- a/usr/src/uts/common/sys/class.h
+++ b/usr/src/uts/common/sys/class.h
@@ -22,6 +22,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/* Copyright (c) 1988 AT&T */
@@ -115,7 +117,7 @@ typedef struct sclass {
#define SCHED_INSTALLED(s) ((s)->cl_funcs != NULL)
#define ALLOCATED_SCHED(s) ((s)->cl_lock != NULL)
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#define CLASS_KERNEL(cid) ((cid) == syscid || (cid) == sysdccid)
diff --git a/usr/src/uts/common/sys/cmn_err.h b/usr/src/uts/common/sys/cmn_err.h
index 736c77b9dc..4ebcb1d4f1 100644
--- a/usr/src/uts/common/sys/cmn_err.h
+++ b/usr/src/uts/common/sys/cmn_err.h
@@ -27,13 +27,13 @@
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * Copyright 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SYS_CMN_ERR_H
#define _SYS_CMN_ERR_H
-#if defined(_KERNEL) && !defined(_ASM)
+#if !defined(_ASM) && (defined(_KERNEL) || defined(_FAKE_KERNEL))
#include <sys/va_list.h>
#endif
@@ -51,9 +51,7 @@ extern "C" {
#define CE_PANIC 3 /* panic */
#define CE_IGNORE 4 /* print nothing */
-#ifndef _ASM
-
-#ifdef _KERNEL
+#if !defined(_ASM) && (defined(_KERNEL) || defined(_FAKE_KERNEL))
/*PRINTFLIKE2*/
extern void cmn_err(int, const char *, ...)
@@ -111,8 +109,7 @@ extern void panic(const char *, ...)
extern void vpanic(const char *, __va_list)
__KVPRINTFLIKE(1) __NORETURN;
-#endif /* _KERNEL */
-#endif /* !_ASM */
+#endif /* !_ASM && _KERNEL ... */
#ifdef __cplusplus
}
diff --git a/usr/src/uts/common/sys/disp.h b/usr/src/uts/common/sys/disp.h
index 534feb4bd0..5fe926de7b 100644
--- a/usr/src/uts/common/sys/disp.h
+++ b/usr/src/uts/common/sys/disp.h
@@ -21,6 +21,8 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -30,8 +32,6 @@
#ifndef _SYS_DISP_H
#define _SYS_DISP_H
-#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.11 */
-
#include <sys/priocntl.h>
#include <sys/thread.h>
#include <sys/class.h>
@@ -79,7 +79,7 @@ typedef struct _disp {
hrtime_t disp_steal; /* time when threads become stealable */
} disp_t;
-#if defined(_KERNEL)
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#define MAXCLSYSPRI 99
#define MINCLSYSPRI 60
@@ -96,6 +96,9 @@ extern pri_t minclsyspri; /* minimum level of any system class */
extern pri_t maxclsyspri; /* maximum level of any system class */
extern pri_t intr_pri; /* interrupt thread priority base level */
+#endif /* _KERNEL || _FAKE_KERNEL */
+#if defined(_KERNEL)
+
/*
* Minimum amount of time that a thread can remain runnable before it can
* be stolen by another CPU (in nanoseconds).
diff --git a/usr/src/uts/common/sys/extdirent.h b/usr/src/uts/common/sys/extdirent.h
index 3f9a665f00..bf09c44db6 100644
--- a/usr/src/uts/common/sys/extdirent.h
+++ b/usr/src/uts/common/sys/extdirent.h
@@ -21,20 +21,20 @@
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SYS_EXTDIRENT_H
#define _SYS_EXTDIRENT_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
#include <sys/types.h>
-#if defined(_KERNEL)
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
/*
* Extended file-system independent directory entry. This style of
diff --git a/usr/src/uts/common/sys/fem.h b/usr/src/uts/common/sys/fem.h
index 9b3cd142e4..beb838fdfa 100644
--- a/usr/src/uts/common/sys/fem.h
+++ b/usr/src/uts/common/sys/fem.h
@@ -21,6 +21,8 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SYS_FEM_H
@@ -40,7 +42,7 @@
extern "C" {
#endif
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
struct fs_operation_def; /* from vfs.h */
diff --git a/usr/src/uts/common/sys/flock.h b/usr/src/uts/common/sys/flock.h
index 3ea7afb23b..e0cc609960 100644
--- a/usr/src/uts/common/sys/flock.h
+++ b/usr/src/uts/common/sys/flock.h
@@ -28,7 +28,7 @@
* Use is subject to license terms.
*/
/*
- * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SYS_FLOCK_H
@@ -201,7 +201,7 @@ typedef enum {
FLK_LOCKMGR_DOWN
} flk_lockmgr_status_t;
-#if defined(_KERNEL)
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
/*
* The following structure is used to hold a list of locks returned
diff --git a/usr/src/uts/common/sys/kmem.h b/usr/src/uts/common/sys/kmem.h
index bf6e09f4cf..e54d83e499 100644
--- a/usr/src/uts/common/sys/kmem.h
+++ b/usr/src/uts/common/sys/kmem.h
@@ -22,6 +22,7 @@
/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -51,7 +52,7 @@ extern "C" {
#define KM_FLAGS 0xffff /* all settable kmem flags */
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
extern void *kmem_alloc(size_t size, int kmflags);
extern void *kmem_zalloc(size_t size, int kmflags);
@@ -94,7 +95,7 @@ typedef enum kmem_cbrc {
KMEM_CBRC_DONT_KNOW
} kmem_cbrc_t;
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
/*
* Helps clients implementing the move() callback to recognize known objects by
diff --git a/usr/src/uts/common/sys/kstat.h b/usr/src/uts/common/sys/kstat.h
index b18509c07a..5ae814d81d 100644
--- a/usr/src/uts/common/sys/kstat.h
+++ b/usr/src/uts/common/sys/kstat.h
@@ -21,13 +21,13 @@
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SYS_KSTAT_H
#define _SYS_KSTAT_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
/*
* Definition of general kernel statistics structures and /dev/kstat ioctls
*/
@@ -698,7 +698,7 @@ typedef struct kstat_timer {
#define KSTAT_TIMER_PTR(kptr) ((kstat_timer_t *)(kptr)->ks_data)
-#if defined(_KERNEL)
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#include <sys/t_lock.h>
diff --git a/usr/src/uts/common/sys/mode.h b/usr/src/uts/common/sys/mode.h
index 1d0ad60f82..a628a3f8d4 100644
--- a/usr/src/uts/common/sys/mode.h
+++ b/usr/src/uts/common/sys/mode.h
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -30,7 +32,7 @@
#ifndef _SYS_MODE_H
#define _SYS_MODE_H
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#include <sys/stat.h>
#include <sys/vnode.h>
diff --git a/usr/src/uts/common/sys/random.h b/usr/src/uts/common/sys/random.h
index b835d2f5ac..6a0d421a15 100644
--- a/usr/src/uts/common/sys/random.h
+++ b/usr/src/uts/common/sys/random.h
@@ -23,8 +23,8 @@
* Use is subject to license terms.
*/
/*
- * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2015, Joyent, Inc.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SYS_RANDOM_H
@@ -54,7 +54,7 @@ typedef struct swrand_stats {
/* the pool */
} swrand_stats_t;
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#define BUMP_CPU_RND_STATS(rm, x, v) (((rm)->rm_mag.rm_stats).x += (v))
#define BUMP_RND_STATS(x, v) atomic_add_64(&(rnd_stats).x, (v))
diff --git a/usr/src/uts/common/sys/refstr.h b/usr/src/uts/common/sys/refstr.h
index 8e7016823a..a92dde061e 100644
--- a/usr/src/uts/common/sys/refstr.h
+++ b/usr/src/uts/common/sys/refstr.h
@@ -22,13 +22,13 @@
/*
* Copyright (c) 1999 by Sun Microsystems, Inc.
* All rights reserved.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SYS_REFSTR_H
#define _SYS_REFSTR_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -40,7 +40,7 @@ extern "C" {
typedef struct refstr refstr_t;
-#if defined(_KERNEL)
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
refstr_t *refstr_alloc(const char *);
const char *refstr_value(refstr_t *);
diff --git a/usr/src/uts/common/sys/select.h b/usr/src/uts/common/sys/select.h
index 418cb56838..aa6ef3185e 100644
--- a/usr/src/uts/common/sys/select.h
+++ b/usr/src/uts/common/sys/select.h
@@ -22,6 +22,8 @@
/*
* Copyright 2014 Garrett D'Amore <garrett@damore.org>
*
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
+ *
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -44,12 +46,12 @@
#include <sys/feature_tests.h>
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
#if !defined(__XOPEN_OR_POSIX) || defined(_XPG6) || defined(__EXTENSIONS__)
#include <sys/time_impl.h>
#endif
#include <sys/time.h>
-#endif /* _KERNEL */
+#endif /* !_KERNEL */
#ifdef __cplusplus
extern "C" {
@@ -147,13 +149,13 @@ typedef struct __fd_set {
#define FD_ISSET(__n, __p) (((__p)->fds_bits[(__n)/FD_NFDBITS] & \
(1ul << ((__n) % FD_NFDBITS))) != 0l)
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#define FD_ZERO(p) bzero((p), sizeof (*(p)))
#else
#define FD_ZERO(__p) (void) memset((__p), 0, sizeof (*(__p)))
#endif /* _KERNEL */
-#ifndef _KERNEL
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL)
extern int select(int, fd_set *_RESTRICT_KYWD, fd_set *_RESTRICT_KYWD,
fd_set *_RESTRICT_KYWD, struct timeval *_RESTRICT_KYWD);
diff --git a/usr/src/uts/common/sys/sid.h b/usr/src/uts/common/sys/sid.h
index d38fc64eed..eef4bb2eb1 100644
--- a/usr/src/uts/common/sys/sid.h
+++ b/usr/src/uts/common/sys/sid.h
@@ -22,6 +22,8 @@
/*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SYS_SID_H
@@ -29,7 +31,7 @@
#include <sys/types.h>
#include <sys/avl.h>
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#include <sys/zone.h>
#endif
@@ -53,7 +55,7 @@ extern "C" {
#define SIDSYS_SID2ID 0
#define SIDSYS_ID2SID 1
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#define KSIDLIST_MEM(n) (sizeof (ksidlist_t) + ((n) - 1) * sizeof (ksid_t))
/* Domains are stored in AVL trees so we can share them among SIDs */
@@ -122,7 +124,7 @@ ksiddomain_t *ksid_lookupdomain(const char *);
ksidlist_t *kcrsid_gidstosids(zone_t *, int, gid_t *);
-#else
+#else /* _KERNEL */
int allocids(int, int, uid_t *, int, gid_t *);
int __idmap_reg(int);
diff --git a/usr/src/uts/common/sys/socket.h b/usr/src/uts/common/sys/socket.h
index 590551f6f2..da8e3ab351 100644
--- a/usr/src/uts/common/sys/socket.h
+++ b/usr/src/uts/common/sys/socket.h
@@ -217,7 +217,7 @@ struct fil_info {
#define FILF_AUTO 0x2 /* automatic attach */
#define FILF_BYPASS 0x4 /* filter is not active */
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
/*
* new socket open flags to identify socket and acceptor streams
*/
@@ -361,7 +361,7 @@ struct msghdr {
#endif /* defined(_XPG4_2) || defined(_KERNEL) */
};
-#if defined(_KERNEL)
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
/*
* N.B.: we assume that omsghdr and nmsghdr are isomorphic, with
diff --git a/usr/src/uts/common/sys/stream.h b/usr/src/uts/common/sys/stream.h
index 7a3b4e3448..a04019a9ce 100644
--- a/usr/src/uts/common/sys/stream.h
+++ b/usr/src/uts/common/sys/stream.h
@@ -35,7 +35,8 @@
*/
#include <sys/isa_defs.h>
#ifdef _KERNEL
-#include <sys/vnode.h>
+#include <sys/kmem.h>
+#include <sys/uio.h>
#endif
#include <sys/poll.h>
#include <sys/strmdep.h>
diff --git a/usr/src/uts/common/sys/sunddi.h b/usr/src/uts/common/sys/sunddi.h
index 8d1fd5e730..bb063c23db 100644
--- a/usr/src/uts/common/sys/sunddi.h
+++ b/usr/src/uts/common/sys/sunddi.h
@@ -329,7 +329,7 @@ typedef enum {
DDI_DEVSTATE_UP = 32
} ddi_devstate_t;
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
/*
* Common property definitions
@@ -504,6 +504,9 @@ extern int kiconv_close(kiconv_t);
extern size_t kiconvstr(const char *, const char *, char *, size_t *, char *,
size_t *, int, int *);
+#endif /* _KERNEL || _FAKE_KERNEL */
+#ifdef _KERNEL
+
/*
* ddi_map_regs
*
diff --git a/usr/src/uts/common/sys/sysmacros.h b/usr/src/uts/common/sys/sysmacros.h
index 71042eba85..b565968dda 100644
--- a/usr/src/uts/common/sys/sysmacros.h
+++ b/usr/src/uts/common/sys/sysmacros.h
@@ -26,7 +26,7 @@
* Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*
- * Copyright 2011, 2012 Nexenta Systems, Inc. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SYS_SYSMACROS_H
@@ -132,7 +132,7 @@ extern unsigned char bcd_to_byte[256];
#define getminor(x) (minor_t)((x) & L_MAXMIN)
-#else
+#else /* _KERNEL */
/* major part of a device external from the kernel (same as emajor below) */
@@ -367,7 +367,7 @@ extern unsigned char bcd_to_byte[256];
#endif /* _BIT_FIELDS_LTOH */
/* avoid any possibility of clashing with <stddef.h> version */
-#if defined(_KERNEL) && !defined(_KMEMUSER)
+#if (defined(_KERNEL) || defined(_FAKE_KERNEL)) && !defined(_KMEMUSER)
#if !defined(offsetof)
#define offsetof(s, m) ((size_t)(&(((s *)0)->m)))
diff --git a/usr/src/uts/common/sys/systm.h b/usr/src/uts/common/sys/systm.h
index 8edfd994ab..9880b79406 100644
--- a/usr/src/uts/common/sys/systm.h
+++ b/usr/src/uts/common/sys/systm.h
@@ -54,7 +54,8 @@ typedef uintptr_t pc_t;
* Random set of variables used by more than one routine.
*/
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
+#include <sys/types32.h>
#include <sys/varargs.h>
#include <sys/uadmin.h>
@@ -193,7 +194,10 @@ int strident_valid(const char *);
void strident_canon(char *, size_t);
int getsubopt(char **optionsp, char * const *tokens, char **valuep);
char *append_subopt(const char *, size_t, char *, const char *);
+#ifndef _FAKE_KERNEL
+/* conflicts with libc definition */
int ffs(uintmax_t);
+#endif
int copyin(const void *, void *, size_t);
void copyin_noerr(const void *, void *, size_t);
int xcopyin(const void *, void *, size_t);
@@ -246,7 +250,8 @@ int suword64(void *, uint64_t);
void suword64_noerr(void *, uint64_t);
#endif
-#if !defined(_BOOT)
+#if !defined(_BOOT) && !defined(_FAKE_KERNEL)
+/* conflicts with libc definition */
int setjmp(label_t *) __RETURNS_TWICE;
extern void longjmp(label_t *)
__NORETURN;
@@ -382,7 +387,7 @@ union rval {
typedef union rval rval_t;
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
extern void reset_syscall_args(void);
extern int save_syscall_args(void);
@@ -421,7 +426,7 @@ extern int start_init_common(void);
#endif /* _KERNEL */
-#if defined(_KERNEL) || defined(_BOOT)
+#if defined(_KERNEL) || defined(_FAKE_KERNEL) || defined(_BOOT)
size_t strlcat(char *, const char *, size_t);
size_t strlen(const char *) __PURE;
@@ -429,6 +434,13 @@ char *strcat(char *, const char *);
char *strncat(char *, const char *, size_t);
char *strcpy(char *, const char *);
char *strncpy(char *, const char *, size_t);
+
+extern size_t strlcpy(char *, const char *, size_t);
+extern size_t strspn(const char *, const char *);
+extern size_t strcspn(const char *, const char *);
+extern char *strdup(const char *);
+extern void strfree(char *);
+
/* Need to be consistent with <string.h> C++ definitions */
#if __cplusplus >= 199711L
extern const char *strchr(const char *, int);
diff --git a/usr/src/uts/common/sys/taskq.h b/usr/src/uts/common/sys/taskq.h
index 8b601c86a5..7548149ef6 100644
--- a/usr/src/uts/common/sys/taskq.h
+++ b/usr/src/uts/common/sys/taskq.h
@@ -21,6 +21,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SYS_TASKQ_H
@@ -60,7 +62,7 @@ struct proc;
#define TQ_NOALLOC 0x04 /* cannot allocate memory; may fail */
#define TQ_FRONT 0x08 /* Put task at the front of the queue */
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
extern taskq_t *system_taskq;
diff --git a/usr/src/uts/common/sys/time.h b/usr/src/uts/common/sys/time.h
index bdf1c02ea4..b2ba0a3091 100644
--- a/usr/src/uts/common/sys/time.h
+++ b/usr/src/uts/common/sys/time.h
@@ -13,6 +13,8 @@
*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SYS_TIME_H
@@ -68,7 +70,7 @@ struct timeval {
#define TIMEVAL_OVERFLOW(tv) \
((tv)->tv_sec < TIME32_MIN || (tv)->tv_sec > TIME32_MAX)
-#endif /* _SYSCALL32 || _KERNEL */
+#endif /* _SYSCALL32 */
#endif /* _ASM */
#endif /* !defined(__XOPEN_OR_POSIX) || defined(_XPG4_2) ... */
@@ -250,7 +252,7 @@ struct itimerval32 {
*/
typedef longlong_t hrtime_t;
-#ifdef _KERNEL
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#include <sys/time_impl.h>
#include <sys/mutex.h>
@@ -445,7 +447,7 @@ int gettimeofday(struct timeval *_RESTRICT_KYWD, void *_RESTRICT_KYWD);
* non-X/Open applications, including this header will still make
* visible these definitions.
*/
-#if !defined(_BOOT) && !defined(_KERNEL) && \
+#if !defined(_BOOT) && !defined(_KERNEL) && !defined(_FAKE_KERNEL) && \
!defined(__XOPEN_OR_POSIX) || defined(__EXTENSIONS__)
#include <time.h>
#endif
@@ -457,8 +459,9 @@ int gettimeofday(struct timeval *_RESTRICT_KYWD, void *_RESTRICT_KYWD);
* beginning with XSH4v2. Placement required after definition
* for itimerval.
*/
-#if !defined(_KERNEL) && !defined(__XOPEN_OR_POSIX) || defined(_XPG4_2) || \
- defined(__EXTENSIONS__)
+#if !defined(_KERNEL) && !defined(_FAKE_KERNEL) && \
+ !defined(__XOPEN_OR_POSIX) || \
+ defined(_XPG4_2) || defined(__EXTENSIONS__)
#include <sys/select.h>
#endif
diff --git a/usr/src/uts/common/sys/types.h b/usr/src/uts/common/sys/types.h
index 3667e25ee0..06a0443b0d 100644
--- a/usr/src/uts/common/sys/types.h
+++ b/usr/src/uts/common/sys/types.h
@@ -25,6 +25,8 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
#ifndef _SYS_TYPES_H
@@ -558,7 +560,7 @@ typedef unsigned int uint;
typedef unsigned long ulong;
/* END CSTYLED */
-#if defined(_KERNEL)
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
#define SHRT_MIN (-32768) /* min value of a "short int" */
#define SHRT_MAX 32767 /* max value of a "short int" */
diff --git a/usr/src/uts/common/sys/uio.h b/usr/src/uts/common/sys/uio.h
index b04ca7b8f3..e803efeb45 100644
--- a/usr/src/uts/common/sys/uio.h
+++ b/usr/src/uts/common/sys/uio.h
@@ -23,6 +23,8 @@
*
* Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
+ *
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2015, Joyent, Inc. All rights reserved.
*/
@@ -235,7 +237,7 @@ typedef struct uioasync_s {
#endif /* !defined(_XPG4_2) || defined(__EXTENSIONS__) */
-#if defined(_KERNEL)
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
int uiomove(void *, size_t, enum uio_rw, uio_t *);
void uio_prefaultpages(ssize_t, uio_t *);
diff --git a/usr/src/uts/common/sys/vfs.h b/usr/src/uts/common/sys/vfs.h
index 879f2aad09..a74ce65f86 100644
--- a/usr/src/uts/common/sys/vfs.h
+++ b/usr/src/uts/common/sys/vfs.h
@@ -20,6 +20,7 @@
*/
/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -428,7 +429,7 @@ enum {
*/
#define VFSSP_VERBATIM 0x1 /* do not prefix the supplied path */
-#if defined(_KERNEL)
+#if defined(_KERNEL) || defined(_FAKE_KERNEL)
/*
* Private vfs data, NOT to be used by a file system implementation.