4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
28 * Test program for the smbfs named pipe API.
31 #include <sys/types.h>
40 #include <netsmb/smbfs_api.h>
43 * This is a quick hack for testing client-side named pipes.
44 * Its purpose is to test the ability to connect to a server,
45 * open a pipe, send and receive data. The "hack" aspect is
46 * the use of hand-crafted RPC messages, which allows testing
47 * of the named pipe API separately from the RPC libraries.
49 * I captured the two small name pipe messages sent when
50 * requesting a share list via RPC over /pipe/srvsvc and
51 * dropped them into the arrays below (bind and enum).
52 * This program sends the two messages (with adjustments)
53 * and just dumps whatever comes back over the pipe.
54 * Use wireshark if you want to see decoded messages.
58 extern int optind
, opterr
, optopt
;
60 /* This is a DCE/RPC bind call for "srvsvc". */
63 0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
64 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
65 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
66 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
67 0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01,
68 0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88,
69 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
70 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
71 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00 };
73 /* This is a srvsvc "enum servers" call, in two parts */
76 0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
77 #define ENUM_RPCLEN_OFF 8
78 /* V - RPC frag length */
79 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80 /* ... and the operation number is: VVVV */
81 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x00,
82 #define ENUM_SLEN1_OFF 28
83 #define ENUM_SLEN2_OFF 36
84 /* server name, length 14 vv ... */
85 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
86 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00 };
87 /* UNC server here, i.e.: "\\192.168.1.6" */
91 0x01, 0x00, 0x00, 0x00,
92 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
93 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
96 static uchar_t sendbuf
[1024];
97 static uchar_t recvbuf
[4096];
100 static int pipetest(struct smb_ctx
*);
105 printf("usage: srvenum [-d domain][-u user][-p passwd] server\n");
110 main(int argc
, char *argv
[])
113 struct smb_ctx
*ctx
= NULL
;
118 while ((c
= getopt(argc
, argv
, "vd:u:p:")) != -1) {
140 server
= argv
[optind
];
142 if (pw
!= NULL
&& (dom
== NULL
|| usr
== NULL
)) {
143 fprintf(stderr
, "%s: -p arg requires -d dom -u usr\n",
149 * This section is intended to demonstrate how an
150 * RPC client library might use this interface.
152 error
= smb_ctx_alloc(&ctx
);
154 fprintf(stderr
, "%s: smb_ctx_alloc failed\n", argv
[0]);
159 * Set server, share, domain, user
160 * (in the ctx handle).
162 smb_ctx_setfullserver(ctx
, server
);
163 smb_ctx_setshare(ctx
, "IPC$", USE_IPC
);
165 smb_ctx_setdomain(ctx
, dom
, B_TRUE
);
167 smb_ctx_setuser(ctx
, usr
, B_TRUE
);
169 smb_ctx_setpassword(ctx
, pw
, NULL
);
173 * If this code were in smbutil or mount_smbfs, it would
174 * get system and $HOME/.nsmbrc settings here, like this:
177 error
= smb_ctx_readrc(ctx
);
179 fprintf(stderr
, "%s: smb_ctx_readrc failed\n", argv
[0]);
185 * Resolve the server address,
186 * setup derived defaults.
188 error
= smb_ctx_resolve(ctx
);
190 fprintf(stderr
, "%s: smb_ctx_resolve failed\n", argv
[0]);
195 * Get the session and tree.
197 error
= smb_ctx_get_ssn(ctx
);
199 fprintf(stderr
, "//%s: login failed, error %d\n",
203 error
= smb_ctx_get_tree(ctx
);
205 fprintf(stderr
, "//%s/%s: tree connect failed, %d\n",
206 server
, "IPC$", error
);
211 * Do some named pipe I/O.
213 error
= pipetest(ctx
);
215 fprintf(stderr
, "pipetest, %d\n", error
);
222 return ((error
) ? 1 : 0);
226 hexdump(const uchar_t
*buf
, int len
) {
231 memset(ascii
, '\0', sizeof (ascii
));
235 if ((idx
& 15) == 0) {
236 printf("[%04X] ", idx
);
239 if (*buf
> ' ' && *buf
<= '~')
243 printf("%02x ", *buf
++);
246 if ((idx
& 7) == 0) {
250 if ((idx
& 15) == 0) {
252 printf("%s\n", ascii
);
256 if ((idx
& 15) != 0) {
258 /* column align the last ascii row */
264 } while ((idx
& 15) != 0);
265 printf("%s\n", ascii
);
270 * Put a unicode UNC server name, including the null.
271 * Quick-n-dirty, just for this test...
274 put_uncserver(const char *s
, uchar_t
*buf
)
279 *p
++ = '\\'; *p
++ = '\0';
280 *p
++ = '\\'; *p
++ = '\0';
295 * Send the bind and read the ack.
296 * This tests smb_fh_xactnp.
304 len
= sizeof (recvbuf
);
305 err
= smb_fh_xactnp(fid
,
306 sizeof (srvsvc_bind
), (char *)srvsvc_bind
,
307 &len
, (char *)recvbuf
, &more
);
309 printf("xact bind, err=%d\n", err
);
313 printf("bind ack, len=%d\n", len
);
314 hexdump(recvbuf
, len
);
317 if (more
> sizeof (recvbuf
)) {
318 printf("bogus more=%d\n", more
);
319 more
= sizeof (recvbuf
);
321 len
= smb_fh_read(fid
, 0,
322 more
, (char *)recvbuf
);
325 printf("read enum resp, err=%d\n", err
);
329 printf("bind ack (more), len=%d\n", len
);
330 hexdump(recvbuf
, len
);
340 int err
, len
, rlen
, wlen
;
344 * Build the enum request - three parts.
345 * See above: srvsvc_enum1, srvsvc_enum2
347 * First part: RPC header, etc.
350 len
= sizeof (srvsvc_enum1
); /* 40 */
351 memcpy(p
, srvsvc_enum1
, len
);
354 /* Second part: UNC server name */
355 len
= put_uncserver(server
, p
);
357 sendbuf
[ENUM_SLEN1_OFF
] = len
/ 2;
358 sendbuf
[ENUM_SLEN2_OFF
] = len
/ 2;
360 /* Third part: level, etc. (align4) */
361 for (len
= (p
- sendbuf
) & 3; len
; len
--)
363 len
= sizeof (srvsvc_enum2
); /* 28 */
364 memcpy(p
, srvsvc_enum2
, len
);
368 * Compute total length, and fixup RPC header.
371 sendbuf
[ENUM_RPCLEN_OFF
] = len
;
374 * Send the enum request, read the response.
375 * This tests smb_fh_write, smb_fh_read.
377 wlen
= smb_fh_write(fid
, 0, len
, (char *)sendbuf
);
380 printf("write enum req, err=%d\n", err
);
384 printf("write enum req, short write %d\n", wlen
);
388 rlen
= smb_fh_read(fid
, 0,
389 sizeof (recvbuf
), (char *)recvbuf
);
392 printf("read enum resp, err=%d\n", err
);
396 /* Just dump the response data. */
397 printf("enum recv, len=%d\n", rlen
);
398 hexdump(recvbuf
, rlen
);
404 pipetest(struct smb_ctx
*ctx
)
406 static char path
[] = "/srvsvc";
407 static uchar_t key
[16];
410 printf("open pipe: %s\n", path
);
411 fd
= smb_fh_open(ctx
, path
, O_RDWR
);
418 err
= smb_fh_getssnkey(fd
, key
, sizeof (key
));
420 printf("getssnkey: %d\n", err
);
426 printf("do_bind: %d\n", err
);
431 printf("do_enum: %d\n", err
);