1*7c667cfcSGordon Ross /*
2*7c667cfcSGordon Ross * CDDL HEADER START
3*7c667cfcSGordon Ross *
4*7c667cfcSGordon Ross * The contents of this file are subject to the terms of the
5*7c667cfcSGordon Ross * Common Development and Distribution License (the "License").
6*7c667cfcSGordon Ross * You may not use this file except in compliance with the License.
7*7c667cfcSGordon Ross *
8*7c667cfcSGordon Ross * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7c667cfcSGordon Ross * or http://www.opensolaris.org/os/licensing.
10*7c667cfcSGordon Ross * See the License for the specific language governing permissions
11*7c667cfcSGordon Ross * and limitations under the License.
12*7c667cfcSGordon Ross *
13*7c667cfcSGordon Ross * When distributing Covered Code, include this CDDL HEADER in each
14*7c667cfcSGordon Ross * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7c667cfcSGordon Ross * If applicable, add the following below this CDDL HEADER, with the
16*7c667cfcSGordon Ross * fields enclosed by brackets "[]" replaced with your own identifying
17*7c667cfcSGordon Ross * information: Portions Copyright [yyyy] [name of copyright owner]
18*7c667cfcSGordon Ross *
19*7c667cfcSGordon Ross * CDDL HEADER END
20*7c667cfcSGordon Ross */
21*7c667cfcSGordon Ross
22*7c667cfcSGordon Ross /*
23*7c667cfcSGordon Ross * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24*7c667cfcSGordon Ross * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
25*7c667cfcSGordon Ross */
26*7c667cfcSGordon Ross
27*7c667cfcSGordon Ross /*
28*7c667cfcSGordon Ross * Test program for the smbfs named pipe API.
29*7c667cfcSGordon Ross */
30*7c667cfcSGordon Ross
31*7c667cfcSGordon Ross #include <sys/types.h>
32*7c667cfcSGordon Ross #include <errno.h>
33*7c667cfcSGordon Ross #include <fcntl.h>
34*7c667cfcSGordon Ross #include <stdio.h>
35*7c667cfcSGordon Ross #include <stdlib.h>
36*7c667cfcSGordon Ross #include <string.h>
37*7c667cfcSGordon Ross #include <unistd.h>
38*7c667cfcSGordon Ross #include <libintl.h>
39*7c667cfcSGordon Ross
40*7c667cfcSGordon Ross #include <netsmb/smbfs_api.h>
41*7c667cfcSGordon Ross
42*7c667cfcSGordon Ross /*
43*7c667cfcSGordon Ross * This is a quick hack for testing client-side named pipes.
44*7c667cfcSGordon Ross * Its purpose is to test the ability to connect to a server,
45*7c667cfcSGordon Ross * open a pipe, send and receive data. The "hack" aspect is
46*7c667cfcSGordon Ross * the use of hand-crafted RPC messages, which allows testing
47*7c667cfcSGordon Ross * of the named pipe API separately from the RPC libraries.
48*7c667cfcSGordon Ross *
49*7c667cfcSGordon Ross * I captured the two small name pipe messages sent when
50*7c667cfcSGordon Ross * requesting a share list via RPC over /pipe/srvsvc and
51*7c667cfcSGordon Ross * dropped them into the arrays below (bind and enum).
52*7c667cfcSGordon Ross * This program sends the two messages (with adjustments)
53*7c667cfcSGordon Ross * and just dumps whatever comes back over the pipe.
54*7c667cfcSGordon Ross * Use wireshark if you want to see decoded messages.
55*7c667cfcSGordon Ross */
56*7c667cfcSGordon Ross
57*7c667cfcSGordon Ross extern char *optarg;
58*7c667cfcSGordon Ross extern int optind, opterr, optopt;
59*7c667cfcSGordon Ross
60*7c667cfcSGordon Ross /* This is a DCE/RPC bind call for "srvsvc". */
61*7c667cfcSGordon Ross static const uchar_t
62*7c667cfcSGordon Ross srvsvc_bind[] = {
63*7c667cfcSGordon Ross 0x05, 0x00, 0x0b, 0x03, 0x10, 0x00, 0x00, 0x00,
64*7c667cfcSGordon Ross 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
65*7c667cfcSGordon Ross 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
66*7c667cfcSGordon Ross 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00,
67*7c667cfcSGordon Ross 0xc8, 0x4f, 0x32, 0x4b, 0x70, 0x16, 0xd3, 0x01,
68*7c667cfcSGordon Ross 0x12, 0x78, 0x5a, 0x47, 0xbf, 0x6e, 0xe1, 0x88,
69*7c667cfcSGordon Ross 0x03, 0x00, 0x00, 0x00, 0x04, 0x5d, 0x88, 0x8a,
70*7c667cfcSGordon Ross 0xeb, 0x1c, 0xc9, 0x11, 0x9f, 0xe8, 0x08, 0x00,
71*7c667cfcSGordon Ross 0x2b, 0x10, 0x48, 0x60, 0x02, 0x00, 0x00, 0x00 };
72*7c667cfcSGordon Ross
73*7c667cfcSGordon Ross /* This is a srvsvc "enum servers" call, in two parts */
74*7c667cfcSGordon Ross static const uchar_t
75*7c667cfcSGordon Ross srvsvc_enum1[] = {
76*7c667cfcSGordon Ross 0x05, 0x00, 0x00, 0x03, 0x10, 0x00, 0x00, 0x00,
77*7c667cfcSGordon Ross #define ENUM_RPCLEN_OFF 8
78*7c667cfcSGordon Ross /* V - RPC frag length */
79*7c667cfcSGordon Ross 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
80*7c667cfcSGordon Ross /* ... and the operation number is: VVVV */
81*7c667cfcSGordon Ross 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x0f, 0x00,
82*7c667cfcSGordon Ross #define ENUM_SLEN1_OFF 28
83*7c667cfcSGordon Ross #define ENUM_SLEN2_OFF 36
84*7c667cfcSGordon Ross /* server name, length 14 vv ... */
85*7c667cfcSGordon Ross 0x01, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
86*7c667cfcSGordon Ross 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00 };
87*7c667cfcSGordon Ross /* UNC server here, i.e.: "\\192.168.1.6" */
88*7c667cfcSGordon Ross
89*7c667cfcSGordon Ross static const uchar_t
90*7c667cfcSGordon Ross srvsvc_enum2[] = {
91*7c667cfcSGordon Ross 0x01, 0x00, 0x00, 0x00,
92*7c667cfcSGordon Ross 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
93*7c667cfcSGordon Ross 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94*7c667cfcSGordon Ross 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 };
95*7c667cfcSGordon Ross
96*7c667cfcSGordon Ross static uchar_t sendbuf[1024];
97*7c667cfcSGordon Ross static uchar_t recvbuf[4096];
98*7c667cfcSGordon Ross static char *server;
99*7c667cfcSGordon Ross
100*7c667cfcSGordon Ross static int pipetest(struct smb_ctx *);
101*7c667cfcSGordon Ross
102*7c667cfcSGordon Ross static void
srvenum_usage(void)103*7c667cfcSGordon Ross srvenum_usage(void)
104*7c667cfcSGordon Ross {
105*7c667cfcSGordon Ross printf("usage: srvenum [-d domain][-u user][-p passwd] server\n");
106*7c667cfcSGordon Ross exit(1);
107*7c667cfcSGordon Ross }
108*7c667cfcSGordon Ross
109*7c667cfcSGordon Ross int
main(int argc,char * argv[])110*7c667cfcSGordon Ross main(int argc, char *argv[])
111*7c667cfcSGordon Ross {
112*7c667cfcSGordon Ross int c, error;
113*7c667cfcSGordon Ross struct smb_ctx *ctx = NULL;
114*7c667cfcSGordon Ross char *dom = NULL;
115*7c667cfcSGordon Ross char *usr = NULL;
116*7c667cfcSGordon Ross char *pw = NULL;
117*7c667cfcSGordon Ross
118*7c667cfcSGordon Ross while ((c = getopt(argc, argv, "vd:u:p:")) != -1) {
119*7c667cfcSGordon Ross switch (c) {
120*7c667cfcSGordon Ross case 'v':
121*7c667cfcSGordon Ross smb_verbose = 1;
122*7c667cfcSGordon Ross break;
123*7c667cfcSGordon Ross
124*7c667cfcSGordon Ross case 'd':
125*7c667cfcSGordon Ross dom = optarg;
126*7c667cfcSGordon Ross break;
127*7c667cfcSGordon Ross case 'u':
128*7c667cfcSGordon Ross usr = optarg;
129*7c667cfcSGordon Ross break;
130*7c667cfcSGordon Ross case 'p':
131*7c667cfcSGordon Ross pw = optarg;
132*7c667cfcSGordon Ross break;
133*7c667cfcSGordon Ross case '?':
134*7c667cfcSGordon Ross srvenum_usage();
135*7c667cfcSGordon Ross break;
136*7c667cfcSGordon Ross }
137*7c667cfcSGordon Ross }
138*7c667cfcSGordon Ross if (optind >= argc)
139*7c667cfcSGordon Ross srvenum_usage();
140*7c667cfcSGordon Ross server = argv[optind];
141*7c667cfcSGordon Ross
142*7c667cfcSGordon Ross if (pw != NULL && (dom == NULL || usr == NULL)) {
143*7c667cfcSGordon Ross fprintf(stderr, "%s: -p arg requires -d dom -u usr\n",
144*7c667cfcSGordon Ross argv[0]);
145*7c667cfcSGordon Ross srvenum_usage();
146*7c667cfcSGordon Ross }
147*7c667cfcSGordon Ross
148*7c667cfcSGordon Ross /*
149*7c667cfcSGordon Ross * This section is intended to demonstrate how an
150*7c667cfcSGordon Ross * RPC client library might use this interface.
151*7c667cfcSGordon Ross */
152*7c667cfcSGordon Ross error = smb_ctx_alloc(&ctx);
153*7c667cfcSGordon Ross if (error) {
154*7c667cfcSGordon Ross fprintf(stderr, "%s: smb_ctx_alloc failed\n", argv[0]);
155*7c667cfcSGordon Ross goto out;
156*7c667cfcSGordon Ross }
157*7c667cfcSGordon Ross
158*7c667cfcSGordon Ross /*
159*7c667cfcSGordon Ross * Set server, share, domain, user
160*7c667cfcSGordon Ross * (in the ctx handle).
161*7c667cfcSGordon Ross */
162*7c667cfcSGordon Ross smb_ctx_setfullserver(ctx, server);
163*7c667cfcSGordon Ross smb_ctx_setshare(ctx, "IPC$", USE_IPC);
164*7c667cfcSGordon Ross if (dom)
165*7c667cfcSGordon Ross smb_ctx_setdomain(ctx, dom, B_TRUE);
166*7c667cfcSGordon Ross if (usr)
167*7c667cfcSGordon Ross smb_ctx_setuser(ctx, usr, B_TRUE);
168*7c667cfcSGordon Ross if (pw)
169*7c667cfcSGordon Ross smb_ctx_setpassword(ctx, pw, NULL);
170*7c667cfcSGordon Ross
171*7c667cfcSGordon Ross
172*7c667cfcSGordon Ross /*
173*7c667cfcSGordon Ross * If this code were in smbutil or mount_smbfs, it would
174*7c667cfcSGordon Ross * get system and $HOME/.nsmbrc settings here, like this:
175*7c667cfcSGordon Ross */
176*7c667cfcSGordon Ross #if 0
177*7c667cfcSGordon Ross error = smb_ctx_readrc(ctx);
178*7c667cfcSGordon Ross if (error) {
179*7c667cfcSGordon Ross fprintf(stderr, "%s: smb_ctx_readrc failed\n", argv[0]);
180*7c667cfcSGordon Ross goto out;
181*7c667cfcSGordon Ross }
182*7c667cfcSGordon Ross #endif
183*7c667cfcSGordon Ross
184*7c667cfcSGordon Ross /*
185*7c667cfcSGordon Ross * Resolve the server address,
186*7c667cfcSGordon Ross * setup derived defaults.
187*7c667cfcSGordon Ross */
188*7c667cfcSGordon Ross error = smb_ctx_resolve(ctx);
189*7c667cfcSGordon Ross if (error) {
190*7c667cfcSGordon Ross fprintf(stderr, "%s: smb_ctx_resolve failed\n", argv[0]);
191*7c667cfcSGordon Ross goto out;
192*7c667cfcSGordon Ross }
193*7c667cfcSGordon Ross
194*7c667cfcSGordon Ross /*
195*7c667cfcSGordon Ross * Get the session and tree.
196*7c667cfcSGordon Ross */
197*7c667cfcSGordon Ross error = smb_ctx_get_ssn(ctx);
198*7c667cfcSGordon Ross if (error) {
199*7c667cfcSGordon Ross fprintf(stderr, "//%s: login failed, error %d\n",
200*7c667cfcSGordon Ross server, error);
201*7c667cfcSGordon Ross goto out;
202*7c667cfcSGordon Ross }
203*7c667cfcSGordon Ross error = smb_ctx_get_tree(ctx);
204*7c667cfcSGordon Ross if (error) {
205*7c667cfcSGordon Ross fprintf(stderr, "//%s/%s: tree connect failed, %d\n",
206*7c667cfcSGordon Ross server, "IPC$", error);
207*7c667cfcSGordon Ross goto out;
208*7c667cfcSGordon Ross }
209*7c667cfcSGordon Ross
210*7c667cfcSGordon Ross /*
211*7c667cfcSGordon Ross * Do some named pipe I/O.
212*7c667cfcSGordon Ross */
213*7c667cfcSGordon Ross error = pipetest(ctx);
214*7c667cfcSGordon Ross if (error) {
215*7c667cfcSGordon Ross fprintf(stderr, "pipetest, %d\n", error);
216*7c667cfcSGordon Ross goto out;
217*7c667cfcSGordon Ross }
218*7c667cfcSGordon Ross
219*7c667cfcSGordon Ross out:
220*7c667cfcSGordon Ross smb_ctx_free(ctx);
221*7c667cfcSGordon Ross
222*7c667cfcSGordon Ross return ((error) ? 1 : 0);
223*7c667cfcSGordon Ross }
224*7c667cfcSGordon Ross
225*7c667cfcSGordon Ross static void
hexdump(const uchar_t * buf,int len)226*7c667cfcSGordon Ross hexdump(const uchar_t *buf, int len) {
227*7c667cfcSGordon Ross int idx;
228*7c667cfcSGordon Ross char ascii[24];
229*7c667cfcSGordon Ross char *pa = ascii;
230*7c667cfcSGordon Ross
231*7c667cfcSGordon Ross memset(ascii, '\0', sizeof (ascii));
232*7c667cfcSGordon Ross
233*7c667cfcSGordon Ross idx = 0;
234*7c667cfcSGordon Ross while (len--) {
235*7c667cfcSGordon Ross if ((idx & 15) == 0) {
236*7c667cfcSGordon Ross printf("[%04X] ", idx);
237*7c667cfcSGordon Ross pa = ascii;
238*7c667cfcSGordon Ross }
239*7c667cfcSGordon Ross if (*buf > ' ' && *buf <= '~')
240*7c667cfcSGordon Ross *pa++ = *buf;
241*7c667cfcSGordon Ross else
242*7c667cfcSGordon Ross *pa++ = '.';
243*7c667cfcSGordon Ross printf("%02x ", *buf++);
244*7c667cfcSGordon Ross
245*7c667cfcSGordon Ross idx++;
246*7c667cfcSGordon Ross if ((idx & 7) == 0) {
247*7c667cfcSGordon Ross *pa++ = ' ';
248*7c667cfcSGordon Ross putchar(' ');
249*7c667cfcSGordon Ross }
250*7c667cfcSGordon Ross if ((idx & 15) == 0) {
251*7c667cfcSGordon Ross *pa = '\0';
252*7c667cfcSGordon Ross printf("%s\n", ascii);
253*7c667cfcSGordon Ross }
254*7c667cfcSGordon Ross }
255*7c667cfcSGordon Ross
256*7c667cfcSGordon Ross if ((idx & 15) != 0) {
257*7c667cfcSGordon Ross *pa = '\0';
258*7c667cfcSGordon Ross /* column align the last ascii row */
259*7c667cfcSGordon Ross do {
260*7c667cfcSGordon Ross printf(" ");
261*7c667cfcSGordon Ross idx++;
262*7c667cfcSGordon Ross if ((idx & 7) == 0)
263*7c667cfcSGordon Ross putchar(' ');
264*7c667cfcSGordon Ross } while ((idx & 15) != 0);
265*7c667cfcSGordon Ross printf("%s\n", ascii);
266*7c667cfcSGordon Ross }
267*7c667cfcSGordon Ross }
268*7c667cfcSGordon Ross
269*7c667cfcSGordon Ross /*
270*7c667cfcSGordon Ross * Put a unicode UNC server name, including the null.
271*7c667cfcSGordon Ross * Quick-n-dirty, just for this test...
272*7c667cfcSGordon Ross */
273*7c667cfcSGordon Ross static int
put_uncserver(const char * s,uchar_t * buf)274*7c667cfcSGordon Ross put_uncserver(const char *s, uchar_t *buf)
275*7c667cfcSGordon Ross {
276*7c667cfcSGordon Ross uchar_t *p = buf;
277*7c667cfcSGordon Ross char c;
278*7c667cfcSGordon Ross
279*7c667cfcSGordon Ross *p++ = '\\'; *p++ = '\0';
280*7c667cfcSGordon Ross *p++ = '\\'; *p++ = '\0';
281*7c667cfcSGordon Ross
282*7c667cfcSGordon Ross do {
283*7c667cfcSGordon Ross c = *s++;
284*7c667cfcSGordon Ross if (c == '/')
285*7c667cfcSGordon Ross c = '\\';
286*7c667cfcSGordon Ross *p++ = c;
287*7c667cfcSGordon Ross *p++ = '\0';
288*7c667cfcSGordon Ross
289*7c667cfcSGordon Ross } while (c != 0);
290*7c667cfcSGordon Ross
291*7c667cfcSGordon Ross return (p - buf);
292*7c667cfcSGordon Ross }
293*7c667cfcSGordon Ross
294*7c667cfcSGordon Ross /*
295*7c667cfcSGordon Ross * Send the bind and read the ack.
296*7c667cfcSGordon Ross * This tests smb_fh_xactnp.
297*7c667cfcSGordon Ross */
298*7c667cfcSGordon Ross static int
do_bind(int fid)299*7c667cfcSGordon Ross do_bind(int fid)
300*7c667cfcSGordon Ross {
301*7c667cfcSGordon Ross int err, len, more;
302*7c667cfcSGordon Ross
303*7c667cfcSGordon Ross more = 0;
304*7c667cfcSGordon Ross len = sizeof (recvbuf);
305*7c667cfcSGordon Ross err = smb_fh_xactnp(fid,
306*7c667cfcSGordon Ross sizeof (srvsvc_bind), (char *)srvsvc_bind,
307*7c667cfcSGordon Ross &len, (char *)recvbuf, &more);
308*7c667cfcSGordon Ross if (err) {
309*7c667cfcSGordon Ross printf("xact bind, err=%d\n", err);
310*7c667cfcSGordon Ross return (err);
311*7c667cfcSGordon Ross }
312*7c667cfcSGordon Ross if (smb_verbose) {
313*7c667cfcSGordon Ross printf("bind ack, len=%d\n", len);
314*7c667cfcSGordon Ross hexdump(recvbuf, len);
315*7c667cfcSGordon Ross }
316*7c667cfcSGordon Ross if (more > 0) {
317*7c667cfcSGordon Ross if (more > sizeof (recvbuf)) {
318*7c667cfcSGordon Ross printf("bogus more=%d\n", more);
319*7c667cfcSGordon Ross more = sizeof (recvbuf);
320*7c667cfcSGordon Ross }
321*7c667cfcSGordon Ross len = smb_fh_read(fid, 0,
322*7c667cfcSGordon Ross more, (char *)recvbuf);
323*7c667cfcSGordon Ross if (len == -1) {
324*7c667cfcSGordon Ross err = EIO;
325*7c667cfcSGordon Ross printf("read enum resp, err=%d\n", err);
326*7c667cfcSGordon Ross return (err);
327*7c667cfcSGordon Ross }
328*7c667cfcSGordon Ross if (smb_verbose) {
329*7c667cfcSGordon Ross printf("bind ack (more), len=%d\n", len);
330*7c667cfcSGordon Ross hexdump(recvbuf, len);
331*7c667cfcSGordon Ross }
332*7c667cfcSGordon Ross }
333*7c667cfcSGordon Ross
334*7c667cfcSGordon Ross return (0);
335*7c667cfcSGordon Ross }
336*7c667cfcSGordon Ross
337*7c667cfcSGordon Ross static int
do_enum(int fid)338*7c667cfcSGordon Ross do_enum(int fid)
339*7c667cfcSGordon Ross {
340*7c667cfcSGordon Ross int err, len, rlen, wlen;
341*7c667cfcSGordon Ross uchar_t *p;
342*7c667cfcSGordon Ross
343*7c667cfcSGordon Ross /*
344*7c667cfcSGordon Ross * Build the enum request - three parts.
345*7c667cfcSGordon Ross * See above: srvsvc_enum1, srvsvc_enum2
346*7c667cfcSGordon Ross *
347*7c667cfcSGordon Ross * First part: RPC header, etc.
348*7c667cfcSGordon Ross */
349*7c667cfcSGordon Ross p = sendbuf;
350*7c667cfcSGordon Ross len = sizeof (srvsvc_enum1); /* 40 */
351*7c667cfcSGordon Ross memcpy(p, srvsvc_enum1, len);
352*7c667cfcSGordon Ross p += len;
353*7c667cfcSGordon Ross
354*7c667cfcSGordon Ross /* Second part: UNC server name */
355*7c667cfcSGordon Ross len = put_uncserver(server, p);
356*7c667cfcSGordon Ross p += len;
357*7c667cfcSGordon Ross sendbuf[ENUM_SLEN1_OFF] = len / 2;
358*7c667cfcSGordon Ross sendbuf[ENUM_SLEN2_OFF] = len / 2;
359*7c667cfcSGordon Ross
360*7c667cfcSGordon Ross /* Third part: level, etc. (align4) */
361*7c667cfcSGordon Ross for (len = (p - sendbuf) & 3; len; len--)
362*7c667cfcSGordon Ross *p++ = '\0';
363*7c667cfcSGordon Ross len = sizeof (srvsvc_enum2); /* 28 */
364*7c667cfcSGordon Ross memcpy(p, srvsvc_enum2, len);
365*7c667cfcSGordon Ross p += len;
366*7c667cfcSGordon Ross
367*7c667cfcSGordon Ross /*
368*7c667cfcSGordon Ross * Compute total length, and fixup RPC header.
369*7c667cfcSGordon Ross */
370*7c667cfcSGordon Ross len = p - sendbuf;
371*7c667cfcSGordon Ross sendbuf[ENUM_RPCLEN_OFF] = len;
372*7c667cfcSGordon Ross
373*7c667cfcSGordon Ross /*
374*7c667cfcSGordon Ross * Send the enum request, read the response.
375*7c667cfcSGordon Ross * This tests smb_fh_write, smb_fh_read.
376*7c667cfcSGordon Ross */
377*7c667cfcSGordon Ross wlen = smb_fh_write(fid, 0, len, (char *)sendbuf);
378*7c667cfcSGordon Ross if (wlen == -1) {
379*7c667cfcSGordon Ross err = errno;
380*7c667cfcSGordon Ross printf("write enum req, err=%d\n", err);
381*7c667cfcSGordon Ross return (err);
382*7c667cfcSGordon Ross }
383*7c667cfcSGordon Ross if (wlen != len) {
384*7c667cfcSGordon Ross printf("write enum req, short write %d\n", wlen);
385*7c667cfcSGordon Ross return (EIO);
386*7c667cfcSGordon Ross }
387*7c667cfcSGordon Ross
388*7c667cfcSGordon Ross rlen = smb_fh_read(fid, 0,
389*7c667cfcSGordon Ross sizeof (recvbuf), (char *)recvbuf);
390*7c667cfcSGordon Ross if (rlen == -1) {
391*7c667cfcSGordon Ross err = errno;
392*7c667cfcSGordon Ross printf("read enum resp, err=%d\n", err);
393*7c667cfcSGordon Ross return (err);
394*7c667cfcSGordon Ross }
395*7c667cfcSGordon Ross
396*7c667cfcSGordon Ross /* Just dump the response data. */
397*7c667cfcSGordon Ross printf("enum recv, len=%d\n", rlen);
398*7c667cfcSGordon Ross hexdump(recvbuf, rlen);
399*7c667cfcSGordon Ross
400*7c667cfcSGordon Ross return (0);
401*7c667cfcSGordon Ross }
402*7c667cfcSGordon Ross
403*7c667cfcSGordon Ross static int
pipetest(struct smb_ctx * ctx)404*7c667cfcSGordon Ross pipetest(struct smb_ctx *ctx)
405*7c667cfcSGordon Ross {
406*7c667cfcSGordon Ross static char path[] = "/srvsvc";
407*7c667cfcSGordon Ross static uchar_t key[16];
408*7c667cfcSGordon Ross int err, fd;
409*7c667cfcSGordon Ross
410*7c667cfcSGordon Ross printf("open pipe: %s\n", path);
411*7c667cfcSGordon Ross fd = smb_fh_open(ctx, path, O_RDWR);
412*7c667cfcSGordon Ross if (fd < 0) {
413*7c667cfcSGordon Ross perror(path);
414*7c667cfcSGordon Ross return (errno);
415*7c667cfcSGordon Ross }
416*7c667cfcSGordon Ross
417*7c667cfcSGordon Ross /* Test this too. */
418*7c667cfcSGordon Ross err = smb_fh_getssnkey(fd, key, sizeof (key));
419*7c667cfcSGordon Ross if (err) {
420*7c667cfcSGordon Ross printf("getssnkey: %d\n", err);
421*7c667cfcSGordon Ross goto out;
422*7c667cfcSGordon Ross }
423*7c667cfcSGordon Ross
424*7c667cfcSGordon Ross err = do_bind(fd);
425*7c667cfcSGordon Ross if (err) {
426*7c667cfcSGordon Ross printf("do_bind: %d\n", err);
427*7c667cfcSGordon Ross goto out;
428*7c667cfcSGordon Ross }
429*7c667cfcSGordon Ross err = do_enum(fd);
430*7c667cfcSGordon Ross if (err)
431*7c667cfcSGordon Ross printf("do_enum: %d\n", err);
432*7c667cfcSGordon Ross
433*7c667cfcSGordon Ross out:
434*7c667cfcSGordon Ross smb_fh_close(fd);
435*7c667cfcSGordon Ross return (0);
436*7c667cfcSGordon Ross }
437