diff options
| author | Gordon Ross <gwr@nexenta.com> | 2017-08-12 10:54:18 -0400 |
|---|---|---|
| committer | Gordon Ross <gwr@nexenta.com> | 2019-03-14 10:38:30 -0400 |
| commit | 8329232e00f1048795bae53acb230316243aadb5 (patch) | |
| tree | 0d9a71c0dd22bd5288debd1dcc2cd3f0e7131d67 /usr/src/cmd/fs.d/smbclnt | |
| parent | ebee07ff4f102cbd3179db7c5070283da35a79f3 (diff) | |
| download | illumos-joyent-8329232e00f1048795bae53acb230316243aadb5.tar.gz | |
9874 Add fksmbcl development tool
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Approved by: Joshua M. Clulow <josh@sysmgr.org>
Diffstat (limited to 'usr/src/cmd/fs.d/smbclnt')
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/Makefile | 4 | ||||
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/fksmbcl/.dbxrc | 24 | ||||
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/fksmbcl/Makefile | 104 | ||||
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/fksmbcl/README | 99 | ||||
| -rwxr-xr-x | usr/src/cmd/fs.d/smbclnt/fksmbcl/Run.sh | 32 | ||||
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/fksmbcl/Watch-fksmbcl.d | 85 | ||||
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/fksmbcl/fkdev.c | 98 | ||||
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/fksmbcl/fkiod_cl.c | 150 | ||||
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/fksmbcl/fknewvc.c | 143 | ||||
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/fksmbcl/fksmbcl_main.c | 926 | ||||
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/fksmbcl/shares.c (renamed from usr/src/cmd/fs.d/smbclnt/test/srvenum.c) | 236 | ||||
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/test/Makefile | 85 | ||||
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/test/srvinfo.c | 415 | ||||
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/test/tconn.c | 171 |
14 files changed, 1704 insertions, 868 deletions
diff --git a/usr/src/cmd/fs.d/smbclnt/Makefile b/usr/src/cmd/fs.d/smbclnt/Makefile index 5e26c570b3..e6b660643f 100644 --- a/usr/src/cmd/fs.d/smbclnt/Makefile +++ b/usr/src/cmd/fs.d/smbclnt/Makefile @@ -20,8 +20,8 @@ # # -# Copyright 2011 Nexenta Systems, Inc. All rights reserved. # Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. # # @@ -33,7 +33,7 @@ include $(SRC)/Makefile.master SUBDIRS_CATALOG= smbutil mount umount share SUBDIRS= $(SUBDIRS_CATALOG) chacl lsacl \ - smbiod smbiod-svc svc test + smbiod smbiod-svc svc fksmbcl # for messaging catalog files # diff --git a/usr/src/cmd/fs.d/smbclnt/fksmbcl/.dbxrc b/usr/src/cmd/fs.d/smbclnt/fksmbcl/.dbxrc new file mode 100644 index 0000000000..8c05f688c5 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/fksmbcl/.dbxrc @@ -0,0 +1,24 @@ + +# +# 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. +# + +# set -o emacs + +# fksmbcl is always 32-bit +setenv LD_LIBRARY_PATH ${ROOT}/usr/lib/smbfs:${ROOT}/usr/lib:${ROOT}/lib + +echo 'Do one of: attach ${PID}' +echo 'or: debug ${ROOT}/usr/lib/smbfs/fksmbcl' +echo 'then: run -v //localhost' diff --git a/usr/src/cmd/fs.d/smbclnt/fksmbcl/Makefile b/usr/src/cmd/fs.d/smbclnt/fksmbcl/Makefile new file mode 100644 index 0000000000..5ae4f56e1b --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/fksmbcl/Makefile @@ -0,0 +1,104 @@ +# +# 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 2017 Nexenta Systems, Inc. All rights reserved. +# + +PROG= fksmbcl + +OBJS_LOCAL = \ + fksmbcl_main.o \ + fkdev.o \ + fknewvc.o \ + fkiod_cl.o \ + shares.o + +OBJS= ${OBJS_LOCAL} +SRCS= ${OBJS_LOCAL:.o=.c} + +include ../../../Makefile.cmd +include ../../../Makefile.ctf + +# Force SOURCEDEBUG +CSOURCEDEBUGFLAGS = -g +CCSOURCEDEBUGFLAGS = -g +STRIP_STABS = : + +# Note: need our sys includes _before_ ENVCPPFLAGS, proto etc. +# Also, like Makefile.uts, reset CPPFLAGS +# CPPFLAGS.first += -I$(SRC)/lib/libfakekernel/common +CPPFLAGS.first += -I$(SRC)/lib/smbclnt/libfknsmb/common +CPPFLAGS= $(CPPFLAGS.first) + +INCS += -I$(SRC)/uts/common/fs/smbclnt +INCS += -I$(SRC)/uts/common +INCS += -I$(SRC)/common/smbclnt +INCS += -I$(SRC)/common + +# Allow cpp to find libfknsmb.h etc. via +# include <libfknsmb/common/libfknsmb.h> +INCS += -I$(SRC)/lib/smbclnt +INCS += -I$(SRC)/lib/libsmbfs +INCS += -I$(SRC)/lib/libsmbfs/netsmb + +CPPFLAGS += $(INCS) +CPPFLAGS += -D_REENTRANT +CPPFLAGS += -D_FILE_OFFSET_BITS=64 +CPPFLAGS += -D_LARGEFILE64_SOURCE=1 +CPPFLAGS += -DFKSMBCL +# Always want DEBUG here +CPPFLAGS += -DDEBUG + +CSTD= $(CSTD_GNU99) + +CFLAGS += $(CCVERBOSE) +CFLAGS64 += $(CCVERBOSE) + +LDFLAGS += $(ZNOLAZYLOAD) +LDFLAGS += -R/usr/lib/smbfs +LDLIBS += -L$(ROOT)/usr/lib/smbfs +LDLIBS += -lsmbfs -lfksmbfs -lfknsmb +LDLIBS += -lsocket + +ROOTSMBDDIR = $(ROOTLIB)/smbfs +ROOTSMBDFILE = $(PROG:%=$(ROOTSMBDDIR)/%) + +.KEEP_STATE: + +all: $(PROG) + +$(PROG): $(OBJS) + $(LINK.c) -o $(PROG) $(OBJS) $(LDLIBS) + $(POST_PROCESS) + +clean: + -$(RM) $(OBJS) + +# lots of lint due to mixing kernel+user stuff. give up. +lint: # lint_SRCS + +include ../../../Makefile.targ + +install: all $(ROOTSMBDFILE) + +$(ROOTSMBDDIR)/%: % + $(INS.file) diff --git a/usr/src/cmd/fs.d/smbclnt/fksmbcl/README b/usr/src/cmd/fs.d/smbclnt/fksmbcl/README new file mode 100644 index 0000000000..811401bc65 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/fksmbcl/README @@ -0,0 +1,99 @@ + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +# +# Copyright 2017 Nexenta Systems, Inc. All rights reserved. +# + +This directory builds a program linking all of the SMB client code +into a user-level process. The result is not a fully functional +SMB client but is very useful for some kinds of development work. + +The architecture of this roughly parallels the in-kernel version, +where the kernel modules are built as libraries including: + libfksmbfs, libfknsmb + +Just as with the kernel code, there are mdb modules that know +how to walk data structures in libfksmbfs, etc. + +For debugging, etc. it's easiest to run this as a normal user, +i.e. yourself (not root) + +Now you can run fksmbcl from the proto area using this script: + ./Run.sh -df + +You can also run it under dbx (see the .dbxrc file). +To run it under mdb (with mdb modules build here): + mdb -L $ROOT/usr/lib/mdb/proc:/usr/lib/mdb/proc ... +where ... is one of: fksmbcl, core.nnn, -p $PID + +There are also some dtrace scripts in here, and in ../dtrace +for watching either all activity or only selected areas. +Run these like: dtrace -s Watch-all.d -p $PID -o output + +These two (from over in ../dtrace) also work with fksmbcl: + dtrace -s fksmbcl.d -p `pgrep fksmbcl` -o output + +Here is the help output: + + > help + Commands: + help + exit + logon [user [dom [pass]]] + logoff [close-driver] + shares + mount {share} [optstr] + umount + unmount + statfs + dir {rdir} [lfile] + dirx {rdir} [lfile] + get {rfile} [lfile] + put {lfile} [rfile] + mv {from} {to} + rm {rfile} + mkdir {rfile} + rmdir {rfile} + opt {option} + + +Here is an example of how to connect, mount, and list a directory: + + $ ./Run.sh //myserver + # Start with: + > logon [user [dom [pw]]] + > shares + > mount {share} + + > logon test test test + > shares + open pipe: /srvsvc + enum strings + junk + c$ + Default Share + test1 + ipc$ + Remote IPC + test + > mount test + > dir + 1224750917 . + 1224750917 .. + 900818955 test9.dat + 3908265151 lock1.txt + 2452346625 test_dir + > umount + > logoff + > exit + $ diff --git a/usr/src/cmd/fs.d/smbclnt/fksmbcl/Run.sh b/usr/src/cmd/fs.d/smbclnt/fksmbcl/Run.sh new file mode 100755 index 0000000000..df731bf733 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/fksmbcl/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 2017 Nexenta Systems, Inc. All rights reserved. +# + +# Helper program to run fksmbd (user-space smbd for debugging) +# using binaries from the proto area. + +[ -n "$ROOT" ] || { + echo "Need a bldenv to set ROOT=..." + exit 1; +} + +# OK, setup env. to run it. + +LD_LIBRARY_PATH=$ROOT/usr/lib/smbfs:$ROOT/usr/lib:$ROOT/lib +export LD_LIBRARY_PATH + +# run with the passed options +exec $ROOT/usr/lib/smbfs/fksmbcl "$@" diff --git a/usr/src/cmd/fs.d/smbclnt/fksmbcl/Watch-fksmbcl.d b/usr/src/cmd/fs.d/smbclnt/fksmbcl/Watch-fksmbcl.d new file mode 100644 index 0000000000..823115bf9c --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/fksmbcl/Watch-fksmbcl.d @@ -0,0 +1,85 @@ +#!/usr/sbin/dtrace -s +/* + * This file and its contents are supplied under the terms of the + * Common Development and Distribution License ("CDDL"), version 1.0. + * You may only use this file in accordance with the terms of version + * 1.0 of the CDDL. + * + * A full copy of the text of the CDDL should have accompanied this + * source. A copy of the CDDL is also available via the Internet at + * http://www.illumos.org/license/CDDL. + */ + +/* + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * User-level dtrace for fksmbcl + * Usage: dtrace -s Watch-fksmbcl.d -p $PID + */ + +self int trace; + +/* + * Trace almost everything + */ +pid$target:fksmbcl::entry +{ + self->trace++; +} + +pid$target:fksmbcl::return +{ + self->trace--; +} + +/* + * If traced, print entry/return + */ +pid$target:fksmbcl::entry, +pid$target:libsmbfs.so.1::entry, +pid$target:libfksmbfs.so.1::entry, +pid$target:libfknsmb.so.1::entry, +pid$target:libfakekernel.so.1::entry +/self->trace > 0/ +{ + printf("\t0x%x", arg0); + printf("\t0x%x", arg1); + printf("\t0x%x", arg2); + printf("\t0x%x", arg3); + printf("\t0x%x", arg4); + printf("\t0x%x", arg5); +} + +pid$target:fksmbcl::return, +pid$target:libsmbfs.so.1::return, +pid$target:libfksmbfs.so.1::return, +pid$target:libfknsmb.so.1::return, +pid$target:libfakekernel.so.1::entry +/self->trace > 0/ +{ + printf("\t0x%x", arg1); +} + +pid$target::smbfslookup:entry +{ + printf("\tname = %s\n", copyinstr(arg1)); +} + +pid$target:libfknsmb.so.1:smb_dtrace2:entry +/copyinstr(arg0) == "debugmsg2"/ +{ + this->f = copyinstr(arg1); + this->m = copyinstr(arg2); + printf("\n\t debugmsg2: %s: %s ", this->f, this->m); +} + +pid$target:libfknsmb.so.1:smb_dtrace3:entry +/copyinstr(arg0) == "debugmsg3"/ +{ + this->f = copyinstr(arg1); + this->m = copyinstr(arg2); + printf("\n\t debugmsg3: %s: %s ", this->f, this->m); + trace(arg3); +} diff --git a/usr/src/cmd/fs.d/smbclnt/fksmbcl/fkdev.c b/usr/src/cmd/fs.d/smbclnt/fksmbcl/fkdev.c new file mode 100644 index 0000000000..34da749e78 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/fksmbcl/fkdev.c @@ -0,0 +1,98 @@ +/* + * 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. + */ + +/* + * This file implements device open/close/ioctl wrappers that + * redirect access from the real "nsmb" device to the in-process + * device simulation in libfknsmb. + */ + +#include <sys/param.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/mount.h> +#include <sys/types.h> +#include <sys/byteorder.h> + +#include <fcntl.h> +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include <pwd.h> +#include <grp.h> +#include <unistd.h> +#include <libintl.h> +#include <assert.h> +#include <nss_dbdefs.h> + +#include <cflib.h> +#include <netsmb/smb_lib.h> +#include <netsmb/netbios.h> +#include <netsmb/nb_lib.h> +#include <netsmb/smb_dev.h> + +#include <libfknsmb/common/libfknsmb.h> + +#include "smb/charsets.h" +#include "smb/private.h" + +int +smb_open_driver(void) +{ + dev32_t dev; + int fd; + int rc; + + rc = nsmb_drv_open(&dev, 0, 0); + if (rc != 0) { + errno = rc; + return (-1); + } + + assert((dev & 0xFFFF0000) != 0); + fd = (int)dev; + + return (fd); +} + +int +nsmb_ioctl(int fd, int cmd, void *arg) +{ + dev32_t dev; + int err; + + dev = (dev32_t)fd; + assert((dev & 0xFFFF0000) != 0); + err = nsmb_drv_ioctl(dev, cmd, (intptr_t)arg, 0); + if (err != 0) { + errno = err; + return (-1); + } + return (0); +} + +int +nsmb_close(int fd) +{ + dev32_t dev; + + dev = (dev32_t)fd; + assert((dev & 0xFFFF0000) != 0); + (void) nsmb_drv_close(dev, 0, 0); + return (0); +} diff --git a/usr/src/cmd/fs.d/smbclnt/fksmbcl/fkiod_cl.c b/usr/src/cmd/fs.d/smbclnt/fksmbcl/fkiod_cl.c new file mode 100644 index 0000000000..be26854bd3 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/fksmbcl/fkiod_cl.c @@ -0,0 +1,150 @@ +/* + * 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) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright 2017 Nexenta Systems, Inc. All rights reserved. + */ + +/* + * Client-side interface to the IO Daemon (IOD) + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include <unistd.h> +#include <netdb.h> +#include <libintl.h> +#include <thread.h> + +#include <sys/byteorder.h> +#include <sys/types.h> +#include <sys/fcntl.h> +#include <sys/ioctl.h> +#include <sys/time.h> +#include <sys/socket.h> + +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> + +#include <netsmb/smb_lib.h> +#include <netsmb/netbios.h> +#include <netsmb/nb_lib.h> +#include <netsmb/smb_dev.h> + +#include <assert.h> + +#include "smb/charsets.h" +#include "smb/private.h" + +/* + * Make sure we don't call the real IOD here. + */ +int +smb_iod_open_door(int *fdp) +{ + *fdp = -1; + return (ENOTSUP); +} + +/* + * Get a door handle to the IOD... + */ +int +smb_iod_start(smb_ctx_t *ctx) +{ + return (0); +} + +void * +iod_work(void *arg) +{ + smb_ctx_t *ctx = arg; + (void) smb_iod_work(ctx); + smb_ctx_free(ctx); + return (NULL); +} + +/* + * Ask the IOD to connect using the info in ctx. + * Called by newvc. + * + * This function largely follows smbiod.c : iod_newvc() + */ +int +smb_iod_cl_newvc(smb_ctx_t *cl_ctx) +{ + smb_ctx_t *ctx; + thread_t tid; + int err = 0; + + /* + * Clone the context, like in smbiod.c + */ + err = smb_ctx_alloc(&ctx); + if (err) + return (err); + bcopy(&cl_ctx->ct_iod_ssn, &ctx->ct_iod_ssn, + sizeof (ctx->ct_iod_ssn)); + + /* + * Create the driver session first... + */ + if ((err = smb_ctx_gethandle(ctx)) != 0) + goto out; + if (nsmb_ioctl(ctx->ct_dev_fd, SMBIOC_SSN_CREATE, &ctx->ct_ssn) < 0) { + err = errno; + if (err == EEXIST) + err = 0; /* see above */ + goto out; + } + + /* + * Do the initial connection setup here, so we can + * report the outcome to the door client. + */ + err = smb_iod_connect(ctx); + if (err != 0) { + fprintf(stderr, "smb_iod_connect, err=%d\n", err); + goto out; + } + + /* The rest happens in the iod_work thread. */ + err = thr_create(NULL, 0, iod_work, ctx, THR_DETACHED, &tid); + if (err == 0) { + /* + * Given to the new thread. + * free at end of iod_work + */ + ctx = NULL; + } + +out: + if (ctx != NULL) + smb_ctx_free(ctx); + + return (err); +} diff --git a/usr/src/cmd/fs.d/smbclnt/fksmbcl/fknewvc.c b/usr/src/cmd/fs.d/smbclnt/fksmbcl/fknewvc.c new file mode 100644 index 0000000000..7f66b3b5bb --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/fksmbcl/fknewvc.c @@ -0,0 +1,143 @@ +/* + * 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. + */ + +/* + * Create a new VC given a list of addresses. + */ + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include <unistd.h> +#include <netdb.h> +#include <libintl.h> +#include <xti.h> +#include <assert.h> + +#include <sys/types.h> +#include <sys/time.h> +#include <sys/byteorder.h> +#include <sys/socket.h> +#include <sys/fcntl.h> + +#include <netinet/in.h> +#include <netinet/tcp.h> +#include <arpa/inet.h> + +#include <netsmb/smb.h> +#include <netsmb/smb_lib.h> +#include <netsmb/netbios.h> +#include <netsmb/nb_lib.h> +#include <netsmb/smb_dev.h> + +#include "smb/charsets.h" +#include "smb/private.h" + +/* + * Ask the IOD to create a VC with this IP address. + */ +static int +fknewvc(struct smb_ctx *ctx, struct addrinfo *ai) +{ + char host[256]; + char svc[32]; + smbioc_ossn_t *ssn = &ctx->ct_ssn; + int err; + + if (smb_debug) { + err = getnameinfo(ai->ai_addr, ai->ai_addrlen, + host, sizeof (host), svc, sizeof (svc), + AI_NUMERICHOST); + if (err != 0) { + strlcpy(host, "(?)", sizeof (host)); + strlcpy(svc, "?", sizeof (host)); + } + printf("fknewvc: Try AF=%d %s:%s\n", + ai->ai_family, host, svc); + } + + /* + * Copy the passed address into ssn_srvaddr, + * but first sanity-check lengths. Also, + * zero it first to avoid trailing junk. + */ + if (ai->ai_addrlen > sizeof (ssn->ssn_srvaddr)) + return (EINVAL); + bzero(&ssn->ssn_srvaddr, sizeof (ssn->ssn_srvaddr)); + bcopy(ai->ai_addr, &ssn->ssn_srvaddr, ai->ai_addrlen); + + /* Ask the IOD to connect using the info in ctx. */ + err = smb_iod_cl_newvc(ctx); + if (smb_debug) { + printf("fknewvc: iod_cl_newvc err=%d\n", err); + } + + return (err); +} + +/* + * Setup a new VC via the IOD. + * Similar to findvc.c + */ +int +smb_ctx_newvc(struct smb_ctx *ctx) +{ + struct addrinfo *ai; + int err; + + /* Should already have the address list. */ + if ((ctx->ct_flags & SMBCF_RESOLVED) == 0) + return (EINVAL); + + err = EPROTONOSUPPORT; /* in case no AF match */ + for (ai = ctx->ct_addrinfo; ai; ai = ai->ai_next) { + + switch (ai->ai_family) { + + case AF_INET: + case AF_INET6: + case AF_NETBIOS: + err = fknewvc(ctx, ai); + if (err == 0) + return (0); + break; + + default: + break; + } + } + + /* + * In the error case, the caller may try again + * with new auth. info, so keep the door open. + * Error return will close in smb_ctx_done. + */ + return (err); +} diff --git a/usr/src/cmd/fs.d/smbclnt/fksmbcl/fksmbcl_main.c b/usr/src/cmd/fs.d/smbclnt/fksmbcl/fksmbcl_main.c new file mode 100644 index 0000000000..65b0312558 --- /dev/null +++ b/usr/src/cmd/fs.d/smbclnt/fksmbcl/fksmbcl_main.c @@ -0,0 +1,926 @@ +/* + * 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. + */ + +/* + * Test & debug program for the SMB client + * + * This implements a simple command reader which accepts + * commands to simulate system calls into the file system. + */ + +#include <sys/types.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/mount.h> +#include <sys/dirent.h> +#include <sys/strlog.h> /* SL_NOTE */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <strings.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> + +#include <sys/fs/smbfs_mount.h> +#include <netsmb/smb_lib.h> +#include <libfknsmb/common/libfknsmb.h> +#include <libfksmbfs/common/libfksmbfs.h> + +#if _FILE_OFFSET_BITS != 64 +#error "This calls (fake) VFS code which requires 64-bit off_t" +#endif + +extern int list_shares(struct smb_ctx *); + +#define MAXARG 10 + +struct cmd_tbl_ent { + void (*ce_func)(int, char **); + const char *ce_name; + const char *ce_argdesc; +}; +static struct cmd_tbl_ent cmd_tbl[]; + +static struct smb_ctx *ctx = NULL; +static char *server = NULL; + +static vfs_t *vfsp = NULL; + +static void show_dents(vnode_t *, offset_t *, char *, int); +static void run_cli(void); + +#define TBUFSZ 8192 +static char tbuf[TBUFSZ]; + +static void +fksmbcl_usage(void) +{ + printf("usage: fksmbcl //user@server (like smbutil)\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int error, opt; + + /* + * Initializations + */ + nsmb_drv_load(); + nsmb_drv_init(); + fksmbfs_init(); + + while ((opt = getopt(argc, argv, "dv")) != -1) { + switch (opt) { + case 'd': + smb_debug++; + break; + case 'v': + smb_verbose++; + break; + case '?': + fksmbcl_usage(); + break; + } + } + if (optind >= argc) + fksmbcl_usage(); + server = argv[optind]; + + /* + * Setup the libsmbfs context + */ + error = smb_ctx_alloc(&ctx); + if (error) { + fprintf(stderr, "%s: smb_ctx_alloc failed (%d)\n", + argv[0], error); + return (1); + } + + error = smb_ctx_scan_argv(ctx, argc, argv, + SMBL_SERVER, SMBL_SERVER, USE_WILDCARD); + if (error) { + fprintf(stderr, "logon: smb_ctx_scan_argv, error %d\n", error); + return (1); + } + error = smb_ctx_readrc(ctx); + if (error) { + fprintf(stderr, "logon: smb_ctx_readrc, error %d\n", error); + return (1); + } + + /* Do smb_ctx_setshare later, and smb_ctx_resolve. */ + + /* + * Next would be smb_ctx_get_ssn() but don't do that until + * the "logon" command so one can set breakpoints etc. + */ + + /* + * Run the CLI + */ + run_cli(); + + /* + * Cleanup + */ + fksmbfs_fini(); + nsmb_drv_fini(); + + return (0); +} + +static void +run_cli() +{ + static char cmdbuf[100]; + int argc, i; + char *argv[MAXARG]; + char *cmd; + char *savep = NULL; + char *sep = " \t\n"; + char *prompt = NULL; + struct cmd_tbl_ent *ce; + + if (isatty(0)) { + fputs("# Start with:\n" + "> logon [user [dom [pw]]]\n" + "> shares\n" + "> mount {share}\n\n", + stdout); + prompt = "> "; + } + + for (;;) { + if (prompt) { + fputs(prompt, stdout); + fflush(stdout); + } + + cmd = fgets(cmdbuf, sizeof (cmdbuf), stdin); + if (cmd == NULL) + break; + if (cmd[0] == '#') + continue; + + if (prompt == NULL) { + /* Put commands in the output too. */ + fprintf(stdout, "+ %s", cmdbuf); + } + + argv[0] = strtok_r(cmd, sep, &savep); + if (argv[0] == NULL) + continue; + for (argc = 1; argc < MAXARG; argc++) { + argv[argc] = strtok_r(NULL, sep, &savep); + if (argv[argc] == NULL) + break; + } + for (i = argc; i < MAXARG; i++) + argv[i++] = NULL; + + for (ce = cmd_tbl; ce->ce_name != NULL; ce++) + if (strcmp(ce->ce_name, argv[0]) == 0) + break; + if (ce->ce_name != NULL) { + ce->ce_func(argc, argv); + } else { + fprintf(stderr, "%s unknown command. Try help\n", + argv[0]); + } + } +} + +/* + * Command handlers + */ + +static void +do_exit(int argc, char **argv) +{ + exit(0); +} + +static void +do_help(int argc, char **argv) +{ + struct cmd_tbl_ent *ce; + + printf("Commands:\n"); + for (ce = cmd_tbl; ce->ce_func != NULL; ce++) + printf("%s %s\n", ce->ce_name, ce->ce_argdesc); +} + +static void +do_logon(int argc, char **argv) +{ + int error; + + if (argc > 1) { + if (argv[1][0] == '-') { + smb_ctx_setuser(ctx, "", B_TRUE); + ctx->ct_flags |= SMBCF_NOPWD; + } else { + smb_ctx_setuser(ctx, argv[1], B_TRUE); + } + } + if (argc > 2) + smb_ctx_setdomain(ctx, argv[2], B_TRUE); + if (argc > 3) + smb_ctx_setpassword(ctx, argv[3], NULL); + + /* + * Resolve the server address, setup derived defaults. + */ + error = smb_ctx_resolve(ctx); + if (error) { + fprintf(stderr, "logon: smb_ctx_resolve, error %d\n", error); + return; + } + + /* + * Have server, share, etc. now. + * Get the logon session. + */ +again: + error = smb_ctx_get_ssn(ctx); + if (error == EAUTH) { + int err2; + err2 = smb_get_authentication(ctx); + if (err2 == 0) + goto again; + } + if (error) { + fprintf(stderr, "//%s: login failed, error %d\n", + ctx->ct_fullserver, error); + } +} + +/* + * Drop session created by the "logon" command. + */ +static void +do_logoff(int argc, char **argv) +{ + + (void) nsmb_ioctl(ctx->ct_dev_fd, SMBIOC_SSN_RELE, NULL); + if (argc > 1) { + smb_ctx_done(ctx); + (void) smb_ctx_init(ctx); + } +} + +/* + * List shares + */ +static void +do_shares(int argc, char **argv) +{ + int error; + + smb_ctx_setshare(ctx, "IPC$", USE_IPC); + error = smb_ctx_get_tree(ctx); + if (error) { + fprintf(stderr, "shares, tcon IPC$, error=%d\n", error); + return; + } + + error = list_shares(ctx); + if (error) { + fprintf(stderr, "shares, enum, error=%d\n", error); + } + + (void) nsmb_ioctl(ctx->ct_dev_fd, SMBIOC_TREE_RELE, NULL); +} + +char mnt_opt_buf[MAX_MNTOPT_STR]; +char mnt_resource[MAXPATHLEN]; + +/* + * Minimal excerpt from vfs.c:domount() + */ +void +do_mount(int argc, char **argv) +{ + struct smbfs_args mdata; + struct mounta ma; + char *shrname; + int error; + + if (vfsp != NULL) { + fprintf(stderr, "Already mounted\n"); + return; + } + + if (argc < 2) { + fprintf(stderr, "%s: missing share name\n", argv[0]); + return; + } + shrname = argv[1]; + if (argc > 2) + strlcpy(mnt_opt_buf, argv[2], sizeof (mnt_opt_buf)); + else + memset(mnt_opt_buf, 0, sizeof (mnt_opt_buf)); + + smb_ctx_setshare(ctx, shrname, USE_DISKDEV); + error = smb_ctx_get_tree(ctx); + if (error) { + fprintf(stderr, "//%s/%s: tree connect failed, %d\n", + server, shrname, error); + return; + } + + (void) snprintf(mnt_resource, sizeof (mnt_resource), + "//%s/%s", ctx->ct_fullserver, shrname); + + bzero(&mdata, sizeof (mdata)); + mdata.version = SMBFS_VERSION; /* smbfs mount version */ + mdata.file_mode = S_IRWXU; + mdata.dir_mode = S_IRWXU; + mdata.devfd = ctx->ct_dev_fd; + + /* Build mount args */ + bzero(&ma, sizeof (ma)); + ma.spec = mnt_resource; + ma.dir = "/"; + ma.flags = MS_DATA | MS_OPTIONSTR | MS_NOSPLICE | MS_NOSUID; + ma.fstype = "smbfs"; + ma.dataptr = (void *) &mdata; + ma.datalen = sizeof (mdata); + ma.optptr = mnt_opt_buf; + ma.optlen = sizeof (mnt_opt_buf); + + error = fake_domount("smbfs", &ma, &vfsp); + if (error != 0) { + fprintf(stderr, "domount error=%d\n", error); + } + + /* Mount takes a ref, so always rele here. */ + (void) nsmb_ioctl(ctx->ct_dev_fd, SMBIOC_TREE_RELE, NULL); +} + +void +do_unmount(int argc, char **argv) +{ + int error; + + if (vfsp == NULL) { + fprintf(stderr, "Not mounted\n"); + return; + } + + error = fake_dounmount(vfsp, 0); + if (error != 0) { + fprintf(stderr, "dounmount error=%d\n", error); + return; + } + vfsp = NULL; +} + +void +do_statfs(int argc, char **argv) +{ + statvfs64_t st; + int error; + + if (vfsp == NULL) { + fprintf(stderr, "Not mounted\n"); + return; + } + + error = fsop_statfs(vfsp, &st); + if (error != 0) { + fprintf(stderr, "df error=%d\n", error); + return; + } + printf("bsize=%ld\n", st.f_bsize); + printf("frsize=%ld\n", st.f_frsize); + printf("blocks=%" PRIu64 "\n", st.f_blocks); + printf(" bfree=%" PRIu64 "\n", st.f_bfree); + printf("bavail=%" PRIu64 "\n", st.f_bavail); +} + +void +do_dir(int argc, char **argv) +{ + char *rdir; + vnode_t *vp = NULL; + offset_t off; + int cnt; + int error; + + if (vfsp == NULL) { + fprintf(stderr, "mnt required first\n"); + return; + } + if (argc > 1) + rdir = argv[1]; + else + rdir = ""; + + error = vn_open(rdir, 0, FREAD, 0, &vp, 0, 0); + if (error != 0) { + fprintf(stderr, "do_dir, vn_open error=%d\n", error); + return; + } + + off = 0; + do { + cnt = fake_getdents(vp, &off, tbuf, TBUFSZ); + if (cnt < 0) { + fprintf(stderr, "do_dir, getdents %d\n", -cnt); + break; + } + show_dents(vp, &off, tbuf, cnt); + } while (cnt > 0); + + if (vp != NULL) + vn_close_rele(vp, 0); +} + +void +do_dirx(int argc, char **argv) +{ + char *rdir; + vnode_t *vp = NULL; + offset_t off; + int cnt; + int error; + + if (vfsp == NULL) { + fprintf(stderr, "mnt required first\n"); + return; + } + if (argc > 1) + rdir = argv[1]; + else + rdir = ""; + + error = vn_open(rdir, 0, FREAD|FXATTRDIROPEN, 0, &vp, 0, 0); + if (error != 0) { + fprintf(stderr, "do_dirx, vn_open error=%d\n", error); + return; + } + + off = 0; + do { + cnt = fake_getdents(vp, &off, tbuf, TBUFSZ); + if (cnt < 0) { + fprintf(stderr, "do_dirx, getdents %d\n", -cnt); + break; + } + show_dents(vp, &off, tbuf, cnt); + } while (cnt > 0); + + if (vp != NULL) + vn_close_rele(vp, 0); +} + +static void +show_dents(vnode_t *dvp, offset_t *offp, char *buf, int cnt) +{ + char time_buf[40]; + struct stat64 st; + vnode_t *vp; + char *p; + dirent_t *d; + offset_t offset = (offset_t)-1L; + int error; + uint_t mode; + char type; + + p = buf; + while (p < (buf + cnt)) { + d = (dirent_t *)(void *)p; + p += d->d_reclen; + offset = d->d_off; + + error = fake_lookup(dvp, d->d_name, &vp); + if (error != 0) { + fprintf(stderr, "%s: lookup error=%d\n", + d->d_name, error); + continue; + } + error = fake_stat(vp, &st, 0); + vn_rele(vp); + if (error != 0) { + fprintf(stderr, "%s: stat error=%d\n", + d->d_name, error); + continue; + } + + /* + * Print type, mode, size, name + * First mode (only dir, file expected here) + */ + if (S_ISDIR(st.st_mode)) { + type = 'd'; + } else if (S_ISREG(st.st_mode)) { + type = ' '; + } else { + type = '?'; + } + mode = st.st_mode & 0777; + (void) strftime(time_buf, sizeof (time_buf), + "%b %e %T %Y", localtime(&st.st_mtime)); + + printf("%c 0%3o %9" PRIu64 " %s %s\n", + type, mode, + (uint64_t)st.st_size, + time_buf, + d->d_name); + } + *offp = offset; +} + +/* + * get rname [lname] + */ +void +do_get(int argc, char **argv) +{ + struct stat64 st; + char *rname; + char *lname; + vnode_t *vp = NULL; + offset_t off; + ssize_t cnt, x; + int oflg = O_RDWR | O_CREAT; + int lfd = -1; + int error; + + if (vfsp == NULL) { + fprintf(stderr, "mnt required first\n"); + return; + } + if (argc < 2) { + fprintf(stderr, "rname required\n"); + return; + } + rname = argv[1]; + if (argc > 2) { + lname = argv[2]; + /* + * When local name is specified, overwrite. + * Convenient for scripts etc. + */ + oflg |= O_TRUNC; + } else { + lname = rname; + /* Local file should not exist. */ + oflg |= O_EXCL; + } + + lfd = open(lname, oflg, 0644); + if (lfd < 0) { + perror(lname); + return; + } + + error = vn_open(rname, 0, FREAD, 0, &vp, 0, 0); + if (error != 0) { + fprintf(stderr, "do_get, vn_open error=%d\n", error); + goto out; + } + error = fake_stat(vp, &st, 0); + if (error != 0) { + fprintf(stderr, "do_get, stat error=%d\n", error); + goto out; + } + + off = 0; + do { + cnt = fake_pread(vp, tbuf, TBUFSZ, off); + if (cnt < 0) { + fprintf(stderr, "do_get, read %d\n", -cnt); + goto out; + } + x = write(lfd, tbuf, cnt); + if (x < 0) { + fprintf(stderr, "do_get, write %d\n", errno); + goto out; + } + off += x; + } while (off < st.st_size); + +out: + if (vp != NULL) + vn_close_rele(vp, 0); + if (lfd != -1) + close(lfd); +} + +/* + * put lname [rname] + */ +void +do_put(int argc, char **argv) +{ + struct stat64 rst; + struct stat st; + char *rname; + char *lname; + vnode_t *vp = NULL; + offset_t off; + ssize_t cnt, x; + int oflg = FREAD|FWRITE|FCREAT; + int lfd = -1; + int error; + + if (vfsp == NULL) { + fprintf(stderr, "mnt required first\n"); + return; + } + if (argc < 2) { + fprintf(stderr, "lname required\n"); + return; + } + lname = argv[1]; + if (argc > 2) { + rname = argv[2]; + /* + * When remote name is specified, overwrite. + * Convenient for scripts etc. + */ + oflg |= FTRUNC; + } else { + rname = lname; + /* Remote file should not exist. */ + oflg |= FEXCL; + } + + lfd = open(lname, O_RDONLY, 0); + if (lfd < 0) { + perror(lname); + return; + } + error = fstat(lfd, &st); + if (error != 0) { + fprintf(stderr, "do_put, stat error=%d\n", error); + goto out; + } + + error = vn_open(rname, 0, oflg, 0, &vp, 0, 0); + if (error != 0) { + fprintf(stderr, "do_put, vn_open error=%d\n", error); + goto out; + } + + off = 0; + do { + cnt = pread(lfd, tbuf, TBUFSZ, off); + if (cnt < 0) { + fprintf(stderr, "do_put, read %d\n", errno); + goto out; + } + x = fake_pwrite(vp, tbuf, cnt, off); + if (x < 0) { + fprintf(stderr, "do_put, write %d\n", -x); + goto out; + } + off += cnt; + } while (off < st.st_size); + + /* This getattr should go OtW. */ + error = fake_stat(vp, &rst, 0); + if (error != 0) { + fprintf(stderr, "do_put, stat error=%d\n", error); + goto out; + } + if (rst.st_size != st.st_size) { + fprintf(stderr, "do_put, wrong size?\n"); + } + +out: + if (vp != NULL) + vn_close_rele(vp, 0); + if (lfd != -1) + close(lfd); +} + +/* + * rm rname + */ +void +do_rm(int argc, char **argv) +{ + char *rname; + int error; + + if (vfsp == NULL) { + fprintf(stderr, "mnt required first\n"); + return; + } + if (argc < 2) { + fprintf(stderr, "rname required\n"); + return; + } + rname = argv[1]; + + error = fake_unlink(rname, 0); + if (error != 0) { + fprintf(stderr, "do_rm, unlink error=%d\n", error); + } +} + +/* + * mv fromname toname + */ +void +do_mv(int argc, char **argv) +{ + int error; + + if (vfsp == NULL) { + fprintf(stderr, "mnt required first\n"); + return; + } + if (argc < 3) { + fprintf(stderr, "from_name to_name required\n"); + return; + } + + error = fake_rename(argv[1], argv[2]); + if (error != 0) { + fprintf(stderr, "do_mv, rename error=%d\n", error); + } +} + +/* + * mkdir rname + */ +void +do_mkdir(int argc, char **argv) +{ + char *rname; + vnode_t *vp = NULL; + int error; + + if (vfsp == NULL) { + fprintf(stderr, "mnt required first\n"); + return; + } + if (argc < 2) { + fprintf(stderr, "rname required\n"); + return; + } + rname = argv[1]; + + error = vn_open(rname, 0, FCREAT, 0, &vp, CRMKDIR, 0); + if (error != 0) { + fprintf(stderr, "do_mkdir, vn_open error=%d\n", error); + } + + if (vp != NULL) + vn_close_rele(vp, 0); +} + +/* + * rmdir rname + */ +void +do_rmdir(int argc, char **argv) +{ + char *rname; + int error; + + if (vfsp == NULL) { + fprintf(stderr, "mnt required first\n"); + return; + } + if (argc < 2) { + fprintf(stderr, "rname required\n"); + return; + } + rname = argv[1]; + + error = fake_unlink(rname, AT_REMOVEDIR); + if (error != 0) { + fprintf(stderr, "do_rmdir, unlink error=%d\n", error); + } +} + +/* + * Simple option setting + * + * Each arg is handled as one line in .nsmbrc [default] + */ +void +do_opt(int argc, char **argv) +{ + static char template[20] = "/tmp/fksmbclXXXXXX"; + static char rcname[30]; + char *tdname; + char *save_home; + FILE *fp; + int err, i; + + if (argc < 2) { + fprintf(stderr, "opt {key}[=value]\n"); + return; + } + + tdname = mkdtemp(template); + if (tdname == NULL) { + perror("mkdtemp"); + return; + } + (void) snprintf(rcname, sizeof (rcname), + "%s/.nsmbrc", tdname); + + fp = fopen(rcname, "w"); + if (fp == NULL) { + perror(rcname); + goto out; + } + fprintf(fp, "[default]\n"); + for (i = 1; i < argc; i++) + fprintf(fp, "%s\n", argv[i]); + fclose(fp); + + save_home = ctx->ct_home; + ctx->ct_home = tdname; + err = smb_ctx_readrc(ctx); + ctx->ct_home = save_home; + + if (err != 0) + fprintf(stderr, "readrc, err=%d\n", err); + +out: + (void) unlink(rcname); + (void) rmdir(tdname); +} + +/* + * Command table + */ +static struct cmd_tbl_ent +cmd_tbl[] = { + { do_help, "help", "" }, + { do_exit, "exit", "" }, + { do_logon, "logon", "[user [dom [pass]]]" }, + { do_logoff, "logoff", "[close-driver]" }, + { do_shares, "shares", "" }, + { do_mount, "mount", "{share} [optstr]" }, + { do_unmount, "umount", "" }, + { do_unmount, "unmount", "" }, + { do_statfs, "statfs", "" }, + { do_dir, "dir", "{rdir} [lfile]" }, + { do_dirx, "dirx", "{rdir} [lfile]" }, + { do_get, "get", "{rfile} [lfile]" }, + { do_put, "put", "{lfile} [rfile]" }, + { do_mv, "mv", "{from} {to}" }, + { do_rm, "rm", "{rfile}" }, + { do_mkdir, "mkdir", "{rfile}" }, + { do_rmdir, "rmdir", "{rfile}" }, + { do_opt, "opt", "{option}" }, + { NULL, NULL, NULL } +}; + +/* + * Provide a real function (one that prints something) to replace + * the stub in libfakekernel. This prints cmn_err() messages. + */ +void +fakekernel_putlog(char *msg, size_t len, int flags) +{ + + /* + * [CE_CONT, CE_NOTE, CE_WARN, CE_PANIC] maps to + * [SL_NOTE, SL_NOTE, SL_WARN, SL_FATAL] + */ + if (smb_debug == 0 && (flags & SL_NOTE)) + return; + (void) fwrite(msg, 1, len, stdout); + (void) fflush(stdout); +} + +/* + * Enable libumem debugging + */ +const char * +_umem_debug_init(void) +{ + return ("default,verbose"); /* $UMEM_DEBUG setting */ +} + +const char * +_umem_logging_init(void) +{ + return ("fail,contents"); /* $UMEM_LOGGING setting */ +} diff --git a/usr/src/cmd/fs.d/smbclnt/test/srvenum.c b/usr/src/cmd/fs.d/smbclnt/fksmbcl/shares.c index ee3aeba014..2d8d0cf6da 100644 --- a/usr/src/cmd/fs.d/smbclnt/test/srvenum.c +++ b/usr/src/cmd/fs.d/smbclnt/fksmbcl/shares.c @@ -21,7 +21,7 @@ /* * Copyright (c) 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. */ /* @@ -36,27 +36,17 @@ #include <string.h> #include <unistd.h> #include <libintl.h> +#include <ctype.h> -#include <netsmb/smbfs_api.h> +#include <netsmb/smb_lib.h> /* * This is a quick hack for testing client-side named pipes. - * Its purpose is to test the ability to connect to a server, - * open a pipe, send and receive data. The "hack" aspect is - * the use of hand-crafted RPC messages, which allows testing - * of the named pipe API separately from the RPC libraries. - * - * I captured the two small name pipe messages sent when - * requesting a share list via RPC over /pipe/srvsvc and - * dropped them into the arrays below (bind and enum). - * This program sends the two messages (with adjustments) - * and just dumps whatever comes back over the pipe. - * Use wireshark if you want to see decoded messages. + * Its purpose is to test SMB named-pipe interface separately + * from the RPC implementation. It's a "hack" because it uses + * hand-crafted RPC messages (extracted from network traffic). */ -extern char *optarg; -extern int optind, opterr, optopt; - /* This is a DCE/RPC bind call for "srvsvc". */ static const uchar_t srvsvc_bind[] = { @@ -95,175 +85,35 @@ srvsvc_enum2[] = { static uchar_t sendbuf[1024]; static uchar_t recvbuf[4096]; -static char *server; - -static int pipetest(struct smb_ctx *); +/* + * Print strings found in the buffer. + */ static void -srvenum_usage(void) +pstrings(const uchar_t *buf, int len) { - printf("usage: srvenum [-d domain][-u user][-p passwd] server\n"); - exit(1); -} - -int -main(int argc, char *argv[]) -{ - int c, error; - struct smb_ctx *ctx = NULL; - char *dom = NULL; - char *usr = NULL; - char *pw = NULL; - - while ((c = getopt(argc, argv, "vd:u:p:")) != -1) { - switch (c) { - case 'v': - smb_verbose = 1; - break; - - case 'd': - dom = optarg; - break; - case 'u': - usr = optarg; - break; - case 'p': - pw = optarg; - break; - case '?': - srvenum_usage(); - break; + const uchar_t *p = buf; + uint16_t u2; + boolean_t instr = B_FALSE; + + while (len > 2) { + u2 = *p++; + u2 |= (*p++) << 8; + len -= 2; + + if ((u2 & 0xFF80) == 0 && isprint(u2)) { + /* printable */ + instr = B_TRUE; + putchar(u2); + } else { + /* not printalbe */ + if (instr) + putchar('\n'); + instr = B_FALSE; } } - if (optind >= argc) - srvenum_usage(); - server = argv[optind]; - - if (pw != NULL && (dom == NULL || usr == NULL)) { - fprintf(stderr, "%s: -p arg requires -d dom -u usr\n", - argv[0]); - srvenum_usage(); - } - - /* - * This section is intended to demonstrate how an - * RPC client library might use this interface. - */ - error = smb_ctx_alloc(&ctx); - if (error) { - fprintf(stderr, "%s: smb_ctx_alloc failed\n", argv[0]); - goto out; - } - - /* - * Set server, share, domain, user - * (in the ctx handle). - */ - smb_ctx_setfullserver(ctx, server); - smb_ctx_setshare(ctx, "IPC$", USE_IPC); - if (dom) - smb_ctx_setdomain(ctx, dom, B_TRUE); - if (usr) - smb_ctx_setuser(ctx, usr, B_TRUE); - if (pw) - smb_ctx_setpassword(ctx, pw, NULL); - - - /* - * If this code were in smbutil or mount_smbfs, it would - * get system and $HOME/.nsmbrc settings here, like this: - */ -#if 0 - error = smb_ctx_readrc(ctx); - if (error) { - fprintf(stderr, "%s: smb_ctx_readrc failed\n", argv[0]); - goto out; - } -#endif - - /* - * Resolve the server address, - * setup derived defaults. - */ - error = smb_ctx_resolve(ctx); - if (error) { - fprintf(stderr, "%s: smb_ctx_resolve failed\n", argv[0]); - goto out; - } - - /* - * Get the session and tree. - */ - error = smb_ctx_get_ssn(ctx); - if (error) { - fprintf(stderr, "//%s: login failed, error %d\n", - server, error); - goto out; - } - error = smb_ctx_get_tree(ctx); - if (error) { - fprintf(stderr, "//%s/%s: tree connect failed, %d\n", - server, "IPC$", error); - goto out; - } - - /* - * Do some named pipe I/O. - */ - error = pipetest(ctx); - if (error) { - fprintf(stderr, "pipetest, %d\n", error); - goto out; - } - -out: - smb_ctx_free(ctx); - - return ((error) ? 1 : 0); -} - -static 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 & 7) == 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 */ - do { - printf(" "); - idx++; - if ((idx & 7) == 0) - putchar(' '); - } while ((idx & 15) != 0); - printf("%s\n", ascii); - } + if (instr) + putchar('\n'); } /* @@ -309,10 +159,6 @@ do_bind(int fid) printf("xact bind, err=%d\n", err); return (err); } - if (smb_verbose) { - printf("bind ack, len=%d\n", len); - hexdump(recvbuf, len); - } if (more > 0) { if (more > sizeof (recvbuf)) { printf("bogus more=%d\n", more); @@ -325,17 +171,13 @@ do_bind(int fid) printf("read enum resp, err=%d\n", err); return (err); } - if (smb_verbose) { - printf("bind ack (more), len=%d\n", len); - hexdump(recvbuf, len); - } } return (0); } static int -do_enum(int fid) +do_enum(char *server, int fid) { int err, len, rlen, wlen; uchar_t *p; @@ -393,18 +235,22 @@ do_enum(int fid) return (err); } - /* Just dump the response data. */ - printf("enum recv, len=%d\n", rlen); - hexdump(recvbuf, rlen); + /* + * Just dump strings found in the response data. + * Skip the first 0x90 (RPC wrappers). + */ + printf("enum strings\n"); + pstrings(recvbuf + 0x90, rlen - 0x90); return (0); } -static int -pipetest(struct smb_ctx *ctx) +int +list_shares(struct smb_ctx *ctx) { static char path[] = "/srvsvc"; static uchar_t key[16]; + char *server = ctx->ct_srvname; int err, fd; printf("open pipe: %s\n", path); @@ -426,7 +272,7 @@ pipetest(struct smb_ctx *ctx) printf("do_bind: %d\n", err); goto out; } - err = do_enum(fd); + err = do_enum(server, fd); if (err) printf("do_enum: %d\n", err); diff --git a/usr/src/cmd/fs.d/smbclnt/test/Makefile b/usr/src/cmd/fs.d/smbclnt/test/Makefile deleted file mode 100644 index affd6d9a00..0000000000 --- a/usr/src/cmd/fs.d/smbclnt/test/Makefile +++ /dev/null @@ -1,85 +0,0 @@ -# -# 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 2013 Nexenta Systems, Inc. All rights reserved. -# Copyright (c) 2019, Joyent, Inc. -# - -include $(SRC)/cmd/Makefile.cmd - -PROG= srvenum srvinfo tconn -OBJS = $(PROG:%=%.o) -SRCS = $(OBJS:%.o=%.c) - -# ROOTFS_PROG= $(LIBPROG) -# include ../../Makefile.fstype - -ROOTOPTPKG = $(ROOT)/opt/smbcl-tests -TESTDIR = $(ROOTOPTPKG)/tests -INST_CMDS = $(PROG:%=$(TESTDIR)/%) - -# OBJS= $(LIBPROG).o -# SRCS= $(LIBPROG).c $(FSLIBSRC) - -CPPFLAGS += -I../../../../uts/common -CPPFLAGS += -I../../../../lib/libsmbfs - -LDLIBS += -R'$$ORIGIN/../../../usr/lib' -LDLIBS += -lsmbfs -LINTLIBS= -L$(ROOTLIB) -lsmbfs - -CFLAGS += $(CCVERBOSE) -CERRWARN += -_gcc=-Wno-unused-variable -CSTD= $(CSTD_GNU99) - -# not linted -SMATCH=off - -LINTFLAGS += -erroff=E_FUNC_RET_ALWAYS_IGNOR2 - -# CLOBBERFILES += $(LIBPROG) - -all: $(PROG) - -install: all $(ROOTOPTPKG) $(TESTDIR) $(INST_CMDS) - -lint: - for f in $(SRCS); do ;\ - $(LINT.c) $$f $(LINTLIBS) ; done - -clobber: clean - -$(RM) $(PROG) - -clean: - -$(RM) $(OBJS) - -$(ROOTOPTPKG): - $(INS.dir) - -$(TESTDIR): - $(INS.dir) - -$(TESTDIR)/%: % - $(INS.file) - -.KEEP_STATE: diff --git a/usr/src/cmd/fs.d/smbclnt/test/srvinfo.c b/usr/src/cmd/fs.d/smbclnt/test/srvinfo.c deleted file mode 100644 index 81ba8c9afc..0000000000 --- a/usr/src/cmd/fs.d/smbclnt/test/srvinfo.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * 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) 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. - */ - -/* - * Test program for the smbfs named pipe API. - */ - -#include <sys/types.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <libintl.h> - -#include <netsmb/smbfs_api.h> - -/* - * This is a quick hack for testing client-side named pipes. - * Its purpose is to test the ability to connect to a server, - * open a pipe, send and receive data. The "hack" aspect is - * the use of hand-crafted RPC messages, which allows testing - * of the named pipe API separately from the RPC libraries. - * - * I captured the two small name pipe messages sent when - * requesting a server info via RPC over /pipe/srvsvc and - * dropped them into the arrays below (bind and info). - * This program sends the two messages (with adjustments) - * and just dumps whatever comes back over the pipe. - * Use wireshark if you want to see decoded messages. - */ - -extern char *optarg; -extern int optind, opterr, optopt; - -/* This is a DCE/RPC bind call for "srvsvc". */ -static const uchar_t -srvsvc_bind[] = { - 0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00, - 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, - 0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01, - 0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88, - 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a, - 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00, - 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00 }; - -/* This is a srvsvc "get server info" call, in two parts */ -static const uchar_t -srvsvc_info[] = { - 0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00, -#define INFO_RPCLEN_OFF 8 - /* V - RPC frag length */ - 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* ... and the operation number is: VVVV */ - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x15, 0x00, -#define INFO_SLEN1_OFF 28 -#define INFO_SLEN2_OFF 36 - /* server name, length 14 vv ... */ - 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00 }; - /* UNC server here, i.e.: "\\192.168.1.6" */ - -static uchar_t sendbuf[1024]; -static uchar_t recvbuf[1024]; -static char *server; - -static int pipetest(struct smb_ctx *); - -static void -srvinfo_usage(void) -{ - printf("usage: srvinfo [-d domain][-u user][-p passwd] server\n"); - exit(1); -} - -int -main(int argc, char *argv[]) -{ - int c, error; - struct smb_ctx *ctx = NULL; - char *dom = NULL; - char *usr = NULL; - char *pw = NULL; - - while ((c = getopt(argc, argv, "vd:u:p:")) != -1) { - switch (c) { - case 'v': - smb_verbose = 1; - break; - - case 'd': - dom = optarg; - break; - case 'u': - usr = optarg; - break; - case 'p': - pw = optarg; - break; - case '?': - srvinfo_usage(); - break; - } - } - if (optind >= argc) - srvinfo_usage(); - server = argv[optind]; - - if (pw != NULL && (dom == NULL || usr == NULL)) { - fprintf(stderr, "%s: -p arg requires -d dom -u usr\n", - argv[0]); - srvinfo_usage(); - } - - /* - * This section is intended to demonstrate how an - * RPC client library might use this interface. - */ - error = smb_ctx_alloc(&ctx); - if (error) { - fprintf(stderr, "%s: smb_ctx_alloc failed\n", argv[0]); - goto out; - } - - /* - * Set server, share, domain, user - * (in the ctx handle). - */ - smb_ctx_setfullserver(ctx, server); - smb_ctx_setshare(ctx, "IPC$", USE_IPC); - if (dom) - smb_ctx_setdomain(ctx, dom, B_TRUE); - if (usr) - smb_ctx_setuser(ctx, usr, B_TRUE); - if (pw) - smb_ctx_setpassword(ctx, pw, NULL); - - - /* - * If this code were in smbutil or mount_smbfs, it would - * get system and $HOME/.nsmbrc settings here, like this: - */ -#if 0 - error = smb_ctx_readrc(ctx); - if (error) { - fprintf(stderr, "%s: smb_ctx_readrc failed\n", argv[0]); - goto out; - } -#endif - - /* - * Resolve the server address, - * setup derived defaults. - */ - error = smb_ctx_resolve(ctx); - if (error) { - fprintf(stderr, "%s: smb_ctx_resolve failed\n", argv[0]); - goto out; - } - - /* - * Get the session and tree. - */ - error = smb_ctx_get_ssn(ctx); - if (error) { - fprintf(stderr, "//%s: login failed, error %d\n", - server, error); - goto out; - } - error = smb_ctx_get_tree(ctx); - if (error) { - fprintf(stderr, "//%s/%s: tree connect failed, %d\n", - server, "IPC$", error); - goto out; - } - - /* - * Do some named pipe I/O. - */ - error = pipetest(ctx); - if (error) { - fprintf(stderr, "pipetest, %d\n", error); - goto out; - } - -out: - smb_ctx_free(ctx); - - return ((error) ? 1 : 0); -} - -static void -hexdump(const uchar_t *buf, int len) { - int ofs = 0; - - while (len--) { - if (ofs % 16 == 0) - printf("\n%02X: ", ofs); - printf("%02x ", *buf++); - ofs++; - } - printf("\n"); -} - -/* - * Put a unicode UNC server name, including the null. - * Quick-n-dirty, just for this test... - */ -static int -put_uncserver(const char *s, uchar_t *buf) -{ - uchar_t *p = buf; - char c; - - *p++ = '\\'; *p++ = '\0'; - *p++ = '\\'; *p++ = '\0'; - - do { - c = *s++; - if (c == '/') - c = '\\'; - *p++ = c; - *p++ = '\0'; - - } while (c != 0); - - return (p - buf); -} - -/* Get a little-endian int. Just for testing. */ -static int -getint(const uchar_t *p) -{ - return (p[0] + (p[1]<<8) + (p[2]<<16) + (p[3]<<24)); -} - -/* - * Send the bind and read the ack. - * This tests smb_fh_xactnp. - */ -static int -do_bind(int fid) -{ - int err, len, more; - - more = 0; - len = sizeof (recvbuf); - err = smb_fh_xactnp(fid, - sizeof (srvsvc_bind), (char *)srvsvc_bind, - &len, (char *)recvbuf, &more); - if (err) { - printf("xact bind, err=%d\n", err); - return (err); - } - if (smb_verbose) { - printf("bind ack, len=%d\n", len); - hexdump(recvbuf, len); - } - if (more > 0) { - if (more > sizeof (recvbuf)) { - printf("bogus more=%d\n", more); - more = sizeof (recvbuf); - } - len = smb_fh_read(fid, 0, - more, (char *)recvbuf); - if (len == -1) { - err = EIO; - printf("read info resp, err=%d\n", err); - return (err); - } - if (smb_verbose) { - printf("bind ack (more), len=%d\n", len); - hexdump(recvbuf, len); - } - } - - return (0); -} - -static int -do_info(int fid) -{ - int err, len, rlen, wlen, x; - uchar_t *p; - - /* - * Build the info request - two parts. - * See above: srvsvc_info - * - * First part: RPC header, etc. - */ - p = sendbuf; - len = sizeof (srvsvc_info); /* 40 */ - memcpy(p, srvsvc_info, len); - p += len; - - /* Second part: UNC server name */ - len = put_uncserver(server, p); - p += len; - sendbuf[INFO_SLEN1_OFF] = len / 2; - sendbuf[INFO_SLEN2_OFF] = len / 2; - - /* Third part: level, etc. (align4) */ - for (len = (p - sendbuf) & 3; len; len--) - *p++ = '\0'; - *p++ = 101; /* the "level" */ - *p++ = 0; *p++ = 0; *p++ = 0; - - /* - * Compute total length, and fixup RPC header. - */ - len = p - sendbuf; - sendbuf[INFO_RPCLEN_OFF] = len; - - /* - * Send the info request, read the response. - * This tests smb_fh_write, smb_fh_read. - */ - wlen = smb_fh_write(fid, 0, len, (char *)sendbuf); - if (wlen == -1) { - err = errno; - printf("write info req, err=%d\n", err); - return (err); - } - if (wlen != len) { - printf("write info req, short write %d\n", wlen); - return (EIO); - } - - rlen = smb_fh_read(fid, 0, - sizeof (recvbuf), (char *)recvbuf); - if (rlen == -1) { - err = errno; - printf("read info resp, err=%d\n", err); - return (err); - } - - if (smb_verbose) { - printf("info recv, len=%d\n", rlen); - hexdump(recvbuf, rlen); - } - - x = getint(recvbuf + 4); - if (x != 0x10) { - printf("Data representation 0x%x not supported\n", x); - return (ENOTSUP); - } - printf("Platform Id: %d\n", getint(recvbuf + 0x20)); - printf("Version Major: %d\n", getint(recvbuf + 0x28)); - printf("Version Minor: %d\n", getint(recvbuf + 0x2c)); - printf("Srv type flags: 0x%x\n", getint(recvbuf + 0x30)); - - return (0); -} - -static int -pipetest(struct smb_ctx *ctx) -{ - static char path[] = "/srvsvc"; - static uchar_t key[16]; - int err, fd; - - printf("open pipe: %s\n", path); - fd = smb_fh_open(ctx, path, O_RDWR); - if (fd < 0) { - perror(path); - return (errno); - } - - /* Test this too. */ - err = smb_fh_getssnkey(fd, key, sizeof (key)); - if (err) { - printf("getssnkey: %d\n", err); - goto out; - } - - err = do_bind(fd); - if (err) { - printf("do_bind: %d\n", err); - goto out; - } - err = do_info(fd); - if (err) - printf("do_info: %d\n", err); - -out: - smb_fh_close(fd); - return (err); -} diff --git a/usr/src/cmd/fs.d/smbclnt/test/tconn.c b/usr/src/cmd/fs.d/smbclnt/test/tconn.c deleted file mode 100644 index bfeac98fe0..0000000000 --- a/usr/src/cmd/fs.d/smbclnt/test/tconn.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * 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) 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright 2013 Nexenta Systems, Inc. All rights reserved. - */ - -/* - * Test program for opening an SMB connection directly. - */ - -#include <sys/types.h> -#include <errno.h> -#include <fcntl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <netdb.h> -#include <libintl.h> - -#include <netsmb/smb_lib.h> - -extern char *optarg; -extern int optind, opterr, optopt; -extern int smb_iod_connect(struct smb_ctx *); - -static char *server; - -static void -tconn_usage(void) -{ - printf("usage: tconn [-d domain][-u user][-p passwd] server\n"); - exit(1); -} - -int -main(int argc, char *argv[]) -{ - int c, error, aflags; - struct smb_ctx *ctx = NULL; - char *dom = NULL; - char *usr = NULL; - char *pw = NULL; - char *secopt = NULL; - struct addrinfo *ai; - - while ((c = getopt(argc, argv, "vd:p:s:u:")) != -1) { - switch (c) { - case 'v': - smb_debug = 1; - smb_verbose = 1; - break; - - case 'd': - dom = optarg; - break; - case 'u': - usr = optarg; - break; - case 'p': - pw = optarg; - break; - case 's': - secopt = optarg; - break; - case '?': - tconn_usage(); - break; - } - } - if (optind >= argc) - tconn_usage(); - server = argv[optind]; - - if (pw != NULL && (dom == NULL || usr == NULL)) { - fprintf(stderr, "%s: -p arg requires -d dom -u usr\n", - argv[0]); - tconn_usage(); - } - - /* - * This section is intended to demonstrate how an - * RPC client library might use this interface. - */ - error = smb_ctx_alloc(&ctx); - if (error) { - fprintf(stderr, "%s: smb_ctx_alloc failed\n", argv[0]); - goto out; - } - - /* - * Set server, share, domain, user - * (in the ctx handle). - */ - smb_ctx_setfullserver(ctx, server); - smb_ctx_setshare(ctx, "IPC$", USE_IPC); - if (dom) - smb_ctx_setdomain(ctx, dom, B_TRUE); - if (usr) - smb_ctx_setuser(ctx, usr, B_TRUE); - if (pw) - smb_ctx_setpassword(ctx, pw, NULL); - - /* - * Hackish option to override the Authentication Type flags. - * Sorry about exposing the flag values here, but this is - * really a programmer's test tool. See smbfs_api.h for - * the SMB_AT_... flag values. - */ - if (secopt != NULL) { - aflags = atoi(secopt); - if (aflags < 1 || aflags > 0x1f) { - fprintf(stderr, "%s: -s {0..31}\n", argv[0]); - tconn_usage(); - } - smb_ctx_setauthflags(ctx, aflags); - } - - /* - * Resolve the server address, - * setup derived defaults. - */ - error = smb_ctx_resolve(ctx); - if (error) { - fprintf(stderr, "%s: smb_ctx_resolve failed\n", argv[0]); - goto out; - } - - if ((ai = ctx->ct_addrinfo) == NULL) { - fprintf(stderr, "%s: no ct_addrinfo\n", argv[0]); - goto out; - } - memcpy(&ctx->ct_srvaddr, ai->ai_addr, ai->ai_addrlen); - - /* - * If this code were in smbutil or mount_smbfs, it would - * get system and $HOME/.nsmbrc settings here, like this: - */ - error = smb_iod_connect(ctx); - if (error) { - fprintf(stderr, "%s: smb_iod_connect failed\n", argv[0]); - goto out; - } - - printf("Yea, we connected!\n"); - -out: - smb_ctx_free(ctx); - - return ((error) ? 1 : 0); -} |
