diff options
| author | Gordon Ross <gwr@nexenta.com> | 2011-06-30 17:58:05 -0400 |
|---|---|---|
| committer | Gordon Ross <gwr@nexenta.com> | 2011-06-30 17:58:05 -0400 |
| commit | 430b4c467020edf2445feb0c21db01c88b86243a (patch) | |
| tree | d13826bc812dd8c21ad1b0629bdb756bc9cfd257 /usr/src/cmd/fs.d/smbclnt | |
| parent | 9ecc7612020c1993e4dbadd3422a74b210279739 (diff) | |
| download | illumos-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/Makefile | 3 | ||||
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/smbutil/print.c | 17 | ||||
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/test/Makefile | 58 | ||||
| -rw-r--r-- | usr/src/cmd/fs.d/smbclnt/test/testnp.c | 416 |
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); +} |
