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