diff options
author | Jerry Jelinek <jerry.jelinek@joyent.com> | 2019-06-04 12:19:59 +0000 |
---|---|---|
committer | Jerry Jelinek <jerry.jelinek@joyent.com> | 2019-06-04 12:19:59 +0000 |
commit | 4263771df9801298a3c76c40fc650aab69de04e7 (patch) | |
tree | 3171caa421a185f7bb1b5171dd8f61e3b3f19120 | |
parent | 9240ea30ee29d2a499bcf3eed9e12dd9921f39f8 (diff) | |
parent | 93bc28dbaee6387120d48b12b3dc1ba5f7418e6e (diff) | |
download | illumos-joyent-4263771df9801298a3c76c40fc650aab69de04e7.tar.gz |
[illumos-gate merge]
commit 93bc28dbaee6387120d48b12b3dc1ba5f7418e6e
1841 SMB dtrace provider is incomplete
11180 SMB2 IOCTL FSCTL_LMR_REQUEST_RESILIENCY Returns Incorrect Response
commit a44e7c2c55fc7960907cf98ac651ed37325d79ad
10999 Misc. SMB changes missed in prior upstreams
commit 7d1ffc32e5e72873791b96934af035e0f051fc14
7587 SMB should support enhanced Unicode
commit 07a6ae61f8958faa11352bf1b552d85d79e9cbbe
10997 Incorrect directory listing response for non-UNICODE clients
commit 6f214831a73efcf0c7ce197b21d38588265645a1
10942 want nm option to not sort symbols
10943 nm should be smatch and CERRWARN clean
Conflicts:
usr/src/uts/common/dtrace/sdt_subr.c
usr/src/man/man1/nm.1
98 files changed, 5136 insertions, 1299 deletions
diff --git a/exception_lists/check_rtime b/exception_lists/check_rtime index a3b1f1c898..c31e6822b2 100644 --- a/exception_lists/check_rtime +++ b/exception_lists/check_rtime @@ -230,6 +230,7 @@ FORBIDDEN_DEP usr/lib/MACH(smbfs)/libfknsmb.so.1 FORBIDDEN_DEP usr/lib/MACH(smbfs)/libfksmbfs.so.1 FORBIDDEN_DEP usr/lib/MACH(smbsrv)/libfksmbsrv.so.1 FORBIDDEN_DEP usr/lib/smbsrv/fksmbd +FORBIDDEN_DEP usr/lib/smbsrv/test-msgbuf FORBIDDEN_DEP usr/sbin/amd64/zdb FORBIDDEN_DEP usr/sbin/i86/zdb FORBIDDEN_DEP usr/sbin/sparcv7/zdb diff --git a/exception_lists/packaging b/exception_lists/packaging index 3339cfb28e..e7ab7b63a0 100644 --- a/exception_lists/packaging +++ b/exception_lists/packaging @@ -603,6 +603,7 @@ usr/lib/smbsrv/libfksmbsrv.so.1 usr/lib/smbsrv/libmlsvc.so usr/lib/smbsrv/libsmb.so usr/lib/smbsrv/libsmbns.so +usr/lib/smbsrv/test-msgbuf # # # Private/Internal 64-bit libraries of smbsrv. Do not ship. @@ -5494,6 +5494,7 @@ f usr/lib/dtrace/regs.d 0644 root bin f usr/lib/dtrace/sched.d 0644 root bin f usr/lib/dtrace/scsi.d 0644 root bin f usr/lib/dtrace/signal.d 0644 root bin +f usr/lib/dtrace/smb.d 0644 root bin f usr/lib/dtrace/srp.d 0644 root bin f usr/lib/dtrace/sysevent.d 0644 root bin f usr/lib/dtrace/tcp.d 0644 root bin @@ -10239,6 +10240,8 @@ f usr/lib/smbfs/smbiod 0555 root bin f usr/lib/smbfs/smbiod-svc 0555 root bin d usr/lib/smbsrv 0755 root bin d usr/lib/smbsrv/dtrace 0755 root bin +f usr/lib/smbsrv/dtrace/smb-trace.d 0555 root bin +f usr/lib/smbsrv/dtrace/smb2-trace.d 0555 root bin f usr/lib/smbsrv/dtrace/smbd-all.d 0555 root bin f usr/lib/smbsrv/dtrace/smbd-authsvc.d 0555 root bin f usr/lib/smbsrv/dtrace/smbd-doorsvc.d 0555 root bin diff --git a/usr/src/cmd/smbsrv/Makefile b/usr/src/cmd/smbsrv/Makefile index 641026e8e9..193ce84c88 100644 --- a/usr/src/cmd/smbsrv/Makefile +++ b/usr/src/cmd/smbsrv/Makefile @@ -25,7 +25,8 @@ # Copyright 2013 Nexenta Systems, Inc. All rights reserved. # -SUBDIRS = smbadm smbd smbstat dtrace fksmbd bind-helper +SUBDIRS = smbadm smbd smbstat dtrace fksmbd bind-helper \ + test-msgbuf MSGSUBDIRS = smbadm smbstat include ../Makefile.cmd diff --git a/usr/src/cmd/smbsrv/dtrace/Makefile b/usr/src/cmd/smbsrv/dtrace/Makefile index fb892315fa..0ed2c858af 100644 --- a/usr/src/cmd/smbsrv/dtrace/Makefile +++ b/usr/src/cmd/smbsrv/dtrace/Makefile @@ -22,11 +22,11 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# Copyright 2014 Nexenta Systems, Inc. All rights reserved. +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. # SRCS= smbd-all.d smbd-authsvc.d smbd-doorsvc.d smbd-pipesvc.d \ - smbnode.d smbsrv.d smbvfs.d + smbnode.d smbsrv.d smbvfs.d smb-trace.d smb2-trace.d include ../../Makefile.cmd diff --git a/usr/src/cmd/smbsrv/dtrace/smb-trace.d b/usr/src/cmd/smbsrv/dtrace/smb-trace.d new file mode 100644 index 0000000000..32162dca2b --- /dev/null +++ b/usr/src/cmd/smbsrv/dtrace/smb-trace.d @@ -0,0 +1,44 @@ +/* + * 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 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Example using the "smb" dtrace provider. + * Traces all SMB commands. + * + * All these probes provide: + * args[0] conninfo_t + * args[1] smbopinfo_t + * Some also provide one of: (not used here) + * args[2] smb_name_args_t + * args[2] smb_open_args_t + * args[2] smb_rw_args_t + */ + +smb:::op-*-start +{ + printf("clnt=%s mid=0x%x uid=0x%x tid=0x%x\n", + args[0]->ci_remote, + args[1]->soi_mid, + args[1]->soi_uid, + args[1]->soi_tid); +} + +smb:::op-*-done +{ + printf("clnt=%s mid=0x%x status=0x%x\n", + args[0]->ci_remote, + args[1]->soi_mid, + args[1]->soi_status); +} diff --git a/usr/src/cmd/smbsrv/dtrace/smb2-trace.d b/usr/src/cmd/smbsrv/dtrace/smb2-trace.d new file mode 100644 index 0000000000..4e83216785 --- /dev/null +++ b/usr/src/cmd/smbsrv/dtrace/smb2-trace.d @@ -0,0 +1,43 @@ +/* + * 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 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Example using the "smb2" dtrace provider. + * Traces all SMB commands. + * + * All these probes provide: + * args[0] conninfo_t + * args[1] smb2opinfo_t + * Some also provide one of: (not used here) + * args[2] smb_open_args_t + * args[2] smb_rw_args_t + */ + +smb2:::op-*-start +{ + printf("clnt=%s mid=0x%x uid=0x%x tid=0x%x\n", + args[0]->ci_remote, + args[1]->soi_mid, + args[1]->soi_uid, + args[1]->soi_tid); +} + +smb2:::op-*-done +{ + printf("clnt=%s mid=0x%x status=0x%x\n", + args[0]->ci_remote, + args[1]->soi_mid, + args[1]->soi_status); +} diff --git a/usr/src/cmd/smbsrv/dtrace/smbsrv.d b/usr/src/cmd/smbsrv/dtrace/smbsrv.d index 162839bd71..6cbd806c2e 100644 --- a/usr/src/cmd/smbsrv/dtrace/smbsrv.d +++ b/usr/src/cmd/smbsrv/dtrace/smbsrv.d @@ -11,7 +11,7 @@ */ /* - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -19,8 +19,6 @@ * Usage: dtrace -s smbsrv.d */ -#pragma D option flowindent - self int trace; self int mask; @@ -87,3 +85,26 @@ fbt:smbsrv::return { self->trace--; } + +/* + * Use the "smb", "smb2" dtrace providers. + */ + +smb:::op-*-start, +smb2:::op-*-start +{ + printf("clnt=%s mid=0x%x uid=0x%x tid=0x%x\n", + args[0]->ci_remote, + args[1]->soi_mid, + args[1]->soi_uid, + args[1]->soi_tid); +} + +smb:::op-*-done, +smb2:::op-*-done +{ + printf("clnt=%s mid=0x%x status=0x%x\n", + args[0]->ci_remote, + args[1]->soi_mid, + args[1]->soi_status); +} diff --git a/usr/src/cmd/smbsrv/fksmbd/Watch-all.d b/usr/src/cmd/smbsrv/fksmbd/Watch-all.d index dbf612f7df..67cb7a90f3 100644 --- a/usr/src/cmd/smbsrv/fksmbd/Watch-all.d +++ b/usr/src/cmd/smbsrv/fksmbd/Watch-all.d @@ -11,7 +11,7 @@ */ /* - * Copyright 2018 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -19,8 +19,6 @@ * Usage: dtrace -s Watch-all.d -p $PID */ -#pragma D option flowindent - self int trace; self int mask; @@ -34,7 +32,7 @@ pid$target:libmlrpc.so.2::entry, pid$target:libsmbns.so.1::entry, pid$target:libsmb.so.1::entry { - self->trace++; + self->trace++; } /* @@ -48,10 +46,12 @@ 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); + printf("\t0x%x", arg0); + printf("\t0x%x", arg1); + printf("\t0x%x", arg2); + printf("\t0x%x", arg3); + printf("\t0x%x", arg4); + printf("\t0x%x", arg5); } /* @@ -69,7 +69,7 @@ pid$target::smb_strlwr:entry, pid$target::smb_strupr:entry, pid$target::smb_wcequiv_strlen:entry { - self->mask++; + self->mask++; } /* @@ -86,7 +86,7 @@ pid$target::smb_strlwr:return, pid$target::smb_strupr:return, pid$target::smb_wcequiv_strlen:return { - self->mask--; + self->mask--; } pid$target:fksmbd::return, @@ -97,7 +97,7 @@ pid$target:libsmbns.so.1::return, pid$target:libsmb.so.1::return /self->trace > 0 && self->mask == 0/ { - printf("\t0x%x", arg1); + printf("\t0x%x", arg1); } pid$target:fksmbd::return, @@ -107,5 +107,55 @@ pid$target:libmlrpc.so.2::return, pid$target:libsmbns.so.1::return, pid$target:libsmb.so.1::return { - self->trace--; + self->trace--; +} + +/* + * fksmb dtrace provder + */ + +fksmb$target:::smb_start +{ + this->pn = copyinstr(arg0); + this->sr = (userland pid`smb_request_t *)arg1; + + printf(" %s mid=0x%x uid=0x%x tid=0x%x\n", + this->pn, + this->sr->smb_mid, + this->sr->smb_uid, + this->sr->smb_tid); +} + +fksmb$target:::smb_done +{ + this->pn = copyinstr(arg0); + this->sr = (userland pid`smb_request_t *)arg1; + + printf(" %s mid=0x%x status=0x%x\n", + this->pn, + this->sr->smb_mid, + this->sr->smb_error.status); +} + +fksmb$target:::smb2_start +{ + this->pn = copyinstr(arg0); + this->sr = (userland pid`smb_request_t *)arg1; + + printf(" %s mid=0x%x uid=0x%x tid=0x%x\n", + this->pn, + this->sr->smb2_messageid, + this->sr->smb2_ssnid, + this->sr->smb_tid); +} + +fksmb$target:::smb2_done +{ + this->pn = copyinstr(arg0); + this->sr = (userland pid`smb_request_t *)arg1; + + printf(" %s mid=0x%x status=0x%x\n", + this->pn, + this->sr->smb2_messageid, + this->sr->smb2_status); } diff --git a/usr/src/cmd/smbsrv/fksmbd/Watch-fksmb.d b/usr/src/cmd/smbsrv/fksmbd/Watch-fksmb.d new file mode 100644 index 0000000000..1bcaec5702 --- /dev/null +++ b/usr/src/cmd/smbsrv/fksmbd/Watch-fksmb.d @@ -0,0 +1,72 @@ +/* + * 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 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Example using the "fksmb$pid" dtrace provider. + * Traces all SMB commands using the probes: + * start, done + * all of which have two args: + * args[0]: char * (probe-name) + * args[1]: ulong (struct smb_request *) + * + * Note: the "userland" type classifier causes dtrace to + * automatically copyin the struct for us. (Nice!) + */ + +fksmb$target:::smb_start +{ + this->pn = copyinstr(arg0); + this->sr = (userland pid`smb_request_t *)arg1; + + printf(" %s mid=0x%x uid=0x%x tid=0x%x\n", + this->pn, + this->sr->smb_mid, + this->sr->smb_uid, + this->sr->smb_tid); +} + +fksmb$target:::smb_done +{ + this->pn = copyinstr(arg0); + this->sr = (userland pid`smb_request_t *)arg1; + + printf(" %s mid=0x%x status=0x%x\n", + this->pn, + this->sr->smb_mid, + this->sr->smb_error.status); +} + +fksmb$target:::smb2_start +{ + this->pn = copyinstr(arg0); + this->sr = (userland pid`smb_request_t *)arg1; + + printf(" %s mid=0x%x uid=0x%x tid=0x%x\n", + this->pn, + this->sr->smb2_messageid, + this->sr->smb2_ssnid, + this->sr->smb_tid); +} + +fksmb$target:::smb2_done +{ + this->pn = copyinstr(arg0); + this->sr = (userland pid`smb_request_t *)arg1; + + printf(" %s mid=0x%x status=0x%x\n", + this->pn, + this->sr->smb2_messageid, + this->sr->smb2_status); +} diff --git a/usr/src/cmd/smbsrv/smbd/smbd_authsvc.c b/usr/src/cmd/smbsrv/smbd/smbd_authsvc.c index b507148b72..c4535f8c06 100644 --- a/usr/src/cmd/smbsrv/smbd/smbd_authsvc.c +++ b/usr/src/cmd/smbsrv/smbd/smbd_authsvc.c @@ -103,7 +103,7 @@ int smbd_authsvc_slowdown = 0; * But note: it's really the _client's_ preference that matters. * See &pref in the spnegoIsMechTypeAvailable() calls below. * Careful with this table; the code below knows its format and - * may skip the fist two entries to ommit Kerberos. + * may skip the fist two entries to omit Kerberos. */ static const spnego_mech_handler_t mech_table[] = { @@ -785,7 +785,7 @@ smbd_authsvc_escmn(authsvc_context_t *ctx) /* tell the client the selected mech. */ oid = ctx->ctx_mech_oid; } else { - /* Ommit the "supported mech." field. */ + /* Omit the "supported mech." field. */ oid = spnego_mech_oid_NotUsed; } @@ -919,7 +919,7 @@ smbd_authsvc_gettoken(authsvc_context_t *ctx) /* * Initialization time code to figure out what mechanisms we support. * Careful with this table; the code below knows its format and may - * skip the fist two entries to ommit Kerberos. + * skip the fist two entries to omit Kerberos. */ static SPNEGO_MECH_OID MechTypeList[] = { spnego_mech_oid_Kerberos_V5, diff --git a/usr/src/cmd/smbsrv/test-msgbuf/.dbxrc b/usr/src/cmd/smbsrv/test-msgbuf/.dbxrc new file mode 100644 index 0000000000..983ebcfb35 --- /dev/null +++ b/usr/src/cmd/smbsrv/test-msgbuf/.dbxrc @@ -0,0 +1,22 @@ + +# +# 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 2018 Nexenta Systems, Inc. All rights reserved. +# + +set -o emacs + +setenv ROOT ${CODEMGR_WS}/proto/root_i386 +setenv LD_LIBRARY_PATH ${ROOT}/usr/lib/smbsrv:${ROOT}/usr/lib:${ROOT}/lib + +echo debug ${ROOT}/usr/lib/smbsrv/test-msgbuf diff --git a/usr/src/cmd/smbsrv/test-msgbuf/Makefile b/usr/src/cmd/smbsrv/test-msgbuf/Makefile new file mode 100644 index 0000000000..96ab0292d1 --- /dev/null +++ b/usr/src/cmd/smbsrv/test-msgbuf/Makefile @@ -0,0 +1,124 @@ +# +# 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 2018 Nexenta Systems, Inc. All rights reserved. +# + + +PROG= test-msgbuf + +OBJS_LOCAL= test_main.o test_misc.o test_conv.o \ + test_mbmarshal.o test_msgbuf.o +OBJS_SMBSRV= smb_mbuf_marshaling.o smb_mbuf_util.o smb_alloc.o +OBJS_SMBCMN= smb_msgbuf.o smb_string.o smb_utf8.o + +OBJS= ${OBJS_LOCAL} ${OBJS_SMBSRV} ${OBJS_SMBCMN} + +SMBSRV_SRCDIR=../../../uts/common/fs/smbsrv +SMBSRV_CMNDIR=../../../common/smbsrv +SRCS= ${OBJS_LOCAL:.o=.c} \ + ${OBJS_SMBSRV:%.o=${SMBSRV_SRCDIR}/%.c} \ + ${OBJS_SMBCMN:%.o=${SMBSRV_CMNDIR}/%.c} + +include ../../Makefile.cmd +include ../../Makefile.ctf + +# Note: need our sys includes _before_ ENVCPPFLAGS, proto etc. +CPPFLAGS.first += -I. +CPPFLAGS.first += -I../../../lib/libfakekernel/common +CPPFLAGS.first += -I../../../lib/smbsrv/libfksmbsrv/common + +INCS += -I../../../uts/common +INCS += -I../../../uts/common/smbsrv +INCS += -I../../../common/smbsrv + +CSTD= $(CSTD_GNU99) +C99LMODE= -Xc99=%all + +CFLAGS += $(CCVERBOSE) +CFLAGS64 += $(CCVERBOSE) + +CERRWARN += -_gcc=-Wno-parentheses + +CPPFLAGS += -D_REENTRANT +CPPFLAGS += -DTESTJIG +CPPFLAGS += -Dsyslog=smb_syslog +CPPFLAGS += -D_LARGEFILE64_SOURCE=1 +# Always debug here +CPPFLAGS += -DDEBUG +CPPFLAGS += $(INCS) + +LDFLAGS += $(ZNOLAZYLOAD) +LDFLAGS += '-R$$ORIGIN/..' +LDLIBS += -lfakekernel -lcmdutils + +LINTFLAGS += -xerroff=E_NAME_DEF_NOT_USED2 +LINTFLAGS += -xerroff=E_NAME_USED_NOT_DEF2 +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) + +test_main.o : test_main.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D_KMEMUSER -c test_main.c + $(POST_PROCESS_O) + +test_misc.o : test_misc.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D_FAKE_KERNEL \ + -I../../../uts/common/smbsrv \ + -I../../../common/smbsrv -c test_misc.c + $(POST_PROCESS_O) + +# OBJS_SMBSRV +%.o: ../../../uts/common/fs/smbsrv/%.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D_FAKE_KERNEL \ + -I../../../uts/common/smbsrv \ + -I../../../common/smbsrv -c $< + $(POST_PROCESS_O) + +# OBJS_SMBCMN +%.o: ../../../common/smbsrv/%.c + $(CC) $(CFLAGS) $(CPPFLAGS) -D_FAKE_KERNEL \ + -I../../../uts/common/smbsrv \ + -I../../../common/smbsrv -c $< + $(POST_PROCESS_O) + +$(ROOTSMBDDIR)/%: % + $(INS.file) diff --git a/usr/src/cmd/smbsrv/test-msgbuf/Run.sh b/usr/src/cmd/smbsrv/test-msgbuf/Run.sh new file mode 100755 index 0000000000..9063607a95 --- /dev/null +++ b/usr/src/cmd/smbsrv/test-msgbuf/Run.sh @@ -0,0 +1,32 @@ +#!/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 2018 Nexenta Systems, Inc. All rights reserved. +# + +# Helper program to run test-msgbuf (unit test program) +# using binaries from the proto area. + +[ -n "$CODEMGR_WS" ] || { + echo "Need a buildenv to set CODEMGR_WS=..." + exit 1; +} + +ROOT=${CODEMGR_WS}/proto/root_i386 +LD_LIBRARY_PATH=$ROOT/usr/lib/smbsrv:$ROOT/usr/lib:$ROOT/lib +export LD_LIBRARY_PATH +export UMEM_DEBUG=default + +# run with the passed options +exec $ROOT/usr/lib/smbsrv/test-msgbuf "$@" diff --git a/usr/src/cmd/smbsrv/test-msgbuf/test_conv.c b/usr/src/cmd/smbsrv/test-msgbuf/test_conv.c new file mode 100644 index 0000000000..224d0373ec --- /dev/null +++ b/usr/src/cmd/smbsrv/test-msgbuf/test_conv.c @@ -0,0 +1,342 @@ +/* + * 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 2018 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Test conversion of strings UTF-8 to/from UTF-16 etc. + * + * This tests both 16-bit unicode symbols (UCS-2) and so called + * "enhanced" unicode symbols such as the "poop emoji" that are + * above 65535 and encode to four bytes as UTF-8. + */ + +#include <sys/types.h> +#include <sys/debug.h> +#include <sys/u8_textprep.h> +#include <smbsrv/string.h> +#include <stdio.h> +#include <string.h> + +#include "test_defs.h" + +#define U_FW_A 0xff21 // full-width A (A) +static const char fwA[4] = "\xef\xbc\xa1"; + +#define U_POOP 0x1f4a9 // poop emoji (💩) +static const char poop[5] = "\xf0\x9f\x92\xa9"; + +static char mbsa[] = "A\xef\xbc\xa1."; // A fwA . (5) +static char mbsp[] = "P\xf0\x9f\x92\xa9."; // P poop . (6) +static smb_wchar_t wcsa[] = { 'A', U_FW_A, '.', 0 }; // (3) +static smb_wchar_t wcsp[] = { 'P', 0xd83d, 0xdca9, '.', 0 }; // (4) + + +static void +conv_wctomb() +{ + char mbs[8]; + int len; + + len = smb_wctomb(mbs, U_FW_A); + if (len != 3) { + printf("Fail: conv_wctomb fwA ret=%d\n", len); + return; + } + mbs[len] = '\0'; + if (strcmp(mbs, fwA)) { + printf("Fail: conv_wctomb fwA cmp:\n"); + hexdump((uchar_t *)mbs, len+1); + return; + } + + len = smb_wctomb(mbs, U_POOP); + if (len != 4) { + printf("Fail: conv_wctomb poop ret=%d\n", len); + return; + } + mbs[len] = '\0'; + if (strcmp(mbs, poop)) { + printf("Fail: conv_wctomb poop cmp:\n"); + hexdump((uchar_t *)mbs, len+1); + return; + } + + /* null wc to mbs should return 1 and put a null */ + len = smb_wctomb(mbs, 0); + if (len != 1) { + printf("Fail: conv_wctomb null ret=%d\n", len); + return; + } + if (mbs[0] != '\0') { + printf("Fail: conv_wctomb null cmp:\n"); + hexdump((uchar_t *)mbs, len+1); + return; + } + + printf("Pass: conv_wctomb\n"); +} + +static void +conv_mbtowc() +{ + uint32_t wch = 0; + int len; + + /* + * The (void *) cast here is to let this build both + * before and after an interface change in smb_mbtowc + * (uint16_t vs uint32_t) + */ + len = smb_mbtowc((void *)&wch, fwA, 4); + if (len != 3) { + printf("Fail: conv_mbtowc fwA ret=%d\n", len); + return; + } + if (wch != U_FW_A) { + printf("Fail: conv_mbtowc fwA cmp: 0x%x\n", wch); + return; + } + + len = smb_mbtowc((void *)&wch, poop, 4); // poop emoji + if (len != 4) { + printf("Fail: conv_mbtowc poop ret=%d\n", len); + return; + } + if (wch != U_POOP) { + printf("Fail: conv_mbtowc poop cmp: 0x%x\n", wch); + return; + } + + /* null mbs to wc should return 0 (and set wch=0) */ + len = smb_mbtowc((void *)&wch, "", 4); + if (len != 0) { + printf("Fail: conv_mbtowc null ret=%d\n", len); + return; + } + if (wch != 0) { + printf("Fail: conv_mbtowc null cmp: 0x%x\n", wch); + return; + } + + printf("Pass: conv_mbtowc\n"); +} + +static void +conv_wcstombs() +{ + char tmbs[16]; + int len; + + len = smb_wcstombs(tmbs, wcsa, sizeof (tmbs)); + if (len != 5) { + printf("Fail: conv_wcstombs A ret=%d\n", len); + return; + } + if (strcmp(tmbs, mbsa)) { + printf("Fail: conv_wcstombs A cmp:\n"); + hexdump((uchar_t *)tmbs, len+2); + return; + } + + len = smb_wcstombs(tmbs, wcsp, sizeof (tmbs)); + if (len != 6) { + printf("Fail: conv_wcstombs f ret=%d\n", len); + return; + } + if (strcmp(tmbs, mbsp)) { + printf("Fail: conv_wcstombs f cmp:\n"); + hexdump((uchar_t *)tmbs, len+2); + return; + } + + printf("Pass: conv_wcstombs\n"); +} + +static void +conv_mbstowcs() +{ + smb_wchar_t twcs[8]; + uint32_t wch = 0; + int len; + + len = smb_mbstowcs(twcs, mbsa, sizeof (twcs)); + if (len != 3) { + printf("Fail: conv_mbstowcs A ret=%d\n", len); + return; + } + if (memcmp(twcs, wcsa, len+2)) { + printf("Fail: conv_mbstowcs A cmp: 0x%x\n", wch); + hexdump((uchar_t *)twcs, len+2); + return; + } + + len = smb_mbstowcs(twcs, mbsp, sizeof (twcs)); + if (len != 4) { + printf("Fail: conv_mbstowcs P ret=%d\n", len); + return; + } + if (memcmp(twcs, wcsp, len+2)) { + printf("Fail: conv_mbstowcs P cmp: 0x%x\n", wch); + hexdump((uchar_t *)twcs, len+2); + return; + } + + printf("Pass: conv_mbstowcs\n"); +} + +/* + * An OEM string that will require iconv. + */ +static uchar_t fubar_oem[] = "F\201bar"; // CP850 x81 (ü) +static char fubar_mbs[] = "F\303\274bar"; // UTF8 xC3 xBC + + +static void +conv_oemtombs() +{ + char tmbs[16]; + int len; + + len = smb_oemtombs(tmbs, (uchar_t *)"foo", 4); + if (len != 3) { + printf("Fail: conv_wctomb foo ret=%d\n", len); + return; + } + if (strcmp(tmbs, "foo")) { + printf("Fail: conv_wctomb foo cmp:\n"); + hexdump((uchar_t *)tmbs, len+1); + return; + } + + len = smb_oemtombs(tmbs, fubar_oem, 7); + if (len != 6) { + printf("Fail: conv_oemtombs fubar ret=%d\n", len); + return; + } + if (strcmp(tmbs, fubar_mbs)) { + printf("Fail: conv_oemtombs fubar cmp:\n"); + hexdump((uchar_t *)tmbs, len+1); + return; + } + + printf("Pass: conv_oemtombs\n"); +} + +static void +conv_mbstooem() +{ + uint8_t oemcs[8]; + uint32_t wch = 0; + int len; + + len = smb_mbstooem(oemcs, "foo", 8); + if (len != 3) { + printf("Fail: conv_mbstooem foo ret=%d\n", len); + return; + } + if (memcmp(oemcs, "foo", len+1)) { + printf("Fail: conv_mbstooem P cmp: 0x%x\n", wch); + hexdump((uchar_t *)oemcs, len+1); + return; + } + + len = smb_mbstooem(oemcs, fubar_mbs, 8); + if (len != 5) { + printf("Fail: conv_mbstooem fubar ret=%d\n", len); + return; + } + if (memcmp(oemcs, (char *)fubar_oem, len+1)) { + printf("Fail: conv_mbstooem fubar cmp: 0x%x\n", wch); + hexdump((uchar_t *)oemcs, len+1); + return; + } + + len = smb_mbstooem(oemcs, mbsp, 8); + if (len != 3) { + printf("Fail: conv_mbstooem poop ret=%d\n", len); + return; + } + if (memcmp(oemcs, "P?.", len+1)) { + printf("Fail: conv_mbstooem poop cmp: 0x%x\n", wch); + hexdump((uchar_t *)oemcs, len+1); + return; + } + + printf("Pass: conv_mbstooem\n"); +} + +static void +conv_sbequiv_strlen() +{ + int len; + + len = (int)smb_sbequiv_strlen("a"); + if (len != 1) { + printf("Fail: conv_sbequiv_strlen (a) len=%d\n", len); + return; + } + + len = (int)smb_sbequiv_strlen(fubar_mbs); + if (len != strlen((char *)fubar_oem)) { + printf("Fail: conv_sbequiv_strlen (fubar) len=%d\n", len); + return; + } + + len = (int)smb_sbequiv_strlen(mbsp); + if (len != 3) { // "P?." + printf("Fail: conv_sbequiv_strlen (poop) len=%d\n", len); + return; + } + + printf("Pass: conv_sbequiv_strlen\n"); +} + +static void +conv_wcequiv_strlen() +{ + int len; + + len = (int)smb_wcequiv_strlen("a"); + if (len != 2) { + printf("Fail: conv_wcequiv_strlen (a) len=%d\n", len); + return; + } + + len = (int)smb_wcequiv_strlen(fwA); + if (len != 2) { + printf("Fail: conv_wcequiv_strlen (fwA) len=%d\n", len); + return; + } + + len = (int)smb_wcequiv_strlen(poop); + if (len != 4) { + printf("Fail: conv_wcequiv_strlen (poop) len=%d\n", len); + return; + } + + printf("Pass: conv_wcequiv_strlen\n"); +} + +void +test_conv() +{ + conv_wctomb(); + conv_mbtowc(); + conv_wcstombs(); + conv_mbstowcs(); + conv_oemtombs(); + conv_mbstooem(); + conv_sbequiv_strlen(); + conv_wcequiv_strlen(); +} diff --git a/usr/src/cmd/smbsrv/test-msgbuf/test_defs.h b/usr/src/cmd/smbsrv/test-msgbuf/test_defs.h new file mode 100644 index 0000000000..c7e6a4eeb1 --- /dev/null +++ b/usr/src/cmd/smbsrv/test-msgbuf/test_defs.h @@ -0,0 +1,36 @@ +/* + * 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 2018 Nexenta Systems, Inc. All rights reserved. + */ + +#ifndef _TEST_DEFS_H +#define _TEST_DEFS_H + +/* + * Describe the purpose of the file here. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern void hexdump(const uchar_t *buf, int len); +extern void test_conv(void); +extern void test_mbmarshal(void); +extern void test_msgbuf(void); + +#ifdef __cplusplus +} +#endif + +#endif /* _TEST_DEFS_H */ diff --git a/usr/src/cmd/smbsrv/test-msgbuf/test_main.c b/usr/src/cmd/smbsrv/test-msgbuf/test_main.c new file mode 100644 index 0000000000..e79ccc08da --- /dev/null +++ b/usr/src/cmd/smbsrv/test-msgbuf/test_main.c @@ -0,0 +1,86 @@ +/* + * 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 2018 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Test & debug program for smb_msgbuf.c and smb_mbuf_marshaling.c + */ + +#include <sys/types.h> +#include <sys/debug.h> + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <unistd.h> + +#include "test_defs.h" + + +int +main(int argc, char *argv[]) +{ + + test_conv(); + test_mbmarshal(); + test_msgbuf(); + + return (0); +} + +void +hexdump(const uchar_t *buf, int len) +{ + int idx; + char ascii[24]; + char *pa = ascii; + + memset(ascii, '\0', sizeof (ascii)); + + idx = 0; + while (len--) { + if ((idx & 15) == 0) { + printf("%04X: ", idx); + pa = ascii; + } + if (*buf > ' ' && *buf <= '~') + *pa++ = *buf; + else + *pa++ = '.'; + printf("%02x ", *buf++); + + idx++; + if ((idx & 3) == 0) { + *pa++ = ' '; + putchar(' '); + } + if ((idx & 15) == 0) { + *pa = '\0'; + printf("%s\n", ascii); + } + } + + if ((idx & 15) != 0) { + *pa = '\0'; + /* column align the last ascii row */ + while ((idx & 15) != 0) { + if ((idx & 3) == 0) + putchar(' '); + printf(" "); + idx++; + } + printf("%s\n", ascii); + } +} diff --git a/usr/src/cmd/smbsrv/test-msgbuf/test_mbmarshal.c b/usr/src/cmd/smbsrv/test-msgbuf/test_mbmarshal.c new file mode 100644 index 0000000000..967915688e --- /dev/null +++ b/usr/src/cmd/smbsrv/test-msgbuf/test_mbmarshal.c @@ -0,0 +1,680 @@ +/* + * 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 2018 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Test putting/getting unicode strings in mbchains. + */ + +#include <sys/types.h> +#include <sys/debug.h> +#include <sys/varargs.h> +#include <smbsrv/smb_kproto.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> + +#include "test_defs.h" + +static char mbsa[] = "A\xef\xbc\xa1."; // A fwA . (5) +static char mbsp[] = "P\xf0\x9f\x92\xa9."; // P poop . (6) +static smb_wchar_t wcsa[] = { 'A', 0xff21, '.', 0 }; // (3) +static smb_wchar_t wcsp[] = { 'P', 0xd83d, 0xdca9, '.', 0 }; // (4) + +smb_session_t test_ssn; +smb_request_t test_sr; + +/* + * Put ASCII string with NULL + */ +static void +mbm_put_a0() +{ + uint8_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; + mbuf_chain_t *mbc; + int rc; + + mbc = smb_mbc_alloc(100); + + rc = smb_mbc_encodef(mbc, "sw", "one", 42); + if (rc != 0) { + printf("Fail: mbm_put_a0 encode\n"); + goto out; + } + if (mbc->chain->m_len != 6) { + printf("Fail: mbm_put_a0 len=%d\n", + mbc->chain->m_len); + return; + } + + if (memcmp(mbc->chain->m_data, wire, 6)) { + printf("Fail: mbm_put_a0 cmp:\n"); + hexdump((uchar_t *)mbc->chain->m_data, 6); + return; + } + + printf("Pass: mbm_put_a0\n"); + +out: + smb_mbc_free(mbc); +} + +/* + * Put ASCII string, no NULL + */ +static void +mbm_put_a1() +{ + uint8_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; + mbuf_chain_t *mbc; + int rc; + + mbc = smb_mbc_alloc(100); + + rc = smb_mbc_encodef(mbc, "4sw", "one.", 42); + if (rc != 0) { + printf("Fail: mbm_put_a1 encode\n"); + goto out; + } + if (mbc->chain->m_len != 6) { + printf("Fail: mbm_put_a1 len=%d\n", + mbc->chain->m_len); + return; + } + + if (memcmp(mbc->chain->m_data, wire, 6)) { + printf("Fail: mbm_put_a1 cmp:\n"); + hexdump((uchar_t *)mbc->chain->m_data, 6); + return; + } + + printf("Pass: mbm_put_a1\n"); + +out: + smb_mbc_free(mbc); +} + +static void +mbm_put_apad() +{ + uint8_t wire[] = { 'o', 'n', 'e', 0, 0 }; + mbuf_chain_t *mbc; + int rc; + + mbc = smb_mbc_alloc(100); + + /* Encode with wire length > strlen */ + rc = smb_mbc_encodef(mbc, "5s", "one"); + if (rc != 0) { + printf("Fail: mbm_put_apad encode\n"); + goto out; + } + if (mbc->chain->m_len != 5) { + printf("Fail: mbm_put_apad len=%d\n", + mbc->chain->m_len); + return; + } + + if (memcmp(mbc->chain->m_data, wire, 5)) { + printf("Fail: mbm_put_apad cmp:\n"); + hexdump((uchar_t *)mbc->chain->m_data, 5); + return; + } + + printf("Pass: mbm_put_apad\n"); + +out: + smb_mbc_free(mbc); +} + +static void +mbm_put_atrunc() +{ + uint8_t wire[] = { 'o', 'n', 'e', 't', }; + mbuf_chain_t *mbc; + int rc; + + mbc = smb_mbc_alloc(100); + + /* Encode with wire length < strlen */ + rc = smb_mbc_encodef(mbc, "4s", "onetwo"); + if (rc != 0) { + printf("Fail: mbm_put_atrunc encode\n"); + goto out; + } + /* Trunc should put exactly 4 */ + if (mbc->chain->m_len != 4) { + printf("Fail: mbm_put_atrunc len=%d\n", + mbc->chain->m_len); + return; + } + + if (memcmp(mbc->chain->m_data, wire, 4)) { + printf("Fail: mbm_put_atrunc cmp:\n"); + hexdump((uchar_t *)mbc->chain->m_data, 4); + return; + } + + printf("Pass: mbm_put_atrunc\n"); + +out: + smb_mbc_free(mbc); +} + +/* + * Put unicode string with NULL + */ +static void +mbm_put_u0() +{ + uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; + mbuf_chain_t *mbc; + int rc; + + mbc = smb_mbc_alloc(100); + + rc = smb_mbc_encodef(mbc, "Uw", "one", 42); + if (rc != 0) { + printf("Fail: mbm_put_u0 encode\n"); + goto out; + } + if (mbc->chain->m_len != 10) { + printf("Fail: mbm_put_u0 len=%d\n", + mbc->chain->m_len); + return; + } + + if (memcmp(mbc->chain->m_data, wire, 10)) { + printf("Fail: mbm_put_u0 cmp:\n"); + hexdump((uchar_t *)mbc->chain->m_data, 10); + return; + } + + printf("Pass: mbm_put_u0\n"); + +out: + smb_mbc_free(mbc); +} + +/* + * Put unicode string, no NULL + */ +static void +mbm_put_u1() +{ + uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; + mbuf_chain_t *mbc; + int rc; + + mbc = smb_mbc_alloc(100); + + rc = smb_mbc_encodef(mbc, "8Uw", "one.", 42); + if (rc != 0) { + printf("Fail: mbm_put_u1 encode\n"); + goto out; + } + if (mbc->chain->m_len != 10) { + printf("Fail: mbm_put_u1 len=%d\n", + mbc->chain->m_len); + return; + } + + if (memcmp(mbc->chain->m_data, wire, 10)) { + printf("Fail: mbm_put_u1 cmp:\n"); + hexdump((uchar_t *)mbc->chain->m_data, 10); + return; + } + + printf("Pass: mbm_put_u1\n"); + +out: + smb_mbc_free(mbc); +} + +static void +mbm_put_u3() +{ + mbuf_chain_t *mbc; + int rc; + + mbc = smb_mbc_alloc(100); + + rc = smb_mbc_encodef(mbc, "U", mbsa); + if (rc != 0) { + printf("Fail: mbm_put_u3 encode\n"); + goto out; + } + if (mbc->chain->m_len != 8) { + printf("Fail: mbm_put_u3 len=%d\n", + mbc->chain->m_len); + return; + } + + if (memcmp(mbc->chain->m_data, wcsa, 8)) { + printf("Fail: mbm_put_u3 cmp:\n"); + hexdump((uchar_t *)mbc->chain->m_data, 8); + return; + } + + printf("Pass: mbm_put_u3\n"); + +out: + smb_mbc_free(mbc); +} + +static void +mbm_put_u4() +{ + mbuf_chain_t *mbc; + int rc; + + mbc = smb_mbc_alloc(100); + + rc = smb_mbc_encodef(mbc, "U", mbsp); + if (rc != 0) { + printf("Fail: mbm_put_u4 encode\n"); + goto out; + } + if (mbc->chain->m_len != 10) { + printf("Fail: mbm_put_u4 len=%d\n", + mbc->chain->m_len); + return; + } + + if (memcmp(mbc->chain->m_data, wcsp, 10)) { + printf("Fail: mbm_put_u4 cmp:\n"); + hexdump((uchar_t *)mbc->chain->m_data, 10); + return; + } + + printf("Pass: mbm_put_u4\n"); + +out: + smb_mbc_free(mbc); +} + +static void +mbm_put_upad() +{ + uint16_t wire[] = { 'o', 'n', 'e', 0, 0 }; + mbuf_chain_t *mbc; + int rc; + + mbc = smb_mbc_alloc(100); + + /* Encode with wire length > strlen */ + rc = smb_mbc_encodef(mbc, "10U", "one"); + if (rc != 0) { + printf("Fail: mbm_put_upad encode\n"); + goto out; + } + if (mbc->chain->m_len != 10) { + printf("Fail: mbm_put_upad len=%d\n", + mbc->chain->m_len); + return; + } + + if (memcmp(mbc->chain->m_data, wire, 10)) { + printf("Fail: mbm_put_upad cmp:\n"); + hexdump((uchar_t *)mbc->chain->m_data, 10); + return; + } + + printf("Pass: mbm_put_upad\n"); + +out: + smb_mbc_free(mbc); +} + +static void +mbm_put_utrunc() +{ + uint16_t wire[] = { 'o', 'n', 'e', 't' }; + mbuf_chain_t *mbc; + int rc; + + mbc = smb_mbc_alloc(100); + + /* Encode with wire length < strlen */ + rc = smb_mbc_encodef(mbc, "8U", "onetwo"); + if (rc != 0) { + printf("Fail: mbm_put_utrunc encode\n"); + goto out; + } + /* Trunc should put exactly 8 */ + if (mbc->chain->m_len != 8) { + printf("Fail: mbm_put_utrunc len=%d\n", + mbc->chain->m_len); + return; + } + + if (memcmp(mbc->chain->m_data, wire, 8)) { + printf("Fail: mbm_put_utrunc cmp:\n"); + hexdump((uchar_t *)mbc->chain->m_data, 8); + return; + } + + printf("Pass: mbm_put_utrunc\n"); + +out: + smb_mbc_free(mbc); +} + +/* + * Parse an ascii string. + */ +static void +mbm_get_a0() +{ + uint8_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; + mbuf_chain_t mbc; + char *s; + int rc; + uint16_t w; + + bzero(&mbc, sizeof (mbc)); + MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); + + rc = smb_mbc_decodef(&mbc, "%sw", &test_sr, &s, &w); + if (rc != 0) { + printf("Fail: mbm_get_a0 decode\n"); + goto out; + } + /* + * Decode a word after the string to make sure we + * end up positioned correctly after the string. + */ + if (w != 42) { + printf("Fail: mbm_get_a0 w=%d\n", w); + return; + } + if (strcmp(s, "one") != 0) { + printf("Fail: mbm_get_a0 cmp: <%s>\n", s); + return; + } + + printf("Pass: mbm_get_a0\n"); + +out: + MBC_FLUSH(&mbc); +} + +/* + * Parse an ascii string, no NULL + */ +static void +mbm_get_a1() +{ + uint8_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; + mbuf_chain_t mbc; + char *s; + int rc; + uint16_t w; + + bzero(&mbc, sizeof (mbc)); + MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); + + rc = smb_mbc_decodef(&mbc, "%3s.w", &test_sr, &s, &w); + if (rc != 0) { + printf("Fail: mbm_get_a1 decode\n"); + goto out; + } + /* + * Decode a word after the string to make sure we + * end up positioned correctly after the string. + */ + if (w != 42) { + printf("Fail: mbm_get_a1 w=%d\n", w); + return; + } + if (strcmp(s, "one") != 0) { + printf("Fail: mbm_get_a1 cmp: <%s>\n", s); + return; + } + + printf("Pass: mbm_get_a1\n"); + +out: + MBC_FLUSH(&mbc); +} + +/* parse exactly to end of data */ +static void +mbm_get_a2() +{ + uint8_t wire[] = { 'o', 'n', 'e' }; + mbuf_chain_t mbc; + char *s; + int rc; + + bzero(&mbc, sizeof (mbc)); + MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); + + rc = smb_mbc_decodef(&mbc, "%3s", &test_sr, &s); + if (rc != 0) { + printf("Fail: mbm_get_a2 decode\n"); + goto out; + } + if (mbc.chain_offset != 3) { + printf("Fail: mbm_get_a2 wrong pos\n"); + return; + } + if (strcmp(s, "one") != 0) { + printf("Fail: mbm_get_a2 cmp: <%s>\n", s); + return; + } + + printf("Pass: mbm_get_a2\n"); + +out: + MBC_FLUSH(&mbc); +} + +/* + * Parse a unicode string. + */ +static void +mbm_get_u0() +{ + uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; + mbuf_chain_t mbc; + char *s; + int rc; + uint16_t w; + + bzero(&mbc, sizeof (mbc)); + MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); + + rc = smb_mbc_decodef(&mbc, "%Uw", &test_sr, &s, &w); + if (rc != 0) { + printf("Fail: mbm_get_u0 decode\n"); + goto out; + } + /* + * Decode a word after the string to make sure we + * end up positioned correctly after the string. + */ + if (w != 42) { + printf("Fail: mbm_get_u0 w=%d\n", w); + return; + } + if (strcmp(s, "one") != 0) { + printf("Fail: mbm_get_u0 cmp: <%s>\n", s); + return; + } + + printf("Pass: mbm_get_u0\n"); + +out: + MBC_FLUSH(&mbc); +} + +/* + * Parse a string that's NOT null terminated. + */ +static void +mbm_get_u1() +{ + uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; + mbuf_chain_t mbc; + char *s; + int rc; + uint16_t w; + + bzero(&mbc, sizeof (mbc)); + MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); + + rc = smb_mbc_decodef(&mbc, "%6U..w", &test_sr, &s, &w); + if (rc != 0) { + printf("Fail: mbm_get_u1 decode\n"); + goto out; + } + /* + * Decode a word after the string to make sure we + * end up positioned correctly after the string. + */ + if (w != 42) { + printf("Fail: mbm_get_u1 w=%d\n", w); + return; + } + if (strcmp(s, "one") != 0) { + printf("Fail: mbm_get_u1 cmp: <%s>\n", s); + return; + } + + printf("Pass: mbm_get_u1\n"); + +out: + MBC_FLUSH(&mbc); +} + +/* parse exactly to end of data */ +static void +mbm_get_u2() +{ + uint16_t wire[] = { 't', 'w', 'o' }; + mbuf_chain_t mbc; + char *s; + int rc; + + bzero(&mbc, sizeof (mbc)); + MBC_ATTACH_BUF(&mbc, (uchar_t *)wire, sizeof (wire)); + + rc = smb_mbc_decodef(&mbc, "%6U", &test_sr, &s); + if (rc != 0) { + printf("Fail: mbm_get_u2 decode\n"); + goto out; + } + if (mbc.chain_offset != 6) { + printf("Fail: mbm_get_u2 wrong pos\n"); + return; + } + if (strcmp(s, "two") != 0) { + printf("Fail: mbm_get_u2 cmp: <%s>\n", s); + return; + } + + printf("Pass: mbm_get_a2\n"); + +out: + MBC_FLUSH(&mbc); +} + +static void +mbm_get_u3() +{ + mbuf_chain_t mbc; + char *s; + int rc; + + bzero(&mbc, sizeof (mbc)); + MBC_ATTACH_BUF(&mbc, (uchar_t *)wcsa, sizeof (wcsa)); + + rc = smb_mbc_decodef(&mbc, "%#U", &test_sr, sizeof (wcsa), &s); + if (rc != 0) { + printf("Fail: mbm_get_u3 decode\n"); + goto out; + } + if (strcmp(s, mbsa) != 0) { + printf("Fail: mbm_get_u3 cmp: <%s>\n", s); + return; + } + + printf("Pass: mbm_get_u3\n"); + +out: + MBC_FLUSH(&mbc); +} + +static void +mbm_get_u4() +{ + mbuf_chain_t mbc; + char *s; + int rc; + + bzero(&mbc, sizeof (mbc)); + MBC_ATTACH_BUF(&mbc, (uchar_t *)wcsp, sizeof (wcsp)); + + rc = smb_mbc_decodef(&mbc, "%#U", &test_sr, sizeof (wcsp), &s); + if (rc != 0) { + printf("Fail: mbm_get_u4 decode\n"); + goto out; + } + if (strcmp(s, mbsp) != 0) { + printf("Fail: mbm_get_u4 cmp: <%s>\n", s); + return; + } + + printf("Pass: mbm_get_u4\n"); + +out: + MBC_FLUSH(&mbc); +} + +void +test_mbmarshal() +{ + + smb_mbc_init(); + + test_ssn.dialect = 0x210; // SMB 2.1 + test_sr.session = &test_ssn; + test_sr.sr_magic = SMB_REQ_MAGIC; + smb_srm_init(&test_sr); + + mbm_put_a0(); + mbm_put_a1(); + mbm_put_apad(); + mbm_put_atrunc(); + + mbm_put_u0(); + mbm_put_u1(); + mbm_put_u3(); + mbm_put_u4(); + mbm_put_upad(); + mbm_put_utrunc(); + + mbm_get_a0(); + mbm_get_a1(); + mbm_get_a2(); + mbm_get_u0(); + mbm_get_u1(); + mbm_get_u2(); + mbm_get_u3(); + mbm_get_u4(); + + smb_srm_fini(&test_sr); + smb_mbc_fini(); +} diff --git a/usr/src/cmd/smbsrv/test-msgbuf/test_misc.c b/usr/src/cmd/smbsrv/test-msgbuf/test_misc.c new file mode 100644 index 0000000000..c93634ba67 --- /dev/null +++ b/usr/src/cmd/smbsrv/test-msgbuf/test_misc.c @@ -0,0 +1,301 @@ +/* + * 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 2018 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * A few excerpts from smb_kutil.c + */ + +#include <sys/param.h> +#include <sys/types.h> +#include <sys/tzfile.h> +#include <sys/atomic.h> +#include <sys/debug.h> +#include <sys/time.h> +#include <smbsrv/smb_kproto.h> + +time_t tzh_leapcnt = 0; + +struct tm +*smb_gmtime_r(time_t *clock, struct tm *result); + +time_t +smb_timegm(struct tm *tm); + +struct tm { + int tm_sec; + int tm_min; + int tm_hour; + int tm_mday; + int tm_mon; + int tm_year; + int tm_wday; + int tm_yday; + int tm_isdst; +}; + +static const int days_in_month[] = { + 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 +}; + +uint64_t +smb_time_unix_to_nt(timestruc_t *unix_time) +{ + uint64_t nt_time; + + if ((unix_time->tv_sec == 0) && (unix_time->tv_nsec == 0)) + return (0); + + nt_time = unix_time->tv_sec; + nt_time *= 10000000; /* seconds to 100ns */ + nt_time += unix_time->tv_nsec / 100; + return (nt_time + NT_TIME_BIAS); +} + +void +smb_time_nt_to_unix(uint64_t nt_time, timestruc_t *unix_time) +{ + uint32_t seconds; + + ASSERT(unix_time); + + if ((nt_time == 0) || (nt_time == -1)) { + unix_time->tv_sec = 0; + unix_time->tv_nsec = 0; + return; + } + + /* + * Can't represent times less than or equal NT_TIME_BIAS, + * so convert them to the oldest date we can store. + * Note that time zero is "special" being converted + * both directions as 0:0 (unix-to-nt, nt-to-unix). + */ + if (nt_time <= NT_TIME_BIAS) { + unix_time->tv_sec = 0; + unix_time->tv_nsec = 100; + return; + } + + nt_time -= NT_TIME_BIAS; + seconds = nt_time / 10000000; + unix_time->tv_sec = seconds; + unix_time->tv_nsec = (nt_time % 10000000) * 100; +} + + +/* + * smb_time_dos_to_unix + * + * Convert SMB_DATE & SMB_TIME values to a unix timestamp. + * + * A date/time field of 0 means that that server file system + * assigned value need not be changed. The behaviour when the + * date/time field is set to -1 is not documented but is + * generally treated like 0. + * If date or time is 0 or -1 the unix time is returned as 0 + * so that the caller can identify and handle this special case. + */ +int32_t +smb_time_dos_to_unix(int16_t date, int16_t time) +{ + struct tm atm; + + if (((date == 0) || (time == 0)) || + ((date == -1) || (time == -1))) { + return (0); + } + + atm.tm_year = ((date >> 9) & 0x3F) + 80; + atm.tm_mon = ((date >> 5) & 0x0F) - 1; + atm.tm_mday = ((date >> 0) & 0x1F); + atm.tm_hour = ((time >> 11) & 0x1F); + atm.tm_min = ((time >> 5) & 0x3F); + atm.tm_sec = ((time >> 0) & 0x1F) << 1; + + return (smb_timegm(&atm)); +} + +void +smb_time_unix_to_dos(int32_t ux_time, int16_t *date_p, int16_t *time_p) +{ + struct tm atm; + int i; + time_t tmp_time; + + if (ux_time == 0) { + *date_p = 0; + *time_p = 0; + return; + } + + tmp_time = (time_t)ux_time; + (void) smb_gmtime_r(&tmp_time, &atm); + + if (date_p) { + i = 0; + i += atm.tm_year - 80; + i <<= 4; + i += atm.tm_mon + 1; + i <<= 5; + i += atm.tm_mday; + + *date_p = (short)i; + } + if (time_p) { + i = 0; + i += atm.tm_hour; + i <<= 6; + i += atm.tm_min; + i <<= 5; + i += atm.tm_sec >> 1; + + *time_p = (short)i; + } +} + +/* + * smb_gmtime_r + * + * Thread-safe version of smb_gmtime. Returns a null pointer if either + * input parameter is a null pointer. Otherwise returns a pointer + * to result. + * + * Day of the week calculation: the Epoch was a thursday. + * + * There are no timezone corrections so tm_isdst and tm_gmtoff are + * always zero, and the zone is always WET. + */ +struct tm * +smb_gmtime_r(time_t *clock, struct tm *result) +{ + time_t tsec; + int year; + int month; + int sec_per_month; + + if (clock == 0 || result == 0) + return (0); + + bzero(result, sizeof (struct tm)); + tsec = *clock; + tsec -= tzh_leapcnt; + + result->tm_wday = tsec / SECSPERDAY; + result->tm_wday = (result->tm_wday + TM_THURSDAY) % DAYSPERWEEK; + + year = EPOCH_YEAR; + while (tsec >= (isleap(year) ? (SECSPERDAY * DAYSPERLYEAR) : + (SECSPERDAY * DAYSPERNYEAR))) { + if (isleap(year)) + tsec -= SECSPERDAY * DAYSPERLYEAR; + else + tsec -= SECSPERDAY * DAYSPERNYEAR; + + ++year; + } + + result->tm_year = year - TM_YEAR_BASE; + result->tm_yday = tsec / SECSPERDAY; + + for (month = TM_JANUARY; month <= TM_DECEMBER; ++month) { + sec_per_month = days_in_month[month] * SECSPERDAY; + + if (month == TM_FEBRUARY && isleap(year)) + sec_per_month += SECSPERDAY; + + if (tsec < sec_per_month) + break; + + tsec -= sec_per_month; + } + + result->tm_mon = month; + result->tm_mday = (tsec / SECSPERDAY) + 1; + tsec %= SECSPERDAY; + result->tm_sec = tsec % 60; + tsec /= 60; + result->tm_min = tsec % 60; + tsec /= 60; + result->tm_hour = (int)tsec; + + return (result); +} + + +/* + * smb_timegm + * + * Converts the broken-down time in tm to a time value, i.e. the number + * of seconds since the Epoch (00:00:00 UTC, January 1, 1970). This is + * not a POSIX or ANSI function. Per the man page, the input values of + * tm_wday and tm_yday are ignored and, as the input data is assumed to + * represent GMT, we force tm_isdst and tm_gmtoff to 0. + * + * Before returning the clock time, we use smb_gmtime_r to set up tm_wday + * and tm_yday, and bring the other fields within normal range. I don't + * think this is really how it should be done but it's convenient for + * now. + */ +time_t +smb_timegm(struct tm *tm) +{ + time_t tsec; + int dd; + int mm; + int yy; + int year; + + if (tm == 0) + return (-1); + + year = tm->tm_year + TM_YEAR_BASE; + tsec = tzh_leapcnt; + + for (yy = EPOCH_YEAR; yy < year; ++yy) { + if (isleap(yy)) + tsec += SECSPERDAY * DAYSPERLYEAR; + else + tsec += SECSPERDAY * DAYSPERNYEAR; + } + + for (mm = TM_JANUARY; mm < tm->tm_mon; ++mm) { + dd = days_in_month[mm] * SECSPERDAY; + + if (mm == TM_FEBRUARY && isleap(year)) + dd += SECSPERDAY; + + tsec += dd; + } + + tsec += (tm->tm_mday - 1) * SECSPERDAY; + tsec += tm->tm_sec; + tsec += tm->tm_min * SECSPERMIN; + tsec += tm->tm_hour * SECSPERHOUR; + + tm->tm_isdst = 0; + (void) smb_gmtime_r(&tsec, tm); + return (tsec); +} diff --git a/usr/src/cmd/smbsrv/test-msgbuf/test_msgbuf.c b/usr/src/cmd/smbsrv/test-msgbuf/test_msgbuf.c new file mode 100644 index 0000000000..b58bd54b83 --- /dev/null +++ b/usr/src/cmd/smbsrv/test-msgbuf/test_msgbuf.c @@ -0,0 +1,638 @@ +/* + * 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 2018 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Test putting/getting unicode strings in mbchains. + */ + +#include <sys/types.h> +#include <sys/debug.h> +#include <sys/varargs.h> +#include <smbsrv/smb_kproto.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> + +#include "test_defs.h" + +static char mbsa[] = "A\xef\xbc\xa1."; // A fwA . (5) +static char mbsp[] = "P\xf0\x9f\x92\xa9."; // P poop . (6) +static smb_wchar_t wcsa[] = { 'A', 0xff21, '.', 0 }; // (3) +static smb_wchar_t wcsp[] = { 'P', 0xd83d, 0xdca9, '.', 0 }; // (4) + +/* + * Put ASCII string with NULL + */ +static void +msg_put_a0() +{ + uint8_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; + uint8_t temp[32]; + smb_msgbuf_t mb; + int mbflags = 0; + int rc; + + smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); + + rc = smb_msgbuf_encode(&mb, "sw", "one", 42); + if (rc != 6) { + printf("Fail: msg_put_a0 encode\n"); + goto out; + } + + if (memcmp(temp, wire, 6)) { + printf("Fail: msg_put_a0 cmp:\n"); + hexdump((uchar_t *)temp, 6); + return; + } + + printf("Pass: msg_put_a0\n"); + +out: + smb_msgbuf_term(&mb); +} + +/* + * Put ASCII string, no NULL + */ +static void +msg_put_a1() +{ + uint8_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; + uint8_t temp[32]; + smb_msgbuf_t mb; + int mbflags = 0; + int rc; + + smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); + + rc = smb_msgbuf_encode(&mb, "4sw", "one.", 42); + if (rc != 6) { + printf("Fail: msg_put_a1 encode\n"); + goto out; + } + + if (memcmp(temp, wire, 6)) { + printf("Fail: msg_put_a1 cmp:\n"); + hexdump((uchar_t *)temp, 6); + return; + } + + printf("Pass: msg_put_a1\n"); + +out: + smb_msgbuf_term(&mb); +} + +static void +msg_put_apad() +{ + uint8_t wire[] = { 'o', 'n', 'e', 0, 0 }; + uint8_t temp[32]; + smb_msgbuf_t mb; + int mbflags = 0; + int rc; + + smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); + + /* Encode with wire length > strlen */ + rc = smb_msgbuf_encode(&mb, "5s", "one"); + if (rc != 5) { + printf("Fail: msg_put_apad encode\n"); + goto out; + } + + if (memcmp(temp, wire, 5)) { + printf("Fail: msg_put_apad cmp:\n"); + hexdump((uchar_t *)temp, 5); + return; + } + + printf("Pass: msg_put_apad\n"); + +out: + smb_msgbuf_term(&mb); +} + +static void +msg_put_atrunc() +{ + uint8_t wire[] = { 'o', 'n', 'e', 't', }; + uint8_t temp[32]; + smb_msgbuf_t mb; + int mbflags = 0; + int rc; + + smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); + + /* Encode with wire length < strlen */ + rc = smb_msgbuf_encode(&mb, "4s", "onetwo"); + /* Trunc should put exactly 4 */ + if (rc != 4) { + printf("Fail: msg_put_atrunc encode\n"); + goto out; + } + + if (memcmp(temp, wire, 4)) { + printf("Fail: msg_put_atrunc cmp:\n"); + hexdump((uchar_t *)temp, 4); + return; + } + + printf("Pass: msg_put_atrunc\n"); + +out: + smb_msgbuf_term(&mb); +} + +/* + * Put unicode string with NULL + */ +static void +msg_put_u0() +{ + uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; + uint8_t temp[32]; + smb_msgbuf_t mb; + int mbflags = 0; + int rc; + + smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); + + rc = smb_msgbuf_encode(&mb, "Uw", "one", 42); + if (rc != 10) { + printf("Fail: msg_put_u0 encode\n"); + goto out; + } + + if (memcmp(temp, wire, 10)) { + printf("Fail: msg_put_u0 cmp:\n"); + hexdump((uchar_t *)temp, 10); + return; + } + + printf("Pass: msg_put_u0\n"); + +out: + smb_msgbuf_term(&mb); +} + +/* + * Put unicode string, no NULL + */ +static void +msg_put_u1() +{ + uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; + uint8_t temp[32]; + smb_msgbuf_t mb; + int mbflags = 0; + int rc; + + smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); + + rc = smb_msgbuf_encode(&mb, "8Uw", "one.", 42); + if (rc != 10) { + printf("Fail: msg_put_u1 encode\n"); + goto out; + } + + if (memcmp(temp, wire, 10)) { + printf("Fail: msg_put_u1 cmp:\n"); + hexdump((uchar_t *)temp, 10); + return; + } + + printf("Pass: msg_put_u1\n"); + +out: + smb_msgbuf_term(&mb); +} + +static void +msg_put_u3() +{ + uint8_t temp[32]; + smb_msgbuf_t mb; + int mbflags = 0; + int rc; + + smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); + + rc = smb_msgbuf_encode(&mb, "U", mbsa); + if (rc != 8) { + printf("Fail: msg_put_u3 encode\n"); + goto out; + } + + if (memcmp(temp, wcsa, 8)) { + printf("Fail: msg_put_u3 cmp:\n"); + hexdump((uchar_t *)temp, 8); + return; + } + + printf("Pass: msg_put_u3\n"); + +out: + smb_msgbuf_term(&mb); +} + +static void +msg_put_u4() +{ + uint8_t temp[32]; + smb_msgbuf_t mb; + int mbflags = 0; + int rc; + + smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); + + rc = smb_msgbuf_encode(&mb, "U", mbsp); + if (rc != 10) { + printf("Fail: msg_put_u4 encode\n"); + goto out; + } + + if (memcmp(temp, wcsp, 10)) { + printf("Fail: msg_put_u4 cmp:\n"); + hexdump((uchar_t *)temp, 10); + return; + } + + printf("Pass: msg_put_u4\n"); + +out: + smb_msgbuf_term(&mb); +} + +static void +msg_put_upad() +{ + uint16_t wire[] = { 'o', 'n', 'e', 0, 0 }; + uint8_t temp[32]; + smb_msgbuf_t mb; + int mbflags = 0; + int rc; + + smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); + + /* Encode with wire length > strlen */ + rc = smb_msgbuf_encode(&mb, "10U", "one"); + if (rc != 10) { + printf("Fail: msg_put_upad encode\n"); + goto out; + } + + if (memcmp(temp, wire, 10)) { + printf("Fail: msg_put_upad cmp:\n"); + hexdump((uchar_t *)temp, 10); + return; + } + + printf("Pass: msg_put_upad\n"); + +out: + smb_msgbuf_term(&mb); +} + +static void +msg_put_utrunc() +{ + uint16_t wire[] = { 'o', 'n', 'e', 't' }; + uint8_t temp[32]; + smb_msgbuf_t mb; + int mbflags = 0; + int rc; + + smb_msgbuf_init(&mb, temp, sizeof (temp), mbflags); + + /* Encode with wire length < strlen */ + rc = smb_msgbuf_encode(&mb, "8U", "onetwo"); + /* Trunc should put exactly 8 */ + if (rc != 8) { + printf("Fail: msg_put_utrunc encode\n"); + goto out; + } + + if (memcmp(temp, wire, 8)) { + printf("Fail: msg_put_utrunc cmp:\n"); + hexdump((uchar_t *)temp, 8); + return; + } + + printf("Pass: msg_put_utrunc\n"); + +out: + smb_msgbuf_term(&mb); +} + +/* + * Parse an ascii string. + */ +static void +msg_get_a0() +{ + uint8_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; + smb_msgbuf_t mb; + int mbflags = 0; + char *s; + int rc; + uint16_t w; + + smb_msgbuf_init(&mb, wire, sizeof (wire), mbflags); + + rc = smb_msgbuf_decode(&mb, "sw", &s, &w); + if (rc != 6) { + printf("Fail: msg_get_a0 decode\n"); + goto out; + } + /* + * Decode a word after the string to make sure we + * end up positioned correctly after the string. + */ + if (w != 42) { + printf("Fail: msg_get_a0 w=%d\n", w); + return; + } + if (strcmp(s, "one") != 0) { + printf("Fail: msg_get_a0 cmp: <%s>\n", s); + return; + } + + printf("Pass: msg_get_a0\n"); + +out: + smb_msgbuf_term(&mb); +} + +/* + * Parse an ascii string, no NULL + */ +static void +msg_get_a1() +{ + uint8_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; + smb_msgbuf_t mb; + int mbflags = 0; + char *s; + int rc; + uint16_t w; + + smb_msgbuf_init(&mb, wire, sizeof (wire), mbflags); + + rc = smb_msgbuf_decode(&mb, "3s.w", &s, &w); + if (rc != 6) { + printf("Fail: msg_get_a1 decode\n"); + goto out; + } + /* + * Decode a word after the string to make sure we + * end up positioned correctly after the string. + */ + if (w != 42) { + printf("Fail: msg_get_a1 w=%d\n", w); + return; + } + if (strcmp(s, "one") != 0) { + printf("Fail: msg_get_a1 cmp: <%s>\n", s); + return; + } + + printf("Pass: msg_get_a1\n"); + +out: + smb_msgbuf_term(&mb); +} + +/* parse exactly to end of data */ +static void +msg_get_a2() +{ + uint8_t wire[] = { 'o', 'n', 'e' }; + smb_msgbuf_t mb; + int mbflags = 0; + char *s; + int rc; + + smb_msgbuf_init(&mb, wire, sizeof (wire), mbflags); + + rc = smb_msgbuf_decode(&mb, "3s", &s); + if (rc != 3) { + printf("Fail: msg_get_a2 decode\n"); + goto out; + } + if (mb.scan != mb.end) { + printf("Fail: msg_get_a2 wrong pos\n"); + return; + } + if (strcmp(s, "one") != 0) { + printf("Fail: msg_get_a2 cmp: <%s>\n", s); + return; + } + + printf("Pass: msg_get_a2\n"); + +out: + smb_msgbuf_term(&mb); +} + +/* + * Parse a unicode string. + */ +static void +msg_get_u0() +{ + uint16_t wire[] = { 'o', 'n', 'e', 0, 42, 0 }; + smb_msgbuf_t mb; + int mbflags = 0; + char *s; + int rc; + uint16_t w; + + smb_msgbuf_init(&mb, (uint8_t *)wire, sizeof (wire), mbflags); + + rc = smb_msgbuf_decode(&mb, "Uw", &s, &w); + if (rc != 10) { + printf("Fail: msg_get_u0 decode\n"); + goto out; + } + /* + * Decode a word after the string to make sure we + * end up positioned correctly after the string. + */ + if (w != 42) { + printf("Fail: msg_get_u0 w=%d\n", w); + return; + } + if (strcmp(s, "one") != 0) { + printf("Fail: msg_get_u0 cmp: <%s>\n", s); + return; + } + + printf("Pass: msg_get_u0\n"); + +out: + smb_msgbuf_term(&mb); +} + +/* + * Parse a string that's NOT null terminated. + */ +static void +msg_get_u1() +{ + uint16_t wire[] = { 'o', 'n', 'e', '.', 42, 0 }; + smb_msgbuf_t mb; + int mbflags = 0; + char *s; + int rc; + uint16_t w; + + smb_msgbuf_init(&mb, (uint8_t *)wire, sizeof (wire), mbflags); + + rc = smb_msgbuf_decode(&mb, "6U..w", &s, &w); + if (rc != 10) { + printf("Fail: msg_get_u1 decode\n"); + goto out; + } + /* + * Decode a word after the string to make sure we + * end up positioned correctly after the string. + */ + if (w != 42) { + printf("Fail: msg_get_u1 w=%d\n", w); + return; + } + if (strcmp(s, "one") != 0) { + printf("Fail: msg_get_u1 cmp: <%s>\n", s); + return; + } + + printf("Pass: msg_get_u1\n"); + +out: + smb_msgbuf_term(&mb); +} + +/* parse exactly to end of data */ +static void +msg_get_u2() +{ + uint16_t wire[] = { 'o', 'n', 'e' }; + smb_msgbuf_t mb; + int mbflags = 0; + char *s; + int rc; + + smb_msgbuf_init(&mb, (uint8_t *)wire, sizeof (wire), mbflags); + + rc = smb_msgbuf_decode(&mb, "6U", &s); + if (rc != 6) { + printf("Fail: msg_get_u2 decode\n"); + goto out; + } + if (mb.scan != mb.end) { + printf("Fail: msg_get_u2 wrong pos\n"); + return; + } + if (strcmp(s, "one") != 0) { + printf("Fail: msg_get_u2 cmp: <%s>\n", s); + return; + } + + printf("Pass: msg_get_u2\n"); + +out: + smb_msgbuf_term(&mb); +} + +static void +msg_get_u3() +{ + smb_msgbuf_t mb; + int mbflags = 0; + char *s; + int rc; + + smb_msgbuf_init(&mb, (uint8_t *)wcsa, sizeof (wcsa), mbflags); + + rc = smb_msgbuf_decode(&mb, "#U", sizeof (wcsa), &s); + if (rc != 8) { + printf("Fail: msg_get_u3 decode\n"); + goto out; + } + if (strcmp(s, mbsa) != 0) { + printf("Fail: msg_get_u3 cmp: <%s>\n", s); + return; + } + + printf("Pass: msg_get_u3\n"); + +out: + smb_msgbuf_term(&mb); +} + +static void +msg_get_u4() +{ + smb_msgbuf_t mb; + int mbflags = 0; + char *s; + int rc; + + smb_msgbuf_init(&mb, (uint8_t *)wcsp, sizeof (wcsp), mbflags); + + rc = smb_msgbuf_decode(&mb, "#U", sizeof (wcsp), &s); + if (rc != 10) { + printf("Fail: msg_get_u4 decode\n"); + goto out; + } + if (strcmp(s, mbsp) != 0) { + printf("Fail: msg_get_u4 cmp: <%s>\n", s); + return; + } + + printf("Pass: msg_get_u4\n"); + +out: + smb_msgbuf_term(&mb); +} + +void +test_msgbuf() +{ + + msg_put_a0(); + msg_put_a1(); + msg_put_apad(); + msg_put_atrunc(); + + msg_put_u0(); + msg_put_u1(); + msg_put_u3(); + msg_put_u4(); + msg_put_upad(); + msg_put_utrunc(); + + msg_get_a0(); + msg_get_a1(); + msg_get_a2(); + msg_get_u0(); + msg_get_u1(); + msg_get_u2(); + msg_get_u3(); + msg_get_u4(); + +} diff --git a/usr/src/common/smbsrv/smb_match.c b/usr/src/common/smbsrv/smb_match.c index e687e3cc9f..b35833ff29 100644 --- a/usr/src/common/smbsrv/smb_match.c +++ b/usr/src/common/smbsrv/smb_match.c @@ -142,7 +142,7 @@ smb_match_private(const char *pat, const char *str, struct match_priv *priv) const char *limit; char pc; /* current pattern char */ int rc; - smb_wchar_t wcpat, wcstr; /* current wchar in pat, str */ + uint32_t wcpat, wcstr; /* current wchar in pat, str */ int nbpat, nbstr; /* multi-byte length of it */ if (priv->depth >= SMB_MATCH_DEPTH_MAX) diff --git a/usr/src/common/smbsrv/smb_msgbuf.c b/usr/src/common/smbsrv/smb_msgbuf.c index 54cb75e066..b11cd39a50 100644 --- a/usr/src/common/smbsrv/smb_msgbuf.c +++ b/usr/src/common/smbsrv/smb_msgbuf.c @@ -22,7 +22,7 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ /* @@ -53,6 +53,12 @@ static int buf_encode(smb_msgbuf_t *, char *, va_list ap); static void *smb_msgbuf_malloc(smb_msgbuf_t *, size_t); static int smb_msgbuf_chkerc(char *text, int erc); +static int msgbuf_get_oem_string(smb_msgbuf_t *, char **, int); +static int msgbuf_get_unicode_string(smb_msgbuf_t *, char **, int); +static int msgbuf_put_oem_string(smb_msgbuf_t *, char *, int); +static int msgbuf_put_unicode_string(smb_msgbuf_t *, char *, int); + + /* * Returns the offset or number of bytes used within the buffer. */ @@ -177,7 +183,7 @@ smb_msgbuf_term(smb_msgbuf_t *mb) * Decode a smb_msgbuf buffer as indicated by the format string into * the variable arg list. This is similar to a scanf operation. * - * On success, returns the number of bytes encoded. Otherwise + * On success, returns the number of bytes decoded. Otherwise * returns a -ve error code. */ int @@ -213,15 +219,12 @@ smb_msgbuf_decode(smb_msgbuf_t *mb, char *fmt, ...) static int buf_decode(smb_msgbuf_t *mb, char *fmt, va_list ap) { - uint32_t ival; uint8_t c; uint8_t *bvalp; uint16_t *wvalp; uint32_t *lvalp; uint64_t *llvalp; - char *cvalp; char **cvalpp; - smb_wchar_t wchar; boolean_t repc_specified; int repc; int rc; @@ -324,75 +327,23 @@ buf_decode(smb_msgbuf_t *mb, char *fmt, va_list ap) goto unicode_translation; /*FALLTHROUGH*/ - case 's': /* get string */ - if (!repc_specified) - repc = strlen((const char *)mb->scan) + 1; - if (smb_msgbuf_has_space(mb, repc) == 0) - return (SMB_MSGBUF_UNDERFLOW); - if ((cvalp = smb_msgbuf_malloc(mb, repc * 2)) == 0) - return (SMB_MSGBUF_UNDERFLOW); + case 's': /* get OEM string */ cvalpp = va_arg(ap, char **); - *cvalpp = cvalp; - /* Translate OEM to mbs */ - while (repc > 0) { - wchar = *mb->scan++; - repc--; - if (wchar == 0) - break; - ival = smb_wctomb(cvalp, wchar); - cvalp += ival; - } - *cvalp = '\0'; - if (repc > 0) - mb->scan += repc; + if (!repc_specified) + repc = 0; + rc = msgbuf_get_oem_string(mb, cvalpp, repc); + if (rc != 0) + return (rc); break; - case 'U': /* get unicode string */ + case 'U': /* get UTF-16 string */ unicode_translation: - /* - * Unicode strings are always word aligned. - * The malloc'd area is larger than the - * original string because the UTF-8 chars - * may be longer than the wide-chars. - */ - smb_msgbuf_word_align(mb); - if (!repc_specified) { - /* - * Count bytes, including the null. - */ - uint8_t *tmp_scan = mb->scan; - repc = 2; /* the null */ - while ((wchar = LE_IN16(tmp_scan)) != 0) { - tmp_scan += 2; - repc += 2; - } - } - if (smb_msgbuf_has_space(mb, repc) == 0) - return (SMB_MSGBUF_UNDERFLOW); - /* - * Get space for translated string - * Allocates worst-case size. - */ - if ((cvalp = smb_msgbuf_malloc(mb, repc * 2)) == 0) - return (SMB_MSGBUF_UNDERFLOW); cvalpp = va_arg(ap, char **); - *cvalpp = cvalp; - /* - * Translate unicode to mbs, stopping after - * null or repc limit. - */ - while (repc >= 2) { - wchar = LE_IN16(mb->scan); - mb->scan += 2; - repc -= 2; - if (wchar == 0) - break; - ival = smb_wctomb(cvalp, wchar); - cvalp += ival; - } - *cvalp = '\0'; - if (repc > 0) - mb->scan += repc; + if (!repc_specified) + repc = 0; + rc = msgbuf_get_unicode_string(mb, cvalpp, repc); + if (rc != 0) + return (rc); break; case 'M': @@ -416,6 +367,151 @@ unicode_translation: return (SMB_MSGBUF_SUCCESS); } +/* + * msgbuf_get_oem_string + * + * Decode an OEM string, returning its UTF-8 form in strpp, + * allocated using smb_msgbuf_malloc (automatically freed). + * If max_bytes != 0, consume at most max_bytes of the mb. + * See also: mbc_marshal_get_oem_string + */ +static int +msgbuf_get_oem_string(smb_msgbuf_t *mb, char **strpp, int max_bytes) +{ + char *mbs; + uint8_t *oembuf = NULL; + int oemlen; // len of OEM string, w/o null + int datalen; // OtW data len + int mbsmax; // max len of ret str + int rlen; + + if (max_bytes == 0) + max_bytes = 0xffff; + + /* + * Determine the OtW data length and OEM string length + * Note: oemlen is the string length (w/o null) and + * datalen is how much we move mb->scan + */ + datalen = 0; + oemlen = 0; + for (;;) { + if (datalen >= max_bytes) + break; + /* in-line smb_msgbuf_has_space */ + if ((mb->scan + datalen) >= mb->end) + return (SMB_MSGBUF_UNDERFLOW); + datalen++; + if (mb->scan[datalen - 1] == 0) + break; + oemlen++; + } + + /* + * Get datalen bytes into a temp buffer + * sized with room to add a null. + * Free oembuf in smb_msgbuf_term + */ + oembuf = smb_msgbuf_malloc(mb, datalen + 1); + if (oembuf == NULL) + return (SMB_MSGBUF_UNDERFLOW); + bcopy(mb->scan, oembuf, datalen); + mb->scan += datalen; + oembuf[oemlen] = '\0'; + + /* + * Get the buffer we'll return and convert to UTF-8. + * May take as much as double the space. + */ + mbsmax = oemlen * 2; + mbs = smb_msgbuf_malloc(mb, mbsmax + 1); + if (mbs == NULL) + return (SMB_MSGBUF_UNDERFLOW); + rlen = smb_oemtombs(mbs, oembuf, mbsmax); + if (rlen < 0) + return (SMB_MSGBUF_UNDERFLOW); + if (rlen > mbsmax) + rlen = mbsmax; + mbs[rlen] = '\0'; + *strpp = mbs; + return (0); +} + +/* + * msgbuf_get_unicode_string + * + * Decode a UTF-16 string, returning its UTF-8 form in strpp, + * allocated using smb_msgbuf_malloc (automatically freed). + * If max_bytes != 0, consume at most max_bytes of the mb. + * See also: mbc_marshal_get_unicode_string + */ +static int +msgbuf_get_unicode_string(smb_msgbuf_t *mb, char **strpp, int max_bytes) +{ + char *mbs; + uint16_t *wcsbuf = NULL; + int wcslen; // wchar count + int datalen; // OtW data len + size_t mbsmax; // max len of ret str + size_t rlen; + + if (max_bytes == 0) + max_bytes = 0xffff; + + /* + * Unicode strings are always word aligned. + */ + smb_msgbuf_word_align(mb); + + /* + * Determine the OtW data length and (WC) string length + * Note: wcslen counts 16-bit wide_chars (w/o null), + * and datalen is how much we move mb->scan + */ + datalen = 0; + wcslen = 0; + for (;;) { + if (datalen >= max_bytes) + break; + /* in-line smb_msgbuf_has_space */ + if ((mb->scan + datalen) >= mb->end) + return (SMB_MSGBUF_UNDERFLOW); + datalen += 2; + if (mb->scan[datalen - 2] == 0 && + mb->scan[datalen - 1] == 0) + break; + wcslen++; + } + + /* + * Get datalen bytes into a temp buffer + * sized with room to add a (WC) null. + * Note: wcsbuf has little-endian order + */ + wcsbuf = smb_msgbuf_malloc(mb, datalen + 2); + if (wcsbuf == NULL) + return (SMB_MSGBUF_UNDERFLOW); + bcopy(mb->scan, wcsbuf, datalen); + mb->scan += datalen; + wcsbuf[wcslen] = 0; + + /* + * Get the buffer we'll return and convert to UTF-8. + * May take as much 4X number of wide chars. + */ + mbsmax = wcslen * MTS_MB_CUR_MAX; + mbs = smb_msgbuf_malloc(mb, mbsmax + 1); + if (mbs == NULL) + return (SMB_MSGBUF_UNDERFLOW); + rlen = smb_wcstombs(mbs, wcsbuf, mbsmax); + if (rlen == (size_t)-1) + return (SMB_MSGBUF_UNDERFLOW); + if (rlen > mbsmax) + rlen = mbsmax; + mbs[rlen] = '\0'; + *strpp = mbs; + return (0); +} /* * smb_msgbuf_encode @@ -466,8 +562,6 @@ buf_encode(smb_msgbuf_t *mb, char *fmt, va_list ap) uint8_t *bvalp; char *cvalp; uint8_t c; - smb_wchar_t wchar; - int count; boolean_t repc_specified; int repc; int rc; @@ -571,80 +665,23 @@ buf_encode(smb_msgbuf_t *mb, char *fmt, va_list ap) goto unicode_translation; /* FALLTHROUGH */ - case 's': /* put string */ + case 's': /* put OEM string */ cvalp = va_arg(ap, char *); - if (!repc_specified) { - repc = smb_sbequiv_strlen(cvalp); - if (repc == -1) - return (SMB_MSGBUF_OVERFLOW); - if (!(mb->flags & SMB_MSGBUF_NOTERM)) - repc++; - } - if (smb_msgbuf_has_space(mb, repc) == 0) - return (SMB_MSGBUF_OVERFLOW); - while (repc > 0) { - count = smb_mbtowc(&wchar, cvalp, - MTS_MB_CHAR_MAX); - if (count < 0) - return (SMB_MSGBUF_DATA_ERROR); - cvalp += count; - if (wchar == 0) - break; - *mb->scan++ = (uint8_t)wchar; - repc--; - if (wchar & 0xff00) { - *mb->scan++ = wchar >> 8; - repc--; - } - } - if (*cvalp == '\0' && repc > 0 && - (mb->flags & SMB_MSGBUF_NOTERM) == 0) { - *mb->scan++ = 0; - repc--; - } - while (repc > 0) { - *mb->scan++ = 0; - repc--; - } + if (!repc_specified) + repc = 0; + rc = msgbuf_put_oem_string(mb, cvalp, repc); + if (rc != 0) + return (rc); break; - case 'U': /* put unicode string */ + case 'U': /* put UTF-16 string */ unicode_translation: - /* - * Unicode strings are always word aligned. - */ - smb_msgbuf_word_align(mb); cvalp = va_arg(ap, char *); - if (!repc_specified) { - repc = smb_wcequiv_strlen(cvalp); - if (!(mb->flags & SMB_MSGBUF_NOTERM)) - repc += 2; - } - if (!smb_msgbuf_has_space(mb, repc)) - return (SMB_MSGBUF_OVERFLOW); - while (repc >= 2) { - count = smb_mbtowc(&wchar, cvalp, - MTS_MB_CHAR_MAX); - if (count < 0) - return (SMB_MSGBUF_DATA_ERROR); - cvalp += count; - if (wchar == 0) - break; - - LE_OUT16(mb->scan, wchar); - mb->scan += 2; - repc -= 2; - } - if (*cvalp == '\0' && repc >= 2 && - (mb->flags & SMB_MSGBUF_NOTERM) == 0) { - LE_OUT16(mb->scan, 0); - mb->scan += 2; - repc -= 2; - } - while (repc > 0) { - *mb->scan++ = 0; - repc--; - } + if (!repc_specified) + repc = 0; + rc = msgbuf_put_unicode_string(mb, cvalp, repc); + if (rc != 0) + return (rc); break; case 'M': @@ -665,6 +702,141 @@ unicode_translation: return (SMB_MSGBUF_SUCCESS); } +/* + * Marshal a UTF-8 string (str) into mbc, converting to OEM codeset. + * Also write a null unless the repc count limits the length we put. + * When (repc > 0) the length we marshal must be exactly repc, and + * truncate or pad the mb data as necessary. + * See also: mbc_marshal_put_oem_string + */ +static int +msgbuf_put_oem_string(smb_msgbuf_t *mb, char *mbs, int repc) +{ + uint8_t *oembuf = NULL; + uint8_t *s; + int oemlen; + int rlen; + + /* + * Compute length of converted OEM string, + * NOT including null terminator + */ + if ((oemlen = smb_sbequiv_strlen(mbs)) == -1) + return (SMB_MSGBUF_DATA_ERROR); + + /* + * If repc not specified, put whole string + NULL, + * otherwise will truncate or pad as needed. + */ + if (repc <= 0) { + repc = oemlen; + if ((mb->flags & SMB_MSGBUF_NOTERM) == 0) + repc += sizeof (char); + } + if (smb_msgbuf_has_space(mb, repc) == 0) + return (SMB_MSGBUF_OVERFLOW); + + /* + * Convert into a temporary buffer + * Free oembuf in smb_msgbuf_term. + */ + oembuf = smb_msgbuf_malloc(mb, oemlen + 1); + if (oembuf == NULL) + return (SMB_MSGBUF_UNDERFLOW); + rlen = smb_mbstooem(oembuf, mbs, oemlen); + if (rlen < 0) + return (SMB_MSGBUF_DATA_ERROR); + if (rlen > oemlen) + rlen = oemlen; + oembuf[rlen] = '\0'; + + /* + * Copy the converted string into the message, + * truncated or paded as required. + */ + s = oembuf; + while (repc > 0) { + *mb->scan++ = *s; + if (*s != '\0') + s++; + repc--; + } + + return (0); +} + +/* + * Marshal a UTF-8 string (str) into mbc, converting to UTF-16. + * Also write a null unless the repc count limits the length. + * When (repc > 0) the length we marshal must be exactly repc, + * and truncate or pad the mb data as necessary. + * See also: mbc_marshal_put_unicode_string + */ +static int +msgbuf_put_unicode_string(smb_msgbuf_t *mb, char *mbs, int repc) +{ + smb_wchar_t *wcsbuf = NULL; + smb_wchar_t *wp; + size_t wcslen, wcsbytes; + size_t rlen; + + /* align to word boundary */ + smb_msgbuf_word_align(mb); + + /* + * Compute length of converted UTF-16 string, + * NOT including null terminator (in bytes). + */ + wcsbytes = smb_wcequiv_strlen(mbs); + if (wcsbytes == (size_t)-1) + return (SMB_MSGBUF_DATA_ERROR); + + /* + * If repc not specified, put whole string + NULL, + * otherwise will truncate or pad as needed. + */ + if (repc <= 0) { + repc = (int)wcsbytes; + if ((mb->flags & SMB_MSGBUF_NOTERM) == 0) + repc += sizeof (smb_wchar_t); + } + if (smb_msgbuf_has_space(mb, repc) == 0) + return (SMB_MSGBUF_OVERFLOW); + + /* + * Convert into a temporary buffer + * Free wcsbuf in smb_msgbuf_term + */ + wcslen = wcsbytes / 2; + wcsbuf = smb_msgbuf_malloc(mb, wcsbytes + 2); + if (wcsbuf == NULL) + return (SMB_MSGBUF_UNDERFLOW); + rlen = smb_mbstowcs(wcsbuf, mbs, wcslen); + if (rlen == (size_t)-1) + return (SMB_MSGBUF_DATA_ERROR); + if (rlen > wcslen) + rlen = wcslen; + wcsbuf[rlen] = 0; + + /* + * Copy the converted string into the message, + * truncated or paded as required. Preserve + * little-endian order while copying. + */ + wp = wcsbuf; + while (repc > 1) { + smb_wchar_t wchar = LE_IN16(wp); + LE_OUT16(mb->scan, wchar); + mb->scan += 2; + if (wchar != 0) + wp++; + repc -= sizeof (smb_wchar_t); + } + if (repc > 0) + *mb->scan++ = '\0'; + + return (0); +} /* * smb_msgbuf_malloc diff --git a/usr/src/common/smbsrv/smb_string.c b/usr/src/common/smbsrv/smb_string.c index 3d2abc474b..7922d84916 100644 --- a/usr/src/common/smbsrv/smb_string.c +++ b/usr/src/common/smbsrv/smb_string.c @@ -174,8 +174,8 @@ smb_islower(int c) * If the specified character is lowercase, the uppercase value will * be returned. Otherwise the original value will be returned. */ -int -smb_toupper(int c) +uint32_t +smb_toupper(uint32_t c) { uint16_t mask = is_unicode ? 0xffff : 0xff; @@ -187,8 +187,8 @@ smb_toupper(int c) * If the specified character is uppercase, the lowercase value will * be returned. Otherwise the original value will be returned. */ -int -smb_tolower(int c) +uint32_t +smb_tolower(uint32_t c) { uint16_t mask = is_unicode ? 0xffff : 0xff; @@ -204,7 +204,7 @@ smb_tolower(int c) char * smb_strupr(char *s) { - smb_wchar_t c; + uint32_t c; char *p = s; while (*p) { @@ -235,7 +235,7 @@ smb_strupr(char *s) char * smb_strlwr(char *s) { - smb_wchar_t c; + uint32_t c; char *p = s; while (*p) { @@ -264,7 +264,7 @@ smb_strlwr(char *s) int smb_isstrlwr(const char *s) { - smb_wchar_t c; + uint32_t c; int n; const char *p = s; @@ -295,7 +295,7 @@ smb_isstrlwr(const char *s) int smb_isstrupr(const char *s) { - smb_wchar_t c; + uint32_t c; int n; const char *p = s; @@ -440,7 +440,7 @@ smb_unicode_init(void) * unc_server server or domain name with no leading/trailing '\' * unc_share share name with no leading/trailing '\' * unc_path relative path to the share with no leading/trailing '\' - * it is valid for unc_path to be NULL. + * it is valid for unc_path to be NULL. * * Upon successful return of this function, smb_unc_free() * MUST be called when returned 'unc' is no longer needed. diff --git a/usr/src/common/smbsrv/smb_utf8.c b/usr/src/common/smbsrv/smb_utf8.c index 3b84363dbd..8446fb0b9e 100644 --- a/usr/src/common/smbsrv/smb_utf8.c +++ b/usr/src/common/smbsrv/smb_utf8.c @@ -22,43 +22,25 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ /* - * Multibyte/wide-char conversion routines. Wide-char encoding provides - * a fixed size character encoding that maps to the Unicode 16-bit - * (UCS-2) character set standard. Multibyte or UCS transformation - * format (UTF) encoding is a variable length character encoding scheme - * that s compatible with existing ASCII characters and guarantees that - * the resultant strings do not contain embedded null characters. Both - * types of encoding provide a null terminator: single byte for UTF-8 - * and a wide-char null for Unicode. See RFC 2044. - * - * The table below illustrates the UTF-8 encoding scheme. The letter x - * indicates bits available for encoding the character value. - * - * UCS-2 UTF-8 octet sequence (binary) - * 0x0000-0x007F 0xxxxxxx - * 0x0080-0x07FF 110xxxxx 10xxxxxx - * 0x0800-0xFFFF 1110xxxx 10xxxxxx 10xxxxxx - * - * RFC 2044 - * UTF-8,a transformation format of UNICODE and ISO 10646 - * F. Yergeau - * Alis Technologies - * October 1996 + * Multibyte/wide-char conversion routines. SMB uses UTF-16 on the wire + * (smb_wchar_t) and we use UTF-8 internally (our multi-byte, or mbs). */ #if defined(_KERNEL) || defined(_FAKE_KERNEL) #include <sys/types.h> #include <sys/sunddi.h> -#else +#else /* _KERNEL || _FAKE_KERNEL */ #include <stdio.h> #include <stdlib.h> -#include <assert.h> #include <strings.h> -#endif +#include <iconv.h> +#include <assert.h> +#endif /* _KERNEL || _FAKE_KERNEL */ +#include <sys/u8_textprep.h> #include <smbsrv/string.h> @@ -75,26 +57,37 @@ * multibyte character is encountered. */ size_t -smb_mbstowcs(smb_wchar_t *wcstring, const char *mbstring, size_t nwchars) +smb_mbstowcs(smb_wchar_t *wcs, const char *mbs, size_t nwchars) { - int len; - smb_wchar_t *start = wcstring; - - while (nwchars--) { - len = smb_mbtowc(wcstring, mbstring, MTS_MB_CHAR_MAX); - if (len < 0) { - *wcstring = 0; - return ((size_t)-1); - } + size_t mbslen, wcslen; + int err; - if (*mbstring == 0) - break; + /* NULL or empty input is allowed. */ + if (mbs == NULL || *mbs == '\0') { + if (wcs != NULL && nwchars > 0) + *wcs = 0; + return (0); + } - ++wcstring; - mbstring += len; + /* + * Traditional mbstowcs(3C) allows wcs==NULL to get the length. + * SMB never calls it that way, but let's future-proof. + */ + if (wcs == NULL) { + return ((size_t)-1); } - return (wcstring - start); + mbslen = strlen(mbs); + wcslen = nwchars; + err = uconv_u8tou16((const uchar_t *)mbs, &mbslen, + wcs, &wcslen, UCONV_OUT_LITTLE_ENDIAN); + if (err != 0) + return ((size_t)-1); + + if (wcslen < nwchars) + wcs[wcslen] = 0; + + return (wcslen); } @@ -113,49 +106,36 @@ smb_mbstowcs(smb_wchar_t *wcstring, const char *mbstring, size_t nwchars) * states. Otherwise it should be return 0. * * If mbchar is non-null, returns the number of bytes processed in - * mbchar. If mbchar is invalid, returns -1. + * mbchar. If mbchar is null, convert the null (wcharp=0) but + * return length zero. If mbchar is invalid, returns -1. */ int /*ARGSUSED*/ -smb_mbtowc(smb_wchar_t *wcharp, const char *mbchar, size_t nbytes) +smb_mbtowc(uint32_t *wcharp, const char *mbchar, size_t nbytes) { - unsigned char mbyte; - smb_wchar_t wide_char; - int count; - int bytes_left; + uint32_t wide_char; + int count, err; + size_t mblen; + size_t wclen; if (mbchar == NULL) return (0); /* no shift states */ - /* 0xxxxxxx -> 1 byte ASCII encoding */ - if (((mbyte = *mbchar++) & 0x80) == 0) { - if (wcharp) - *wcharp = (smb_wchar_t)mbyte; - - return (mbyte ? 1 : 0); - } - - /* 10xxxxxx -> invalid first byte */ - if ((mbyte & 0x40) == 0) + /* + * How many bytes in this symbol? + */ + count = u8_validate((char *)mbchar, nbytes, NULL, 0, &err); + if (count < 0) return (-1); - wide_char = mbyte; - if ((mbyte & 0x20) == 0) { - wide_char &= 0x1f; - bytes_left = 1; - } else if ((mbyte & 0x10) == 0) { - wide_char &= 0x0f; - bytes_left = 2; - } else { + mblen = count; + wclen = 1; + err = uconv_u8tou32((const uchar_t *)mbchar, &mblen, + &wide_char, &wclen, UCONV_OUT_SYSTEM_ENDIAN); + if (err != 0) return (-1); - } - - count = 1; - while (bytes_left--) { - if (((mbyte = *mbchar++) & 0xc0) != 0x80) - return (-1); - - count++; - wide_char = (wide_char << 6) | (mbyte & 0x3f); + if (wclen == 0) { + wide_char = 0; + count = 0; } if (wcharp) @@ -173,25 +153,27 @@ smb_mbtowc(smb_wchar_t *wcharp, const char *mbchar, size_t nbytes) * mbchar must be large enough to accommodate the multibyte character. * * Returns the numberof bytes written to mbchar. + * Note: handles null like any 1-byte char. */ int -smb_wctomb(char *mbchar, smb_wchar_t wchar) +smb_wctomb(char *mbchar, uint32_t wchar) { - if ((wchar & ~0x7f) == 0) { - *mbchar = (char)wchar; - return (1); - } + char junk[MTS_MB_CUR_MAX+1]; + size_t mblen; + size_t wclen; + int err; - if ((wchar & ~0x7ff) == 0) { - *mbchar++ = (wchar >> 6) | 0xc0; - *mbchar = (wchar & 0x3f) | 0x80; - return (2); - } + if (mbchar == NULL) + mbchar = junk; - *mbchar++ = (wchar >> 12) | 0xe0; - *mbchar++ = ((wchar >> 6) & 0x3f) | 0x80; - *mbchar = (wchar & 0x3f) | 0x80; - return (3); + mblen = MTS_MB_CUR_MAX; + wclen = 1; + err = uconv_u32tou8(&wchar, &wclen, (uchar_t *)mbchar, &mblen, + UCONV_IN_SYSTEM_ENDIAN | UCONV_IGNORE_NULL); + if (err != 0) + return (-1); + + return ((int)mblen); } @@ -205,46 +187,46 @@ smb_wctomb(char *mbchar, smb_wchar_t wchar) * terminated if there is room. * * Returns the number of bytes converted, not counting the terminating - * null byte. + * null byte. Returns -1 if an invalid WC sequence is encountered. */ size_t -smb_wcstombs(char *mbstring, const smb_wchar_t *wcstring, size_t nbytes) +smb_wcstombs(char *mbs, const smb_wchar_t *wcs, size_t nbytes) { - char *start = mbstring; - const smb_wchar_t *wcp = wcstring; - smb_wchar_t wide_char = 0; - char buf[4]; - size_t len; + size_t mbslen, wcslen; + int err; - if ((mbstring == NULL) || (wcstring == NULL)) + /* NULL or empty input is allowed. */ + if (wcs == NULL || *wcs == 0) { + if (mbs != NULL && nbytes > 0) + *mbs = '\0'; return (0); + } - while (nbytes > MTS_MB_CHAR_MAX) { - wide_char = *wcp++; - len = smb_wctomb(mbstring, wide_char); - - if (wide_char == 0) - /*LINTED E_PTRDIFF_OVERFLOW*/ - return (mbstring - start); - - mbstring += len; - nbytes -= len; + /* + * Traditional wcstombs(3C) allows mbs==NULL to get the length. + * SMB never calls it that way, but let's future-proof. + */ + if (mbs == NULL) { + return ((size_t)-1); } - while (wide_char && nbytes) { - wide_char = *wcp++; - if ((len = smb_wctomb(buf, wide_char)) > nbytes) { - *mbstring = 0; - break; - } + /* + * Compute wcslen + */ + wcslen = 0; + while (wcs[wcslen] != 0) + wcslen++; - bcopy(buf, mbstring, len); - mbstring += len; - nbytes -= len; - } + mbslen = nbytes; + err = uconv_u16tou8(wcs, &wcslen, + (uchar_t *)mbs, &mbslen, UCONV_IN_LITTLE_ENDIAN); + if (err != 0) + return ((size_t)-1); + + if (mbslen < nbytes) + mbs[mbslen] = '\0'; - /*LINTED E_PTRDIFF_OVERFLOW*/ - return (mbstring - start); + return (mbslen); } @@ -256,7 +238,7 @@ smb_wcstombs(char *mbstring, const smb_wchar_t *wcstring, size_t nbytes) size_t smb_wcequiv_strlen(const char *mbs) { - smb_wchar_t wide_char; + uint32_t wide_char; size_t bytes; size_t len = 0; @@ -264,9 +246,15 @@ smb_wcequiv_strlen(const char *mbs) bytes = smb_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX); if (bytes == ((size_t)-1)) return ((size_t)-1); + mbs += bytes; len += sizeof (smb_wchar_t); - mbs += bytes; + if (bytes > 3) { + /* + * Extended unicode, so TWO smb_wchar_t + */ + len += sizeof (smb_wchar_t); + } } return (len); @@ -275,25 +263,38 @@ smb_wcequiv_strlen(const char *mbs) /* * Returns the number of bytes that would be written if the multi- - * byte string mbs was converted to a single byte character string, - * not counting the terminating null character. + * byte string mbs was converted to an OEM character string, + * (smb_mbstooem) not counting the terminating null character. */ size_t smb_sbequiv_strlen(const char *mbs) { - smb_wchar_t wide_char; size_t nbytes; size_t len = 0; while (*mbs) { - nbytes = smb_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX); + nbytes = smb_mbtowc(NULL, mbs, MTS_MB_CHAR_MAX); if (nbytes == ((size_t)-1)) return ((size_t)-1); + if (nbytes == 0) + break; - if (wide_char & 0xFF00) - len += sizeof (smb_wchar_t); - else - ++len; + if (nbytes == 1) { + /* ASCII */ + len++; + } else if (nbytes < 8) { + /* Compute OEM length */ + char mbsbuf[8]; + uint8_t oembuf[8]; + int oemlen; + (void) strlcpy(mbsbuf, mbs, nbytes+1); + oemlen = smb_mbstooem(oembuf, mbsbuf, 8); + if (oemlen < 0) + return ((size_t)-1); + len += oemlen; + } else { + return ((size_t)-1); + } mbs += nbytes; } @@ -301,106 +302,174 @@ smb_sbequiv_strlen(const char *mbs) return (len); } +/* + * Convert OEM strings to/from internal (UTF-8) form. + * + * We rarely encounter these anymore because all modern + * SMB clients use Unicode (UTF-16). The few cases where + * this IS still called are normally using ASCII, i.e. + * tag names etc. so short-cut those cases. If we get + * something non-ASCII we have to call iconv. + * + * If we were to really support OEM code pages, we would + * need to have a way to set the OEM code page from some + * configuration value. For now it's always CP850. + * See also ./smb_oem.c + */ +static char smb_oem_codepage[32] = "CP850"; /* - * stombs + * smb_oemtombs * - * Convert a regular null terminated string 'string' to a UTF-8 encoded - * null terminated multi-byte string 'mbstring'. Only full converted - * UTF-8 characters will be written 'mbstring'. If a character will not - * fit within the remaining buffer space or 'mbstring' will overflow - * max_mblen, the conversion process will be terminated and 'mbstring' - * will be null terminated. + * Convert a null terminated OEM string 'string' to a UTF-8 string + * no longer than max_mblen (null terminated if space). * - * Returns the number of bytes written to 'mbstring', excluding the - * terminating null character. + * If the input string contains invalid OEM characters, a value + * of -1 will be returned. Otherwise returns the length of 'mbs', + * excluding the terminating null character. * * If either mbstring or string is a null pointer, -1 is returned. */ int -smb_stombs(char *mbstring, char *string, int max_mblen) +smb_oemtombs(char *mbs, const uint8_t *oems, int max_mblen) { - char *start = mbstring; - unsigned char *p = (unsigned char *)string; - int space_left = max_mblen; - int len; - smb_wchar_t wide_char; - char buf[4]; - - if (!mbstring || !string) + uchar_t *p; + int oemlen; + int rlen; + boolean_t need_iconv = B_FALSE; + + if (mbs == NULL || oems == NULL) return (-1); - while (*p && space_left > 2) { - wide_char = *p++; - len = smb_wctomb(mbstring, wide_char); - mbstring += len; - space_left -= len; + /* + * Check if the oems is all ASCII (and get the length + * while we're at it) so we know if we need to iconv. + * We usually can avoid the iconv calls. + */ + oemlen = 0; + p = (uchar_t *)oems; + while (*p != '\0') { + oemlen++; + if (*p & 0x80) + need_iconv = B_TRUE; + p++; } - if (*p) { - wide_char = *p; - if ((len = smb_wctomb(buf, wide_char)) < 2) { - *mbstring = *buf; - mbstring += len; - space_left -= len; - } + if (need_iconv) { + int rc; + char *obuf = mbs; + size_t olen = max_mblen; + size_t ilen = oemlen; +#if defined(_KERNEL) || defined(_FAKE_KERNEL) + char *ibuf = (char *)oems; + kiconv_t ic; + int err; + + ic = kiconv_open("UTF-8", smb_oem_codepage); + if (ic == (kiconv_t)-1) + goto just_copy; + rc = kiconv(ic, &ibuf, &ilen, &obuf, &olen, &err); + (void) kiconv_close(ic); +#else /* _KERNEL || _FAKE_KERNEL */ + const char *ibuf = (char *)oems; + iconv_t ic; + ic = iconv_open("UTF-8", smb_oem_codepage); + if (ic == (iconv_t)-1) + goto just_copy; + rc = iconv(ic, &ibuf, &ilen, &obuf, &olen); + (void) iconv_close(ic); +#endif /* _KERNEL || _FAKE_KERNEL */ + if (rc < 0) + return (-1); + /* Return val. is output bytes. */ + rlen = (max_mblen - olen); + } else { + just_copy: + rlen = oemlen; + if (rlen > max_mblen) + rlen = max_mblen; + bcopy(oems, mbs, rlen); } + if (rlen < max_mblen) + mbs[rlen] = '\0'; - *mbstring = '\0'; - - /*LINTED E_PTRDIFF_OVERFLOW*/ - return (mbstring - start); + return (rlen); } - /* - * mbstos + * smb_mbstooem * - * Convert a null terminated multi-byte string 'mbstring' to a regular - * null terminated string 'string'. A 1-byte character in 'mbstring' - * maps to a 1-byte character in 'string'. A 2-byte character in - * 'mbstring' will be mapped to 2-bytes, if the upper byte is non-null. - * Otherwise the upper byte null will be discarded to ensure that the - * output stream does not contain embedded null characters. + * Convert a null terminated multi-byte string 'mbs' to an OEM string + * no longer than max_oemlen (null terminated if space). * - * If the input stream contains invalid multi-byte characters, a value - * of -1 will be returned. Otherwise the length of 'string', excluding - * the terminating null character, is returned. + * If the input string contains invalid multi-byte characters, a value + * of -1 will be returned. Otherwise returns the length of 'oems', + * excluding the terminating null character. * * If either mbstring or string is a null pointer, -1 is returned. */ int -smb_mbstos(char *string, const char *mbstring) +smb_mbstooem(uint8_t *oems, const char *mbs, int max_oemlen) { - smb_wchar_t wc; - unsigned char *start = (unsigned char *)string; - int len; + uchar_t *p; + int mbslen; + int rlen; + boolean_t need_iconv = B_FALSE; - if (string == NULL || mbstring == NULL) + if (oems == NULL || mbs == NULL) return (-1); - while (*mbstring) { - if ((len = smb_mbtowc(&wc, mbstring, MTS_MB_CHAR_MAX)) < 0) { - *string = 0; - return (-1); - } - - if (wc & 0xFF00) { - /*LINTED E_BAD_PTR_CAST_ALIGN*/ - *((smb_wchar_t *)string) = wc; - string += sizeof (smb_wchar_t); - } - else - { - *string = (unsigned char)wc; - string++; - } - - mbstring += len; + /* + * Check if the mbs is all ASCII (and get the length + * while we're at it) so we know if we need to iconv. + * We usually can avoid the iconv calls. + */ + mbslen = 0; + p = (uchar_t *)mbs; + while (*p != '\0') { + mbslen++; + if (*p & 0x80) + need_iconv = B_TRUE; + p++; } - *string = 0; + if (need_iconv) { + int rc; + char *obuf = (char *)oems; + size_t olen = max_oemlen; + size_t ilen = mbslen; +#if defined(_KERNEL) || defined(_FAKE_KERNEL) + char *ibuf = (char *)mbs; + kiconv_t ic; + int err; + + ic = kiconv_open(smb_oem_codepage, "UTF-8"); + if (ic == (kiconv_t)-1) + goto just_copy; + rc = kiconv(ic, &ibuf, &ilen, &obuf, &olen, &err); + (void) kiconv_close(ic); +#else /* _KERNEL || _FAKE_KERNEL */ + const char *ibuf = mbs; + iconv_t ic; + ic = iconv_open(smb_oem_codepage, "UTF-8"); + if (ic == (iconv_t)-1) + goto just_copy; + rc = iconv(ic, &ibuf, &ilen, &obuf, &olen); + (void) iconv_close(ic); +#endif /* _KERNEL || _FAKE_KERNEL */ + if (rc < 0) + return (-1); + /* Return val. is output bytes. */ + rlen = (max_oemlen - olen); + } else { + just_copy: + rlen = mbslen; + if (rlen > max_oemlen) + rlen = max_oemlen; + bcopy(mbs, oems, rlen); + } + if (rlen < max_oemlen) + oems[rlen] = '\0'; - /*LINTED E_PTRDIFF_OVERFLOW*/ - return ((unsigned char *)string - start); + return (rlen); } diff --git a/usr/src/lib/libdtrace/Makefile.com b/usr/src/lib/libdtrace/Makefile.com index ed46637115..3e6aa94d9b 100644 --- a/usr/src/lib/libdtrace/Makefile.com +++ b/usr/src/lib/libdtrace/Makefile.com @@ -97,6 +97,7 @@ DLIBSRCS += \ sched.d \ signal.d \ scsi.d \ + smb.d \ srp.d \ sysevent.d \ tcp.d \ diff --git a/usr/src/lib/libdtrace/common/smb.d b/usr/src/lib/libdtrace/common/smb.d new file mode 100644 index 0000000000..c58cb4bf1c --- /dev/null +++ b/usr/src/lib/libdtrace/common/smb.d @@ -0,0 +1,161 @@ +/* + * 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 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#pragma D depends_on library ip.d +#pragma D depends_on library net.d +#pragma D depends_on module genunix +#pragma D depends_on module smbsrv + +#pragma D binding "1.5" translator +translator conninfo_t < struct smb_request *P > { + ci_protocol = + P->session->ipaddr.a_family == AF_INET6 ? "tcp6" : + P->session->ipaddr.a_family == AF_INET ? "tcp" : + "<unknown>"; + ci_local = "<any>"; /* not interesting */ + ci_remote = P->session->ip_addr_str; +}; + +/* + * The smbopinfo_t structure describes the internal form of a + * single SMB request (SMB v1). + */ +typedef struct smbopinfo { + cred_t *soi_cred; /* credentials for operation */ + string soi_share; /* share name */ + string soi_curpath; /* file handle path (if any) */ + uint64_t soi_sid; /* session id */ + uint32_t soi_pid; /* process id */ + uint32_t soi_status; /* status */ + uint16_t soi_tid; /* tree id */ + uint16_t soi_uid; /* user id */ + uint16_t soi_mid; /* request id */ + uint16_t soi_fid; /* file id */ + uint16_t soi_flags2; /* flags2 */ + uint8_t soi_flags; /* flags */ +} smbopinfo_t; + +#pragma D binding "1.5" translator +translator smbopinfo_t < struct smb_request *P > { + soi_cred = (cred_t *)P->user_cr; + soi_sid = P->session->s_kid; + soi_pid = P->smb_pid; + soi_status = P->smb_error.status; + soi_tid = P->smb_tid; + soi_uid = P->smb_uid; + soi_mid = P->smb_mid; + soi_fid = P->smb_fid; + soi_flags2 = P->smb_flg2; + soi_flags = P->smb_flg; + + soi_share = (P->tid_tree == NULL) ? "<NULL>" : + P->tid_tree->t_sharename; + + soi_curpath = (P->fid_ofile == NULL || + P->fid_ofile->f_node == NULL || + P->fid_ofile->f_node->vp == NULL || + P->fid_ofile->f_node->vp->v_path == NULL) ? "<NULL>" : + P->fid_ofile->f_node->vp->v_path; +}; + +typedef struct smb_rw_args { + off_t soa_offset; + uint_t soa_count; +} smb_rw_args_t; + +#pragma D binding "1.5" translator +translator smb_rw_args_t < smb_request_t *P > { + soa_offset = P->arg.rw->rw_offset; + soa_count = P->arg.rw->rw_count; +}; + +typedef struct smb_name_args { + string soa_name; +} smb_name_args_t; + +#pragma D binding "1.5" translator +translator smb_name_args_t < smb_request_t *P > { + soa_name = (P->arg.dirop.fqi.fq_path.pn_path == NULL) ? "<NULL>" : + P->arg.dirop.fqi.fq_path.pn_path; +}; + +typedef struct smb_open_args { + string soa_name; + uint32_t soa_desired_access; + uint32_t soa_share_access; + uint32_t soa_create_options; + uint32_t soa_create_disposition; +} smb_open_args_t; + +#pragma D binding "1.5" translator +translator smb_open_args_t < smb_request_t *P > { + soa_name = (P->arg.open.fqi.fq_path.pn_path == NULL) ? "<NULL>" : + P->arg.open.fqi.fq_path.pn_path; + soa_desired_access = P->arg.open.desired_access; + soa_share_access = P->arg.open.share_access; + soa_create_options = P->arg.open.create_options; + soa_create_disposition = P->arg.open.create_disposition; +}; + +/* + * The smb2opinfo_t structure describes the internal form of a + * single SMB2 request (SMB v2 and later). + */ +typedef struct smb2opinfo { + cred_t *soi_cred; /* credentials for operation */ + string soi_share; /* share name */ + string soi_curpath; /* file handle path (if any) */ + uint64_t soi_sid; /* (internal) session ID */ + uint64_t soi_mid; /* Message ID */ + uint64_t soi_asyncid; /* Message ID (when async) */ + uint64_t soi_uid; /* user ID (SMB2 Session ID) */ + uint32_t soi_tid; /* tree ID */ + uint32_t soi_status; + uint32_t soi_flags; +} smb2opinfo_t; + +#pragma D binding "1.5" translator +translator smb2opinfo_t < struct smb_request *P > { + soi_cred = (cred_t *)P->user_cr; + soi_sid = P->session->s_kid; + soi_mid = P->smb2_messageid; + soi_asyncid = P->smb2_async_id; + soi_uid = P->smb2_ssnid; + soi_tid = P->smb_tid; + soi_status = P->smb2_status; + soi_flags = P->smb2_hdr_flags; + + soi_share = (P->tid_tree == NULL) ? "<NULL>" : + P->tid_tree->t_sharename; + + soi_curpath = (P->fid_ofile == NULL || + P->fid_ofile->f_node == NULL || + P->fid_ofile->f_node->vp == NULL || + P->fid_ofile->f_node->vp->v_path == NULL) ? "<NULL>" : + P->fid_ofile->f_node->vp->v_path; +}; diff --git a/usr/src/lib/smbsrv/libfksmbsrv/Makefile b/usr/src/lib/smbsrv/libfksmbsrv/Makefile index c1d45118f3..b04b794e4a 100644 --- a/usr/src/lib/smbsrv/libfksmbsrv/Makefile +++ b/usr/src/lib/smbsrv/libfksmbsrv/Makefile @@ -22,7 +22,13 @@ # Copyright 2007 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# Copyright 2013 Nexenta Systems, Inc. All rights reserved. +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. # include ../Makefile.smbsrv + +CLOBBERFILES += common/fksmb_dt.h +all: install_h +install_h: common/fksmb_dt.h +common/fksmb_dt.h : common/fksmb_dt.d + $(DTRACE) -xnolibs -h -o $@ -s common/fksmb_dt.d diff --git a/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com b/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com index 52acd7c10f..6809bde3c3 100644 --- a/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com +++ b/usr/src/lib/smbsrv/libfksmbsrv/Makefile.com @@ -31,7 +31,6 @@ VERS = .1 OBJS_LOCAL = \ fksmb_cred.o \ - fksmb_dt.o \ fksmb_fem.o \ fksmb_idmap.o \ fksmb_init.o \ @@ -178,6 +177,11 @@ OBJS_MISC = \ smb_status2winerr.o \ xattr_common.o +# This one can't be in OBJECTS, as it has to depend on +# all of those for the COMPILE.d rule (which processes +# all those objects collecting probe instances). +DTRACE_OBJS = fksmb_dt.o + OBJECTS = \ $(OBJS_LOCAL) \ $(OBJS_FS_SMBSRV) \ @@ -233,10 +237,6 @@ pics/acl_common.o: $(SRC)/common/acl/acl_common.c $(COMPILE.c) -o $@ $(SRC)/common/acl/acl_common.c $(POST_PROCESS_O) -pics/smb_status2winerr.o: $(SRC)/common/smbclnt/smb_status2winerr.c - $(COMPILE.c) -o $@ $(SRC)/common/smbclnt/smb_status2winerr.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) @@ -245,6 +245,10 @@ pics/refstr.o: $(SRC)/uts/common/os/refstr.c $(COMPILE.c) -o $@ $(SRC)/uts/common/os/refstr.c $(POST_PROCESS_O) +pics/smb_status2winerr.o: $(SRC)/common/smbclnt/smb_status2winerr.c + $(COMPILE.c) -o $@ $(SRC)/common/smbclnt/smb_status2winerr.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) @@ -255,3 +259,12 @@ pics/xattr_common.o: $(SRC)/common/xattr/xattr_common.c include ../../Makefile.targ include ../../../Makefile.targ + +EXTPICS= $(DTRACE_OBJS:%=pics/%) +CLEANFILES += $(EXTPICS) + +$(OBJS) $(PICS) : ../common/fksmb_dt.h + +pics/fksmb_dt.o: ../common/fksmb_dt.d $(PICS) + $(COMPILE.d) -C -s ../common/fksmb_dt.d -o $@ $(PICS) + $(POST_PROCESS_O) diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_dt.c b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_dt.c deleted file mode 100644 index e9f03d4c06..0000000000 --- a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_dt.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * 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. - */ - -#include <smbsrv/smb_kproto.h> - -/* - * See: DTRACE_PROBE... in smb_kproto.h - */ - -int fksmbd_dtrace_log = 0; - -void -smb_dtrace1(const char *f, const char *n, - const char *t1, long v1) -{ - if (fksmbd_dtrace_log) { - cmn_err(CE_CONT, "dtrace1:%s:%s," - " (%s) 0x%lx\n", - f, n, t1, v1); - } -} - -void -smb_dtrace2(const char *f, const char *n, - const char *t1, long v1, - const char *t2, long v2) -{ - if (fksmbd_dtrace_log) { - cmn_err(CE_CONT, "dtrace2:%s:%s," - " (%s) 0x%lx, (%s) 0x%lx\n", - f, n, t1, v1, t2, v2); - } -} - -void -smb_dtrace3(const char *f, const char *n, - const char *t1, long v1, - const char *t2, long v2, - const char *t3, long v3) -{ - if (fksmbd_dtrace_log) { - cmn_err(CE_CONT, "dtrace3:%s:%s," - " (%s) 0x%lx, (%s) 0x%lx, (%s) 0x%lx\n", - f, n, t1, v1, t2, v2, t3, v3); - } -} diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_dt.d b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_dt.d new file mode 100644 index 0000000000..019f0ca5fc --- /dev/null +++ b/usr/src/lib/smbsrv/libfksmbsrv/common/fksmb_dt.d @@ -0,0 +1,40 @@ +/* + * 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 (c) 2013 by Delphix. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * See: DTRACE_PROBE... in ./sys/sdt.h + */ + +provider fksmb { + /* generic probes */ + probe probe0(char *probename); + probe probe1(char *probename, unsigned long arg1); + probe probe2(char *probename, unsigned long arg1, unsigned long arg2); + probe probe3(char *probename, unsigned long arg1, unsigned long arg2, + unsigned long arg3); + /* smb provider probes */ + probe smb_start(char *probename, unsigned long arg1); + probe smb_done(char *probename, unsigned long arg1); + /* smb2 provider probes */ + probe smb2_start(char *probename, unsigned long arg1); + probe smb2_done(char *probename, unsigned long arg1); +}; + +#pragma D attributes Evolving/Evolving/ISA provider fksmb provider +#pragma D attributes Private/Private/Unknown provider fksmb module +#pragma D attributes Private/Private/Unknown provider fksmb function +#pragma D attributes Evolving/Evolving/ISA provider fksmb name +#pragma D attributes Evolving/Evolving/ISA provider fksmb args diff --git a/usr/src/lib/smbsrv/libfksmbsrv/common/sys/sdt.h b/usr/src/lib/smbsrv/libfksmbsrv/common/sys/sdt.h new file mode 100644 index 0000000000..58d4cd654e --- /dev/null +++ b/usr/src/lib/smbsrv/libfksmbsrv/common/sys/sdt.h @@ -0,0 +1,92 @@ +/* + * 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 (c) 2013 by Delphix. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +#ifndef _SYS_SDT_H +#define _SYS_SDT_H + +#include <sys/stdint.h> +#include <fksmb_dt.h> + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _KERNEL +#error "libfksmbsrv/common/sys/sdt.h in kernel?" +#endif + +/* + * DTrace SDT probes have different signatures in userland than they do in + * the kernel. This file is strictly for libfksmbsrv, where we compile the + * smbsrv kernel code for user space. In "fksmbd", we can use the probes + * defined for the (real, in-kernel) "smb" and "smb2" SDT provider by + * mapping them onto the USDT proviver defined in ../fksmb_dt.d + * + * An example of how to use these probes can be found in: + * $SRC/cmd/smbsrv/fksmbd/Watch-fksmb.d + */ + +/* + * Map "smb" provider probes. + */ + +#define DTRACE_SMB_START(name, type1, arg1) \ + FKSMB_SMB_START(#name, (unsigned long)arg1) +#define DTRACE_SMB_DONE(name, type1, arg1) \ + FKSMB_SMB_DONE(#name, (unsigned long)arg1) + +/* + * Map "smb2" provider probes. + */ + +#define DTRACE_SMB2_START(name, type1, arg1) \ + FKSMB_SMB2_START(#name, (unsigned long)arg1) +#define DTRACE_SMB2_DONE(name, type1, arg1) \ + FKSMB_SMB2_DONE(#name, (unsigned long)arg1) + +/* + * These are for the other (specialized) dtrace SDT probes sprinkled + * through the smbsrv code. These are less often used. + */ + +#define DTRACE_PROBE(name, type1, arg1) \ + FKSMB_PROBE0(#name) + +#define DTRACE_PROBE1(name, type1, arg1) \ + FKSMB_PROBE1(#name, (unsigned long)arg1) + +#define DTRACE_PROBE2(name, type1, arg1, type2, arg2) \ + FKSMB_PROBE2(#name, (unsigned long)arg1, (unsigned long)arg2) + +#define DTRACE_PROBE3(name, type1, arg1, type2, arg2, type3, arg3) \ + FKSMB_PROBE3(#name, (unsigned long)arg1, (unsigned long)arg2, \ + (unsigned long)arg3) + +#ifdef __cplusplus +} +#endif + +#endif /* _SYS_SDT_H */ diff --git a/usr/src/lib/smbsrv/libsmb/common/libsmb.h b/usr/src/lib/smbsrv/libsmb/common/libsmb.h index db6f6c6650..06c072e70f 100644 --- a/usr/src/lib/smbsrv/libsmb/common/libsmb.h +++ b/usr/src/lib/smbsrv/libsmb/common/libsmb.h @@ -32,6 +32,7 @@ extern "C" { #endif #include <sys/types.h> +#include <sys/inttypes.h> #include <sys/list.h> #include <sys/avl.h> #include <arpa/inet.h> diff --git a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers index aaa9d368b3..37b8272be4 100644 --- a/usr/src/lib/smbsrv/libsmb/common/mapfile-vers +++ b/usr/src/lib/smbsrv/libsmb/common/mapfile-vers @@ -270,7 +270,7 @@ SYMBOL_VERSION SUNWprivate { smb_lookup_name; smb_lookup_sid; smb_match_netlogon_seqnum; - smb_mbstos; + smb_mbstooem; smb_mbstowcs; smb_mbtowc; smb_msgbuf_base; @@ -309,6 +309,7 @@ SYMBOL_VERSION SUNWprivate { smb_nic_getnum; smb_nic_init; smb_notify_dc_changed; + smb_oemtombs; smb_priv_getbyname; smb_priv_getbyvalue; smb_priv_presentable_ids; @@ -376,7 +377,6 @@ SYMBOL_VERSION SUNWprivate { smb_smf_restart_service; smb_smf_scf_fini; smb_smf_scf_init; - smb_stombs; smb_strcasecmp; smb_string_decode; smb_string_encode; diff --git a/usr/src/man/man1/nm.1 b/usr/src/man/man1/nm.1 index 880e92ebf7..8e6b82a346 100644 --- a/usr/src/man/man1/nm.1 +++ b/usr/src/man/man1/nm.1 @@ -158,7 +158,7 @@ information. \fB\fB-i\fR\fR .ad .RS 13n -Display symbols in the existing symbol table order, do not sort the symbols. +Display symbols in the existing symbol table order; do not sort them. .RE .sp diff --git a/usr/src/pkg/manifests/developer-dtrace.mf b/usr/src/pkg/manifests/developer-dtrace.mf index cf98c41b84..9008243f46 100644 --- a/usr/src/pkg/manifests/developer-dtrace.mf +++ b/usr/src/pkg/manifests/developer-dtrace.mf @@ -200,6 +200,7 @@ file path=usr/lib/dtrace/regs.d mode=0444 file path=usr/lib/dtrace/sched.d mode=0444 file path=usr/lib/dtrace/scsi.d mode=0444 file path=usr/lib/dtrace/signal.d mode=0444 +file path=usr/lib/dtrace/smb.d mode=0444 file path=usr/lib/dtrace/srp.d mode=0444 file path=usr/lib/dtrace/sysevent.d mode=0444 file path=usr/lib/dtrace/tcp.d mode=0444 diff --git a/usr/src/pkg/manifests/service-file-system-smb.mf b/usr/src/pkg/manifests/service-file-system-smb.mf index 6a9242b816..9950a416e3 100644 --- a/usr/src/pkg/manifests/service-file-system-smb.mf +++ b/usr/src/pkg/manifests/service-file-system-smb.mf @@ -78,6 +78,8 @@ file path=usr/lib/mdb/kvm/$(ARCH64)/smbsrv.so group=sys mode=0555 file path=usr/lib/mdb/proc/libmlsvc.so group=sys mode=0555 file path=usr/lib/reparse/libreparse_smb.so.1 file path=usr/lib/security/pam_smb_passwd.so.1 +file path=usr/lib/smbsrv/dtrace/smb-trace.d mode=0555 +file path=usr/lib/smbsrv/dtrace/smb2-trace.d mode=0555 file path=usr/lib/smbsrv/dtrace/smbd-all.d mode=0555 file path=usr/lib/smbsrv/dtrace/smbd-authsvc.d mode=0555 file path=usr/lib/smbsrv/dtrace/smbd-doorsvc.d mode=0555 diff --git a/usr/src/tools/quick/make-smbsrv b/usr/src/tools/quick/make-smbsrv index 45a6f2d178..9e2381288d 100755 --- a/usr/src/tools/quick/make-smbsrv +++ b/usr/src/tools/quick/make-smbsrv @@ -11,7 +11,7 @@ # # -# Copyright 2018 Nexenta Systems, Inc. All rights reserved. +# Copyright 2019 Nexenta Systems, Inc. All rights reserved. # # Use normal make (not dmake) by default. diff --git a/usr/src/uts/common/dtrace/sdt_subr.c b/usr/src/uts/common/dtrace/sdt_subr.c index 3d350ff278..a3e99544d2 100644 --- a/usr/src/uts/common/dtrace/sdt_subr.c +++ b/usr/src/uts/common/dtrace/sdt_subr.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2012, Joyent, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <sys/sdt_impl.h> @@ -97,6 +98,14 @@ static dtrace_pattr_t iscsi_attr = { { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA }, }; +static dtrace_pattr_t smb_attr = { +{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA }, +{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, +{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, +{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA }, +{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA }, +}; + /* * When adding a new provider you must add it before sdt as sdt is a catch all * for remaining probes. @@ -117,6 +126,8 @@ sdt_provider_t sdt_providers[] = { { "iscsi", "__iscsi_", &iscsi_attr }, { "nfsv3", "__nfsv3_", &stab_attr }, { "nfsv4", "__nfsv4_", &stab_attr }, + { "smb", "__smb_", &smb_attr }, + { "smb2", "__smb2_", &smb_attr }, { "xpv", "__xpv_", &xpv_attr }, { "fc", "__fc_", &fc_attr }, { "srp", "__srp_", &fc_attr }, @@ -880,6 +891,439 @@ sdt_argdesc_t sdt_args[] = { "nfsv4cbinfo_t *" }, { "nfsv4", "cb-recall-done", 2, 2, "CB_RECALL4res *" }, + /* Tables like this get really ugly when line-wrapped. */ + /* BEGIN CSTYLED */ + { "smb", "op-Close-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Close-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Close-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Close-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-CloseAndTreeDisconnect-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-CloseAndTreeDisconnect-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-CloseAndTreeDisconnect-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-CloseAndTreeDisconnect-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Transaction-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Transaction-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Transaction-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Transaction-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-TransactionSecondary-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-TransactionSecondary-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-TransactionSecondary-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-TransactionSecondary-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Ioctl-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Ioctl-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Ioctl-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Ioctl-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Transaction2-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Transaction2-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Transaction2-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Transaction2-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Transaction2Secondary-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Transaction2Secondary-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Transaction2Secondary-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Transaction2Secondary-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-NtTransact-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-NtTransact-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-NtTransact-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-NtTransact-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-NtTransactSecondary-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-NtTransactSecondary-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-NtTransactSecondary-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-NtTransactSecondary-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Create-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Create-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Create-start", 2, 0, "smb_request_t *", "smb_open_args_t *" }, + { "smb", "op-Create-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Create-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-CreateNew-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-CreateNew-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-CreateNew-start", 2, 0, "smb_request_t *", "smb_open_args_t *" }, + { "smb", "op-CreateNew-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-CreateNew-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-CreateTemporary-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-CreateTemporary-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-CreateTemporary-start", 2, 0, "smb_request_t *", "smb_open_args_t *" }, + { "smb", "op-CreateTemporary-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-CreateTemporary-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Delete-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Delete-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Delete-start", 2, 0, "smb_request_t *", "smb_name_args_t *" }, + { "smb", "op-Delete-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Delete-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-CreateDirectory-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-CreateDirectory-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-CreateDirectory-start", 2, 0, "smb_request_t *", "smb_name_args_t *" }, + { "smb", "op-CreateDirectory-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-CreateDirectory-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-DeleteDirectory-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-DeleteDirectory-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-DeleteDirectory-start", 2, 0, "smb_request_t *", "smb_name_args_t *" }, + { "smb", "op-DeleteDirectory-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-DeleteDirectory-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-CheckDirectory-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-CheckDirectory-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-CheckDirectory-start", 2, 0, "smb_request_t *", "smb_name_args_t *" }, + { "smb", "op-CheckDirectory-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-CheckDirectory-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Invalid-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Invalid-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Invalid-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Invalid-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Echo-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Echo-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Echo-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Echo-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Search-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Search-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Search-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Search-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Find-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Find-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Find-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Find-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-FindClose-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-FindClose-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-FindClose-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-FindClose-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-FindUnique-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-FindUnique-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-FindUnique-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-FindUnique-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Flush-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Flush-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Flush-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Flush-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-QueryInformationDisk-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-QueryInformationDisk-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-QueryInformationDisk-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-QueryInformationDisk-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-LockByteRange-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-LockByteRange-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-LockByteRange-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-LockByteRange-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-LockingX-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-LockingX-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-LockingX-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-LockingX-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-LogoffX-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-LogoffX-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-LogoffX-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-LogoffX-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Negotiate-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Negotiate-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Negotiate-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Negotiate-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-NtCancel-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-NtCancel-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-NtCancel-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-NtCancel-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-NtCreateX-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-NtCreateX-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-NtCreateX-start", 2, 0, "smb_request_t *", "smb_open_args_t *" }, + { "smb", "op-NtCreateX-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-NtCreateX-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-NtTransactCreate-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-NtTransactCreate-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-NtTransactCreate-start", 2, 0, "smb_request_t *", "smb_open_args_t *" }, + { "smb", "op-NtTransactCreate-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-NtTransactCreate-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Open-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Open-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Open-start", 2, 0, "smb_request_t *", "smb_open_args_t *" }, + { "smb", "op-Open-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Open-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-OpenX-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-OpenX-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-OpenX-start", 2, 0, "smb_request_t *", "smb_open_args_t *" }, + { "smb", "op-OpenX-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-OpenX-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-OpenPrintFile-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-OpenPrintFile-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-OpenPrintFile-start", 2, 0, "smb_request_t *", "smb_open_args_t *" }, + { "smb", "op-OpenPrintFile-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-OpenPrintFile-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-ClosePrintFile-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-ClosePrintFile-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-ClosePrintFile-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-ClosePrintFile-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-GetPrintQueue-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-GetPrintQueue-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-GetPrintQueue-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-GetPrintQueue-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-WritePrintFile-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-WritePrintFile-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-WritePrintFile-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-WritePrintFile-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-ProcessExit-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-ProcessExit-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-ProcessExit-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-ProcessExit-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-QueryInformation-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-QueryInformation-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-QueryInformation-start", 2, 0, "smb_request_t *", "smb_name_args_t *" }, + { "smb", "op-QueryInformation-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-QueryInformation-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-QueryInformation2-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-QueryInformation2-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-QueryInformation2-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-QueryInformation2-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Read-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Read-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Read-start", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + { "smb", "op-Read-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Read-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Read-done", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + + { "smb", "op-LockAndRead-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-LockAndRead-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-LockAndRead-start", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + { "smb", "op-LockAndRead-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-LockAndRead-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-LockAndRead-done", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + + { "smb", "op-ReadRaw-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-ReadRaw-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-ReadRaw-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-ReadRaw-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-ReadX-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-ReadX-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-ReadX-start", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + { "smb", "op-ReadX-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-ReadX-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-ReadX-done", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + + { "smb", "op-Rename-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Rename-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Rename-start", 2, 0, "smb_request_t *", "smb_name_args_t *" }, + { "smb", "op-Rename-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Rename-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-NtRename-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-NtRename-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-NtRename-start", 2, 0, "smb_request_t *", "smb_name_args_t *" }, + { "smb", "op-NtRename-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-NtRename-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Seek-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Seek-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Seek-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Seek-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-SessionSetupX-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-SessionSetupX-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-SessionSetupX-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-SessionSetupX-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-SetInformation-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-SetInformation-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-SetInformation-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-SetInformation-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-SetInformation2-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-SetInformation2-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-SetInformation2-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-SetInformation2-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-FindClose2-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-FindClose2-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-FindClose2-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-FindClose2-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-TreeConnect-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-TreeConnect-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-TreeConnect-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-TreeConnect-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-TreeConnectX-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-TreeConnectX-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-TreeConnectX-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-TreeConnectX-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-TreeDisconnect-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-TreeDisconnect-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-TreeDisconnect-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-TreeDisconnect-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-UnlockByteRange-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-UnlockByteRange-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-UnlockByteRange-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-UnlockByteRange-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-Write-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Write-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Write-start", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + { "smb", "op-Write-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-Write-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-Write-done", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + + { "smb", "op-WriteAndClose-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-WriteAndClose-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-WriteAndClose-start", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + { "smb", "op-WriteAndClose-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-WriteAndClose-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-WriteAndClose-done", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + + { "smb", "op-WriteAndUnlock-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-WriteAndUnlock-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-WriteAndUnlock-start", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + { "smb", "op-WriteAndUnlock-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-WriteAndUnlock-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-WriteAndUnlock-done", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + + { "smb", "op-WriteRaw-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-WriteRaw-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-WriteRaw-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-WriteRaw-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + + { "smb", "op-WriteX-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-WriteX-start", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-WriteX-start", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + { "smb", "op-WriteX-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb", "op-WriteX-done", 1, 0, "smb_request_t *", "smbopinfo_t *" }, + { "smb", "op-WriteX-done", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + + { "smb2", "op-Cancel-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Cancel-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-Cancel-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Cancel-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-ChangeNotify-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-ChangeNotify-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-ChangeNotify-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-ChangeNotify-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-Close-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Close-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-Close-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Close-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-Create-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Create-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-Create-start", 2, 0, "smb_request_t *", "smb_open_args_t *" }, + { "smb2", "op-Create-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Create-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-Echo-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Echo-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-Echo-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Echo-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-Flush-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Flush-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-Flush-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Flush-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-Ioctl-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Ioctl-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-Ioctl-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Ioctl-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-Lock-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Lock-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-Lock-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Lock-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-Logoff-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Logoff-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-Logoff-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Logoff-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-Negotiate-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Negotiate-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-Negotiate-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Negotiate-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-OplockBreak-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-OplockBreak-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-OplockBreak-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-OplockBreak-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-QueryDirectory-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-QueryDirectory-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-QueryDirectory-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-QueryDirectory-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-QueryInfo-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-QueryInfo-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-QueryInfo-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-QueryInfo-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-Read-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Read-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-Read-start", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + { "smb2", "op-Read-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Read-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-Read-done", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + + { "smb2", "op-SessionSetup-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-SessionSetup-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-SessionSetup-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-SessionSetup-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-SetInfo-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-SetInfo-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-SetInfo-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-SetInfo-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-TreeConnect-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-TreeConnect-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-TreeConnect-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-TreeConnect-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-TreeDisconnect-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-TreeDisconnect-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-TreeDisconnect-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-TreeDisconnect-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + + { "smb2", "op-Write-start", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Write-start", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-Write-start", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + { "smb2", "op-Write-done", 0, 0, "smb_request_t *", "conninfo_t *" }, + { "smb2", "op-Write-done", 1, 0, "smb_request_t *", "smb2opinfo_t *" }, + { "smb2", "op-Write-done", 2, 0, "smb_request_t *", "smb_rw_args_t *" }, + + /* END CSTYLED */ + { "ip", "send", 0, 0, "mblk_t *", "pktinfo_t *" }, { "ip", "send", 1, 1, "conn_t *", "csinfo_t *" }, { "ip", "send", 2, 2, "void_ip_t *", "ipinfo_t *" }, diff --git a/usr/src/uts/common/fs/smbsrv/smb2_cancel.c b/usr/src/uts/common/fs/smbsrv/smb2_cancel.c index 5b05640f49..1116a432f7 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_cancel.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_cancel.c @@ -42,11 +42,15 @@ smb2_newrq_cancel(smb_request_t *sr) if (sr->smb2_next_command != 0) return (EINVAL); + DTRACE_SMB2_START(op__Cancel, smb_request_t *, sr); + if (sr->smb2_hdr_flags & SMB2_FLAGS_ASYNC_COMMAND) smb2_cancel_async(sr); else smb2_cancel_sync(sr); + DTRACE_SMB2_DONE(op__Cancel, smb_request_t *, sr); + return (0); } @@ -65,12 +69,16 @@ smb2_cancel(smb_request_t *sr) if (sr->smb2_cmd_hdr != 0 || sr->smb2_next_command != 0) return (SDRC_DROP_VC); + DTRACE_SMB2_START(op__Cancel, smb_request_t *, sr); + if (sr->smb2_hdr_flags & SMB2_FLAGS_ASYNC_COMMAND) { smb2_cancel_async(sr); } else { smb2_cancel_sync(sr); } + DTRACE_SMB2_DONE(op__Cancel, smb_request_t *, sr); + return (SDRC_NO_REPLY); } diff --git a/usr/src/uts/common/fs/smbsrv/smb2_change_notify.c b/usr/src/uts/common/fs/smbsrv/smb2_change_notify.c index a7da4c6fcb..135d3b4d4e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_change_notify.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_change_notify.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. - * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -63,8 +63,10 @@ smb2_change_notify(smb_request_t *sr) return (SDRC_ERROR); status = smb2sr_lookup_fid(sr, &smb2fid); + DTRACE_SMB2_START(op__ChangeNotify, smb_request_t *, sr); + if (status != 0) - goto puterror; + goto errout; /* Bad FID */ CompletionFilter &= FILE_NOTIFY_VALID_MASK; if (iFlags & SMB2_WATCH_TREE) @@ -84,9 +86,13 @@ smb2_change_notify(smb_request_t *sr) status = smb2sr_go_async(sr, smb2_change_notify_async); } - if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_SUCCESS) { - sr->smb2_status = status; +errout: + sr->smb2_status = status; + if (status != NT_STATUS_PENDING) { + DTRACE_SMB2_DONE(op__ChangeNotify, smb_request_t *, sr); + } + if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_SUCCESS) { oBufLength = sr->raw_data.chain_offset; (void) smb_mbc_encodef( &sr->reply, "wwlC", @@ -95,7 +101,6 @@ smb2_change_notify(smb_request_t *sr) oBufLength, /* l */ &sr->raw_data); /* C */ } else { - puterror: smb2sr_put_error(sr, status); } @@ -144,9 +149,11 @@ smb2_change_notify_finish(void *arg) * Common part of notify, puts data in sr->raw_data */ status = smb_notify_act3(sr); - if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_SUCCESS) { - sr->smb2_status = status; + sr->smb2_status = status; + DTRACE_SMB2_DONE(op__ChangeNotify, smb_request_t *, sr); + + if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_SUCCESS) { oBufLength = sr->raw_data.chain_offset; (void) smb_mbc_encodef( &sr->reply, "wwlC", diff --git a/usr/src/uts/common/fs/smbsrv/smb2_close.c b/usr/src/uts/common/fs/smbsrv/smb2_close.c index 449b47cf9f..e019a3c3da 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_close.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_close.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -46,13 +46,17 @@ smb2_close(smb_request_t *sr) if (StructSize != 24) return (SDRC_ERROR); + /* + * Want FID lookup before the start probe. + */ status = smb2sr_lookup_fid(sr, &smb2fid); - if (status) { - smb2sr_put_error(sr, status); - return (SDRC_SUCCESS); - } of = sr->fid_ofile; + DTRACE_SMB2_START(op__Close, smb_request_t *, sr); + + if (status) + goto errout; /* Bad FID */ + bzero(&attr, sizeof (attr)); if (Flags & SMB2_CLOSE_FLAG_POSTQUERY_ATTRIB) { attr.sa_mask = SMB_AT_ALL; @@ -69,6 +73,15 @@ smb2_close(smb_request_t *sr) smb_ofile_close(of, 0); +errout: + sr->smb2_status = status; + DTRACE_SMB2_DONE(op__Close, smb_request_t *, sr); + + if (status) { + smb2sr_put_error(sr, status); + return (SDRC_SUCCESS); + } + /* * SMB2 Close reply */ diff --git a/usr/src/uts/common/fs/smbsrv/smb2_create.c b/usr/src/uts/common/fs/smbsrv/smb2_create.c index 8e9801c151..fb8a7f8823 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_create.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_create.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -42,6 +42,7 @@ typedef struct smb2_create_ctx_elem { } smb2_create_ctx_elem_t; typedef struct smb2_create_ctx { + mbuf_chain_t cc_in_mbc; uint_t cc_in_flags; /* CCTX_... */ uint_t cc_out_flags; /* CCTX_... */ /* Elements we may see in the request. */ @@ -60,9 +61,9 @@ typedef struct smb2_create_ctx { } smb2_create_ctx_t; static uint32_t smb2_decode_create_ctx( - mbuf_chain_t *, smb2_create_ctx_t *); + smb_request_t *, smb2_create_ctx_t *); static uint32_t smb2_encode_create_ctx( - mbuf_chain_t *, smb2_create_ctx_t *); + smb_request_t *, smb2_create_ctx_t *); static int smb2_encode_create_ctx_elem( mbuf_chain_t *, smb2_create_ctx_elem_t *, uint32_t); static void smb2_free_create_ctx(smb2_create_ctx_t *); @@ -73,7 +74,6 @@ smb2_create(smb_request_t *sr) smb_attr_t *attr; smb2_create_ctx_elem_t *cce; smb2_create_ctx_t cctx; - mbuf_chain_t cc_mbc; smb_arg_open_t *op = &sr->arg.open; smb_ofile_t *of = NULL; uint16_t StructSize; @@ -92,7 +92,7 @@ smb2_create(smb_request_t *sr) int rc = 0; bzero(&cctx, sizeof (cctx)); - bzero(&cc_mbc, sizeof (cc_mbc)); + op->create_ctx = &cctx; /* for debugging */ /* * Paranoia. This will set sr->fid_ofile, so @@ -105,13 +105,20 @@ smb2_create(smb_request_t *sr) } /* - * SMB2 Create request + * Decode the SMB2 Create request + * + * Most decode errors return SDRC_ERROR, but + * for some we give a more specific error. + * + * In the "decode section" (starts here) any + * errors should either return SDRC_ERROR, or + * if any cleanup is needed, goto errout. */ rc = smb_mbc_decodef( &sr->smb_data, "wbblqqlllllwwll", &StructSize, /* w */ &SecurityFlags, /* b */ - &OplockLevel, /* b */ + &op->op_oplock_level, /* b */ &ImpersonationLevel, /* l */ &SmbCreateFlags, /* q */ &Reserved4, /* q */ @@ -133,15 +140,17 @@ smb2_create(smb_request_t *sr) */ skip = (NameOffset + sr->smb2_cmd_hdr) - sr->smb_data.chain_offset; - if (skip < 0) { - status = NT_STATUS_OBJECT_PATH_INVALID; - goto errout; - } + if (skip < 0) + return (SDRC_ERROR); if (skip > 0) (void) smb_mbc_decodef(&sr->smb_data, "#.", skip); /* * Get the path name + * + * Name too long is not technically a decode error, + * but it's very rare, so we'll just skip the + * dtrace probes for this error case. */ if (NameLength >= SMB_MAXPATHLEN) { status = NT_STATUS_OBJECT_PATH_INVALID; @@ -159,7 +168,55 @@ smb2_create(smb_request_t *sr) } op->fqi.fq_dnode = sr->tid_tree->t_snode; - switch (OplockLevel) { + /* + * If there is a "Create Context" payload, decode it. + * This may carry things like a security descriptor, + * extended attributes, etc. to be used in create. + * + * The create ctx buffer must start after the headers + * and file name, and must be 8-byte aligned. + */ + if (CreateCtxLength != 0) { + if ((CreateCtxOffset & 7) != 0 || + (CreateCtxOffset + sr->smb2_cmd_hdr) < + sr->smb_data.chain_offset) { + status = NT_STATUS_INVALID_PARAMETER; + goto errout; + } + + rc = MBC_SHADOW_CHAIN(&cctx.cc_in_mbc, &sr->smb_data, + sr->smb2_cmd_hdr + CreateCtxOffset, CreateCtxLength); + if (rc) { + status = NT_STATUS_INVALID_PARAMETER; + goto errout; + } + status = smb2_decode_create_ctx(sr, &cctx); + if (status) + goto errout; + } + + /* + * Everything is decoded into some internal form, so + * in this probe one can look at sr->arg.open etc. + * + * This marks the end of the "decode" section and the + * beginning of the "body" section. Any errors in + * this section should use: goto cmd_done (which is + * just before the dtrace "done" probe). + */ + DTRACE_SMB2_START(op__Create, smb_request_t *, sr); /* arg.open */ + + /* + * Process the incoming create contexts (already decoded), + * that need action before the open, starting with the + * Durable Handle ones, which may override others. + */ + + /* + * Validate the requested oplock level. + * Convert the SMB2 oplock level into SMB1 form. + */ + switch (op->op_oplock_level) { case SMB2_OPLOCK_LEVEL_NONE: op->op_oplock_level = SMB_OPLOCK_NONE; break; @@ -172,25 +229,36 @@ smb2_create(smb_request_t *sr) case SMB2_OPLOCK_LEVEL_BATCH: op->op_oplock_level = SMB_OPLOCK_BATCH; break; - case SMB2_OPLOCK_LEVEL_LEASE: + case SMB2_OPLOCK_LEVEL_LEASE: /* not yet */ + default: + /* Unknown SMB2 oplock level. */ status = NT_STATUS_INVALID_PARAMETER; - goto errout; + goto cmd_done; } op->op_oplock_levelII = B_TRUE; /* - * ImpersonationLevel (spec. says ignore) + * Only disk trees get oplocks or leases. + */ + if ((sr->tid_tree->t_res_type & STYPE_MASK) != STYPE_DISKTREE) { + op->op_oplock_level = SMB2_OPLOCK_LEVEL_NONE; + cctx.cc_in_flags &= ~CCTX_REQUEST_LEASE; + } + + if (cctx.cc_in_flags & CCTX_EA_BUFFER) { + status = NT_STATUS_EAS_NOT_SUPPORTED; + goto cmd_done; + } + + /* + * ImpersonationLevel (spec. says validate + ignore) * SmbCreateFlags (spec. says ignore) */ if ((op->create_options & FILE_DELETE_ON_CLOSE) && !(op->desired_access & DELETE)) { status = NT_STATUS_INVALID_PARAMETER; - goto errout; - } - if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) { - status = NT_STATUS_INVALID_PARAMETER; - goto errout; + goto cmd_done; } if (op->dattr & FILE_FLAG_WRITE_THROUGH) @@ -201,102 +269,20 @@ smb2_create(smb_request_t *sr) op->create_options |= FILE_OPEN_FOR_BACKUP_INTENT; if (op->create_options & FILE_OPEN_FOR_BACKUP_INTENT) sr->user_cr = smb_user_getprivcred(sr->uid_user); - - /* - * If there is a "Create Context" payload, decode it. - * This may carry things like a security descriptor, - * extended attributes, etc. to be used in create. - * - * The create ctx buffer must start after the headers - * and file name, and must be 8-byte aligned. - */ - if (CreateCtxLength != 0) { - if ((CreateCtxOffset & 7) != 0 || - (CreateCtxOffset + sr->smb2_cmd_hdr) < - sr->smb_data.chain_offset) { - status = NT_STATUS_INVALID_PARAMETER; - goto errout; - } - - rc = MBC_SHADOW_CHAIN(&cc_mbc, &sr->smb_data, - sr->smb2_cmd_hdr + CreateCtxOffset, CreateCtxLength); - if (rc) { - status = NT_STATUS_INVALID_PARAMETER; - goto errout; - } - status = smb2_decode_create_ctx(&cc_mbc, &cctx); - if (status) - goto errout; - - if (cctx.cc_in_flags & CCTX_EA_BUFFER) { - status = NT_STATUS_EAS_NOT_SUPPORTED; - goto errout; - } - - if (cctx.cc_in_flags & CCTX_SD_BUFFER) { - smb_sd_t sd; - cce = &cctx.cc_in_sec_desc; - status = smb_decode_sd( - &cce->cce_mbc, &sd); - if (status) - goto errout; - op->sd = kmem_alloc(sizeof (sd), KM_SLEEP); - *op->sd = sd; - } - - if (cctx.cc_in_flags & CCTX_ALLOCATION_SIZE) { - cce = &cctx.cc_in_alloc_size; - rc = smb_mbc_decodef(&cce->cce_mbc, "q", &op->dsize); - if (rc) { - status = NT_STATUS_INVALID_PARAMETER; - goto errout; - } - } - - /* - * Support for opening "Previous Versions". - * [MS-SMB2] 2.2.13.2.7 Data is an NT time. - */ - if (cctx.cc_in_flags & CCTX_TIMEWARP_TOKEN) { - uint64_t timewarp; - cce = &cctx.cc_in_time_warp; - status = smb_mbc_decodef(&cce->cce_mbc, - "q", &timewarp); - if (status) - goto errout; - smb_time_nt_to_unix(timewarp, &op->timewarp); - op->create_timewarp = B_TRUE; - } + if (op->create_disposition > FILE_MAXIMUM_DISPOSITION) { + status = NT_STATUS_INVALID_PARAMETER; + goto cmd_done; } /* * The real open call. Note: this gets attributes into * op->fqi.fq_fattr (SMB_AT_ALL). We need those below. + * When of != NULL, goto errout closes it. */ status = smb_common_open(sr); if (status != NT_STATUS_SUCCESS) - goto errout; - attr = &op->fqi.fq_fattr; - - /* - * Convert the negotiate Oplock level back into - * SMB2 encoding form. - */ - switch (op->op_oplock_level) { - default: - case SMB_OPLOCK_NONE: - OplockLevel = SMB2_OPLOCK_LEVEL_NONE; - break; - case SMB_OPLOCK_LEVEL_II: - OplockLevel = SMB2_OPLOCK_LEVEL_II; - break; - case SMB_OPLOCK_EXCLUSIVE: - OplockLevel = SMB2_OPLOCK_LEVEL_EXCLUSIVE; - break; - case SMB_OPLOCK_BATCH: - OplockLevel = SMB2_OPLOCK_LEVEL_BATCH; - break; - } + goto cmd_done; + of = sr->fid_ofile; /* * NB: after the above smb_common_open() success, @@ -307,7 +293,6 @@ smb2_create(smb_request_t *sr) * though it could later be something larger, * (16 bytes) similar to an NFSv4 open handle. */ - of = sr->fid_ofile; smb2fid.persistent = 0; smb2fid.temporal = sr->smb_fid; @@ -320,50 +305,25 @@ smb2_create(smb_request_t *sr) } /* - * Build the Create Context to return; first the - * per-element parts, then the aggregated buffer. - * - * No response for these: - * CCTX_EA_BUFFER - * CCTX_SD_BUFFER - * CCTX_ALLOCATION_SIZE - * CCTX_TIMEWARP_TOKEN - * - * We don't handle these yet. - * CCTX_DH_REQUEST - * CCTX_DH_RECONNECT - * CCTX_REQUEST_LEASE + * Process any outgoing create contexts that need work + * after the open succeeds. Encode happens later. */ if (cctx.cc_in_flags & CCTX_QUERY_MAX_ACCESS) { - cce = &cctx.cc_out_max_access; - uint32_t MaxAccess = 0; + op->maximum_access = 0; if (of->f_node != NULL) { - smb_fsop_eaccess(sr, of->f_cr, of->f_node, &MaxAccess); + smb_fsop_eaccess(sr, of->f_cr, of->f_node, + &op->maximum_access); } - MaxAccess |= of->f_granted_access; - cce->cce_len = 8; - cce->cce_mbc.max_bytes = 8; - (void) smb_mbc_encodef(&cce->cce_mbc, - "ll", 0, MaxAccess); + op->maximum_access |= of->f_granted_access; cctx.cc_out_flags |= CCTX_QUERY_MAX_ACCESS; } + if ((cctx.cc_in_flags & CCTX_QUERY_ON_DISK_ID) != 0 && of->f_node != NULL) { - cce = &cctx.cc_out_file_id; - fsid_t fsid; - - fsid = SMB_NODE_FSID(of->f_node); - - cce->cce_len = 32; - cce->cce_mbc.max_bytes = 32; - (void) smb_mbc_encodef( - &cce->cce_mbc, "qll.15.", - op->fileid, /* q */ - fsid.val[0], /* l */ - fsid.val[1]); /* l */ - /* reserved (16 bytes) .15. */ + op->op_fsid = SMB_NODE_FSID(of->f_node); cctx.cc_out_flags |= CCTX_QUERY_ON_DISK_ID; } + if ((cctx.cc_in_flags & CCTX_AAPL_EXT) != 0) { cce = &cctx.cc_out_aapl; /* @@ -382,16 +342,53 @@ smb2_create(smb_request_t *sr) } status = 0; } + + /* + * This marks the end of the "body" section and the + * beginning of the "encode" section. Any errors + * encoding the response should use: goto errout + */ +cmd_done: + /* Want status visible in the done probe. */ + sr->smb2_status = status; + DTRACE_SMB2_DONE(op__Create, smb_request_t *, sr); + if (status != NT_STATUS_SUCCESS) + goto errout; + + /* + * Encode all the create contexts to return. + */ if (cctx.cc_out_flags) { sr->raw_data.max_bytes = smb2_max_trans; - status = smb2_encode_create_ctx(&sr->raw_data, &cctx); + status = smb2_encode_create_ctx(sr, &cctx); if (status) goto errout; } /* - * SMB2 Create reply + * Convert the negotiated Oplock level back into + * SMB2 encoding form. + */ + switch (op->op_oplock_level) { + default: + case SMB_OPLOCK_NONE: + OplockLevel = SMB2_OPLOCK_LEVEL_NONE; + break; + case SMB_OPLOCK_LEVEL_II: + OplockLevel = SMB2_OPLOCK_LEVEL_II; + break; + case SMB_OPLOCK_EXCLUSIVE: + OplockLevel = SMB2_OPLOCK_LEVEL_EXCLUSIVE; + break; + case SMB_OPLOCK_BATCH: + OplockLevel = SMB2_OPLOCK_LEVEL_BATCH; + break; + } + + /* + * Encode the SMB2 Create reply */ + attr = &op->fqi.fq_fattr; rc = smb_mbc_encodef( &sr->reply, "wb.lTTTTqqllqqll", @@ -436,25 +433,33 @@ smb2_create(smb_request_t *sr) } else { (void) smb_mbc_encodef(&sr->reply, "."); } - return (SDRC_SUCCESS); -errout: - if (of != NULL) - smb_ofile_close(of, 0); + if (status != 0) { + errout: + if (of != NULL) + smb_ofile_close(of, 0); + smb2sr_put_error(sr, status); + } + if (op->sd != NULL) { + smb_sd_term(op->sd); + kmem_free(op->sd, sizeof (*op->sd)); + } if (cctx.cc_out_flags) smb2_free_create_ctx(&cctx); - smb2sr_put_error(sr, status); + return (SDRC_SUCCESS); } /* * Decode an SMB2 Create Context buffer into our internal form. - * No policy decisions about what's supported here, just decode. + * Avoid policy decisions about what's supported here, just decode. */ static uint32_t -smb2_decode_create_ctx(mbuf_chain_t *in_mbc, smb2_create_ctx_t *cc) +smb2_decode_create_ctx(smb_request_t *sr, smb2_create_ctx_t *cc) { + smb_arg_open_t *op = &sr->arg.open; smb2_create_ctx_elem_t *cce; + mbuf_chain_t *in_mbc = &cc->cc_in_mbc; mbuf_chain_t name_mbc; union { uint32_t i; @@ -469,6 +474,11 @@ smb2_decode_create_ctx(mbuf_chain_t *in_mbc, smb2_create_ctx_t *cc) int top_offset; int rc; + /* + * Any break from the loop below before we've decoded + * the entire create context means it was malformatted, + * so we should return INVALID_PARAMETER. + */ status = NT_STATUS_INVALID_PARAMETER; for (;;) { cce = NULL; @@ -559,18 +569,53 @@ smb2_decode_create_ctx(mbuf_chain_t *in_mbc, smb2_create_ctx_t *cc) break; } - if (cce != NULL && data_len != 0) { - if ((data_off & 7) != 0) - break; - if ((top_offset + data_off) < in_mbc->chain_offset) - break; - rc = MBC_SHADOW_CHAIN(&cce->cce_mbc, in_mbc, - top_offset + data_off, data_len); - if (rc) - break; - cce->cce_len = data_len; + if (cce == NULL || data_len == 0) + goto next_cc; + + if ((data_off & 7) != 0) + break; + if ((top_offset + data_off) < in_mbc->chain_offset) + break; + rc = MBC_SHADOW_CHAIN(&cce->cce_mbc, in_mbc, + top_offset + data_off, data_len); + if (rc) + break; + cce->cce_len = data_len; + + /* + * Additonal decoding for some create contexts. + */ + switch (cc_name.i) { + uint64_t nttime; + + case SMB2_CREATE_SD_BUFFER: /* ("SecD") */ + op->sd = kmem_alloc(sizeof (smb_sd_t), KM_SLEEP); + if (smb_decode_sd(&cce->cce_mbc, op->sd) != 0) + goto errout; + break; + + case SMB2_CREATE_ALLOCATION_SIZE: /* ("AISi") */ + rc = smb_mbc_decodef(&cce->cce_mbc, "q", &op->dsize); + if (rc != 0) + goto errout; + break; + + case SMB2_CREATE_TIMEWARP_TOKEN: /* ("TWrp") */ + /* + * Support for opening "Previous Versions". + * [MS-SMB2] 2.2.13.2.7 Data is an NT time. + */ + rc = smb_mbc_decodef(&cce->cce_mbc, + "q", &nttime); + if (rc != 0) + goto errout; + smb_time_nt_to_unix(nttime, &op->timewarp); + op->create_timewarp = B_TRUE; + break; + } + next_cc: if (next_off == 0) { /* Normal loop termination */ status = 0; @@ -586,22 +631,41 @@ smb2_decode_create_ctx(mbuf_chain_t *in_mbc, smb2_create_ctx_t *cc) in_mbc->chain_offset = top_offset + next_off; } +errout: return (status); } /* * Encode an SMB2 Create Context buffer from our internal form. + * + * Build the Create Context to return; first the + * per-element parts, then the aggregated buffer. + * + * No response for these: + * CCTX_EA_BUFFER + * CCTX_SD_BUFFER + * CCTX_ALLOCATION_SIZE + * CCTX_TIMEWARP_TOKEN + * + * Remember to add code sections to smb2_free_create_ctx() + * for each section here that encodes a context element. */ -/* ARGSUSED */ static uint32_t -smb2_encode_create_ctx(mbuf_chain_t *mbc, smb2_create_ctx_t *cc) +smb2_encode_create_ctx(smb_request_t *sr, smb2_create_ctx_t *cc) { + smb_arg_open_t *op = &sr->arg.open; smb2_create_ctx_elem_t *cce; + mbuf_chain_t *mbc = &sr->raw_data; int last_top = -1; int rc; if (cc->cc_out_flags & CCTX_QUERY_MAX_ACCESS) { cce = &cc->cc_out_max_access; + + cce->cce_mbc.max_bytes = cce->cce_len = 8; + (void) smb_mbc_encodef(&cce->cce_mbc, + "ll", 0, op->maximum_access); + last_top = mbc->chain_offset; rc = smb2_encode_create_ctx_elem(mbc, cce, SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQ); @@ -613,6 +677,15 @@ smb2_encode_create_ctx(mbuf_chain_t *mbc, smb2_create_ctx_t *cc) if (cc->cc_out_flags & CCTX_QUERY_ON_DISK_ID) { cce = &cc->cc_out_file_id; + + cce->cce_mbc.max_bytes = cce->cce_len = 32; + (void) smb_mbc_encodef( + &cce->cce_mbc, "qll.15.", + op->fileid, /* q */ + op->op_fsid.val[0], /* l */ + op->op_fsid.val[1]); /* l */ + /* reserved (16 bytes) .15. */ + last_top = mbc->chain_offset; rc = smb2_encode_create_ctx_elem(mbc, cce, SMB2_CREATE_QUERY_ON_DISK_ID); @@ -624,6 +697,8 @@ smb2_encode_create_ctx(mbuf_chain_t *mbc, smb2_create_ctx_t *cc) if (cc->cc_out_flags & CCTX_AAPL_EXT) { cce = &cc->cc_out_aapl; + /* cc_out_aapl already encoded */ + last_top = mbc->chain_offset; rc = smb2_encode_create_ctx_elem(mbc, cce, SMB2_CREATE_CTX_AAPL); @@ -641,7 +716,7 @@ smb2_encode_create_ctx(mbuf_chain_t *mbc, smb2_create_ctx_t *cc) static int smb2_encode_create_ctx_elem(mbuf_chain_t *out_mbc, - smb2_create_ctx_elem_t *cce, uint32_t id) + smb2_create_ctx_elem_t *cce, uint32_t id) { union { uint32_t i; @@ -658,7 +733,7 @@ smb2_encode_create_ctx_elem(mbuf_chain_t *out_mbc, * layout the data part as [name, payload] and * name is a fixed length, so this easy. * The final layout looks like this: - * a: this header (16 bytes) + * a: this header (16 bytes) * b: the name (4 bytes, 4 pad) * c: the payload (variable) * @@ -671,7 +746,7 @@ smb2_encode_create_ctx_elem(mbuf_chain_t *out_mbc, 4, /* NameLength w */ 0, /* Reserved w */ 24, /* DataOffset w */ - cce->cce_len); /* l */ + cce->cce_len); /* DataLen l */ if (rc) return (rc); diff --git a/usr/src/uts/common/fs/smbsrv/smb2_dispatch.c b/usr/src/uts/common/fs/smbsrv/smb2_dispatch.c index d70a271ca0..39161f7c30 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_dispatch.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_dispatch.c @@ -755,10 +755,17 @@ cmd_done: cmn_err(CE_NOTE, "handler for %u returned 0x%x", sr->smb2_cmd_code, rc); #endif - /* FALLTHROUGH */ + sr->smb2_status = NT_STATUS_INTERNAL_ERROR; + break; case SDRC_ERROR: + /* + * Many command handlers return SDRC_ERROR for any + * problems decoding the request, and don't bother + * setting smb2_status. For those cases, the best + * status return would be "invalid parameter". + */ if (sr->smb2_status == 0) - sr->smb2_status = NT_STATUS_INTERNAL_ERROR; + sr->smb2_status = NT_STATUS_INVALID_PARAMETER; break; case SDRC_DROP_VC: disconnect = B_TRUE; diff --git a/usr/src/uts/common/fs/smbsrv/smb2_echo.c b/usr/src/uts/common/fs/smbsrv/smb2_echo.c index f82a6cbeb4..88a0fbe542 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_echo.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_echo.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -38,6 +38,9 @@ smb2_echo(smb_request_t *sr) if (StructSize != 4) return (SDRC_ERROR); + DTRACE_SMB2_START(op__Echo, smb_request_t *, sr); + DTRACE_SMB2_DONE(op__Echo, smb_request_t *, sr); + /* * SMB2 Echo reply */ diff --git a/usr/src/uts/common/fs/smbsrv/smb2_flush.c b/usr/src/uts/common/fs/smbsrv/smb2_flush.c index 82263d5936..ae001c80e5 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_flush.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_flush.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. * Copyright 2016 Syneto S.R.L. All rights reserved. */ @@ -32,7 +32,7 @@ smb2_flush(smb_request_t *sr) int rc = 0; /* - * SMB2 Flush request + * Decode SMB2 Flush request */ rc = smb_mbc_decodef( &sr->smb_data, "wwlqq", @@ -41,19 +41,26 @@ smb2_flush(smb_request_t *sr) &reserved2, /* l */ &smb2fid.persistent, /* q */ &smb2fid.temporal); /* q */ - if (rc) - return (SDRC_ERROR); - if (StructSize != 24) + if (rc || StructSize != 24) return (SDRC_ERROR); + /* + * Want FID lookup before the start probe. + */ status = smb2sr_lookup_fid(sr, &smb2fid); + DTRACE_SMB2_START(op__Flush, smb_request_t *, sr); + + if (status == 0) + smb_ofile_flush(sr, sr->fid_ofile); + + sr->smb2_status = status; + DTRACE_SMB2_DONE(op__Flush, smb_request_t *, sr); + if (status) { smb2sr_put_error(sr, status); return (SDRC_SUCCESS); } - smb_ofile_flush(sr, sr->fid_ofile); - /* * SMB2 Flush reply */ diff --git a/usr/src/uts/common/fs/smbsrv/smb2_ioctl.c b/usr/src/uts/common/fs/smbsrv/smb2_ioctl.c index 4ed5cba79c..95bb5a68b9 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_ioctl.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_ioctl.c @@ -56,14 +56,15 @@ smb2_ioctl(smb_request_t *sr) uint32_t MaxInputResp; uint32_t OutputOffset; uint32_t Flags; - uint32_t status; + uint32_t status = 0; uint16_t StructSize; int rc = 0; + /* Todo: put fsctl in sr->arg.ioctl (visible in dtrace probes) */ bzero(&in_mbc, sizeof (in_mbc)); /* - * SMB2 Ioctl request + * Decode SMB2 Ioctl request */ rc = smb_mbc_decodef( &sr->smb_data, "w..lqqlllllll4.", @@ -83,11 +84,70 @@ smb2_ioctl(smb_request_t *sr) if (rc || StructSize != 57) return (SDRC_ERROR); + /* + * If there's an input buffer, setup a shadow. + */ + if (fsctl.InputCount) { + if (InputOffset < (SMB2_HDR_SIZE + 56)) + return (SDRC_ERROR); + if (fsctl.InputCount > smb2_max_trans) + return (SDRC_ERROR); + rc = MBC_SHADOW_CHAIN(&in_mbc, &sr->smb_data, + sr->smb2_cmd_hdr + InputOffset, fsctl.InputCount); + if (rc) { + return (SDRC_ERROR); + } + } + fsctl.in_mbc = &in_mbc; + + /* + * If output is possible, setup the output mbuf_chain + */ + if (fsctl.MaxOutputResp > smb2_max_trans) + fsctl.MaxOutputResp = smb2_max_trans; + sr->raw_data.max_bytes = fsctl.MaxOutputResp; + fsctl.out_mbc = &sr->raw_data; + + /* + * [MS-SMB2] 3.3.5.15 + * + * If the Flags field of the request is not SMB2_0_IOCTL_IS_FSCTL + * the server MUST fail the request with STATUS_NOT_SUPPORTED. + * + * If the CtlCode is any of (... see switch below...) and the + * value of FileId in the SMB2 Header of the request is not + * 0xFFFFFFFFFFFFFFFF, then the server MUST fail the request + * with STATUS_INVALID_PARAMETER. (Otherwise lookup the FID.) + */ if (Flags != SMB2_0_IOCTL_IS_FSCTL) { status = NT_STATUS_NOT_SUPPORTED; - goto errout; + } else switch (fsctl.CtlCode) { + case FSCTL_DFS_GET_REFERRALS: + case FSCTL_DFS_GET_REFERRALS_EX: + case FSCTL_QUERY_NETWORK_INTERFACE_INFO: + case FSCTL_VALIDATE_NEGOTIATE_INFO: + case FSCTL_PIPE_WAIT: + if (smb2fid.temporal != ~0LL || + smb2fid.persistent != ~0LL) { + status = NT_STATUS_INVALID_PARAMETER; + } + break; + default: + status = smb2sr_lookup_fid(sr, &smb2fid); + if (status != 0) { + status = NT_STATUS_FILE_CLOSED; + } + break; } + /* + * Keep FID lookup before the start probe. + */ + DTRACE_SMB2_START(op__Ioctl, smb_request_t *, sr); + + if (status) + goto errout; + for (te = smb2_ioc_tbl; te->te_code; te++) { if (te->te_code == fsctl.CtlCode) break; @@ -111,22 +171,6 @@ smb2_ioctl(smb_request_t *sr) } /* - * Note: some ioctl commands don't need a FID. - */ - if (te->te_flags & ITF_NO_FID) { - if (smb2fid.temporal != ~0LL) { - status = NT_STATUS_INVALID_PARAMETER; - goto errout; - } - } else { - status = smb2sr_lookup_fid(sr, &smb2fid); - if (status) { - status = NT_STATUS_FILE_CLOSED; - goto errout; - } - } - - /* * Note: some ioctls require a "disk" fid. */ if (te->te_flags & ITF_DISK_FID) { @@ -138,38 +182,20 @@ smb2_ioctl(smb_request_t *sr) } /* - * If there's an input buffer, setup a shadow. - */ - if (fsctl.InputCount) { - if (InputOffset < (SMB2_HDR_SIZE + 56)) { - status = NT_STATUS_INVALID_PARAMETER; - goto errout; - } - rc = MBC_SHADOW_CHAIN(&in_mbc, &sr->smb_data, - sr->smb2_cmd_hdr + InputOffset, fsctl.InputCount); - if (rc) { - status = NT_STATUS_INVALID_PARAMETER; - goto errout; - } - } - fsctl.in_mbc = &in_mbc; - - /* - * If output is possible, setup the output mbuf_chain - */ - if (fsctl.MaxOutputResp > smb2_max_trans) - fsctl.MaxOutputResp = smb2_max_trans; - sr->raw_data.max_bytes = fsctl.MaxOutputResp; - fsctl.out_mbc = &sr->raw_data; - - /* * Dispatch to the handler for CtlCode */ status = (te->te_func)(sr, &fsctl); + +errout: + sr->smb2_status = status; + DTRACE_SMB2_DONE(op__Ioctl, smb_request_t *, sr); + if (status != 0) { - sr->smb2_status = status; - if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR) - goto errout; + if (NT_SC_SEVERITY(status) == NT_STATUS_SEVERITY_ERROR) { + /* no error data */ + smb2sr_put_error(sr, status); + return (SDRC_SUCCESS); + } /* Warnings like NT_STATUS_BUFFER_OVERFLOW are OK. */ } @@ -180,7 +206,7 @@ smb2_ioctl(smb_request_t *sr) OutputOffset = (fsctl.OutputCount) ? InputOffset : 0; /* - * SMB2 Ioctl reply + * Encode SMB2 Ioctl reply */ StructSize = 49; rc = smb_mbc_encodef( @@ -198,10 +224,9 @@ smb2_ioctl(smb_request_t *sr) /* reserved2 4. */ fsctl.OutputCount, /* # */ &sr->raw_data); /* C */ - return ((rc) ? SDRC_ERROR : SDRC_SUCCESS); + if (rc) + sr->smb2_status = NT_STATUS_INTERNAL_ERROR; -errout: - smb2sr_put_error(sr, status); return (SDRC_SUCCESS); } diff --git a/usr/src/uts/common/fs/smbsrv/smb2_lock.c b/usr/src/uts/common/fs/smbsrv/smb2_lock.c index 2ec3ee0016..91f57dade9 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_lock.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_lock.c @@ -49,7 +49,7 @@ smb2_lock(smb_request_t *sr) int rc; /* - * SMB2 Lock request + * Decode SMB2 Lock request */ rc = smb_mbc_decodef( &sr->smb_data, "wwlqq", @@ -61,9 +61,14 @@ smb2_lock(smb_request_t *sr) if (rc || StructSize != 48) return (SDRC_ERROR); + /* + * Want FID lookup before the start probe. + */ status = smb2sr_lookup_fid(sr, &smb2fid); + DTRACE_SMB2_START(op__Lock, smb_request_t *, sr); + if (status) - goto errout; + goto errout; /* Bad FID */ if (sr->fid_ofile->f_node == NULL || LockCount == 0) { status = NT_STATUS_INVALID_PARAMETER; goto errout; @@ -107,21 +112,26 @@ smb2_lock(smb_request_t *sr) } else { status = smb2_locks(sr); } - if (status) - goto errout; + +errout: + sr->smb2_status = status; + if (status != NT_STATUS_PENDING) { + DTRACE_SMB2_DONE(op__Lock, smb_request_t *, sr); + } + + if (status) { + smb2sr_put_error(sr, status); + return (SDRC_SUCCESS); + } /* - * SMB2 Lock reply (sync) + * Encode SMB2 Lock reply (sync) */ (void) smb_mbc_encodef( &sr->reply, "w..", 4); /* StructSize w */ /* reserved .. */ return (SDRC_SUCCESS); - -errout: - smb2sr_put_error(sr, status); - return (SDRC_SUCCESS); } /* @@ -264,8 +274,15 @@ smb2_lock_async(smb_request_t *sr) status = smb_lock_range(sr, lk->Offset, lk->Length, pid, ltype, timeout); - if (status != 0) - goto errout; + +errout: + sr->smb2_status = status; + DTRACE_SMB2_DONE(op__Lock, smb_request_t *, sr); + + if (status != 0) { + smb2sr_put_error(sr, status); + return (SDRC_SUCCESS); + } /* * SMB2 Lock reply (async) @@ -275,8 +292,4 @@ smb2_lock_async(smb_request_t *sr) 4); /* StructSize w */ /* reserved .. */ return (SDRC_SUCCESS); - -errout: - smb2sr_put_error(sr, status); - return (SDRC_SUCCESS); } diff --git a/usr/src/uts/common/fs/smbsrv/smb2_logoff.c b/usr/src/uts/common/fs/smbsrv/smb2_logoff.c index 6b6f532897..772c8f6e46 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_logoff.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_logoff.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -40,8 +40,13 @@ smb2_logoff(smb_request_t *sr) if (sr->uid_user == NULL) return (SDRC_ERROR); + + DTRACE_SMB2_START(op__Logoff, smb_request_t *, sr); + smb_user_logoff(sr->uid_user); + DTRACE_SMB2_DONE(op__Logoff, smb_request_t *, sr); + /* * SMB2 Logoff reply */ diff --git a/usr/src/uts/common/fs/smbsrv/smb2_negotiate.c b/usr/src/uts/common/fs/smbsrv/smb2_negotiate.c index b5f418982e..a0f9b33cc1 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_negotiate.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_negotiate.c @@ -159,9 +159,14 @@ smb1_negotiate_smb2(smb_request_t *sr) sr->smb2_cmd_code = SMB2_NEGOTIATE; rc = smb2_negotiate_common(sr, smb2_version); + smb2_send_reply(sr); if (rc != 0) return (SDRC_DROP_VC); + /* + * We sent the reply, so tell the SMB1 dispatch + * it should NOT (also) send a reply. + */ return (SDRC_NO_REPLY); } @@ -178,6 +183,9 @@ smb1_negotiate_smb2(smb_request_t *sr) * result of bypassing the normal dispatch mechanism. * * The caller always frees this request. + * + * Return value is 0 for success, and anything else will + * terminate the reader thread (drop the connection). */ int smb2_newrq_negotiate(smb_request_t *sr) @@ -196,7 +204,7 @@ smb2_newrq_negotiate(smb_request_t *sr) if ((sr->smb2_cmd_code != SMB2_NEGOTIATE) || (sr->smb2_next_command != 0)) - return (SDRC_DROP_VC); + return (-1); /* * Decode SMB2 Negotiate (fixed-size part) @@ -213,7 +221,7 @@ smb2_newrq_negotiate(smb_request_t *sr) if (rc != 0) return (rc); if (struct_size != 36 || version_cnt > 8) - return (SDRC_DROP_VC); + return (-1); /* * Decode SMB2 Negotiate (variable part) @@ -221,7 +229,9 @@ smb2_newrq_negotiate(smb_request_t *sr) rc = smb_mbc_decodef(&sr->command, "#w", version_cnt, cl_versions); if (rc != 0) - return (SDRC_DROP_VC); + return (rc); + + DTRACE_SMB2_START(op__Negotiate, smb_request_t *, sr); /* * The client offers an array of protocol versions it @@ -242,16 +252,23 @@ smb2_newrq_negotiate(smb_request_t *sr) s->newrq_func = smb2sr_newrq; rc = smb2_negotiate_common(sr, best_version); - if (rc != 0) - return (SDRC_DROP_VC); - return (0); + /* sr->smb2_status was set */ + DTRACE_SMB2_DONE(op__Negotiate, smb_request_t *, sr); + + smb2_send_reply(sr); + + return (rc); } /* * Common parts of SMB2 Negotiate, used for both the * SMB1-to-SMB2 style, and straight SMB2 style. - * Do negotiation decisions, encode, send the reply. + * Do negotiation decisions and encode the reply. + * The caller does the network send. + * + * Return value is 0 for success, and anything else will + * terminate the reader thread (drop the connection). */ static int smb2_negotiate_common(smb_request_t *sr, uint16_t version) @@ -304,7 +321,7 @@ smb2_negotiate_common(smb_request_t *sr, uint16_t version) (void) smb2_encode_header(sr, B_FALSE); if (sr->smb2_status != 0) { smb2sr_put_error(sr, sr->smb2_status); - smb2_send_reply(sr); + /* smb2_send_reply(sr); in caller */ return (-1); /* will drop */ } @@ -337,7 +354,7 @@ smb2_negotiate_common(smb_request_t *sr, uint16_t version) sr->sr_cfg->skc_negtok_len, /* # */ sr->sr_cfg->skc_negtok); /* c */ - smb2_send_reply(sr); + /* smb2_send_reply(sr); in caller */ (void) ksocket_setsockopt(s->sock, SOL_SOCKET, SO_SNDBUF, (const void *)&smb2_tcp_bufsize, diff --git a/usr/src/uts/common/fs/smbsrv/smb2_oplock.c b/usr/src/uts/common/fs/smbsrv/smb2_oplock.c index 9bfca57c05..ef7ad73d8f 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_oplock.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_oplock.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -48,6 +48,7 @@ smb2_oplock_break_ack(smb_request_t *sr) return (SDRC_ERROR); status = smb2sr_lookup_fid(sr, &smb2fid); + DTRACE_SMB2_START(op__OplockBreak, smb_request_t *, sr); if (status) goto errout; if ((node = sr->fid_ofile->f_node) == NULL) { @@ -81,6 +82,14 @@ smb2_oplock_break_ack(smb_request_t *sr) smb_oplock_ack(node, sr->fid_ofile, brk); +errout: + sr->smb2_status = status; + DTRACE_SMB2_DONE(op__OplockBreak, smb_request_t *, sr); + if (status) { + smb2sr_put_error(sr, status); + return (SDRC_SUCCESS); + } + /* * Generate SMB2 Oplock Break response * [MS-SMB2] 2.2.25 @@ -94,10 +103,6 @@ smb2_oplock_break_ack(smb_request_t *sr) smb2fid.persistent, /* q */ smb2fid.temporal); /* q */ return (SDRC_SUCCESS); - -errout: - smb2sr_put_error(sr, status); - return (SDRC_SUCCESS); } /* diff --git a/usr/src/uts/common/fs/smbsrv/smb2_query_dir.c b/usr/src/uts/common/fs/smbsrv/smb2_query_dir.c index 98f2dc4ad1..11f3515504 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_query_dir.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_query_dir.c @@ -22,7 +22,7 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -112,9 +112,12 @@ smb2_query_dir(smb_request_t *sr) return (SDRC_ERROR); status = smb2sr_lookup_fid(sr, &smb2fid); + of = sr->fid_ofile; + + DTRACE_SMB2_START(op__QueryDirectory, smb_request_t *, sr); + if (status) goto errout; - of = sr->fid_ofile; /* * If there's an input buffer (search pattern), decode it. @@ -250,24 +253,28 @@ smb2_query_dir(smb_request_t *sr) of->f_seek_pos = od->d_offset; - if (status == NT_STATUS_NO_MORE_FILES) { - if (args.fa_fflags & SMB2_QDIR_FLAG_SINGLE) { - status = NT_STATUS_NO_SUCH_FILE; - goto errout; - } - /* - * This is not an error, but a warning that can be - * used to tell the client that this data return - * is the last of the enumeration. Returning this - * warning now (with the data) saves the client a - * round trip that would otherwise be needed to - * find out it's at the end. - */ - sr->smb2_status = status; - status = 0; + if ((args.fa_fflags & SMB2_QDIR_FLAG_SINGLE) && + status == NT_STATUS_NO_MORE_FILES) { + status = NT_STATUS_NO_SUCH_FILE; + } + +errout: + sr->smb2_status = status; + DTRACE_SMB2_DONE(op__QueryDirectory, smb_request_t *, sr); + + /* + * Note: NT_STATUS_NO_MORE_FILES is a warning + * used to tell the client that this data return + * is the last of the enumeration. Returning this + * warning now (with the data) saves the client a + * round trip that would otherwise be needed to + * find out it's at the end. + */ + if (status != 0 && + status != NT_STATUS_NO_MORE_FILES) { + smb2sr_put_error(sr, status); + return (SDRC_SUCCESS); } - if (status) - goto errout; /* * SMB2 Query Directory reply @@ -283,12 +290,10 @@ smb2_query_dir(smb_request_t *sr) &sr->raw_data); /* C */ if (DataLen == 0) (void) smb_mbc_encodef(&sr->reply, "."); - if (rc == 0) - return (SDRC_SUCCESS); - status = NT_STATUS_UNSUCCESSFUL; -errout: - smb2sr_put_error(sr, status); + if (rc) + sr->smb2_status = NT_STATUS_INTERNAL_ERROR; + return (SDRC_SUCCESS); } diff --git a/usr/src/uts/common/fs/smbsrv/smb2_query_info.c b/usr/src/uts/common/fs/smbsrv/smb2_query_info.c index c39bce142c..dc59307fc3 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_query_info.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_query_info.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -32,10 +32,9 @@ smb2_query_info(smb_request_t *sr) smb2fid_t smb2fid; uint16_t DataOff; uint32_t status; - smb_sdrc_t sdrc = SDRC_SUCCESS; int rc = 0; - qi = kmem_zalloc(sizeof (*qi), KM_SLEEP); + qi = smb_srm_zalloc(sr, sizeof (*qi)); /* * SMB2 Query Info request @@ -53,19 +52,8 @@ smb2_query_info(smb_request_t *sr) &qi->qi_Flags, /* l */ &smb2fid.persistent, /* q */ &smb2fid.temporal); /* q */ - if (rc || StructSize != 41) { - sdrc = SDRC_ERROR; - goto out; - } - - status = smb2sr_lookup_fid(sr, &smb2fid); - if (status) { - smb2sr_put_error(sr, status); - goto out; - } - - if (oBufLength > smb2_max_trans) - oBufLength = smb2_max_trans; + if (rc || StructSize != 41) + return (SDRC_ERROR); /* * If there's an input buffer, setup a shadow. @@ -74,13 +62,20 @@ smb2_query_info(smb_request_t *sr) rc = MBC_SHADOW_CHAIN(&qi->in_data, &sr->smb_data, sr->smb2_cmd_hdr + iBufOffset, iBufLength); if (rc) { - smb2sr_put_error(sr, NT_STATUS_INVALID_PARAMETER); - goto out; + return (SDRC_ERROR); } } + if (oBufLength > smb2_max_trans) + oBufLength = smb2_max_trans; sr->raw_data.max_bytes = oBufLength; + status = smb2sr_lookup_fid(sr, &smb2fid); + DTRACE_SMB2_START(op__QueryInfo, smb_request_t *, sr); + + if (status) + goto errout; + switch (qi->qi_InfoType) { case SMB2_0_INFO_FILE: status = smb2_qinfo_file(sr, qi); @@ -99,6 +94,10 @@ smb2_query_info(smb_request_t *sr) break; } +errout: + sr->smb2_status = status; + DTRACE_SMB2_DONE(op__QueryInfo, smb_request_t *, sr); + switch (status) { case 0: /* success */ @@ -106,7 +105,6 @@ smb2_query_info(smb_request_t *sr) case NT_STATUS_BUFFER_OVERFLOW: /* Not really an error, per se. Advisory. */ - sr->smb2_status = status; break; case NT_STATUS_BUFFER_TOO_SMALL: @@ -119,11 +117,11 @@ smb2_query_info(smb_request_t *sr) * that returns one of these errors. */ smb2sr_put_error_data(sr, status, &sr->raw_data); - goto out; + return (SDRC_SUCCESS); default: smb2sr_put_error(sr, status); - goto out; + return (SDRC_SUCCESS); } /* @@ -138,10 +136,7 @@ smb2_query_info(smb_request_t *sr) oBufLength, /* l */ &sr->raw_data); /* C */ if (rc) - sdrc = SDRC_ERROR; - -out: - kmem_free(qi, sizeof (*qi)); + sr->smb2_status = NT_STATUS_INTERNAL_ERROR; - return (sdrc); + return (SDRC_SUCCESS); } diff --git a/usr/src/uts/common/fs/smbsrv/smb2_read.c b/usr/src/uts/common/fs/smbsrv/smb2_read.c index e269e71a1a..623a5b1141 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_read.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_read.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. + * Copyright 2019 Nexenta Systems, Inc. All rights reserved. */ /* @@ -23,6 +23,7 @@ smb_sdrc_t smb2_read(smb_request_t *sr) { + smb_rw_param_t *param = NULL; smb_ofile_t *of = NULL; smb_vdb_t *vdb = NULL; struct mbuf *m = NULL; @@ -63,22 +64,35 @@ smb2_read(smb_request_t *sr) if (StructSize != 49) return (SDRC_ERROR); + /* + * Setup an smb_rw_param_t which contains the VDB we need. + * This is automatically free'd. + */ + param = smb_srm_zalloc(sr, sizeof (*param)); + param->rw_offset = Offset; + param->rw_count = Length; + /* Note that the dtrace provider uses sr->arg.rw */ + sr->arg.rw = param; + + /* + * Want FID lookup before the start probe. + */ status = smb2sr_lookup_fid(sr, &smb2fid); - if (status) { - smb2sr_put_error(sr, status); - return (SDRC_SUCCESS); - } of = sr->fid_ofile; + DTRACE_SMB2_START(op__Read, smb_request_t *, sr); /* arg.rw */ + + if (status) + goto errout; /* Bad FID */ + if (Length > smb2_max_rwsize) { - smb2sr_put_error(sr, NT_STATUS_INVALID_PARAMETER); - return (SDRC_SUCCESS); + status = NT_STATUS_INVALID_PARAMETER; + goto errout; } if (MinCount > Length) MinCount = Length; - /* This is automatically free'd. */ - vdb = smb_srm_zalloc(sr, sizeof (*vdb)); + vdb = ¶m->rw_vdb; vdb->vdb_tag = 0; vdb->vdb_uio.uio_iov = &vdb->vdb_iovec[0]; vdb->vdb_uio.uio_iovcnt = MAX_IOVEC; @@ -111,6 +125,7 @@ smb2_read(smb_request_t *sr) rc = EACCES; break; } + status = smb_errno2status(rc); /* How much data we moved. */ XferCount = Length - vdb->vdb_uio.uio_resid; @@ -124,8 +139,11 @@ smb2_read(smb_request_t *sr) * the returned data so that if m was allocated, * it will be free'd via sr->raw_data cleanup. */ - if (rc) { - smb2sr_put_errno(sr, rc); +errout: + sr->smb2_status = status; + DTRACE_SMB2_DONE(op__Read, smb_request_t *, sr); /* arg.rw */ + if (status) { + smb2sr_put_error(sr, status); return (SDRC_SUCCESS); } @@ -142,8 +160,10 @@ smb2_read(smb_request_t *sr) 0, /* DataRemaining */ /* l */ 0, /* reserved */ /* l */ &sr->raw_data); /* C */ - if (rc) + if (rc) { + sr->smb2_status = NT_STATUS_INTERNAL_ERROR; return (SDRC_ERROR); + } mutex_enter(&of->f_mutex); of->f_seek_pos = Offset + XferCount; diff --git a/usr/src/uts/common/fs/smbsrv/smb2_session_setup.c b/usr/src/uts/common/fs/smbsrv/smb2_session_setup.c index b7d66cf6a3..ff064994de 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_session_setup.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_session_setup.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -81,6 +81,12 @@ smb2_session_setup(smb_request_t *sr) return (SDRC_ERROR); /* + * Decoded everything. Dtrace probe, + * then no more early returns. + */ + DTRACE_SMB2_START(op__SessionSetup, smb_request_t *, sr); + + /* * The real auth. work happens in here. */ status = smb_authenticate_ext(sr); @@ -114,6 +120,9 @@ smb2_session_setup(smb_request_t *sr) break; } + /* sr->smb2_status set above */ + DTRACE_SMB2_DONE(op__SessionSetup, smb_request_t *, sr); + /* * SMB2 Session Setup reply */ @@ -128,7 +137,7 @@ smb2_session_setup(smb_request_t *sr) SecBufLength, /* # */ sinfo->ssi_osecblob); /* c */ if (rc) - return (SDRC_ERROR); + sr->smb2_status = NT_STATUS_INTERNAL_ERROR; return (SDRC_SUCCESS); } diff --git a/usr/src/uts/common/fs/smbsrv/smb2_set_info.c b/usr/src/uts/common/fs/smbsrv/smb2_set_info.c index ba7c5eeaba..445a5335d7 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_set_info.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_set_info.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -32,13 +32,12 @@ smb2_set_info(smb_request_t *sr) smb2fid_t smb2fid; uint32_t status; uint8_t InfoType, InfoClass; - smb_sdrc_t sdrc = SDRC_SUCCESS; int rc = 0; bzero(&sinfo, sizeof (sinfo)); /* - * SMB2 Set Info request + * Decode SMB2 Set Info request */ rc = smb_mbc_decodef( &sr->smb_data, "wbblw..lqq", @@ -51,22 +50,8 @@ smb2_set_info(smb_request_t *sr) &AddlInfo, /* l */ &smb2fid.persistent, /* q */ &smb2fid.temporal); /* q */ - if (rc || StructSize != 33) { - sdrc = SDRC_ERROR; - return (sdrc); - } - - if (iBufLength > smb2_max_trans) { - status = NT_STATUS_INVALID_PARAMETER; - goto errout; - } - - status = smb2sr_lookup_fid(sr, &smb2fid); - if (status) - goto errout; - - sinfo.si_node = sr->fid_ofile->f_node; - sr->user_cr = sr->fid_ofile->f_cr; + if (rc || StructSize != 33) + return (SDRC_ERROR); /* * If there's an input buffer, setup a shadow. @@ -75,14 +60,27 @@ smb2_set_info(smb_request_t *sr) rc = MBC_SHADOW_CHAIN(&sinfo.si_data, &sr->smb_data, sr->smb2_cmd_hdr + iBufOffset, iBufLength); if (rc) { - status = NT_STATUS_INVALID_PARAMETER; - goto errout; + return (SDRC_ERROR); } } /* No output data. */ sr->raw_data.max_bytes = 0; + status = smb2sr_lookup_fid(sr, &smb2fid); + DTRACE_SMB2_START(op__SetInfo, smb_request_t *, sr); + + if (status) + goto errout; + + if (iBufLength > smb2_max_trans) { + status = NT_STATUS_INVALID_PARAMETER; + goto errout; + } + + sinfo.si_node = sr->fid_ofile->f_node; + sr->user_cr = sr->fid_ofile->f_cr; + switch (InfoType) { case SMB2_0_INFO_FILE: status = smb2_setinfo_file(sr, &sinfo, InfoClass); @@ -101,20 +99,21 @@ smb2_set_info(smb_request_t *sr) break; } +errout: + sr->smb2_status = status; + DTRACE_SMB2_DONE(op__SetInfo, smb_request_t *, sr); + if (status) { - errout: smb2sr_put_error(sr, status); - return (sdrc); + return (SDRC_SUCCESS); } /* * SMB2 Query Info reply */ - rc = smb_mbc_encodef( + (void) smb_mbc_encodef( &sr->reply, "w..", 2); /* StructSize */ /* w */ - if (rc) - sdrc = SDRC_ERROR; - return (sdrc); + return (SDRC_SUCCESS); } diff --git a/usr/src/uts/common/fs/smbsrv/smb2_tree_connect.c b/usr/src/uts/common/fs/smbsrv/smb2_tree_connect.c index 840742e40a..90a2c21466 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_tree_connect.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_tree_connect.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -66,7 +66,13 @@ smb2_tree_connect(smb_request_t *sr) if (rc) return (SDRC_ERROR); + DTRACE_SMB2_START(op__TreeConnect, smb_request_t *, sr); + status = smb_tree_connect(sr); + + sr->smb2_status = status; + DTRACE_SMB2_DONE(op__TreeConnect, smb_request_t *, sr); + if (status) { (void) smb2sr_put_error(sr, status); return (SDRC_SUCCESS); @@ -98,7 +104,7 @@ smb2_tree_connect(smb_request_t *sr) /* * SMB2 Tree Connect reply */ - rc = smb_mbc_encodef( + (void) smb_mbc_encodef( &sr->reply, "wb.lll", 16, /* StructSize */ /* w */ @@ -106,8 +112,6 @@ smb2_tree_connect(smb_request_t *sr) ShareFlags, /* l */ Capabilities, /* l */ tree->t_access); /* l */ - if (rc) - return (SDRC_ERROR); return (SDRC_SUCCESS); } diff --git a/usr/src/uts/common/fs/smbsrv/smb2_tree_disconn.c b/usr/src/uts/common/fs/smbsrv/smb2_tree_disconn.c index 6b9d38ee73..d343329044 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_tree_disconn.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_tree_disconn.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -38,12 +38,15 @@ smb2_tree_disconn(smb_request_t *sr) if (StructSize != 4) return (SDRC_ERROR); - if (sr->uid_user == NULL || sr->tid_tree == NULL) - return (SDRC_ERROR); + /* Dispatch makes sure we have uid_user, tid_tree */ + + DTRACE_SMB2_START(op__TreeDisconnect, smb_request_t *, sr); smb_tree_disconnect(sr->tid_tree, B_TRUE); smb_session_cancel_requests(sr->session, sr->tid_tree, sr); + DTRACE_SMB2_DONE(op__TreeDisconnect, smb_request_t *, sr); + /* * SMB2 Tree Disconnect reply */ diff --git a/usr/src/uts/common/fs/smbsrv/smb2_write.c b/usr/src/uts/common/fs/smbsrv/smb2_write.c index 6b1bd3b837..e2df00de5a 100644 --- a/usr/src/uts/common/fs/smbsrv/smb2_write.c +++ b/usr/src/uts/common/fs/smbsrv/smb2_write.c @@ -10,7 +10,7 @@ */ /* - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2019 Nexenta Systems, Inc. All rights reserved. */ /* @@ -23,6 +23,7 @@ smb_sdrc_t smb2_write(smb_request_t *sr) { + smb_rw_param_t *param = NULL; smb_ofile_t *of = NULL; smb_vdb_t *vdb = NULL; uint16_t StructSize; @@ -42,7 +43,7 @@ smb2_write(smb_request_t *sr) int rc = 0; /* - * SMB2 Write request + * Decode SMB2 Write request */ rc = smb_mbc_decodef( &sr->smb_data, @@ -63,43 +64,52 @@ smb2_write(smb_request_t *sr) if (StructSize != 49) return (SDRC_ERROR); - status = smb2sr_lookup_fid(sr, &smb2fid); - if (status) { - smb2sr_put_error(sr, status); - return (SDRC_SUCCESS); - } - of = sr->fid_ofile; - - if (Length > smb2_max_rwsize) { - smb2sr_put_error(sr, NT_STATUS_INVALID_PARAMETER); - return (SDRC_SUCCESS); - } + /* + * Setup an smb_rw_param_t which contains the VDB we need. + * This is automatically free'd. + */ + param = smb_srm_zalloc(sr, sizeof (*param)); + param->rw_offset = Offset; + param->rw_count = Length; + /* Note that the dtrace provider uses sr->arg.rw */ + sr->arg.rw = param; /* * Skip any padding before the write data. */ data_chain_off = sr->smb2_cmd_hdr + DataOff; skip = data_chain_off - sr->smb_data.chain_offset; - if (skip < 0) { - smb2sr_put_error(sr, NT_STATUS_INVALID_PARAMETER); - return (SDRC_SUCCESS); - } - if (skip > 0) { + if (skip < 0) + return (SDRC_ERROR); + if (skip > 0) (void) smb_mbc_decodef(&sr->smb_data, "#.", skip); - } - /* This is automatically free'd. */ - vdb = smb_srm_zalloc(sr, sizeof (*vdb)); + /* + * Decode the write data (payload) + */ + if (Length > smb2_max_rwsize) + return (SDRC_ERROR); + vdb = ¶m->rw_vdb; rc = smb_mbc_decodef(&sr->smb_data, "#B", Length, vdb); - if (rc != 0 || vdb->vdb_len != Length) { - smb2sr_put_error(sr, NT_STATUS_INVALID_PARAMETER); - return (SDRC_SUCCESS); - } + if (rc != 0 || vdb->vdb_len != Length) + return (SDRC_ERROR); vdb->vdb_uio.uio_loffset = (offset_t)Offset; + /* + * Want FID lookup before the start probe. + */ + status = smb2sr_lookup_fid(sr, &smb2fid); + of = sr->fid_ofile; + + DTRACE_SMB2_START(op__Write, smb_request_t *, sr); /* arg.rw */ + + if (status) + goto errout; /* Bad FID */ + + XferCount = 0; if (Length == 0) - goto doreply; + goto errout; switch (of->f_tree->t_res_type & STYPE_MASK) { case STYPE_DISKTREE: @@ -136,16 +146,20 @@ smb2_write(smb_request_t *sr) rc = EACCES; break; } + status = smb_errno2status(rc); - if (rc) { - smb2sr_put_errno(sr, rc); +errout: + sr->smb2_status = status; + DTRACE_SMB2_DONE(op__Write, smb_request_t *, sr); /* arg.rw */ + + if (status) { + smb2sr_put_error(sr, status); return (SDRC_SUCCESS); } /* - * SMB2 Write reply + * Encode SMB2 Write reply */ -doreply: DataOff = SMB2_HDR_SIZE + 16; rc = smb_mbc_encodef( &sr->reply, "wwlll", @@ -154,8 +168,10 @@ doreply: XferCount, /* l */ 0, /* DataRemaining */ /* l */ 0); /* Channel Info */ /* l */ - if (rc) + if (rc) { + sr->smb2_status = NT_STATUS_INTERNAL_ERROR; return (SDRC_ERROR); + } mutex_enter(&of->f_mutex); of->f_seek_pos = Offset + XferCount; diff --git a/usr/src/uts/common/fs/smbsrv/smb_close.c b/usr/src/uts/common/fs/smbsrv/smb_close.c index 6dfd2842ad..bd0a546bf1 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_close.c +++ b/usr/src/uts/common/fs/smbsrv/smb_close.c @@ -22,7 +22,7 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * - * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <smbsrv/smb_kproto.h> @@ -45,14 +45,14 @@ smb_pre_close(smb_request_t *sr) rc = smbsr_decode_vwv(sr, "wl", &sr->smb_fid, &sr->arg.timestamp); - DTRACE_SMB_1(op__Close__start, smb_request_t *, sr); + DTRACE_SMB_START(op__Close, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } void smb_post_close(smb_request_t *sr) { - DTRACE_SMB_1(op__Close__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__Close, smb_request_t *, sr); } smb_sdrc_t @@ -86,14 +86,14 @@ smb_pre_close_and_tree_disconnect(smb_request_t *sr) rc = smbsr_decode_vwv(sr, "wl", &sr->smb_fid, &sr->arg.timestamp); - DTRACE_SMB_1(op__CloseAndTreeDisconnect__start, smb_request_t *, sr); + DTRACE_SMB_START(op__CloseAndTreeDisconnect, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } void smb_post_close_and_tree_disconnect(smb_request_t *sr) { - DTRACE_SMB_1(op__CloseAndTreeDisconnect__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__CloseAndTreeDisconnect, smb_request_t *, sr); } smb_sdrc_t 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 6176a8b002..708ccf741e 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_common_transact.c +++ b/usr/src/uts/common/fs/smbsrv/smb_common_transact.c @@ -55,14 +55,14 @@ static smb_sdrc_t smb_trans2_dispatch(smb_request_t *, smb_xa_t *); smb_sdrc_t smb_pre_transaction(smb_request_t *sr) { - DTRACE_SMB_1(op__Transaction__start, smb_request_t *, sr); + DTRACE_SMB_START(op__Transaction, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_transaction(smb_request_t *sr) { - DTRACE_SMB_1(op__Transaction__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__Transaction, smb_request_t *, sr); } smb_sdrc_t @@ -156,14 +156,14 @@ smb_com_transaction(smb_request_t *sr) smb_sdrc_t smb_pre_transaction_secondary(smb_request_t *sr) { - DTRACE_SMB_1(op__TransactionSecondary__start, smb_request_t *, sr); + DTRACE_SMB_START(op__TransactionSecondary, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_transaction_secondary(smb_request_t *sr) { - DTRACE_SMB_1(op__TransactionSecondary__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__TransactionSecondary, smb_request_t *, sr); } smb_sdrc_t @@ -254,14 +254,14 @@ smb_com_transaction_secondary(smb_request_t *sr) smb_sdrc_t smb_pre_ioctl(smb_request_t *sr) { - DTRACE_SMB_1(op__Ioctl__start, smb_request_t *, sr); + DTRACE_SMB_START(op__Ioctl, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_ioctl(smb_request_t *sr) { - DTRACE_SMB_1(op__Ioctl__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__Ioctl, smb_request_t *, sr); } smb_sdrc_t @@ -285,14 +285,14 @@ smb_com_ioctl(smb_request_t *sr) smb_sdrc_t smb_pre_transaction2(smb_request_t *sr) { - DTRACE_SMB_1(op__Transaction2__start, smb_request_t *, sr); + DTRACE_SMB_START(op__Transaction2, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_transaction2(smb_request_t *sr) { - DTRACE_SMB_1(op__Transaction2__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__Transaction2, smb_request_t *, sr); } smb_sdrc_t @@ -368,14 +368,14 @@ smb_com_transaction2(struct smb_request *sr) smb_sdrc_t smb_pre_transaction2_secondary(smb_request_t *sr) { - DTRACE_SMB_1(op__Transaction2Secondary__start, smb_request_t *, sr); + DTRACE_SMB_START(op__Transaction2Secondary, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_transaction2_secondary(smb_request_t *sr) { - DTRACE_SMB_1(op__Transaction2Secondary__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__Transaction2Secondary, smb_request_t *, sr); } smb_sdrc_t @@ -558,14 +558,14 @@ smb_nt_trans_dispatch(struct smb_request *sr, struct smb_xa *xa) smb_sdrc_t smb_pre_nt_transact(smb_request_t *sr) { - DTRACE_SMB_1(op__NtTransact__start, smb_request_t *, sr); + DTRACE_SMB_START(op__NtTransact, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_nt_transact(smb_request_t *sr) { - DTRACE_SMB_1(op__NtTransact__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__NtTransact, smb_request_t *, sr); } smb_sdrc_t @@ -644,14 +644,14 @@ smb_com_nt_transact(struct smb_request *sr) smb_sdrc_t smb_pre_nt_transact_secondary(smb_request_t *sr) { - DTRACE_SMB_1(op__NtTransactSecondary__start, smb_request_t *, sr); + DTRACE_SMB_START(op__NtTransactSecondary, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_nt_transact_secondary(smb_request_t *sr) { - DTRACE_SMB_1(op__NtTransactSecondary__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__NtTransactSecondary, smb_request_t *, sr); } smb_sdrc_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_create.c b/usr/src/uts/common/fs/smbsrv/smb_create.c index f964ecfcff..a5a320e37b 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_create.c +++ b/usr/src/uts/common/fs/smbsrv/smb_create.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <smbsrv/smb_kproto.h> @@ -47,8 +47,7 @@ smb_pre_create(smb_request_t *sr) op->create_disposition = FILE_OVERWRITE_IF; op->create_options = FILE_NON_DIRECTORY_FILE; - DTRACE_SMB_2(op__Create__start, smb_request_t *, sr, - struct open_param *, op); + DTRACE_SMB_START(op__Create, smb_request_t *, sr); /* arg.open */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -56,7 +55,7 @@ smb_pre_create(smb_request_t *sr) void smb_post_create(smb_request_t *sr) { - DTRACE_SMB_1(op__Create__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__Create, smb_request_t *, sr); } smb_sdrc_t @@ -89,8 +88,7 @@ smb_pre_create_new(smb_request_t *sr) op->create_disposition = FILE_CREATE; - DTRACE_SMB_2(op__CreateNew__start, smb_request_t *, sr, - struct open_param *, op); + DTRACE_SMB_START(op__CreateNew, smb_request_t *, sr); /* arg.open */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -98,7 +96,7 @@ smb_pre_create_new(smb_request_t *sr) void smb_post_create_new(smb_request_t *sr) { - DTRACE_SMB_1(op__CreateNew__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__CreateNew, smb_request_t *, sr); } smb_sdrc_t @@ -132,8 +130,7 @@ smb_pre_create_temporary(smb_request_t *sr) op->create_disposition = FILE_CREATE; - DTRACE_SMB_2(op__CreateTemporary__start, smb_request_t *, sr, - struct open_param *, op); + DTRACE_SMB_START(op__CreateTemporary, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -141,7 +138,7 @@ smb_pre_create_temporary(smb_request_t *sr) void smb_post_create_temporary(smb_request_t *sr) { - DTRACE_SMB_1(op__CreateTemporary__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__CreateTemporary, smb_request_t *, sr); } smb_sdrc_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_delete.c b/usr/src/uts/common/fs/smbsrv/smb_delete.c index 3247ceb9c2..95c2063bca 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_delete.c +++ b/usr/src/uts/common/fs/smbsrv/smb_delete.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <sys/sunddi.h> @@ -104,7 +104,7 @@ smb_pre_delete(smb_request_t *sr) if ((rc = smbsr_decode_vwv(sr, "w", &fqi->fq_sattr)) == 0) rc = smbsr_decode_data(sr, "%S", sr, &fqi->fq_path.pn_path); - DTRACE_SMB_2(op__Delete__start, smb_request_t *, sr, smb_fqi_t *, fqi); + DTRACE_SMB_START(op__Delete, smb_request_t *, sr); /* arg.dirop */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -112,7 +112,7 @@ smb_pre_delete(smb_request_t *sr) void smb_post_delete(smb_request_t *sr) { - DTRACE_SMB_1(op__Delete__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__Delete, smb_request_t *, sr); } /* diff --git a/usr/src/uts/common/fs/smbsrv/smb_directory.c b/usr/src/uts/common/fs/smbsrv/smb_directory.c index 7f6bff1512..007f34fb45 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_directory.c +++ b/usr/src/uts/common/fs/smbsrv/smb_directory.c @@ -22,7 +22,7 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <smbsrv/smb_kproto.h> @@ -59,8 +59,7 @@ smb_pre_create_directory(smb_request_t *sr) rc = smbsr_decode_data(sr, "%S", sr, &sr->arg.dirop.fqi.fq_path.pn_path); - DTRACE_SMB_2(op__CreateDirectory__start, smb_request_t *, sr, - struct dirop *, &sr->arg.dirop); + DTRACE_SMB_START(op__CreateDirectory, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -68,7 +67,7 @@ smb_pre_create_directory(smb_request_t *sr) void smb_post_create_directory(smb_request_t *sr) { - DTRACE_SMB_1(op__CreateDirectory__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__CreateDirectory, smb_request_t *, sr); } smb_sdrc_t @@ -206,8 +205,7 @@ smb_pre_delete_directory(smb_request_t *sr) rc = smbsr_decode_data(sr, "%S", sr, &sr->arg.dirop.fqi.fq_path.pn_path); - DTRACE_SMB_2(op__DeleteDirectory__start, smb_request_t *, sr, - struct dirop *, &sr->arg.dirop); + DTRACE_SMB_START(op__DeleteDirectory, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -215,7 +213,7 @@ smb_pre_delete_directory(smb_request_t *sr) void smb_post_delete_directory(smb_request_t *sr) { - DTRACE_SMB_1(op__DeleteDirectory__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__DeleteDirectory, smb_request_t *, sr); } smb_sdrc_t @@ -361,8 +359,7 @@ smb_pre_check_directory(smb_request_t *sr) rc = smbsr_decode_data(sr, "%S", sr, &sr->arg.dirop.fqi.fq_path.pn_path); - DTRACE_SMB_2(op__CheckDirectory__start, smb_request_t *, sr, - struct dirop *, &sr->arg.dirop); + DTRACE_SMB_START(op__CheckDirectory, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -370,7 +367,7 @@ smb_pre_check_directory(smb_request_t *sr) void smb_post_check_directory(smb_request_t *sr) { - DTRACE_SMB_1(op__CheckDirectory__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__CheckDirectory, smb_request_t *, sr); } smb_sdrc_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c index 17458b4269..add4a009d9 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_dispatch.c +++ b/usr/src/uts/common/fs/smbsrv/smb_dispatch.c @@ -195,10 +195,12 @@ smb_disp_table[SMB_COM_NUM] = { { "Invalid", SMB_SDT_OPS(invalid), 0x17, 0 }, /* 0x17 023 */ { "Invalid", SMB_SDT_OPS(invalid), 0x18, 0 }, /* 0x18 024 */ { "Invalid", SMB_SDT_OPS(invalid), 0x19, 0 }, /* 0x19 025 */ - { "SmbReadRaw", SMB_SDT_OPS(invalid), 0x1A, 0 }, /* 0x1A 026 */ + { "SmbReadRaw", SMB_SDT_OPS(read_raw), /* 0x1A 026 */ + 0x1A, LANMAN1_0 }, { "Invalid", SMB_SDT_OPS(invalid), 0x1B, 0 }, /* 0x1B 027 */ { "Invalid", SMB_SDT_OPS(invalid), 0x1C, 0 }, /* 0x1C 028 */ - { "SmbWriteRaw", SMB_SDT_OPS(invalid), 0x1D, 0 }, /* 0x1D 029 */ + { "SmbWriteRaw", SMB_SDT_OPS(write_raw), /* 0x1D 029 */ + 0x1D, LANMAN1_0 }, { "Invalid", SMB_SDT_OPS(invalid), 0x1E, 0 }, /* 0x1E 030 */ { "Invalid", SMB_SDT_OPS(invalid), 0x1F, 0 }, /* 0x1F 031 */ { "Invalid", SMB_SDT_OPS(invalid), 0x20, 0 }, /* 0x20 032 */ @@ -834,9 +836,9 @@ andx_more: sr->sr_time_start = gethrtime(); if ((sdrc = (*sdd->sdt_pre_op)(sr)) == SDRC_SUCCESS) sdrc = (*sdd->sdt_function)(sr); + (*sdd->sdt_post_op)(sr); if (sdrc != SDRC_SR_KEPT) { - (*sdd->sdt_post_op)(sr); smbsr_cleanup(sr); } @@ -1229,14 +1231,14 @@ is_andx_com(unsigned char com) smb_sdrc_t smb_pre_invalid(smb_request_t *sr) { - DTRACE_SMB_1(op__Invalid__start, smb_request_t *, sr); + DTRACE_SMB_START(op__Invalid, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_invalid(smb_request_t *sr) { - DTRACE_SMB_1(op__Invalid__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__Invalid, smb_request_t *, sr); } smb_sdrc_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_echo.c b/usr/src/uts/common/fs/smbsrv/smb_echo.c index d9ffeb38de..019485a357 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_echo.c +++ b/usr/src/uts/common/fs/smbsrv/smb_echo.c @@ -22,7 +22,7 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <smbsrv/smb_kproto.h> @@ -39,14 +39,14 @@ smb_sdrc_t smb_pre_echo(smb_request_t *sr) { - DTRACE_SMB_1(op__Echo__start, smb_request_t *, sr); + DTRACE_SMB_START(op__Echo, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_echo(smb_request_t *sr) { - DTRACE_SMB_1(op__Echo__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__Echo, smb_request_t *, sr); } static unsigned short smb_max_echo = 10; diff --git a/usr/src/uts/common/fs/smbsrv/smb_find.c b/usr/src/uts/common/fs/smbsrv/smb_find.c index 23b9a5dc61..a8774f72e2 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_find.c +++ b/usr/src/uts/common/fs/smbsrv/smb_find.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <smbsrv/smb_kproto.h> @@ -203,14 +203,14 @@ static void smb_name83(const char *, char *, size_t); smb_sdrc_t smb_pre_search(smb_request_t *sr) { - DTRACE_SMB_1(op__Search__start, smb_request_t *, sr); + DTRACE_SMB_START(op__Search, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_search(smb_request_t *sr) { - DTRACE_SMB_1(op__Search__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__Search, smb_request_t *, sr); } smb_sdrc_t @@ -394,14 +394,14 @@ smb_com_search(smb_request_t *sr) smb_sdrc_t smb_pre_find(smb_request_t *sr) { - DTRACE_SMB_1(op__Find__start, smb_request_t *, sr); + DTRACE_SMB_START(op__Find, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_find(smb_request_t *sr) { - DTRACE_SMB_1(op__Find__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__Find, smb_request_t *, sr); } smb_sdrc_t @@ -547,14 +547,14 @@ smb_com_find(smb_request_t *sr) smb_sdrc_t smb_pre_find_close(smb_request_t *sr) { - DTRACE_SMB_1(op__FindClose__start, smb_request_t *, sr); + DTRACE_SMB_START(op__FindClose, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_find_close(smb_request_t *sr) { - DTRACE_SMB_1(op__FindClose__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__FindClose, smb_request_t *, sr); } smb_sdrc_t @@ -613,14 +613,14 @@ smb_com_find_close(smb_request_t *sr) smb_sdrc_t smb_pre_find_unique(smb_request_t *sr) { - DTRACE_SMB_1(op__FindUnique__start, smb_request_t *, sr); + DTRACE_SMB_START(op__FindUnique, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_find_unique(smb_request_t *sr) { - DTRACE_SMB_1(op__FindUnique__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__FindUnique, smb_request_t *, sr); } smb_sdrc_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_flush.c b/usr/src/uts/common/fs/smbsrv/smb_flush.c index 1d210c3d89..29532e6814 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_flush.c +++ b/usr/src/uts/common/fs/smbsrv/smb_flush.c @@ -23,6 +23,7 @@ * Use is subject to license terms. * * Copyright 2016 Syneto S.R.L. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -60,7 +61,7 @@ smb_pre_flush(smb_request_t *sr) rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid); - DTRACE_SMB_1(op__Flush__start, smb_request_t *, sr); + DTRACE_SMB_START(op__Flush, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -68,7 +69,7 @@ smb_pre_flush(smb_request_t *sr) void smb_post_flush(smb_request_t *sr) { - DTRACE_SMB_1(op__Flush__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__Flush, smb_request_t *, sr); } smb_sdrc_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_fsinfo.c b/usr/src/uts/common/fs/smbsrv/smb_fsinfo.c index e83a8a79c1..c3e70d9249 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_fsinfo.c +++ b/usr/src/uts/common/fs/smbsrv/smb_fsinfo.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <smbsrv/smb_kproto.h> @@ -54,14 +54,14 @@ static int smb_trans2_set_fs_ctrl_info(smb_request_t *, smb_xa_t *); smb_sdrc_t smb_pre_query_information_disk(smb_request_t *sr) { - DTRACE_SMB_1(op__QueryInformationDisk__start, smb_request_t *, sr); + DTRACE_SMB_START(op__QueryInformationDisk, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_query_information_disk(smb_request_t *sr) { - DTRACE_SMB_1(op__QueryInformationDisk__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__QueryInformationDisk, smb_request_t *, sr); } smb_sdrc_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_kutil.c b/usr/src/uts/common/fs/smbsrv/smb_kutil.c index e5ac75cbbc..5c74e4f8cd 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_kutil.c +++ b/usr/src/uts/common/fs/smbsrv/smb_kutil.c @@ -70,22 +70,36 @@ static const int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; +/* + * Given a UTF-8 string (our internal form everywhere) + * return either the Unicode (UTF-16) length in bytes, + * or the OEM length in bytes. Which we return is + * determined by whether the client supports Unicode. + * This length does NOT include the null. + */ int smb_ascii_or_unicode_strlen(struct smb_request *sr, char *str) { if (sr->session->dialect >= SMB_VERS_2_BASE || (sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0) return (smb_wcequiv_strlen(str)); - return (strlen(str)); + return (smb_sbequiv_strlen(str)); } +/* + * Given a UTF-8 string (our internal form everywhere) + * return either the Unicode (UTF-16) length in bytes, + * or the OEM length in bytes. Which we return is + * determined by whether the client supports Unicode. + * This length DOES include the null. + */ int smb_ascii_or_unicode_strlen_null(struct smb_request *sr, char *str) { if (sr->session->dialect >= SMB_VERS_2_BASE || (sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0) return (smb_wcequiv_strlen(str) + 2); - return (strlen(str) + 1); + return (smb_sbequiv_strlen(str) + 1); } int diff --git a/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c b/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c index 0c2c1bb2fb..cff227b0ef 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c +++ b/usr/src/uts/common/fs/smbsrv/smb_lock_byte_range.c @@ -22,7 +22,7 @@ * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * - * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* * SMB: lock_byte_range @@ -64,14 +64,14 @@ smb_sdrc_t smb_pre_lock_byte_range(smb_request_t *sr) { - DTRACE_SMB_1(op__LockByteRange__start, smb_request_t *, sr); + DTRACE_SMB_START(op__LockByteRange, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_lock_byte_range(smb_request_t *sr) { - DTRACE_SMB_1(op__LockByteRange__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__LockByteRange, smb_request_t *, sr); } /* diff --git a/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c b/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c index 11fd90a2b7..63db25f4b6 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_locking_andx.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -221,14 +221,14 @@ int smb_lock_max_elem = 1024; smb_sdrc_t smb_pre_locking_andx(smb_request_t *sr) { - DTRACE_SMB_1(op__LockingX__start, smb_request_t *, sr); + DTRACE_SMB_START(op__LockingX, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_locking_andx(smb_request_t *sr) { - DTRACE_SMB_1(op__LockingX__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__LockingX, smb_request_t *, sr); } struct lreq { diff --git a/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c b/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c index 6e9a00d975..4346de9e74 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_logoff_andx.c @@ -21,6 +21,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <smbsrv/smb_kproto.h> @@ -63,14 +65,14 @@ smb_sdrc_t smb_pre_logoff_andx(smb_request_t *sr) { - DTRACE_SMB_1(op__LogoffX__start, smb_request_t *, sr); + DTRACE_SMB_START(op__LogoffX, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_logoff_andx(smb_request_t *sr) { - DTRACE_SMB_1(op__LogoffX__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__LogoffX, smb_request_t *, sr); } smb_sdrc_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c b/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c index a3fa7f364f..f9b629b24f 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c +++ b/usr/src/uts/common/fs/smbsrv/smb_mbuf_marshaling.c @@ -22,7 +22,7 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. + * Copyright 2018 Nexenta Systems, Inc. All rights reserved. */ /* @@ -39,14 +39,13 @@ #define DECODE_ALLOCATION_ERROR 2 #define DECODE_CONVERSION_ERROR 3 -static int mbc_marshal_cstou8(char *, char *, size_t, char *, size_t); static int mbc_marshal_make_room(mbuf_chain_t *, int32_t); static void mbc_marshal_store_byte(mbuf_chain_t *, uint8_t); static int mbc_marshal_put_char(mbuf_chain_t *mbc, uint8_t); static int mbc_marshal_put_short(mbuf_chain_t *mbc, uint16_t); static int mbc_marshal_put_long(mbuf_chain_t *mbc, uint32_t); static int mbc_marshal_put_long_long(mbuf_chain_t *mbc, uint64_t); -static int mbc_marshal_put_ascii_string(mbuf_chain_t *, char *, int); +static int mbc_marshal_put_oem_string(mbuf_chain_t *, char *, int); static int mbc_marshal_put_unicode_string(mbuf_chain_t *, char *, int); static int mbc_marshal_put_uio(mbuf_chain_t *, struct uio *); static int mbc_marshal_put_mbufs(mbuf_chain_t *mbc, mbuf_t *m); @@ -58,10 +57,10 @@ static int mbc_marshal_get_long(mbuf_chain_t *mbc, uint32_t *data); static uint64_t qswap(uint64_t ll); static int mbc_marshal_get_odd_long_long(mbuf_chain_t *mbc, uint64_t *data); static int mbc_marshal_get_long_long(mbuf_chain_t *mbc, uint64_t *data); -static int mbc_marshal_get_ascii_string(smb_request_t *, mbuf_chain_t *, - uint8_t **ascii, int); +static int mbc_marshal_get_oem_string(smb_request_t *, mbuf_chain_t *, + char **, int); static int mbc_marshal_get_unicode_string(smb_request_t *, mbuf_chain_t *, - uint8_t **, int); + char **, int); static int mbc_marshal_get_mbufs(mbuf_chain_t *, int32_t, mbuf_t **); static int mbc_marshal_get_mbuf_chain(mbuf_chain_t *, int32_t, mbuf_chain_t *); static int mbc_marshal_get_uio(mbuf_chain_t *, struct uio *); @@ -152,7 +151,7 @@ smb_mbc_vdecodef(mbuf_chain_t *mbc, const char *fmt, va_list ap) uint8_t c; uint8_t cval; uint8_t *cvalp; - uint8_t **cvalpp; + char **charpp; uint16_t wval; uint16_t *wvalp; uint32_t *lvalp; @@ -294,7 +293,7 @@ smb_mbc_vdecodef(mbuf_chain_t *mbc, const char *fmt, va_list ap) return (-1); if (cval != 2) return (-1); - goto ascii_conversion; + goto oem_conversion; case 'A': case 'S': @@ -310,27 +309,25 @@ smb_mbc_vdecodef(mbuf_chain_t *mbc, const char *fmt, va_list ap) goto unicode_translation; /* FALLTHROUGH */ - case 's': -ascii_conversion: + case 's': /* get OEM string */ +oem_conversion: ASSERT(sr != NULL); - cvalpp = va_arg(ap, uint8_t **); + charpp = va_arg(ap, char **); if (!repc_specified) repc = 0; - if (mbc_marshal_get_ascii_string(sr, - mbc, cvalpp, repc) != 0) + if (mbc_marshal_get_oem_string(sr, + mbc, charpp, repc) != 0) return (-1); break; - case 'U': /* Convert from unicode */ + case 'U': /* get UTF-16 string */ unicode_translation: ASSERT(sr != 0); - cvalpp = va_arg(ap, uint8_t **); + charpp = va_arg(ap, char **); if (!repc_specified) repc = 0; - if (mbc->chain_offset & 1) - mbc->chain_offset++; if (mbc_marshal_get_unicode_string(sr, - mbc, cvalpp, repc) != 0) + mbc, charpp, repc) != 0) return (-1); break; @@ -519,6 +516,7 @@ smb_mbc_peek(mbuf_chain_t *mbc, int offset, const char *fmt, ...) int smb_mbc_vencodef(mbuf_chain_t *mbc, const char *fmt, va_list ap) { + char *charp; uint8_t *cvalp; timestruc_t *tvp; smb_vdb_t *vdp; @@ -549,7 +547,6 @@ smb_mbc_vencodef(mbuf_chain_t *mbc, const char *fmt, va_list ap) repc = va_arg(ap, int); c = *fmt++; repc_specified = B_TRUE; - } switch (c) { @@ -659,7 +656,7 @@ smb_mbc_vencodef(mbuf_chain_t *mbc, const char *fmt, va_list ap) case 'L': tag = 2; - goto ascii_conversion; + goto oem_conversion; case 'S': case 'A': @@ -680,12 +677,23 @@ smb_mbc_vencodef(mbuf_chain_t *mbc, const char *fmt, va_list ap) goto unicode_translation; /* FALLTHROUGH */ - case 's': /* ASCII/multibyte string */ -ascii_conversion: cvalp = va_arg(ap, uint8_t *); + case 's': /* put OEM string */ +oem_conversion: + charp = va_arg(ap, char *); + if (!repc_specified) + repc = 0; + if (mbc_marshal_put_oem_string(mbc, + charp, repc) != 0) + return (DECODE_NO_MORE_DATA); + break; + + case 'U': /* put UTF-16 string */ +unicode_translation: + charp = va_arg(ap, char *); if (!repc_specified) repc = 0; - if (mbc_marshal_put_ascii_string(mbc, - (char *)cvalp, repc) != 0) + if (mbc_marshal_put_unicode_string(mbc, + charp, repc) != 0) return (DECODE_NO_MORE_DATA); break; @@ -728,18 +736,6 @@ ascii_conversion: cvalp = va_arg(ap, uint8_t *); return (DECODE_NO_MORE_DATA); break; - case 'U': /* Convert to unicode, align to word boundary */ -unicode_translation: - if (mbc->chain_offset & 1) - mbc->chain_offset++; - cvalp = va_arg(ap, uint8_t *); - if (!repc_specified) - repc = 0; - if (mbc_marshal_put_unicode_string(mbc, - (char *)cvalp, repc) != 0) - return (DECODE_NO_MORE_DATA); - break; - default: ASSERT(0); return (-1); @@ -1068,79 +1064,149 @@ mbc_marshal_put_long_long(mbuf_chain_t *mbc, uint64_t data) } /* - * When need to convert from UTF-8 (internal format) to a single - * byte string (external format ) when marshalling a string. + * Marshal a UTF-8 string (str) into mbc, converting to OEM codeset. + * Also write a null unless the repc count limits the length we put. + * When (repc > 0) the length we marshal must be exactly repc, and + * truncate or pad the mbc data as necessary. + * See also: msgbuf_put_oem_string */ static int -mbc_marshal_put_ascii_string(mbuf_chain_t *mbc, char *mbs, int repc) +mbc_marshal_put_oem_string(mbuf_chain_t *mbc, char *mbs, int repc) { - smb_wchar_t wide_char; - int nbytes; - int length; + uint8_t *oembuf = NULL; + uint8_t *s; + int oemlen; + int rlen; + int rc; - if ((length = smb_sbequiv_strlen(mbs)) == -1) + /* + * Compute length of converted OEM string, + * NOT including null terminator + */ + if ((oemlen = smb_sbequiv_strlen(mbs)) == -1) return (DECODE_NO_MORE_DATA); - length += sizeof (char); - - if ((repc > 0) && (repc < length)) - length = repc; - if (mbc_marshal_make_room(mbc, length)) + /* + * If repc not specified, put whole string + NULL, + * otherwise will truncate or pad as needed. + */ + if (repc <= 0) + repc = oemlen + 1; + if (mbc_marshal_make_room(mbc, repc)) return (DECODE_NO_MORE_DATA); - while (*mbs) { - /* - * We should restore oem chars here. - */ - nbytes = smb_mbtowc(&wide_char, mbs, MTS_MB_CHAR_MAX); - if (nbytes == -1) - return (DECODE_NO_MORE_DATA); - - mbc_marshal_store_byte(mbc, (uint8_t)wide_char); - - if (wide_char & 0xFF00) - mbc_marshal_store_byte(mbc, wide_char >> 8); + /* + * Convert into a temporary buffer + * Free oembuf before return. + */ + oembuf = smb_mem_zalloc(oemlen + 1); + ASSERT(oembuf != NULL); + rlen = smb_mbstooem(oembuf, mbs, oemlen); + if (rlen < 0) { + rc = DECODE_NO_MORE_DATA; + goto out; + } + if (rlen > oemlen) + rlen = oemlen; + oembuf[rlen] = '\0'; - mbs += nbytes; + /* + * Copy the converted string into the message, + * truncated or paded as required. + */ + s = oembuf; + while (repc > 0) { + mbc_marshal_store_byte(mbc, *s); + if (*s != '\0') + s++; + repc--; } + rc = 0; - mbc_marshal_store_byte(mbc, 0); - return (0); +out: + if (oembuf != NULL) + smb_mem_free(oembuf); + return (rc); } +/* + * Marshal a UTF-8 string (str) into mbc, converting to UTF-16. + * Also write a null unless the repc count limits the length. + * When (repc > 0) the length we marshal must be exactly repc, + * and truncate or pad the mbc data as necessary. + * See also: msgbuf_put_unicode_string + */ static int -mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *ascii, int repc) +mbc_marshal_put_unicode_string(mbuf_chain_t *mbc, char *mbs, int repc) { - smb_wchar_t wchar; - int consumed; - int length; + smb_wchar_t *wcsbuf = NULL; + smb_wchar_t *wp; + size_t wcslen, wcsbytes; + size_t rlen; + int rc; + + /* align to word boundary */ + if (mbc->chain_offset & 1) { + if (mbc_marshal_make_room(mbc, 1)) + return (DECODE_NO_MORE_DATA); + mbc_marshal_store_byte(mbc, 0); + } - if ((length = smb_wcequiv_strlen(ascii)) == -1) + /* + * Compute length of converted UTF-16 string, + * NOT including null terminator (in bytes). + */ + wcsbytes = smb_wcequiv_strlen(mbs); + if (wcsbytes == (size_t)-1) return (DECODE_NO_MORE_DATA); - length += sizeof (smb_wchar_t); + /* + * If repc not specified, put whole string + NULL, + * otherwise will truncate or pad as needed. + */ + if (repc <= 0) + repc = wcsbytes + 2; + if (mbc_marshal_make_room(mbc, repc)) + return (DECODE_NO_MORE_DATA); - if ((repc > 0) && (repc < length)) - length = repc; + /* + * Convert into a temporary buffer + * Free wcsbuf before return. + */ + wcslen = wcsbytes / 2; + wcsbuf = smb_mem_zalloc(wcsbytes + 2); + ASSERT(wcsbuf != NULL); + rlen = smb_mbstowcs(wcsbuf, mbs, wcslen); + if (rlen == (size_t)-1) { + rc = DECODE_NO_MORE_DATA; + goto out; + } + if (rlen > wcslen) + rlen = wcslen; + wcsbuf[rlen] = 0; - if (mbc_marshal_make_room(mbc, length)) - return (DECODE_NO_MORE_DATA); - while (length > 0) { - consumed = smb_mbtowc(&wchar, ascii, MTS_MB_CHAR_MAX); - if (consumed == -1) - break; /* Invalid sequence */ - /* - * Note that consumed will be 0 when the null terminator - * is encountered and ascii will not be advanced beyond - * that point. Length will continue to be decremented so - * we won't get stuck here. - */ - ascii += consumed; + /* + * Copy the converted string into the message, + * truncated or paded as required. Preserve + * little-endian order while copying. + */ + wp = wcsbuf; + while (repc > 1) { + smb_wchar_t wchar = LE_IN16(wp); mbc_marshal_store_byte(mbc, wchar); mbc_marshal_store_byte(mbc, wchar >> 8); - length -= sizeof (smb_wchar_t); + if (wchar != 0) + wp++; + repc -= sizeof (smb_wchar_t); } - return (0); + if (repc > 0) + mbc_marshal_store_byte(mbc, 0); + + rc = 0; +out: + if (wcsbuf != NULL) + smb_mem_free(wcsbuf); + return (rc); } static int /*ARGSUSED*/ @@ -1375,101 +1441,159 @@ mbc_marshal_get_long_long(mbuf_chain_t *mbc, uint64_t *data) } /* - * mbc_marshal_get_ascii_string - * - * The ascii string in smb includes oem chars. Since the - * system needs utf8 encodes unicode char, conversion is - * required to convert the oem char to unicode and then - * to encode the converted wchars to utf8 format. - * Therefore, the **ascii returned will be in such format - * instead of the real ASCII format. + * mbc_marshal_get_oem_string + * + * Decode an OEM string, returning its UTF-8 form in strpp, + * allocated using smb_srm_zalloc (automatically freed). + * If max_bytes != 0, consume at most max_bytes of the mbc. + * See also: msgbuf_get_oem_string */ static int -mbc_marshal_get_ascii_string( - smb_request_t *sr, - mbuf_chain_t *mbc, - uint8_t **ascii, - int max_ascii) +mbc_marshal_get_oem_string(smb_request_t *sr, + mbuf_chain_t *mbc, char **strpp, int max_bytes) { - char *rcvbuf; - char *ch; - int max; - int length = 0; - - max = MALLOC_QUANTUM; - rcvbuf = smb_srm_zalloc(sr, max); + char *mbs; + uint8_t *oembuf = NULL; + int oemlen, oemmax; + int mbsmax; + int rlen; + int rc; - if (max_ascii == 0) - max_ascii = 0xffff; + if (max_bytes == 0) + max_bytes = 0xffff; - ch = rcvbuf; + /* + * Get the OtW data into a temporary buffer. + * Free oembuf before return. + */ + oemlen = 0; + oemmax = MALLOC_QUANTUM; + oembuf = smb_mem_alloc(oemmax); for (;;) { - while (length < max) { - if (max_ascii-- <= 0) { - *ch++ = 0; - goto multibyte_encode; - } - if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0) { - /* Data will never be available */ - return (DECODE_NO_MORE_DATA); - } - if ((*ch++ = mbc_marshal_fetch_byte(mbc)) == 0) - goto multibyte_encode; - length++; + uint8_t ch; + + if (oemlen >= max_bytes) + break; + if ((oemlen + 2) >= oemmax) { + oemmax += MALLOC_QUANTUM; + oembuf = smb_mem_realloc(oembuf, oemmax); + } + if (mbc_marshal_get_char(mbc, &ch) != 0) { + rc = DECODE_NO_MORE_DATA; + goto out; } - max += MALLOC_QUANTUM; - rcvbuf = smb_srm_rezalloc(sr, rcvbuf, max); - ch = rcvbuf + length; + if (ch == 0) + break; + oembuf[oemlen++] = ch; } + oembuf[oemlen] = '\0'; -multibyte_encode: /* - * UTF-8 encode the string for internal system use. + * Get the buffer we'll return and convert to UTF-8. + * May take as much as double the space. */ - length = strlen(rcvbuf) + 1; - *ascii = smb_srm_zalloc(sr, length * MTS_MB_CHAR_MAX); - return (mbc_marshal_cstou8("CP850", (char *)*ascii, - (size_t)length * MTS_MB_CHAR_MAX, rcvbuf, (size_t)length)); + mbsmax = oemlen * 2; + mbs = smb_srm_zalloc(sr, mbsmax + 1); + ASSERT(mbs != NULL); + rlen = smb_oemtombs(mbs, oembuf, mbsmax); + if (rlen < 0) { + rc = DECODE_NO_MORE_DATA; + goto out; + } + if (rlen > mbsmax) + rlen = mbsmax; + mbs[rlen] = '\0'; + *strpp = mbs; + rc = 0; + +out: + if (oembuf != NULL) + smb_mem_free(oembuf); + return (rc); } +/* + * mbc_marshal_get_unicode_string + * + * Decode a UTF-16 string, returning its UTF-8 form in strpp, + * allocated using smb_srm_zalloc (automatically freed). + * If max_bytes != 0, consume at most max_bytes of the mbc. + * See also: msgbuf_get_unicode_string + */ static int mbc_marshal_get_unicode_string(smb_request_t *sr, - mbuf_chain_t *mbc, uint8_t **ascii, int max_unicode) + mbuf_chain_t *mbc, char **strpp, int max_bytes) { - int max; - uint16_t wchar; - char *ch; - int emitted; - int length = 0; + char *mbs; + uint16_t *wcsbuf = NULL; + int wcslen; // wchar count + int wcsmax; // byte count + size_t mbsmax; + size_t rlen; + int rc; - if (max_unicode == 0) - max_unicode = 0xffff; + if (max_bytes == 0) + max_bytes = 0xffff; - max = MALLOC_QUANTUM; - *ascii = smb_srm_zalloc(sr, max); + /* + * Unicode strings are always word aligned. + */ + if (mbc->chain_offset & 1) { + if (MBC_ROOM_FOR(mbc, sizeof (char)) == 0) + return (DECODE_NO_MORE_DATA); + mbc->chain_offset++; + } - ch = (char *)*ascii; + /* + * Get the OtW data into a temporary buffer. + * Free wcsbuf before return. + */ + wcslen = 0; + wcsmax = MALLOC_QUANTUM; + wcsbuf = smb_mem_alloc(wcsmax); for (;;) { - while ((length + MTS_MB_CHAR_MAX) < max) { - if (max_unicode <= 0) - goto done; - max_unicode -= 2; - - if (mbc_marshal_get_short(mbc, &wchar) != 0) - return (DECODE_NO_MORE_DATA); - - if (wchar == 0) goto done; + uint16_t wchar; - emitted = smb_wctomb(ch, wchar); - length += emitted; - ch += emitted; + if ((wcslen * 2) >= max_bytes) + break; + if (((wcslen * 2) + 4) >= wcsmax) { + wcsmax += MALLOC_QUANTUM; + wcsbuf = smb_mem_realloc(wcsbuf, wcsmax); + } + if (mbc_marshal_get_short(mbc, &wchar) != 0) { + rc = DECODE_NO_MORE_DATA; + goto out; } - max += MALLOC_QUANTUM; - *ascii = smb_srm_rezalloc(sr, *ascii, max); - ch = (char *)*ascii + length; + if (wchar == 0) + break; + /* Keep in little-endian form. */ + LE_OUT16(wcsbuf + wcslen, wchar); + wcslen++; } -done: *ch = 0; - return (0); + wcsbuf[wcslen] = 0; + + /* + * Get the buffer we'll return and convert to UTF-8. + * May take as much 4X number of wide chars. + */ + mbsmax = wcslen * MTS_MB_CUR_MAX; + mbs = smb_srm_zalloc(sr, mbsmax + 1); + ASSERT(mbs != NULL); + rlen = smb_wcstombs(mbs, wcsbuf, mbsmax); + if (rlen == (size_t)-1) { + rc = DECODE_NO_MORE_DATA; + goto out; + } + if (rlen > mbsmax) + rlen = mbsmax; + mbs[rlen] = '\0'; + *strpp = mbs; + rc = 0; + +out: + if (wcsbuf != NULL) + smb_mem_free(wcsbuf); + return (rc); } static int /*ARGSUSED*/ @@ -1571,29 +1695,3 @@ mbc_marshal_get_skip(mbuf_chain_t *mbc, uint_t skip) mbc->chain_offset += skip; return (0); } - -/* - * Converts oem string to UTF-8 string with an output string of max - * maxconv bytes. The string may be truncated or not null-terminated if - * there is not enough room. - * - * returns -1, cnt (partial conversion) or 0 (success) - */ - -static int -mbc_marshal_cstou8(char *cs, char *outbuf, size_t maxconv, - char *inbuf, size_t srcbytes) -{ - kiconv_t t2u; - size_t inlen = srcbytes; - size_t outlen = maxconv; - int err = 0; - size_t rc; - - if ((t2u = kiconv_open("UTF-8", cs)) == (kiconv_t)-1) - return (-1); - - rc = kiconv(t2u, &inbuf, &inlen, &outbuf, &outlen, &err); - (void) kiconv_close(t2u); - return ((int)rc); -} diff --git a/usr/src/uts/common/fs/smbsrv/smb_negotiate.c b/usr/src/uts/common/fs/smbsrv/smb_negotiate.c index 8750b30810..ee04278e66 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 2015 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -280,6 +280,9 @@ uint32_t smb1srv_capabilities = * result of bypassing the normal dispatch mechanism. * * The caller always frees this request. + * + * Return value is 0 for success, and anything else will + * terminate the reader thread (drop the connection). */ int smb1_newrq_negotiate(smb_request_t *sr) @@ -382,8 +385,7 @@ smb_pre_negotiate(smb_request_t *sr) } } - DTRACE_SMB_2(op__Negotiate__start, smb_request_t *, sr, - smb_arg_negotiate_t, negprot); + DTRACE_SMB_START(op__Negotiate, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -393,8 +395,7 @@ smb_post_negotiate(smb_request_t *sr) { smb_arg_negotiate_t *negprot = sr->sr_negprot; - DTRACE_SMB_2(op__Negotiate__done, smb_request_t *, sr, - smb_arg_negotiate_t, negprot); + DTRACE_SMB_DONE(op__Negotiate, smb_request_t *, sr); bzero(negprot, sizeof (smb_arg_negotiate_t)); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c b/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c index f0f93ace84..c5bf4c4792 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_cancel.c @@ -48,14 +48,14 @@ smb_sdrc_t smb_pre_nt_cancel(smb_request_t *sr) { - DTRACE_SMB_1(op__NtCancel__start, smb_request_t *, sr); + DTRACE_SMB_START(op__NtCancel, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_nt_cancel(smb_request_t *sr) { - DTRACE_SMB_1(op__NtCancel__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__NtCancel, smb_request_t *, sr); } /* diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c index a787b9ed27..291942fc7c 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_create_andx.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -212,8 +212,7 @@ smb_pre_nt_create_andx(smb_request_t *sr) op->op_oplock_level = SMB_OPLOCK_EXCLUSIVE; } - DTRACE_SMB_2(op__NtCreateX__start, smb_request_t *, sr, - struct open_param *, op); + DTRACE_SMB_START(op__NtCreateX, smb_request_t *, sr); /* arg.open */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -221,7 +220,7 @@ smb_pre_nt_create_andx(smb_request_t *sr) void smb_post_nt_create_andx(smb_request_t *sr) { - DTRACE_SMB_1(op__NtCreateX__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__NtCreateX, smb_request_t *, sr); if (sr->arg.open.dir != NULL) { smb_ofile_release(sr->arg.open.dir); 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 34bf2d25c9..dbb4efaefb 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 @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -115,8 +115,7 @@ smb_pre_nt_transact_create(smb_request_t *sr, smb_xa_t *xa) op->sd = NULL; } - DTRACE_SMB_2(op__NtTransactCreate__start, smb_request_t *, sr, - struct open_param *, op); + DTRACE_SMB_START(op__NtTransactCreate, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -125,9 +124,9 @@ void smb_post_nt_transact_create(smb_request_t *sr, smb_xa_t *xa) { smb_sd_t *sd = sr->arg.open.sd; + _NOTE(ARGUNUSED(xa)) - DTRACE_SMB_2(op__NtTransactCreate__done, smb_request_t *, sr, - smb_xa_t *, xa); + DTRACE_SMB_DONE(op__NtTransactCreate, smb_request_t *, sr); if (sd) { smb_sd_term(sd); diff --git a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c index 5eed0becee..2c412ba56a 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c +++ b/usr/src/uts/common/fs/smbsrv/smb_nt_transact_notify_change.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -226,6 +226,13 @@ smb_nt_transact_notify_finish(void *arg) &xa->rep_data_mb); sendit: + /* + * When smb_nt_transact_notify_change returned SDRC_SR_KEPT + * the dispatcher skipped the "done" probe, so do it now. + * Note: Don't use this probe in response time statistics. + */ + DTRACE_SMB_DONE(op__NtTransact, smb_request_t *, sr); + sds = &sr->sr_server->sv_disp_stats1[sr->smb_com]; atomic_add_64(&sds->sdt_txb, (int64_t)sr->reply.chain_offset); diff --git a/usr/src/uts/common/fs/smbsrv/smb_open_andx.c b/usr/src/uts/common/fs/smbsrv/smb_open_andx.c index ff26c61119..ca35b03340 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_open_andx.c +++ b/usr/src/uts/common/fs/smbsrv/smb_open_andx.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <smbsrv/smb_kproto.h> @@ -227,8 +227,7 @@ smb_pre_open(smb_request_t *sr) if (rc == 0) rc = smbsr_decode_data(sr, "%S", sr, &op->fqi.fq_path.pn_path); - DTRACE_SMB_2(op__Open__start, smb_request_t *, sr, - struct open_param *, op); + DTRACE_SMB_START(op__Open, smb_request_t *, sr); /* arg.open */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -236,7 +235,7 @@ smb_pre_open(smb_request_t *sr) void smb_post_open(smb_request_t *sr) { - DTRACE_SMB_1(op__Open__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__Open, smb_request_t *, sr); } smb_sdrc_t @@ -367,8 +366,7 @@ smb_pre_open_andx(smb_request_t *sr) op->create_disposition = smb_ofun_to_crdisposition(op->ofun); } - DTRACE_SMB_2(op__OpenX__start, smb_request_t *, sr, - struct open_param *, op); + DTRACE_SMB_START(op__OpenX, smb_request_t *, sr); /* arg.open */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -376,7 +374,7 @@ smb_pre_open_andx(smb_request_t *sr) void smb_post_open_andx(smb_request_t *sr) { - DTRACE_SMB_1(op__OpenX__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__OpenX, smb_request_t *, sr); } smb_sdrc_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_print.c b/usr/src/uts/common/fs/smbsrv/smb_print.c index 17d68abf1f..96156b4f71 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_print.c +++ b/usr/src/uts/common/fs/smbsrv/smb_print.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -78,8 +78,7 @@ smb_pre_open_print_file(smb_request_t *sr) op->create_disposition = FILE_OVERWRITE_IF; op->create_options = FILE_NON_DIRECTORY_FILE; - DTRACE_SMB_2(op__OpenPrintFile__start, smb_request_t *, sr, - struct open_param *, op); + DTRACE_SMB_START(op__OpenPrintFile, smb_request_t *, sr); /* arg.open */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -87,7 +86,7 @@ smb_pre_open_print_file(smb_request_t *sr) void smb_post_open_print_file(smb_request_t *sr) { - DTRACE_SMB_1(op__OpenPrintFile__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__OpenPrintFile, smb_request_t *, sr); } /* @@ -158,14 +157,14 @@ smb_pre_close_print_file(smb_request_t *sr) rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid); - DTRACE_SMB_1(op__ClosePrintFile__start, smb_request_t *, sr); + DTRACE_SMB_START(op__ClosePrintFile, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } void smb_post_close_print_file(smb_request_t *sr) { - DTRACE_SMB_1(op__ClosePrintFile__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__ClosePrintFile, smb_request_t *, sr); } /* @@ -209,14 +208,14 @@ smb_com_close_print_file(smb_request_t *sr) smb_sdrc_t smb_pre_get_print_queue(smb_request_t *sr) { - DTRACE_SMB_1(op__GetPrintQueue__start, smb_request_t *, sr); + DTRACE_SMB_START(op__GetPrintQueue, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_get_print_queue(smb_request_t *sr) { - DTRACE_SMB_1(op__GetPrintQueue__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__GetPrintQueue, smb_request_t *, sr); } smb_sdrc_t @@ -255,14 +254,14 @@ smb_pre_write_print_file(smb_request_t *sr) rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid); - DTRACE_SMB_1(op__WritePrintFile__start, smb_request_t *, sr); + DTRACE_SMB_START(op__WritePrintFile, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } void smb_post_write_print_file(smb_request_t *sr) { - DTRACE_SMB_1(op__WritePrintFile__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__WritePrintFile, smb_request_t *, sr); kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_process_exit.c b/usr/src/uts/common/fs/smbsrv/smb_process_exit.c index 2839ca2807..0bf364c0c0 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_process_exit.c +++ b/usr/src/uts/common/fs/smbsrv/smb_process_exit.c @@ -21,6 +21,8 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -56,14 +58,14 @@ smb_sdrc_t smb_pre_process_exit(smb_request_t *sr) { - DTRACE_SMB_1(op__ProcessExit__start, smb_request_t *, sr); + DTRACE_SMB_START(op__ProcessExit, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_process_exit(smb_request_t *sr) { - DTRACE_SMB_1(op__ProcessExit__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__ProcessExit, smb_request_t *, sr); } smb_sdrc_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c b/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c index 7e9e05a163..2504f524c9 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c +++ b/usr/src/uts/common/fs/smbsrv/smb_query_fileinfo.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <smbsrv/smb_kproto.h> @@ -149,8 +149,7 @@ smb_pre_query_information(smb_request_t *sr) rc = smbsr_decode_data(sr, "%S", sr, &fqi->fq_path.pn_path); - DTRACE_SMB_2(op__QueryInformation__start, smb_request_t *, sr, - smb_fqi_t *, fqi); + DTRACE_SMB_START(op__QueryInformation, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -158,7 +157,7 @@ smb_pre_query_information(smb_request_t *sr) void smb_post_query_information(smb_request_t *sr) { - DTRACE_SMB_1(op__QueryInformation__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__QueryInformation, smb_request_t *, sr); } smb_sdrc_t @@ -187,7 +186,7 @@ smb_pre_query_information2(smb_request_t *sr) int rc; rc = smbsr_decode_vwv(sr, "w", &sr->smb_fid); - DTRACE_SMB_1(op__QueryInformation2__start, smb_request_t *, sr); + DTRACE_SMB_START(op__QueryInformation2, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -195,7 +194,7 @@ smb_pre_query_information2(smb_request_t *sr) void smb_post_query_information2(smb_request_t *sr) { - DTRACE_SMB_1(op__QueryInformation2__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__QueryInformation2, smb_request_t *, sr); } smb_sdrc_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_read.c b/usr/src/uts/common/fs/smbsrv/smb_read.c index d934c09678..2f1c86af4b 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_read.c +++ b/usr/src/uts/common/fs/smbsrv/smb_read.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <smbsrv/smb_kproto.h> @@ -73,8 +73,7 @@ smb_pre_read(smb_request_t *sr) param->rw_count = (uint32_t)count; param->rw_mincnt = 0; - DTRACE_SMB_2(op__Read__start, smb_request_t *, sr, - smb_rw_param_t *, param); + DTRACE_SMB_START(op__Read, smb_request_t *, sr); /* arg.rw */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -82,8 +81,7 @@ smb_pre_read(smb_request_t *sr) void smb_post_read(smb_request_t *sr) { - DTRACE_SMB_2(op__Read__done, smb_request_t *, sr, - smb_rw_param_t *, sr->arg.rw); + DTRACE_SMB_DONE(op__Read, smb_request_t *, sr); /* arg.rw */ kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); } @@ -159,8 +157,7 @@ smb_pre_lock_and_read(smb_request_t *sr) param->rw_count = (uint32_t)count; param->rw_mincnt = 0; - DTRACE_SMB_2(op__LockAndRead__start, smb_request_t *, sr, - smb_rw_param_t *, param); + DTRACE_SMB_START(op__LockAndRead, smb_request_t *, sr); /* arg.rw */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -168,8 +165,7 @@ smb_pre_lock_and_read(smb_request_t *sr) void smb_post_lock_and_read(smb_request_t *sr) { - DTRACE_SMB_2(op__LockAndRead__done, smb_request_t *, sr, - smb_rw_param_t *, sr->arg.rw); + DTRACE_SMB_DONE(op__LockAndRead, smb_request_t *, sr); /* arg.rw */ kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); } @@ -223,6 +219,35 @@ smb_com_lock_and_read(smb_request_t *sr) } /* + * The SMB_COM_READ_RAW protocol was a negotiated option introduced in + * SMB Core Plus to maximize performance when reading a large block + * of data from a server. It's obsolete and no longer supported. + * + * We keep a handler for it so the dtrace provider can see if + * the client tried to use this command. + */ +smb_sdrc_t +smb_pre_read_raw(smb_request_t *sr) +{ + DTRACE_SMB_START(op__ReadRaw, smb_request_t *, sr); + return (SDRC_SUCCESS); +} + +void +smb_post_read_raw(smb_request_t *sr) +{ + DTRACE_SMB_DONE(op__ReadRaw, smb_request_t *, sr); +} + +smb_sdrc_t +smb_com_read_raw(smb_request_t *sr) +{ + smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, ERRDOS, + ERROR_NOT_SUPPORTED); + return (SDRC_ERROR); +} + +/* * Read bytes from a file (SMB Core). This request was extended in * LM 0.12 to support 64-bit offsets, indicated by sending a wct of * 12 and including additional offset information. @@ -272,8 +297,7 @@ smb_pre_read_andx(smb_request_t *sr) param->rw_mincnt = 0; - DTRACE_SMB_2(op__ReadX__start, smb_request_t *, sr, - smb_rw_param_t *, param); + DTRACE_SMB_START(op__ReadX, smb_request_t *, sr); /* arg.rw */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -281,8 +305,7 @@ smb_pre_read_andx(smb_request_t *sr) void smb_post_read_andx(smb_request_t *sr) { - DTRACE_SMB_2(op__ReadX__done, smb_request_t *, sr, - smb_rw_param_t *, sr->arg.rw); + DTRACE_SMB_DONE(op__ReadX, smb_request_t *, sr); /* arg.rw */ kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); } diff --git a/usr/src/uts/common/fs/smbsrv/smb_rename.c b/usr/src/uts/common/fs/smbsrv/smb_rename.c index 1b36aa8f1e..1a717dcb09 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_rename.c +++ b/usr/src/uts/common/fs/smbsrv/smb_rename.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <sys/synch.h> @@ -72,8 +72,7 @@ smb_pre_rename(smb_request_t *sr) dst_fqi->fq_sattr = 0; } - DTRACE_SMB_2(op__Rename__start, smb_request_t *, sr, - struct dirop *, &sr->arg.dirop); + DTRACE_SMB_START(op__Rename, smb_request_t *, sr); /* arg.dirop */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -81,7 +80,7 @@ smb_pre_rename(smb_request_t *sr) void smb_post_rename(smb_request_t *sr) { - DTRACE_SMB_1(op__Rename__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__Rename, smb_request_t *, sr); } smb_sdrc_t @@ -146,8 +145,7 @@ smb_pre_nt_rename(smb_request_t *sr) dst_fqi->fq_sattr = 0; } - DTRACE_SMB_2(op__NtRename__start, smb_request_t *, sr, - struct dirop *, &sr->arg.dirop); + DTRACE_SMB_START(op__NtRename, smb_request_t *, sr); /* arg.dirop */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -155,7 +153,7 @@ smb_pre_nt_rename(smb_request_t *sr) void smb_post_nt_rename(smb_request_t *sr) { - DTRACE_SMB_1(op__NtRename__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__NtRename, smb_request_t *, sr); } smb_sdrc_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_seek.c b/usr/src/uts/common/fs/smbsrv/smb_seek.c index 4e734063d9..bf1e9bf6d4 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_seek.c +++ b/usr/src/uts/common/fs/smbsrv/smb_seek.c @@ -21,6 +21,8 @@ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -80,14 +82,14 @@ smb_sdrc_t smb_pre_seek(smb_request_t *sr) { - DTRACE_SMB_1(op__Seek__start, smb_request_t *, sr); + DTRACE_SMB_START(op__Seek, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_seek(smb_request_t *sr) { - DTRACE_SMB_1(op__Seek__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__Seek, smb_request_t *, sr); } smb_sdrc_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_session.c b/usr/src/uts/common/fs/smbsrv/smb_session.c index 07dc4434a3..c3ce565688 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_session.c +++ b/usr/src/uts/common/fs/smbsrv/smb_session.c @@ -676,6 +676,9 @@ smb_session_reader(smb_session_t *session) * the new request for the session taskq, or smb_request_free it * (in case we've decided to drop this connection). In this * (special) new request handler, we always free the request. + * + * Return value is 0 for success, and anything else will + * terminate the reader thread (drop the connection). */ static int smbsr_newrq_initial(smb_request_t *sr) 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 5f98a16293..bfa07bb1d2 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 @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2014 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <sys/types.h> @@ -189,8 +189,7 @@ done: sr->session->ip_addr_str); } - DTRACE_SMB_2(op__SessionSetupX__start, smb_request_t *, sr, - smb_arg_sessionsetup_t, sinfo); + DTRACE_SMB_START(op__SessionSetupX, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -199,8 +198,7 @@ smb_post_session_setup_andx(smb_request_t *sr) { smb_arg_sessionsetup_t *sinfo = sr->sr_ssetup; - DTRACE_SMB_2(op__SessionSetupX__done, smb_request_t *, sr, - smb_arg_sessionsetup_t, sinfo); + DTRACE_SMB_DONE(op__SessionSetupX, smb_request_t *, sr); if (sinfo->ssi_lmpwd != NULL) bzero(sinfo->ssi_lmpwd, sinfo->ssi_lmpwlen); diff --git a/usr/src/uts/common/fs/smbsrv/smb_set_fileinfo.c b/usr/src/uts/common/fs/smbsrv/smb_set_fileinfo.c index 4405230319..160459ab7f 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_set_fileinfo.c +++ b/usr/src/uts/common/fs/smbsrv/smb_set_fileinfo.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -127,14 +127,14 @@ smb_com_trans2_set_path_information(smb_request_t *sr, smb_xa_t *xa) smb_sdrc_t smb_pre_set_information(smb_request_t *sr) { - DTRACE_SMB_1(op__SetInformation__start, smb_request_t *, sr); + DTRACE_SMB_START(op__SetInformation, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_set_information(smb_request_t *sr) { - DTRACE_SMB_1(op__SetInformation__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__SetInformation, smb_request_t *, sr); } smb_sdrc_t @@ -167,14 +167,14 @@ smb_com_set_information(smb_request_t *sr) smb_sdrc_t smb_pre_set_information2(smb_request_t *sr) { - DTRACE_SMB_1(op__SetInformation2__start, smb_request_t *, sr); + DTRACE_SMB_START(op__SetInformation2, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_set_information2(smb_request_t *sr) { - DTRACE_SMB_1(op__SetInformation2__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__SetInformation2, smb_request_t *, sr); } smb_sdrc_t 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 cdfaf0c8ee..ecb7c5c639 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c +++ b/usr/src/uts/common/fs/smbsrv/smb_trans2_find.c @@ -22,7 +22,7 @@ * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * - * Copyright 2015 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ @@ -213,7 +213,7 @@ * various functions involved in FindFirst, FindNext. */ typedef struct smb_find_args { - uint32_t fa_maxdata; + uint32_t fa_fixedsize; uint16_t fa_infolev; uint16_t fa_maxcount; uint16_t fa_fflag; @@ -225,7 +225,7 @@ typedef struct smb_find_args { static int smb_trans2_find_entries(smb_request_t *, smb_xa_t *, smb_odir_t *, smb_find_args_t *); -static int smb_trans2_find_get_maxdata(smb_request_t *, uint16_t, uint16_t); +static int smb_trans2_find_get_fixedsize(smb_request_t *, uint16_t, uint16_t); static int smb_trans2_find_mbc_encode(smb_request_t *, smb_xa_t *, smb_fileinfo_t *, smb_find_args_t *); @@ -320,9 +320,9 @@ smb_com_trans2_find_first2(smb_request_t *sr, smb_xa_t *xa) odir_flags = SMB_ODIR_OPENF_BACKUP_INTENT; } - args.fa_maxdata = - smb_trans2_find_get_maxdata(sr, args.fa_infolev, args.fa_fflag); - if (args.fa_maxdata == 0) + args.fa_fixedsize = + smb_trans2_find_get_fixedsize(sr, args.fa_infolev, args.fa_fflag); + if (args.fa_fixedsize == 0) return (SDRC_ERROR); status = smb_odir_openpath(sr, pn->pn_path, sattr, odir_flags, &od); @@ -455,9 +455,9 @@ smb_com_trans2_find_next2(smb_request_t *sr, smb_xa_t *xa) if (args.fa_fflag & SMB_FIND_WITH_BACKUP_INTENT) sr->user_cr = smb_user_getprivcred(sr->uid_user); - args.fa_maxdata = - smb_trans2_find_get_maxdata(sr, args.fa_infolev, args.fa_fflag); - if (args.fa_maxdata == 0) + args.fa_fixedsize = + smb_trans2_find_get_fixedsize(sr, args.fa_infolev, args.fa_fflag); + if (args.fa_fixedsize == 0) return (SDRC_ERROR); od = smb_tree_lookup_odir(sr, odid); @@ -536,6 +536,7 @@ smb_trans2_find_entries(smb_request_t *sr, smb_xa_t *xa, smb_odir_t *od, smb_odir_resume_t odir_resume; uint16_t count, maxcount; int rc = -1; + int LastEntryOffset = 0; boolean_t need_rewind = B_FALSE; /* @@ -565,6 +566,7 @@ smb_trans2_find_entries(smb_request_t *sr, smb_xa_t *xa, smb_odir_t *od, if (rc != 0 || args->fa_eos != 0) break; + LastEntryOffset = xa->rep_data_mb.chain_offset; rc = smb_trans2_find_mbc_encode(sr, xa, &fileinfo, args); if (rc == -1) return (-1); /* fatal encoding error */ @@ -584,6 +586,15 @@ smb_trans2_find_entries(smb_request_t *sr, smb_xa_t *xa, smb_odir_t *od, if (args->fa_eos != 0 && rc == ENOENT) rc = 0; + /* + * All but the ancient info levels start with NextEntryOffset. + * That's supposed to be zero in the last entry returned. + */ + if (args->fa_infolev >= SMB_FIND_FILE_DIRECTORY_INFO) { + (void) smb_mbc_poke(&xa->rep_data_mb, + LastEntryOffset, "l", 0); + } + /* save the last cookie returned to client */ if (count != 0) smb_odir_save_fname(od, args->fa_lastkey, args->fa_lastname); @@ -621,20 +632,19 @@ smb_trans2_find_entries(smb_request_t *sr, smb_xa_t *xa, smb_odir_t *od, } /* - * smb_trans2_find_get_maxdata + * smb_trans2_find_get_fixedsize * - * Calculate the minimum response space required for the specified - * information level. + * Calculate the sizeof the fixed part of the response for the + * specified information level. * - * A non-zero return value provides the minimum space required. + * A non-zero return value provides the fixed size. * A return value of zero indicates an unknown information level. */ static int -smb_trans2_find_get_maxdata(smb_request_t *sr, uint16_t infolev, uint16_t fflag) +smb_trans2_find_get_fixedsize(smb_request_t *sr, uint16_t infolev, + uint16_t fflag) { - int maxdata; - - maxdata = smb_ascii_or_unicode_null_len(sr); + int maxdata = 0; switch (infolev) { case SMB_INFO_STANDARD : @@ -736,27 +746,53 @@ smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa, uint32_t resume_key; char buf83[26]; smb_msgbuf_t mb; + int pad = 0; namelen = smb_ascii_or_unicode_strlen(sr, fileinfo->fi_name); if (namelen == -1) return (-1); - /* - * If ascii the filename length returned to the client should - * include the null terminator for levels except STANDARD and - * EASIZE. - */ - if (!(sr->smb_flg2 & SMB_FLAGS2_UNICODE)) { - if ((args->fa_infolev != SMB_INFO_STANDARD) && - (args->fa_infolev != SMB_INFO_QUERY_EA_SIZE)) + if (args->fa_infolev < SMB_FIND_FILE_DIRECTORY_INFO) { + /* + * Ancient info levels don't have a NextEntryOffset + * field, so there's no padding for alignment. + * The client expects a null after the file name, + * and then the next entry. The namelength field + * never includes the null for these old levels. + * Using the pad value to write the null because + * we don't want to add that to namelen. + * [MS-CIFS] sec. 2.8.1.{1-3} + */ + if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0) + pad = 2; /* Unicode null */ + else + pad = 1; /* ascii null */ + next_entry_offset = args->fa_fixedsize + namelen + pad; + if (!MBC_ROOM_FOR(&xa->rep_data_mb, next_entry_offset)) + return (1); + } else { + /* + * Later info levels: The file name is written WITH + * null termination, and the size of that null _is_ + * included in the namelen field. There may also + * be padding, and we pad to align(4) like Windows. + * Don't include the padding in the "room for" test + * because we want to ignore any error writing the + * pad bytes after the last element. + */ + if ((sr->smb_flg2 & SMB_FLAGS2_UNICODE) != 0) + namelen += 2; + else namelen += 1; + next_entry_offset = args->fa_fixedsize + namelen; + if (!MBC_ROOM_FOR(&xa->rep_data_mb, next_entry_offset)) + return (1); + if ((next_entry_offset & 3) != 0) { + pad = 4 - (next_entry_offset & 3); + next_entry_offset += pad; + } } - next_entry_offset = args->fa_maxdata + namelen; - - if (MBC_ROOM_FOR(&xa->rep_data_mb, (args->fa_maxdata + namelen)) == 0) - return (1); - mb_flags = (sr->smb_flg2 & SMB_FLAGS2_UNICODE) ? SMB_MSGBUF_UNICODE : 0; dsize32 = (fileinfo->fi_size > UINT_MAX) ? UINT_MAX : (uint32_t)fileinfo->fi_size; @@ -938,8 +974,11 @@ smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa, (args->fa_lno & 1) != 0) args->fa_lno++; - (void) smb_mbc_encodef(&xa->rep_data_mb, "%u", sr, - fileinfo->fi_name); + (void) smb_mbc_encodef(&xa->rep_data_mb, "%#u", sr, + namelen, fileinfo->fi_name); + + if (pad) + (void) smb_mbc_encodef(&xa->rep_data_mb, "#.", pad); return (0); } @@ -950,14 +989,14 @@ smb_trans2_find_mbc_encode(smb_request_t *sr, smb_xa_t *xa, smb_sdrc_t smb_pre_find_close2(smb_request_t *sr) { - DTRACE_SMB_1(op__FindClose2__start, smb_request_t *, sr); + DTRACE_SMB_START(op__FindClose2, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_find_close2(smb_request_t *sr) { - DTRACE_SMB_1(op__FindClose2__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__FindClose2, smb_request_t *, sr); } smb_sdrc_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c b/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c index 811cdd3a39..7bdc9a7c93 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c +++ b/usr/src/uts/common/fs/smbsrv/smb_tree_connect.c @@ -20,7 +20,7 @@ */ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <smbsrv/smb_kproto.h> @@ -100,8 +100,7 @@ smb_pre_tree_connect(smb_request_t *sr) tcon->flags = 0; tcon->optional_support = 0; - DTRACE_SMB_2(op__TreeConnect__start, smb_request_t *, sr, - smb_arg_tcon_t *, tcon); + DTRACE_SMB_START(op__TreeConnect, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -109,7 +108,7 @@ smb_pre_tree_connect(smb_request_t *sr) void smb_post_tree_connect(smb_request_t *sr) { - DTRACE_SMB_1(op__TreeConnect__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__TreeConnect, smb_request_t *, sr); } smb_sdrc_t @@ -291,8 +290,7 @@ smb_pre_tree_connect_andx(smb_request_t *sr) tcon->optional_support = 0; - DTRACE_SMB_2(op__TreeConnectX__start, smb_request_t *, sr, - smb_arg_tcon_t *, tcon); + DTRACE_SMB_START(op__TreeConnectX, smb_request_t *, sr); return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -300,7 +298,7 @@ smb_pre_tree_connect_andx(smb_request_t *sr) void smb_post_tree_connect_andx(smb_request_t *sr) { - DTRACE_SMB_1(op__TreeConnectX__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__TreeConnectX, smb_request_t *, sr); } smb_sdrc_t @@ -416,14 +414,14 @@ smb_pre_tree_disconnect(smb_request_t *sr) sr->uid_user = smb_session_lookup_uid(sr->session, sr->smb_uid); sr->tid_tree = smb_session_lookup_tree(sr->session, sr->smb_tid); - DTRACE_SMB_1(op__TreeDisconnect__start, smb_request_t *, sr); + DTRACE_SMB_START(op__TreeDisconnect, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_tree_disconnect(smb_request_t *sr) { - DTRACE_SMB_1(op__TreeDisconnect__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__TreeDisconnect, smb_request_t *, sr); } /* diff --git a/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c b/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c index 19e8566769..facd2af559 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c +++ b/usr/src/uts/common/fs/smbsrv/smb_unlock_byte_range.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ /* @@ -57,14 +57,14 @@ smb_sdrc_t smb_pre_unlock_byte_range(smb_request_t *sr) { - DTRACE_SMB_1(op__UnlockByteRange__start, smb_request_t *, sr); + DTRACE_SMB_START(op__UnlockByteRange, smb_request_t *, sr); return (SDRC_SUCCESS); } void smb_post_unlock_byte_range(smb_request_t *sr) { - DTRACE_SMB_1(op__UnlockByteRange__done, smb_request_t *, sr); + DTRACE_SMB_DONE(op__UnlockByteRange, smb_request_t *, sr); } smb_sdrc_t diff --git a/usr/src/uts/common/fs/smbsrv/smb_vops.c b/usr/src/uts/common/fs/smbsrv/smb_vops.c index 23ba643089..7a3905d7bb 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_vops.c +++ b/usr/src/uts/common/fs/smbsrv/smb_vops.c @@ -1587,7 +1587,7 @@ smb_vop_catia_v5tov4(char *name, char *buf, int buflen) { int v4_idx, numbytes, inc; int space_left = buflen - 1; /* one byte reserved for null */ - smb_wchar_t wc; + uint32_t wc; char mbstring[MTS_MB_CHAR_MAX]; char *p, *src = name, *dst = buf; @@ -1644,7 +1644,7 @@ smb_vop_catia_v4tov5(char *name, char *buf, int buflen) { int v5_idx, numbytes; int space_left = buflen - 1; /* one byte reserved for null */ - smb_wchar_t wc; + uint32_t wc; char mbstring[MTS_MB_CHAR_MAX]; char *src = name, *dst = buf; diff --git a/usr/src/uts/common/fs/smbsrv/smb_write.c b/usr/src/uts/common/fs/smbsrv/smb_write.c index ae54cfcf36..7280893042 100644 --- a/usr/src/uts/common/fs/smbsrv/smb_write.c +++ b/usr/src/uts/common/fs/smbsrv/smb_write.c @@ -21,7 +21,7 @@ /* * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2016 Nexenta Systems, Inc. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #include <sys/sdt.h> @@ -61,8 +61,7 @@ smb_pre_write(smb_request_t *sr) param->rw_offset = (uint64_t)off; param->rw_vdb.vdb_uio.uio_loffset = (offset_t)param->rw_offset; - DTRACE_SMB_2(op__Write__start, smb_request_t *, sr, - smb_rw_param_t *, param); + DTRACE_SMB_START(op__Write, smb_request_t *, sr); /* arg.rw */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -70,8 +69,7 @@ smb_pre_write(smb_request_t *sr) void smb_post_write(smb_request_t *sr) { - DTRACE_SMB_2(op__Write__done, smb_request_t *, sr, - smb_rw_param_t *, sr->arg.rw); + DTRACE_SMB_DONE(op__Write, smb_request_t *, sr); /* arg.rw */ kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); } @@ -151,8 +149,7 @@ smb_pre_write_and_close(smb_request_t *sr) param->rw_count = (uint32_t)count; param->rw_offset = (uint64_t)off; - DTRACE_SMB_2(op__WriteAndClose__start, smb_request_t *, sr, - smb_rw_param_t *, param); + DTRACE_SMB_START(op__WriteAndClose, smb_request_t *, sr); /* arg.rw */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -160,8 +157,7 @@ smb_pre_write_and_close(smb_request_t *sr) void smb_post_write_and_close(smb_request_t *sr) { - DTRACE_SMB_2(op__WriteAndClose__done, smb_request_t *, sr, - smb_rw_param_t *, sr->arg.rw); + DTRACE_SMB_DONE(op__WriteAndClose, smb_request_t *, sr); /* arg.rw */ kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); } @@ -249,8 +245,7 @@ smb_pre_write_and_unlock(smb_request_t *sr) param->rw_count = (uint32_t)count; param->rw_offset = (uint64_t)off; - DTRACE_SMB_2(op__WriteAndUnlock__start, smb_request_t *, sr, - smb_rw_param_t *, param); + DTRACE_SMB_START(op__WriteAndUnlock, smb_request_t *, sr); /* arg.rw */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -258,8 +253,7 @@ smb_pre_write_and_unlock(smb_request_t *sr) void smb_post_write_and_unlock(smb_request_t *sr) { - DTRACE_SMB_2(op__WriteAndUnlock__done, smb_request_t *, sr, - smb_rw_param_t *, sr->arg.rw); + DTRACE_SMB_DONE(op__WriteAndUnlock, smb_request_t *, sr); /* arg.rw */ kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); } @@ -325,6 +319,35 @@ smb_com_write_and_unlock(smb_request_t *sr) } /* + * The SMB_COM_WRITE_RAW protocol was a negotiated option introduced in + * SMB Core Plus to maximize performance when writing a large block + * of data to a server. It's obsolete and no longer supported. + * + * We keep a handler for it so the dtrace provider can see if + * the client tried to use this command. + */ +smb_sdrc_t +smb_pre_write_raw(smb_request_t *sr) +{ + DTRACE_SMB_START(op__WriteRaw, smb_request_t *, sr); + return (SDRC_SUCCESS); +} + +void +smb_post_write_raw(smb_request_t *sr) +{ + DTRACE_SMB_DONE(op__WriteRaw, smb_request_t *, sr); +} + +smb_sdrc_t +smb_com_write_raw(struct smb_request *sr) +{ + smbsr_error(sr, NT_STATUS_NOT_SUPPORTED, ERRDOS, + ERROR_NOT_SUPPORTED); + return (SDRC_ERROR); +} + +/* * Write bytes to a file (SMB Core). This request was extended in * LM 0.12 to support 64-bit offsets, indicated by sending a wct of * 14, instead of 12, and including additional offset information. @@ -387,8 +410,7 @@ smb_pre_write_andx(smb_request_t *sr) (sr->smb_data.max_bytes > (sr->smb_data.chain_offset + 0xFFFF))) param->rw_count |= ((uint32_t)datalen_high << 16); - DTRACE_SMB_2(op__WriteX__start, smb_request_t *, sr, - smb_rw_param_t *, param); + DTRACE_SMB_START(op__WriteX, smb_request_t *, sr); /* arg.rw */ return ((rc == 0) ? SDRC_SUCCESS : SDRC_ERROR); } @@ -396,8 +418,7 @@ smb_pre_write_andx(smb_request_t *sr) void smb_post_write_andx(smb_request_t *sr) { - DTRACE_SMB_2(op__WriteX__done, smb_request_t *, sr, - smb_rw_param_t *, sr->arg.rw); + DTRACE_SMB_DONE(op__WriteX, smb_request_t *, sr); /* arg.rw */ kmem_free(sr->arg.rw, sizeof (smb_rw_param_t)); } diff --git a/usr/src/uts/common/smbsrv/smb_kproto.h b/usr/src/uts/common/smbsrv/smb_kproto.h index 5b5a566284..835d50bedf 100644 --- a/usr/src/uts/common/smbsrv/smb_kproto.h +++ b/usr/src/uts/common/smbsrv/smb_kproto.h @@ -55,52 +55,6 @@ 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 we're compiling for user mode (libfksmbsrv) define them as - * either no-op (for the SMB dtrace provider) or libfksmbsrv functions for - * the other SDT probe sites. - */ -#ifndef _KERNEL - -extern void smb_dtrace1(const char *f, const char *n, - const char *t1, long v1); -extern void smb_dtrace2(const char *f, const char *n, - const char *t1, long v1, - const char *t2, long v2); -extern void smb_dtrace3(const char *f, const char *n, - const char *t1, long v1, - const char *t2, long v2, - const char *t3, long v3); - -/* - * These are for the SMB dtrace proivder, which for a user-mode build - * are largely redundant with the fbt probes so make these no-ops. - */ -#undef DTRACE_SMB_1 -#define DTRACE_SMB_1(n, a, b) ((void)b) -#undef DTRACE_SMB_2 -#define DTRACE_SMB_2(n, a, b, c, d) ((void)b, (void)d) - -/* - * These are for the other (specialized) dtrace SDT probes sprinkled - * through the smbsrv code. In libfksmbsrv map these to functions. - */ - -#undef DTRACE_PROBE1 -#define DTRACE_PROBE1(n, a, b) \ - smb_dtrace1(__func__, #n, #a, (long)b) - -#undef DTRACE_PROBE2 -#define DTRACE_PROBE2(n, a, b, c, d) \ - smb_dtrace2(__func__, #n, #a, (long)b, #c, (long)d) - -#undef DTRACE_PROBE3 -#define DTRACE_PROBE3(n, a, b, c, d, e, f) \ - smb_dtrace3(__func__, #n, #a, (long)b, #c, (long)d, #e, (long)f) - -#endif /* _KERNEL */ - extern int smb_maxbufsize; extern int smb_flush_required; extern int smb_dirsymlink_enable; @@ -109,7 +63,6 @@ extern int smb_oplock_timeout; extern int smb_oplock_min_timeout; extern int smb_shortnames; extern int smb_sign_debug; -extern int smb_raw_mode; extern uint_t smb_audit_flags; extern int smb_ssetup_threshold; extern int smb_tcon_threshold; @@ -794,9 +747,6 @@ struct mbuf *smb_mbuf_get(uchar_t *buf, int nbytes); struct mbuf *smb_mbuf_allocate(struct uio *uio); void smb_mbuf_trim(struct mbuf *mhead, int nbytes); -void smb_check_status(void); -int smb_handle_write_raw(smb_session_t *session, smb_request_t *sr); - int32_t smb_time_gmt_to_local(smb_request_t *, int32_t); int32_t smb_time_local_to_gmt(smb_request_t *, int32_t); int32_t smb_time_dos_to_unix(int16_t, int16_t); diff --git a/usr/src/uts/common/smbsrv/smb_ktypes.h b/usr/src/uts/common/smbsrv/smb_ktypes.h index 20b1e1f014..f1802522fc 100644 --- a/usr/src/uts/common/smbsrv/smb_ktypes.h +++ b/usr/src/uts/common/smbsrv/smb_ktypes.h @@ -1489,6 +1489,7 @@ typedef struct open_param { */ uint64_t dsize; /* alloc size, actual size */ uint32_t desired_access; + uint32_t maximum_access; uint32_t share_access; uint32_t create_options; uint32_t create_disposition; @@ -1499,9 +1500,11 @@ typedef struct open_param { uint32_t action_taken; uint64_t fileid; uint32_t rootdirfid; + fsid_t op_fsid; smb_ofile_t *dir; smb_opipe_t *pipe; /* for smb_opipe_open */ struct smb_sd *sd; /* for NTTransactCreate */ + void *create_ctx; uint8_t op_oplock_level; /* requested/granted level */ boolean_t op_oplock_levelII; /* TRUE if levelII supported */ } smb_arg_open_t; diff --git a/usr/src/uts/common/smbsrv/smb_token.h b/usr/src/uts/common/smbsrv/smb_token.h index e30e29fa14..1bc8628228 100644 --- a/usr/src/uts/common/smbsrv/smb_token.h +++ b/usr/src/uts/common/smbsrv/smb_token.h @@ -71,8 +71,8 @@ typedef struct smb_buf32 { * SMB_ATF_BACKUPOP Token belongs to a Power User member * SMB_ATF_ADMIN Token belongs to a Domain Admins member */ -#define SMB_ATF_GUEST 0x00000001 -#define SMB_ATF_ANON 0x00000002 +#define SMB_ATF_ANON 0x00000001 +#define SMB_ATF_GUEST 0x00000002 #define SMB_ATF_POWERUSER 0x00000004 #define SMB_ATF_BACKUPOP 0x00000008 #define SMB_ATF_ADMIN 0x00000010 diff --git a/usr/src/uts/common/smbsrv/string.h b/usr/src/uts/common/smbsrv/string.h index 92c4fc91b4..14b95f6efa 100644 --- a/usr/src/uts/common/smbsrv/string.h +++ b/usr/src/uts/common/smbsrv/string.h @@ -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 2018 Nexenta Systems, Inc. All rights reserved. * Copyright (c) 2017 by Delphix. All rights reserved. */ @@ -85,7 +85,7 @@ typedef enum codepage_id { /* * Maximum number of bytes per multi-byte character. */ -#define MTS_MB_CUR_MAX 3 +#define MTS_MB_CUR_MAX 4 #define MTS_MB_CHAR_MAX MTS_MB_CUR_MAX typedef uint16_t smb_wchar_t; @@ -118,8 +118,8 @@ void smb_codepage_fini(void); int smb_isupper(int); int smb_islower(int); -int smb_toupper(int); -int smb_tolower(int); +uint32_t smb_toupper(uint32_t); +uint32_t smb_tolower(uint32_t); char *smb_strupr(char *); char *smb_strlwr(char *); int smb_isstrupr(const char *); @@ -130,14 +130,14 @@ boolean_t smb_match(const char *, const char *, boolean_t); size_t smb_mbstowcs(smb_wchar_t *, const char *, size_t); size_t smb_wcstombs(char *, const smb_wchar_t *, size_t); -int smb_mbtowc(smb_wchar_t *, const char *, size_t); -int smb_wctomb(char *, smb_wchar_t); +int smb_mbtowc(uint32_t *, const char *, size_t); +int smb_wctomb(char *, uint32_t); size_t smb_wcequiv_strlen(const char *); size_t smb_sbequiv_strlen(const char *); -int smb_stombs(char *, char *, int); -int smb_mbstos(char *, const char *); +int smb_oemtombs(char *, const uint8_t *, int); +int smb_mbstooem(uint8_t *, const char *, int); size_t ucstooem(char *, const smb_wchar_t *, size_t, uint32_t); size_t oemtoucs(smb_wchar_t *, const char *, size_t, uint32_t); diff --git a/usr/src/uts/common/sys/sdt.h b/usr/src/uts/common/sys/sdt.h index 6cbbe856bb..1535734a5c 100644 --- a/usr/src/uts/common/sys/sdt.h +++ b/usr/src/uts/common/sys/sdt.h @@ -21,6 +21,7 @@ /* * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2013 by Delphix. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. */ #ifndef _SYS_SDT_H @@ -244,11 +245,20 @@ extern "C" { #define DTRACE_NFSV4_3(name, type1, arg1, type2, arg2, type3, arg3) \ DTRACE_PROBE3(__nfsv4_##name, type1, arg1, type2, arg2, type3, arg3); -#define DTRACE_SMB_1(name, type1, arg1) \ - DTRACE_PROBE1(__smb_##name, type1, arg1); - -#define DTRACE_SMB_2(name, type1, arg1, type2, arg2) \ - DTRACE_PROBE2(__smb_##name, type1, arg1, type2, arg2); +/* + * The SMB probes are done a little differently from the other probes + * in this file for the benefit of the libfksmbsrv USDT provider. + * See: lib/smbsrv/libfksmbsrv/common/sys/sdt.h + */ +#define DTRACE_SMB_START(name, type1, arg1) \ + DTRACE_PROBE1(__smb_##name##__start, type1, arg1); +#define DTRACE_SMB_DONE(name, type1, arg1) \ + DTRACE_PROBE1(__smb_##name##__done, type1, arg1); + +#define DTRACE_SMB2_START(name, type1, arg1) \ + DTRACE_PROBE1(__smb2_##name##__start, type1, arg1); +#define DTRACE_SMB2_DONE(name, type1, arg1) \ + DTRACE_PROBE1(__smb2_##name##__done, type1, arg1); #define DTRACE_IP(name) \ DTRACE_PROBE(__ip_##name); |