xref: /titanic_44/usr/src/lib/libsmbfs/smb/netshareenum.c (revision 02d09e03eb27f3a2dc299de704e45dae5173f43f)
14bff34e3Sthurlow /*
24bff34e3Sthurlow  * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
34bff34e3Sthurlow  *
44bff34e3Sthurlow  * @APPLE_LICENSE_HEADER_START@
54bff34e3Sthurlow  *
64bff34e3Sthurlow  * "Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
74bff34e3Sthurlow  * Reserved.  This file contains Original Code and/or Modifications of
84bff34e3Sthurlow  * Original Code as defined in and that are subject to the Apple Public
94bff34e3Sthurlow  * Source License Version 1.0 (the 'License').  You may not use this file
104bff34e3Sthurlow  * except in compliance with the License.  Please obtain a copy of the
114bff34e3Sthurlow  * License at http://www.apple.com/publicsource and read it before using
124bff34e3Sthurlow  * this file.
134bff34e3Sthurlow  *
144bff34e3Sthurlow  * The Original Code and all software distributed under the License are
154bff34e3Sthurlow  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
164bff34e3Sthurlow  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
174bff34e3Sthurlow  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
184bff34e3Sthurlow  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
194bff34e3Sthurlow  * License for the specific language governing rights and limitations
204bff34e3Sthurlow  * under the License."
214bff34e3Sthurlow  *
224bff34e3Sthurlow  * @APPLE_LICENSE_HEADER_END@
234bff34e3Sthurlow  */
244bff34e3Sthurlow 
254bff34e3Sthurlow /* BEGIN CSTYLED */
264bff34e3Sthurlow /*
274bff34e3Sthurlow  *      @(#)ui.c      *
284bff34e3Sthurlow  *      (c) 2004   Apple Computer, Inc.  All Rights Reserved
294bff34e3Sthurlow  *
304bff34e3Sthurlow  *
314bff34e3Sthurlow  *      netshareenum.c -- Routines for getting a list of share information
324bff34e3Sthurlow  *			  from a server.
334bff34e3Sthurlow  *
344bff34e3Sthurlow  *      MODIFICATION HISTORY:
354bff34e3Sthurlow  *       27-Nov-2004     Guy Harris	New today
364bff34e3Sthurlow  */
374bff34e3Sthurlow /* END CSTYLED */
384bff34e3Sthurlow 
399c9af259SGordon Ross /*
40613a2f6bSGordon Ross  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
419c9af259SGordon Ross  * Use is subject to license terms.
429c9af259SGordon Ross  */
434bff34e3Sthurlow 
444bff34e3Sthurlow #include <stdlib.h>
454bff34e3Sthurlow #include <string.h>
464bff34e3Sthurlow #include <stdio.h>
474bff34e3Sthurlow #include <errno.h>
484bff34e3Sthurlow 
494bff34e3Sthurlow #include <netsmb/mchain.h>
50613a2f6bSGordon Ross #include <netsmb/smb.h>
514bff34e3Sthurlow #include <netsmb/smb_lib.h>
524bff34e3Sthurlow #include <netsmb/smb_rap.h>
534bff34e3Sthurlow #include <netsmb/smb_netshareenum.h>
549c9af259SGordon Ross #include <smb/charsets.h>
554bff34e3Sthurlow 
564bff34e3Sthurlow #if 0 /* XXX see below */
574bff34e3Sthurlow #include <dce/exc_handling.h>
589c9af259SGordon Ross #include <rpc/attrb.h>
594bff34e3Sthurlow #include "srvsvc.h"
604bff34e3Sthurlow #endif
614bff34e3Sthurlow 
624bff34e3Sthurlow /*
634bff34e3Sthurlow  * Don't want RPC client-side code in here.
644bff34e3Sthurlow  * It's good code; just doesn't belong here.
654bff34e3Sthurlow  *
664bff34e3Sthurlow  * The API provided by this library should be
674bff34e3Sthurlow  * just files and pipes (and not much more).
684bff34e3Sthurlow  * It MAY be useful to provide some of the
694bff34e3Sthurlow  * RAP (remote API) functions functions like
704bff34e3Sthurlow  * rap_netshareenum below...
714bff34e3Sthurlow  *
724bff34e3Sthurlow  * XXX: Not sure this file belongs here at all.
734bff34e3Sthurlow  * smb_rap.h looks like a reasonable API
744bff34e3Sthurlow  * for this library to export.
754bff34e3Sthurlow  */
764bff34e3Sthurlow #if 0 /* XXX */
774bff34e3Sthurlow 
784bff34e3Sthurlow static int
794bff34e3Sthurlow rpc_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
804bff34e3Sthurlow     struct share_info **entries_listp)
814bff34e3Sthurlow {
824bff34e3Sthurlow 	char ctx_string[2+16+1];	/* enough for 64-bit pointer, in hex */
834bff34e3Sthurlow 	unsigned_char_p_t binding;
844bff34e3Sthurlow 	unsigned32 binding_status;
854bff34e3Sthurlow 	rpc_binding_handle_t binding_h;
864bff34e3Sthurlow 	int error, i, entries;
874bff34e3Sthurlow 	char *addrstr, *srvnamestr;
884bff34e3Sthurlow 	unsigned short *usrvnamestr;
894bff34e3Sthurlow 	unsigned32 level;
904bff34e3Sthurlow 	SHARE_ENUM_STRUCT share_info;
914bff34e3Sthurlow 	SHARE_INFO_1_CONTAINER share_info_1_container;
924bff34e3Sthurlow 	SHARE_INFO_1 *shares, *share;
934bff34e3Sthurlow 	unsigned32 total_entries;
944bff34e3Sthurlow 	unsigned32 status, free_status;
954bff34e3Sthurlow 	struct share_info *entry_list, *elp;
964bff34e3Sthurlow 	static EXCEPTION rpc_x_connect_rejected;
974bff34e3Sthurlow 	static int exceptions_initialized;
984bff34e3Sthurlow 
994bff34e3Sthurlow 	sprintf(ctx_string, "%p", ctx);
1004bff34e3Sthurlow 	rpc_string_binding_compose(NULL, "ncacn_np", ctx_string,
1014bff34e3Sthurlow 	    "srvsvc", NULL, &binding, &binding_status);
1024bff34e3Sthurlow 	if (binding_status != rpc_s_ok) {
1034bff34e3Sthurlow 		smb_error(dgettext(TEXT_DOMAIN,
1044bff34e3Sthurlow 		    "rpc_string_binding_compose failed with %d"),
1054bff34e3Sthurlow 		    0, binding_status);
1064bff34e3Sthurlow 		return (EINVAL);
1074bff34e3Sthurlow 	}
1084bff34e3Sthurlow 	rpc_binding_from_string_binding(binding, &binding_h, &status);
1099c9af259SGordon Ross 	rpc_string_free(&binding, (unsigned32 *)&free_status);
1104bff34e3Sthurlow 	if (binding_status != rpc_s_ok) {
1114bff34e3Sthurlow 		smb_error(dgettext(TEXT_DOMAIN,
1124bff34e3Sthurlow 		    "rpc_binding_from_string_binding failed with %d"), 0,
1134bff34e3Sthurlow 		    binding_status);
1144bff34e3Sthurlow 		return (EINVAL);
1154bff34e3Sthurlow 	}
1164bff34e3Sthurlow 	level = 1;
1174bff34e3Sthurlow 	share_info.share_union.level = 1;
1184bff34e3Sthurlow 	share_info.share_union.tagged_union.share1 = &share_info_1_container;
1194bff34e3Sthurlow 	share_info_1_container.share_count = 0;
1204bff34e3Sthurlow 	share_info_1_container.shares = NULL;
1214bff34e3Sthurlow 	/*
1224bff34e3Sthurlow 	 * Convert the server IP address to a string, and send that as
1234bff34e3Sthurlow 	 * the "server name" - that's what Windows appears to do, and
1244bff34e3Sthurlow 	 * that avoids problems with NetBIOS names containing
1254bff34e3Sthurlow 	 * non-ASCII characters.
1264bff34e3Sthurlow 	 */
1274bff34e3Sthurlow 	addrstr = inet_ntoa(ctx->ct_srvinaddr.sin_addr);
1284bff34e3Sthurlow 	srvnamestr = malloc(strlen(addrstr) + 3);
1294bff34e3Sthurlow 	if (srvnamestr == NULL) {
1304bff34e3Sthurlow 		status = errno;
1314bff34e3Sthurlow 		smb_error(dgettext(TEXT_DOMAIN,
1324bff34e3Sthurlow 		    "can't allocate string for server address"), status);
1334bff34e3Sthurlow 		rpc_binding_free(&binding_h, &free_status);
1344bff34e3Sthurlow 		return (status);
1354bff34e3Sthurlow 	}
1364bff34e3Sthurlow 	strcpy(srvnamestr, "\\\\");
1374bff34e3Sthurlow 	strcat(srvnamestr, addrstr);
1384bff34e3Sthurlow 	usrvnamestr = convert_utf8_to_leunicode(srvnamestr);
1394bff34e3Sthurlow 	if (usrvnamestr == NULL) {
1404bff34e3Sthurlow 		smb_error(dgettext(TEXT_DOMAIN,
1414bff34e3Sthurlow 		    "can't convert string for server address to Unicode"), 0);
1424bff34e3Sthurlow 		rpc_binding_free(&binding_h, &free_status);
1439c9af259SGordon Ross 		free(srvnamestr);
1444bff34e3Sthurlow 		return (EINVAL);
1454bff34e3Sthurlow 	}
1464bff34e3Sthurlow 	if (!exceptions_initialized) {
1474bff34e3Sthurlow 		EXCEPTION_INIT(rpc_x_connect_rejected);
1484bff34e3Sthurlow 		exc_set_status(&rpc_x_connect_rejected, rpc_s_connect_rejected);
1494bff34e3Sthurlow 		exceptions_initialized = 1;
1504bff34e3Sthurlow 	}
1514bff34e3Sthurlow 	/* printf("Calling NetrShareEnum.."); XXX */
1524bff34e3Sthurlow 	TRY
1534bff34e3Sthurlow 		status = NetrShareEnum(binding_h, usrvnamestr, &level,
1544bff34e3Sthurlow 		    &share_info, 4294967295U, &total_entries, NULL);
1554bff34e3Sthurlow 		if (status != 0)
1564bff34e3Sthurlow 			smb_error(dgettext(TEXT_DOMAIN,
1574bff34e3Sthurlow 			    "error from NetrShareEnum call: status = 0x%08x"),
1584bff34e3Sthurlow 			    0, status);
1594bff34e3Sthurlow 	/*CSTYLED*/
1604bff34e3Sthurlow 	CATCH (rpc_x_connect_rejected)
1614bff34e3Sthurlow 		/*
1624bff34e3Sthurlow 		 * This is what we get if we can't open the pipe.
1634bff34e3Sthurlow 		 * That's a normal occurrence when we're talking
1644bff34e3Sthurlow 		 * to a system that (presumably) doesn't support
1654bff34e3Sthurlow 		 * DCE RPC on the server side, such as Windows 95/98/Me,
1664bff34e3Sthurlow 		 * so we don't log an error.
1674bff34e3Sthurlow 		 */
1684bff34e3Sthurlow 		/*CSTYLED*/
1694bff34e3Sthurlow 		status = ENOTSUP;
1704bff34e3Sthurlow 	CATCH_ALL
1714bff34e3Sthurlow 		/*
1724bff34e3Sthurlow 		 * XXX - should we handle some exceptions differently,
1734bff34e3Sthurlow 		 * returning different errors, and try RAP only for
1744bff34e3Sthurlow 		 * ENOTSUP?
1754bff34e3Sthurlow 		 */
1764bff34e3Sthurlow 		smb_error(dgettext(TEXT_DOMAIN,
1774bff34e3Sthurlow 		    "error from NetrShareEnum call: exception = %u"),
1784bff34e3Sthurlow 		    0, THIS_CATCH->match.value);
1794bff34e3Sthurlow 		status = ENOTSUP;
1804bff34e3Sthurlow 	ENDTRY
1814bff34e3Sthurlow 	rpc_binding_free(&binding_h, &free_status);
1824bff34e3Sthurlow 	free(srvnamestr);
1834bff34e3Sthurlow 	free(usrvnamestr);
1844bff34e3Sthurlow 	if (status != 0)
1854bff34e3Sthurlow 		return (ENOTSUP);
1864bff34e3Sthurlow 
1874bff34e3Sthurlow 	/*
1884bff34e3Sthurlow 	 * XXX - if the IDL is correct, it's not clear whether the
1894bff34e3Sthurlow 	 * unmarshalling code will properly handle the case where
1904bff34e3Sthurlow 	 * a packet where "share_count" and the max count for the
1914bff34e3Sthurlow 	 * array of shares don't match; a valid DCE RPC implementation
1924bff34e3Sthurlow 	 * won't marshal something like that, but there's no guarantee
1934bff34e3Sthurlow 	 * that the server we're talking to has a valid implementation
1944bff34e3Sthurlow 	 * (which could be a *malicious* implementation!).
1954bff34e3Sthurlow 	 */
1964bff34e3Sthurlow 	entries = share_info.share_union.tagged_union.share1->share_count;
1974bff34e3Sthurlow 	shares = share_info.share_union.tagged_union.share1->shares;
1984bff34e3Sthurlow 	entry_list = calloc(entries, sizeof (struct share_info));
1994bff34e3Sthurlow 	if (entry_list == NULL) {
2004bff34e3Sthurlow 		error = errno;
2014bff34e3Sthurlow 		goto cleanup_and_return;
2024bff34e3Sthurlow 	}
2034bff34e3Sthurlow 	for (share = shares, elp = entry_list, i = 0; i < entries;
2044bff34e3Sthurlow 	    i++, share++) {
2054bff34e3Sthurlow 		elp->type = share->shi1_type;
2064bff34e3Sthurlow 		elp->netname = convert_unicode_to_utf8(share->shi1_share);
2074bff34e3Sthurlow 		if (elp->netname == NULL)
2084bff34e3Sthurlow 			goto fail;
2094bff34e3Sthurlow 		elp->remark = convert_unicode_to_utf8(share->shi1_remark);
2104bff34e3Sthurlow 		if (elp->remark == NULL)
2114bff34e3Sthurlow 			goto fail;
2124bff34e3Sthurlow 		elp++;
2134bff34e3Sthurlow 	}
2144bff34e3Sthurlow 	*entriesp = entries;
2154bff34e3Sthurlow 	*totalp = total_entries;
2164bff34e3Sthurlow 	*entries_listp = entry_list;
2174bff34e3Sthurlow 	error = 0;
2184bff34e3Sthurlow 	goto cleanup_and_return;
2194bff34e3Sthurlow 
2204bff34e3Sthurlow fail:
2214bff34e3Sthurlow 	error = errno;
2224bff34e3Sthurlow 	for (elp = entry_list, i = 0; i < entries; i++, elp++) {
2234bff34e3Sthurlow 		/*
2244bff34e3Sthurlow 		 * elp->netname is set before elp->remark, so if
2254bff34e3Sthurlow 		 * elp->netname is null, elp->remark is also null.
2264bff34e3Sthurlow 		 * If either of them is null, we haven't done anything
2274bff34e3Sthurlow 		 * to any entries after this one.
2284bff34e3Sthurlow 		 */
2294bff34e3Sthurlow 		if (elp->netname == NULL)
2304bff34e3Sthurlow 			break;
2314bff34e3Sthurlow 		free(elp->netname);
2324bff34e3Sthurlow 		if (elp->remark == NULL)
2334bff34e3Sthurlow 			break;
2344bff34e3Sthurlow 		free(elp->remark);
2354bff34e3Sthurlow 	}
2364bff34e3Sthurlow 	free(entry_list);
2374bff34e3Sthurlow 
2384bff34e3Sthurlow cleanup_and_return:
2394bff34e3Sthurlow 	for (share = shares, i = 0; i < entries; i++, share++) {
2404bff34e3Sthurlow 		free(share->shi1_share);
2414bff34e3Sthurlow 		free(share->shi1_remark);
2424bff34e3Sthurlow 	}
2434bff34e3Sthurlow 	free(shares);
2444bff34e3Sthurlow 	/*
2454bff34e3Sthurlow 	 * XXX - "share1" should be a unique pointer, but we haven't
2464bff34e3Sthurlow 	 * changed the marshalling code to support non-full pointers
2474bff34e3Sthurlow 	 * in unions, so we leave it as a full pointer.
2484bff34e3Sthurlow 	 *
2494bff34e3Sthurlow 	 * That means that this might, or might not, be changed from
2504bff34e3Sthurlow 	 * pointing to "share_info_1_container" to pointing to a
2514bff34e3Sthurlow 	 * mallocated structure, according to the DCE RPC 1.1 IDL spec;
2524bff34e3Sthurlow 	 * we free it only if it's changed.
2534bff34e3Sthurlow 	 */
2544bff34e3Sthurlow 	if (share_info.share_union.tagged_union.share1 !=
2554bff34e3Sthurlow 	    &share_info_1_container)
2564bff34e3Sthurlow 		free(share_info.share_union.tagged_union.share1);
2574bff34e3Sthurlow 	return (error);
2584bff34e3Sthurlow }
2594bff34e3Sthurlow #endif /* XXX */
2604bff34e3Sthurlow 
2619c9af259SGordon Ross /*
2629c9af259SGordon Ross  * Enumerate shares using RAP
2639c9af259SGordon Ross  */
2649c9af259SGordon Ross 
2659c9af259SGordon Ross struct smb_share_info_1 {
2669c9af259SGordon Ross 	char		shi1_netname[13];
2679c9af259SGordon Ross 	char		shi1_pad;
2689c9af259SGordon Ross 	uint16_t	shi1_type;
2699c9af259SGordon Ross 	uint32_t	shi1_remark;		/* char * */
2709c9af259SGordon Ross };
2719c9af259SGordon Ross 
2729c9af259SGordon Ross static int
2739c9af259SGordon Ross smb_rap_NetShareEnum(struct smb_ctx *ctx, int sLevel, void *pbBuffer,
2749c9af259SGordon Ross 	int *cbBuffer, int *pcEntriesRead, int *pcTotalAvail)
2759c9af259SGordon Ross {
2769c9af259SGordon Ross 	struct smb_rap *rap;
2779c9af259SGordon Ross 	long lval = -1;
2789c9af259SGordon Ross 	int error;
2799c9af259SGordon Ross 
2809c9af259SGordon Ross 	error = smb_rap_create(0, "WrLeh", "B13BWz", &rap);
2819c9af259SGordon Ross 	if (error)
2829c9af259SGordon Ross 		return (error);
283*02d09e03SGordon Ross 	(void) smb_rap_setNparam(rap, sLevel);		/* W - sLevel */
284*02d09e03SGordon Ross 	(void) smb_rap_setPparam(rap, pbBuffer);	/* r - pbBuffer */
285*02d09e03SGordon Ross 	(void) smb_rap_setNparam(rap, *cbBuffer);	/* L - cbBuffer */
2869c9af259SGordon Ross 	error = smb_rap_request(rap, ctx);
2879c9af259SGordon Ross 	if (error == 0) {
2889c9af259SGordon Ross 		*pcEntriesRead = rap->r_entries;
2899c9af259SGordon Ross 		error = smb_rap_getNparam(rap, &lval);
2909c9af259SGordon Ross 		*pcTotalAvail = lval;
2919c9af259SGordon Ross 		/* Copy the data length into the IN/OUT variable. */
2929c9af259SGordon Ross 		*cbBuffer = rap->r_rcvbuflen;
2939c9af259SGordon Ross 	}
2949c9af259SGordon Ross 	error = smb_rap_error(rap, error);
2959c9af259SGordon Ross 	smb_rap_done(rap);
2969c9af259SGordon Ross 	return (error);
2979c9af259SGordon Ross }
2989c9af259SGordon Ross 
2994bff34e3Sthurlow static int
3004bff34e3Sthurlow rap_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
3014bff34e3Sthurlow     struct share_info **entries_listp)
3024bff34e3Sthurlow {
3034bff34e3Sthurlow 	int error, bufsize, i, entries, total, nreturned;
3044bff34e3Sthurlow 	struct smb_share_info_1 *rpbuf, *ep;
3054bff34e3Sthurlow 	struct share_info *entry_list, *elp;
3064bff34e3Sthurlow 	char *cp;
3074bff34e3Sthurlow 	int lbound, rbound;
3084bff34e3Sthurlow 
3094bff34e3Sthurlow 	bufsize = 0xffe0;	/* samba notes win2k bug for 65535 */
3104bff34e3Sthurlow 	rpbuf = malloc(bufsize);
3114bff34e3Sthurlow 	if (rpbuf == NULL)
3124bff34e3Sthurlow 		return (errno);
3134bff34e3Sthurlow 
3144bff34e3Sthurlow 	error = smb_rap_NetShareEnum(ctx, 1, rpbuf, &bufsize, &entries, &total);
3154bff34e3Sthurlow 	if (error &&
3164bff34e3Sthurlow 	    error != (SMB_ERROR_MORE_DATA | SMB_RAP_ERROR)) {
3174bff34e3Sthurlow 		free(rpbuf);
3184bff34e3Sthurlow 		return (error);
3194bff34e3Sthurlow 	}
3204bff34e3Sthurlow 	entry_list = malloc(entries * sizeof (struct share_info));
3214bff34e3Sthurlow 	if (entry_list == NULL) {
3224bff34e3Sthurlow 		error = errno;
3234bff34e3Sthurlow 		free(rpbuf);
3244bff34e3Sthurlow 		return (error);
3254bff34e3Sthurlow 	}
3264bff34e3Sthurlow 	lbound = entries * (sizeof (struct smb_share_info_1));
3274bff34e3Sthurlow 	rbound = bufsize;
3284bff34e3Sthurlow 	for (ep = rpbuf, elp = entry_list, i = 0, nreturned = 0; i < entries;
3294bff34e3Sthurlow 	    i++, ep++) {
3304bff34e3Sthurlow 		elp->type = letohs(ep->shi1_type);
3314bff34e3Sthurlow 		ep->shi1_pad = '\0'; /* ensure null termination */
3324bff34e3Sthurlow 		elp->netname = convert_wincs_to_utf8(ep->shi1_netname);
3334bff34e3Sthurlow 		if (elp->netname == NULL)
3344bff34e3Sthurlow 			continue;	/* punt on this entry */
3354bff34e3Sthurlow 		/*
3364bff34e3Sthurlow 		 * Check for validity of offset.
3374bff34e3Sthurlow 		 */
3384bff34e3Sthurlow 		if (ep->shi1_remark >= lbound && ep->shi1_remark < rbound) {
3394bff34e3Sthurlow 			cp = (char *)rpbuf + ep->shi1_remark;
3409c9af259SGordon Ross 			elp->remark = convert_wincs_to_utf8(cp);
3414bff34e3Sthurlow 		} else
3424bff34e3Sthurlow 			elp->remark = NULL;
3434bff34e3Sthurlow 		elp++;
3444bff34e3Sthurlow 		nreturned++;
3454bff34e3Sthurlow 	}
3464bff34e3Sthurlow 	*entriesp = nreturned;
3474bff34e3Sthurlow 	*totalp = total;
3484bff34e3Sthurlow 	*entries_listp = entry_list;
3494bff34e3Sthurlow 	free(rpbuf);
3504bff34e3Sthurlow 	return (0);
3514bff34e3Sthurlow }
3524bff34e3Sthurlow 
3534bff34e3Sthurlow /*
3544bff34e3Sthurlow  * First we try the RPC-based NetrShareEnum, and, if that fails, we fall
3554bff34e3Sthurlow  * back on the RAP-based NetShareEnum.
3564bff34e3Sthurlow  */
3574bff34e3Sthurlow int
3584bff34e3Sthurlow smb_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
3594bff34e3Sthurlow     struct share_info **entry_listp)
3604bff34e3Sthurlow {
3614bff34e3Sthurlow 	int error;
3624bff34e3Sthurlow 
3634bff34e3Sthurlow #ifdef NOTYETDEFINED
3644bff34e3Sthurlow 	/*
3654bff34e3Sthurlow 	 * Try getting a list of shares with the SRVSVC RPC service.
3664bff34e3Sthurlow 	 */
3674bff34e3Sthurlow 	error = rpc_netshareenum(ctx, entriesp, totalp, entry_listp);
3684bff34e3Sthurlow 	if (error == 0)
3694bff34e3Sthurlow 		return (0);
3704bff34e3Sthurlow #endif
3714bff34e3Sthurlow 
3724bff34e3Sthurlow 	/*
3734bff34e3Sthurlow 	 * OK, that didn't work - try RAP.
3744bff34e3Sthurlow 	 * XXX - do so only if it failed because we couldn't open
3754bff34e3Sthurlow 	 * the pipe?
3764bff34e3Sthurlow 	 */
377613a2f6bSGordon Ross 	error = rap_netshareenum(ctx, entriesp, totalp, entry_listp);
378613a2f6bSGordon Ross 	return (error);
3794bff34e3Sthurlow }
380