diff options
author | Gordon Ross <gwr@nexenta.com> | 2013-06-17 10:34:00 -0400 |
---|---|---|
committer | Gordon Ross <gwr@nexenta.com> | 2015-06-04 16:46:25 -0400 |
commit | b819cea2f73f98c5662230cc9affc8cc84f77fcf (patch) | |
tree | a3677952ded5706400717b9b79b0aeaa3d93a739 /usr/src | |
parent | 83d2dfe69259e79314662cf95e6d1f9103dcffe2 (diff) | |
download | illumos-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')
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, ×, &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. |