summaryrefslogtreecommitdiff
path: root/usr/src/cmd/fs.d/smbclnt
diff options
context:
space:
mode:
authorGordon Ross <gwr@nexenta.com>2011-06-30 17:58:05 -0400
committerGordon Ross <gwr@nexenta.com>2011-06-30 17:58:05 -0400
commit430b4c467020edf2445feb0c21db01c88b86243a (patch)
treed13826bc812dd8c21ad1b0629bdb756bc9cfd257 /usr/src/cmd/fs.d/smbclnt
parent9ecc7612020c1993e4dbadd3422a74b210279739 (diff)
downloadillumos-joyent-430b4c467020edf2445feb0c21db01c88b86243a.tar.gz
1120 Use real file descriptors for smbfs named pipes.
Reviewed by: Eric Schrock <eric.schrock@delphix.com> Reviewed by: Albert Lee <trisk@nexenta.com> Approved by: Garrett D'Amore <garrett@nexenta.com>
Diffstat (limited to 'usr/src/cmd/fs.d/smbclnt')
-rw-r--r--usr/src/cmd/fs.d/smbclnt/Makefile3
-rw-r--r--usr/src/cmd/fs.d/smbclnt/smbutil/print.c17
-rw-r--r--usr/src/cmd/fs.d/smbclnt/test/Makefile58
-rw-r--r--usr/src/cmd/fs.d/smbclnt/test/testnp.c416
4 files changed, 486 insertions, 8 deletions
diff --git a/usr/src/cmd/fs.d/smbclnt/Makefile b/usr/src/cmd/fs.d/smbclnt/Makefile
index 8fb1d09783..5e26c570b3 100644
--- a/usr/src/cmd/fs.d/smbclnt/Makefile
+++ b/usr/src/cmd/fs.d/smbclnt/Makefile
@@ -20,6 +20,7 @@
#
#
+# Copyright 2011 Nexenta Systems, Inc. All rights reserved.
# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
#
@@ -32,7 +33,7 @@ include $(SRC)/Makefile.master
SUBDIRS_CATALOG= smbutil mount umount share
SUBDIRS= $(SUBDIRS_CATALOG) chacl lsacl \
- smbiod smbiod-svc svc
+ smbiod smbiod-svc svc test
# for messaging catalog files
#
diff --git a/usr/src/cmd/fs.d/smbclnt/smbutil/print.c b/usr/src/cmd/fs.d/smbclnt/smbutil/print.c
index 7379acfd90..f9c223041a 100644
--- a/usr/src/cmd/fs.d/smbclnt/smbutil/print.c
+++ b/usr/src/cmd/fs.d/smbclnt/smbutil/print.c
@@ -33,6 +33,7 @@
*/
/*
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -150,7 +151,7 @@ again:
* Have the printer share connection.
* Print the file.
*/
- snprintf(titlebuf, sizeof (titlebuf), "%s_%s",
+ snprintf(titlebuf, sizeof (titlebuf), "%s %s",
ctx->ct_user, filename);
error = print_file(ctx, titlebuf, file);
@@ -185,13 +186,15 @@ static int
print_file(smb_ctx_t *ctx, char *title, int file)
{
off_t offset;
- int error, rcnt, wcnt;
+ int rcnt, wcnt;
int setup_len = 0; /* No printer setup data */
int mode = MODE_GRAPHICS; /* treat as raw data */
- int fh = -1;
+ int error = 0;
+ int pfd = -1;
- error = smb_printer_open(ctx, setup_len, mode, title, &fh);
- if (error) {
+ pfd = smb_open_printer(ctx, title, setup_len, mode);
+ if (pfd < 0) {
+ error = errno;
smb_error("could not open print job", error);
return (error);
}
@@ -207,7 +210,7 @@ print_file(smb_ctx_t *ctx, char *title, int file)
if (rcnt == 0)
break;
- wcnt = smb_fh_write(ctx, fh, offset, rcnt, databuf);
+ wcnt = smb_fh_write(pfd, offset, rcnt, databuf);
if (wcnt < 0) {
error = errno;
smb_error("error writing spool file\n", error);
@@ -221,6 +224,6 @@ print_file(smb_ctx_t *ctx, char *title, int file)
offset += wcnt;
}
- (void) smb_printer_close(ctx, fh);
+ (void) smb_fh_close(pfd);
return (error);
}
diff --git a/usr/src/cmd/fs.d/smbclnt/test/Makefile b/usr/src/cmd/fs.d/smbclnt/test/Makefile
new file mode 100644
index 0000000000..09e2ebdda9
--- /dev/null
+++ b/usr/src/cmd/fs.d/smbclnt/test/Makefile
@@ -0,0 +1,58 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+#
+# Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+
+FSTYPE= smbfs
+LIBPROG= testnp
+ROOTFS_PROG= $(LIBPROG)
+
+include ../../Makefile.fstype
+
+OBJS= $(LIBPROG).o
+SRCS= $(LIBPROG).c $(FSLIBSRC)
+
+LDLIBS += -lsmbfs
+
+CFLAGS += $(CCVERBOSE)
+C99MODE= $(C99_ENABLE)
+
+CLOBBERFILES += $(LIBPROG)
+
+# uncomment these for dbx debugging
+#COPTFLAG = -g
+#CTF_FLAGS =
+#CTFCONVERT_O=
+#CTFMERGE_LIB=
+
+all: $(ROOTFS_PROG)
+
+install: $(ROOTLIBFSTYPEPROG)
+
+lint: lint_SRCS
+
+clean:
+ $(RM) $(OBJS)
+
+.KEEP_STATE:
diff --git a/usr/src/cmd/fs.d/smbclnt/test/testnp.c b/usr/src/cmd/fs.d/smbclnt/test/testnp.c
new file mode 100644
index 0000000000..7b28194b0b
--- /dev/null
+++ b/usr/src/cmd/fs.d/smbclnt/test/testnp.c
@@ -0,0 +1,416 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
+ * Copyright (c) 2010, Oracle and/or its affiliates. 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
+testnp_usage(void)
+{
+ printf("usage: testnp [-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 '?':
+ testnp_usage();
+ break;
+ }
+ }
+ if (optind >= argc)
+ testnp_usage();
+ server = argv[optind];
+
+ if (pw != NULL && (dom == NULL || usr == NULL)) {
+ fprintf(stderr, "%0: -p arg requires -d dom -u usr\n",
+ argv[0]);
+ testnp_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;
+ int slashcnt = 0;
+ 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);
+}