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 server info via RPC over /pipe/srvsvc and
51 * dropped them into the arrays below (bind and info).
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 "get server info" call, in two parts */
76 0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
77 #define INFO_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, 0x15, 0x00,
82 #define INFO_SLEN1_OFF 28
83 #define INFO_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" */
89 static uchar_t sendbuf
[1024];
90 static uchar_t recvbuf
[1024];
93 static int pipetest(struct smb_ctx
*);
98 printf("usage: srvinfo [-d domain][-u user][-p passwd] server\n");
103 main(int argc
, char *argv
[])
106 struct smb_ctx
*ctx
= NULL
;
111 while ((c
= getopt(argc
, argv
, "vd:u:p:")) != -1) {
133 server
= argv
[optind
];
135 if (pw
!= NULL
&& (dom
== NULL
|| usr
== NULL
)) {
136 fprintf(stderr
, "%s: -p arg requires -d dom -u usr\n",
142 * This section is intended to demonstrate how an
143 * RPC client library might use this interface.
145 error
= smb_ctx_alloc(&ctx
);
147 fprintf(stderr
, "%s: smb_ctx_alloc failed\n", argv
[0]);
152 * Set server, share, domain, user
153 * (in the ctx handle).
155 smb_ctx_setfullserver(ctx
, server
);
156 smb_ctx_setshare(ctx
, "IPC$", USE_IPC
);
158 smb_ctx_setdomain(ctx
, dom
, B_TRUE
);
160 smb_ctx_setuser(ctx
, usr
, B_TRUE
);
162 smb_ctx_setpassword(ctx
, pw
, NULL
);
166 * If this code were in smbutil or mount_smbfs, it would
167 * get system and $HOME/.nsmbrc settings here, like this:
170 error
= smb_ctx_readrc(ctx
);
172 fprintf(stderr
, "%s: smb_ctx_readrc failed\n", argv
[0]);
178 * Resolve the server address,
179 * setup derived defaults.
181 error
= smb_ctx_resolve(ctx
);
183 fprintf(stderr
, "%s: smb_ctx_resolve failed\n", argv
[0]);
188 * Get the session and tree.
190 error
= smb_ctx_get_ssn(ctx
);
192 fprintf(stderr
, "//%s: login failed, error %d\n",
196 error
= smb_ctx_get_tree(ctx
);
198 fprintf(stderr
, "//%s/%s: tree connect failed, %d\n",
199 server
, "IPC$", error
);
204 * Do some named pipe I/O.
206 error
= pipetest(ctx
);
208 fprintf(stderr
, "pipetest, %d\n", error
);
215 return ((error
) ? 1 : 0);
219 hexdump(const uchar_t
*buf
, int len
) {
224 printf("\n%02X: ", ofs
);
225 printf("%02x ", *buf
++);
232 * Put a unicode UNC server name, including the null.
233 * Quick-n-dirty, just for this test...
236 put_uncserver(const char *s
, uchar_t
*buf
)
241 *p
++ = '\\'; *p
++ = '\0';
242 *p
++ = '\\'; *p
++ = '\0';
256 /* Get a little-endian int. Just for testing. */
258 getint(const uchar_t
*p
)
260 return (p
[0] + (p
[1]<<8) + (p
[2]<<16) + (p
[3]<<24));
264 * Send the bind and read the ack.
265 * This tests smb_fh_xactnp.
273 len
= sizeof (recvbuf
);
274 err
= smb_fh_xactnp(fid
,
275 sizeof (srvsvc_bind
), (char *)srvsvc_bind
,
276 &len
, (char *)recvbuf
, &more
);
278 printf("xact bind, err=%d\n", err
);
282 printf("bind ack, len=%d\n", len
);
283 hexdump(recvbuf
, len
);
286 if (more
> sizeof (recvbuf
)) {
287 printf("bogus more=%d\n", more
);
288 more
= sizeof (recvbuf
);
290 len
= smb_fh_read(fid
, 0,
291 more
, (char *)recvbuf
);
294 printf("read info resp, err=%d\n", err
);
298 printf("bind ack (more), len=%d\n", len
);
299 hexdump(recvbuf
, len
);
309 int err
, len
, rlen
, wlen
, x
;
313 * Build the info request - two parts.
314 * See above: srvsvc_info
316 * First part: RPC header, etc.
319 len
= sizeof (srvsvc_info
); /* 40 */
320 memcpy(p
, srvsvc_info
, len
);
323 /* Second part: UNC server name */
324 len
= put_uncserver(server
, p
);
326 sendbuf
[INFO_SLEN1_OFF
] = len
/ 2;
327 sendbuf
[INFO_SLEN2_OFF
] = len
/ 2;
329 /* Third part: level, etc. (align4) */
330 for (len
= (p
- sendbuf
) & 3; len
; len
--)
332 *p
++ = 101; /* the "level" */
333 *p
++ = 0; *p
++ = 0; *p
++ = 0;
336 * Compute total length, and fixup RPC header.
339 sendbuf
[INFO_RPCLEN_OFF
] = len
;
342 * Send the info request, read the response.
343 * This tests smb_fh_write, smb_fh_read.
345 wlen
= smb_fh_write(fid
, 0, len
, (char *)sendbuf
);
348 printf("write info req, err=%d\n", err
);
352 printf("write info req, short write %d\n", wlen
);
356 rlen
= smb_fh_read(fid
, 0,
357 sizeof (recvbuf
), (char *)recvbuf
);
360 printf("read info resp, err=%d\n", err
);
365 printf("info recv, len=%d\n", rlen
);
366 hexdump(recvbuf
, rlen
);
369 x
= getint(recvbuf
+ 4);
371 printf("Data representation 0x%x not supported\n", x
);
374 printf("Platform Id: %d\n", getint(recvbuf
+ 0x20));
375 printf("Version Major: %d\n", getint(recvbuf
+ 0x28));
376 printf("Version Minor: %d\n", getint(recvbuf
+ 0x2c));
377 printf("Srv type flags: 0x%x\n", getint(recvbuf
+ 0x30));
383 pipetest(struct smb_ctx
*ctx
)
385 static char path
[] = "/srvsvc";
386 static uchar_t key
[16];
389 printf("open pipe: %s\n", path
);
390 fd
= smb_fh_open(ctx
, path
, O_RDWR
);
397 err
= smb_fh_getssnkey(fd
, key
, sizeof (key
));
399 printf("getssnkey: %d\n", err
);
405 printf("do_bind: %d\n", err
);
410 printf("do_info: %d\n", err
);