xref: /titanic_51/usr/src/lib/libsmbfs/smb/netshareenum.c (revision 148c5f43199ca0b43fc8e3b643aab11cd66ea327)
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 /*
40*148c5f43SAlan Wright  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
419c9af259SGordon Ross  */
424bff34e3Sthurlow 
434bff34e3Sthurlow #include <stdlib.h>
444bff34e3Sthurlow #include <string.h>
454bff34e3Sthurlow #include <stdio.h>
464bff34e3Sthurlow #include <errno.h>
474bff34e3Sthurlow 
484bff34e3Sthurlow #include <netsmb/mchain.h>
49613a2f6bSGordon Ross #include <netsmb/smb.h>
504bff34e3Sthurlow #include <netsmb/smb_lib.h>
514bff34e3Sthurlow #include <netsmb/smb_rap.h>
524bff34e3Sthurlow #include <netsmb/smb_netshareenum.h>
539c9af259SGordon Ross #include <smb/charsets.h>
544bff34e3Sthurlow 
554bff34e3Sthurlow #if 0 /* XXX see below */
564bff34e3Sthurlow #include <dce/exc_handling.h>
579c9af259SGordon Ross #include <rpc/attrb.h>
584bff34e3Sthurlow #include "srvsvc.h"
594bff34e3Sthurlow #endif
604bff34e3Sthurlow 
614bff34e3Sthurlow /*
624bff34e3Sthurlow  * Don't want RPC client-side code in here.
634bff34e3Sthurlow  * It's good code; just doesn't belong here.
644bff34e3Sthurlow  *
654bff34e3Sthurlow  * The API provided by this library should be
664bff34e3Sthurlow  * just files and pipes (and not much more).
674bff34e3Sthurlow  * It MAY be useful to provide some of the
684bff34e3Sthurlow  * RAP (remote API) functions functions like
694bff34e3Sthurlow  * rap_netshareenum below...
704bff34e3Sthurlow  *
714bff34e3Sthurlow  * XXX: Not sure this file belongs here at all.
724bff34e3Sthurlow  * smb_rap.h looks like a reasonable API
734bff34e3Sthurlow  * for this library to export.
744bff34e3Sthurlow  */
754bff34e3Sthurlow #if 0 /* XXX */
764bff34e3Sthurlow 
774bff34e3Sthurlow static int
784bff34e3Sthurlow rpc_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
794bff34e3Sthurlow     struct share_info **entries_listp)
804bff34e3Sthurlow {
814bff34e3Sthurlow 	char ctx_string[2+16+1];	/* enough for 64-bit pointer, in hex */
824bff34e3Sthurlow 	unsigned_char_p_t binding;
834bff34e3Sthurlow 	unsigned32 binding_status;
844bff34e3Sthurlow 	rpc_binding_handle_t binding_h;
854bff34e3Sthurlow 	int error, i, entries;
864bff34e3Sthurlow 	char *addrstr, *srvnamestr;
874bff34e3Sthurlow 	unsigned short *usrvnamestr;
884bff34e3Sthurlow 	unsigned32 level;
894bff34e3Sthurlow 	SHARE_ENUM_STRUCT share_info;
904bff34e3Sthurlow 	SHARE_INFO_1_CONTAINER share_info_1_container;
914bff34e3Sthurlow 	SHARE_INFO_1 *shares, *share;
924bff34e3Sthurlow 	unsigned32 total_entries;
934bff34e3Sthurlow 	unsigned32 status, free_status;
944bff34e3Sthurlow 	struct share_info *entry_list, *elp;
954bff34e3Sthurlow 	static EXCEPTION rpc_x_connect_rejected;
964bff34e3Sthurlow 	static int exceptions_initialized;
974bff34e3Sthurlow 
984bff34e3Sthurlow 	sprintf(ctx_string, "%p", ctx);
994bff34e3Sthurlow 	rpc_string_binding_compose(NULL, "ncacn_np", ctx_string,
1004bff34e3Sthurlow 	    "srvsvc", NULL, &binding, &binding_status);
1014bff34e3Sthurlow 	if (binding_status != rpc_s_ok) {
1024bff34e3Sthurlow 		smb_error(dgettext(TEXT_DOMAIN,
1034bff34e3Sthurlow 		    "rpc_string_binding_compose failed with %d"),
1044bff34e3Sthurlow 		    0, binding_status);
1054bff34e3Sthurlow 		return (EINVAL);
1064bff34e3Sthurlow 	}
1074bff34e3Sthurlow 	rpc_binding_from_string_binding(binding, &binding_h, &status);
1089c9af259SGordon Ross 	rpc_string_free(&binding, (unsigned32 *)&free_status);
1094bff34e3Sthurlow 	if (binding_status != rpc_s_ok) {
1104bff34e3Sthurlow 		smb_error(dgettext(TEXT_DOMAIN,
1114bff34e3Sthurlow 		    "rpc_binding_from_string_binding failed with %d"), 0,
1124bff34e3Sthurlow 		    binding_status);
1134bff34e3Sthurlow 		return (EINVAL);
1144bff34e3Sthurlow 	}
1154bff34e3Sthurlow 	level = 1;
1164bff34e3Sthurlow 	share_info.share_union.level = 1;
1174bff34e3Sthurlow 	share_info.share_union.tagged_union.share1 = &share_info_1_container;
1184bff34e3Sthurlow 	share_info_1_container.share_count = 0;
1194bff34e3Sthurlow 	share_info_1_container.shares = NULL;
1204bff34e3Sthurlow 	/*
1214bff34e3Sthurlow 	 * Convert the server IP address to a string, and send that as
1224bff34e3Sthurlow 	 * the "server name" - that's what Windows appears to do, and
1234bff34e3Sthurlow 	 * that avoids problems with NetBIOS names containing
1244bff34e3Sthurlow 	 * non-ASCII characters.
1254bff34e3Sthurlow 	 */
1264bff34e3Sthurlow 	addrstr = inet_ntoa(ctx->ct_srvinaddr.sin_addr);
1274bff34e3Sthurlow 	srvnamestr = malloc(strlen(addrstr) + 3);
1284bff34e3Sthurlow 	if (srvnamestr == NULL) {
1294bff34e3Sthurlow 		status = errno;
1304bff34e3Sthurlow 		smb_error(dgettext(TEXT_DOMAIN,
1314bff34e3Sthurlow 		    "can't allocate string for server address"), status);
1324bff34e3Sthurlow 		rpc_binding_free(&binding_h, &free_status);
1334bff34e3Sthurlow 		return (status);
1344bff34e3Sthurlow 	}
1354bff34e3Sthurlow 	strcpy(srvnamestr, "\\\\");
1364bff34e3Sthurlow 	strcat(srvnamestr, addrstr);
1374bff34e3Sthurlow 	usrvnamestr = convert_utf8_to_leunicode(srvnamestr);
1384bff34e3Sthurlow 	if (usrvnamestr == NULL) {
1394bff34e3Sthurlow 		smb_error(dgettext(TEXT_DOMAIN,
1404bff34e3Sthurlow 		    "can't convert string for server address to Unicode"), 0);
1414bff34e3Sthurlow 		rpc_binding_free(&binding_h, &free_status);
1429c9af259SGordon Ross 		free(srvnamestr);
1434bff34e3Sthurlow 		return (EINVAL);
1444bff34e3Sthurlow 	}
1454bff34e3Sthurlow 	if (!exceptions_initialized) {
1464bff34e3Sthurlow 		EXCEPTION_INIT(rpc_x_connect_rejected);
1474bff34e3Sthurlow 		exc_set_status(&rpc_x_connect_rejected, rpc_s_connect_rejected);
1484bff34e3Sthurlow 		exceptions_initialized = 1;
1494bff34e3Sthurlow 	}
1504bff34e3Sthurlow 	/* printf("Calling NetrShareEnum.."); XXX */
1514bff34e3Sthurlow 	TRY
1524bff34e3Sthurlow 		status = NetrShareEnum(binding_h, usrvnamestr, &level,
1534bff34e3Sthurlow 		    &share_info, 4294967295U, &total_entries, NULL);
1544bff34e3Sthurlow 		if (status != 0)
1554bff34e3Sthurlow 			smb_error(dgettext(TEXT_DOMAIN,
1564bff34e3Sthurlow 			    "error from NetrShareEnum call: status = 0x%08x"),
1574bff34e3Sthurlow 			    0, status);
1584bff34e3Sthurlow 	/*CSTYLED*/
1594bff34e3Sthurlow 	CATCH (rpc_x_connect_rejected)
1604bff34e3Sthurlow 		/*
1614bff34e3Sthurlow 		 * This is what we get if we can't open the pipe.
1624bff34e3Sthurlow 		 * That's a normal occurrence when we're talking
1634bff34e3Sthurlow 		 * to a system that (presumably) doesn't support
1644bff34e3Sthurlow 		 * DCE RPC on the server side, such as Windows 95/98/Me,
1654bff34e3Sthurlow 		 * so we don't log an error.
1664bff34e3Sthurlow 		 */
1674bff34e3Sthurlow 		/*CSTYLED*/
1684bff34e3Sthurlow 		status = ENOTSUP;
1694bff34e3Sthurlow 	CATCH_ALL
1704bff34e3Sthurlow 		/*
1714bff34e3Sthurlow 		 * XXX - should we handle some exceptions differently,
1724bff34e3Sthurlow 		 * returning different errors, and try RAP only for
1734bff34e3Sthurlow 		 * ENOTSUP?
1744bff34e3Sthurlow 		 */
1754bff34e3Sthurlow 		smb_error(dgettext(TEXT_DOMAIN,
1764bff34e3Sthurlow 		    "error from NetrShareEnum call: exception = %u"),
1774bff34e3Sthurlow 		    0, THIS_CATCH->match.value);
1784bff34e3Sthurlow 		status = ENOTSUP;
1794bff34e3Sthurlow 	ENDTRY
1804bff34e3Sthurlow 	rpc_binding_free(&binding_h, &free_status);
1814bff34e3Sthurlow 	free(srvnamestr);
1824bff34e3Sthurlow 	free(usrvnamestr);
1834bff34e3Sthurlow 	if (status != 0)
1844bff34e3Sthurlow 		return (ENOTSUP);
1854bff34e3Sthurlow 
1864bff34e3Sthurlow 	/*
1874bff34e3Sthurlow 	 * XXX - if the IDL is correct, it's not clear whether the
1884bff34e3Sthurlow 	 * unmarshalling code will properly handle the case where
1894bff34e3Sthurlow 	 * a packet where "share_count" and the max count for the
1904bff34e3Sthurlow 	 * array of shares don't match; a valid DCE RPC implementation
1914bff34e3Sthurlow 	 * won't marshal something like that, but there's no guarantee
1924bff34e3Sthurlow 	 * that the server we're talking to has a valid implementation
1934bff34e3Sthurlow 	 * (which could be a *malicious* implementation!).
1944bff34e3Sthurlow 	 */
1954bff34e3Sthurlow 	entries = share_info.share_union.tagged_union.share1->share_count;
1964bff34e3Sthurlow 	shares = share_info.share_union.tagged_union.share1->shares;
1974bff34e3Sthurlow 	entry_list = calloc(entries, sizeof (struct share_info));
1984bff34e3Sthurlow 	if (entry_list == NULL) {
1994bff34e3Sthurlow 		error = errno;
2004bff34e3Sthurlow 		goto cleanup_and_return;
2014bff34e3Sthurlow 	}
2024bff34e3Sthurlow 	for (share = shares, elp = entry_list, i = 0; i < entries;
2034bff34e3Sthurlow 	    i++, share++) {
2044bff34e3Sthurlow 		elp->type = share->shi1_type;
2054bff34e3Sthurlow 		elp->netname = convert_unicode_to_utf8(share->shi1_share);
2064bff34e3Sthurlow 		if (elp->netname == NULL)
2074bff34e3Sthurlow 			goto fail;
2084bff34e3Sthurlow 		elp->remark = convert_unicode_to_utf8(share->shi1_remark);
2094bff34e3Sthurlow 		if (elp->remark == NULL)
2104bff34e3Sthurlow 			goto fail;
2114bff34e3Sthurlow 		elp++;
2124bff34e3Sthurlow 	}
2134bff34e3Sthurlow 	*entriesp = entries;
2144bff34e3Sthurlow 	*totalp = total_entries;
2154bff34e3Sthurlow 	*entries_listp = entry_list;
2164bff34e3Sthurlow 	error = 0;
2174bff34e3Sthurlow 	goto cleanup_and_return;
2184bff34e3Sthurlow 
2194bff34e3Sthurlow fail:
2204bff34e3Sthurlow 	error = errno;
2214bff34e3Sthurlow 	for (elp = entry_list, i = 0; i < entries; i++, elp++) {
2224bff34e3Sthurlow 		/*
2234bff34e3Sthurlow 		 * elp->netname is set before elp->remark, so if
2244bff34e3Sthurlow 		 * elp->netname is null, elp->remark is also null.
2254bff34e3Sthurlow 		 * If either of them is null, we haven't done anything
2264bff34e3Sthurlow 		 * to any entries after this one.
2274bff34e3Sthurlow 		 */
2284bff34e3Sthurlow 		if (elp->netname == NULL)
2294bff34e3Sthurlow 			break;
2304bff34e3Sthurlow 		free(elp->netname);
2314bff34e3Sthurlow 		if (elp->remark == NULL)
2324bff34e3Sthurlow 			break;
2334bff34e3Sthurlow 		free(elp->remark);
2344bff34e3Sthurlow 	}
2354bff34e3Sthurlow 	free(entry_list);
2364bff34e3Sthurlow 
2374bff34e3Sthurlow cleanup_and_return:
2384bff34e3Sthurlow 	for (share = shares, i = 0; i < entries; i++, share++) {
2394bff34e3Sthurlow 		free(share->shi1_share);
2404bff34e3Sthurlow 		free(share->shi1_remark);
2414bff34e3Sthurlow 	}
2424bff34e3Sthurlow 	free(shares);
2434bff34e3Sthurlow 	/*
2444bff34e3Sthurlow 	 * XXX - "share1" should be a unique pointer, but we haven't
2454bff34e3Sthurlow 	 * changed the marshalling code to support non-full pointers
2464bff34e3Sthurlow 	 * in unions, so we leave it as a full pointer.
2474bff34e3Sthurlow 	 *
2484bff34e3Sthurlow 	 * That means that this might, or might not, be changed from
2494bff34e3Sthurlow 	 * pointing to "share_info_1_container" to pointing to a
2504bff34e3Sthurlow 	 * mallocated structure, according to the DCE RPC 1.1 IDL spec;
2514bff34e3Sthurlow 	 * we free it only if it's changed.
2524bff34e3Sthurlow 	 */
2534bff34e3Sthurlow 	if (share_info.share_union.tagged_union.share1 !=
2544bff34e3Sthurlow 	    &share_info_1_container)
2554bff34e3Sthurlow 		free(share_info.share_union.tagged_union.share1);
2564bff34e3Sthurlow 	return (error);
2574bff34e3Sthurlow }
2584bff34e3Sthurlow #endif /* XXX */
2594bff34e3Sthurlow 
2609c9af259SGordon Ross /*
2619c9af259SGordon Ross  * Enumerate shares using RAP
2629c9af259SGordon Ross  */
2639c9af259SGordon Ross 
2649c9af259SGordon Ross struct smb_share_info_1 {
2659c9af259SGordon Ross 	char		shi1_netname[13];
2669c9af259SGordon Ross 	char		shi1_pad;
2679c9af259SGordon Ross 	uint16_t	shi1_type;
2689c9af259SGordon Ross 	uint32_t	shi1_remark;		/* char * */
2699c9af259SGordon Ross };
2709c9af259SGordon Ross 
2719c9af259SGordon Ross static int
2729c9af259SGordon Ross smb_rap_NetShareEnum(struct smb_ctx *ctx, int sLevel, void *pbBuffer,
2739c9af259SGordon Ross 	int *cbBuffer, int *pcEntriesRead, int *pcTotalAvail)
2749c9af259SGordon Ross {
2759c9af259SGordon Ross 	struct smb_rap *rap;
2769c9af259SGordon Ross 	long lval = -1;
2779c9af259SGordon Ross 	int error;
2789c9af259SGordon Ross 
2799c9af259SGordon Ross 	error = smb_rap_create(0, "WrLeh", "B13BWz", &rap);
2809c9af259SGordon Ross 	if (error)
2819c9af259SGordon Ross 		return (error);
28202d09e03SGordon Ross 	(void) smb_rap_setNparam(rap, sLevel);		/* W - sLevel */
28302d09e03SGordon Ross 	(void) smb_rap_setPparam(rap, pbBuffer);	/* r - pbBuffer */
28402d09e03SGordon Ross 	(void) smb_rap_setNparam(rap, *cbBuffer);	/* L - cbBuffer */
2859c9af259SGordon Ross 	error = smb_rap_request(rap, ctx);
2869c9af259SGordon Ross 	if (error == 0) {
2879c9af259SGordon Ross 		*pcEntriesRead = rap->r_entries;
2889c9af259SGordon Ross 		error = smb_rap_getNparam(rap, &lval);
2899c9af259SGordon Ross 		*pcTotalAvail = lval;
2909c9af259SGordon Ross 		/* Copy the data length into the IN/OUT variable. */
2919c9af259SGordon Ross 		*cbBuffer = rap->r_rcvbuflen;
2929c9af259SGordon Ross 	}
2939c9af259SGordon Ross 	error = smb_rap_error(rap, error);
2949c9af259SGordon Ross 	smb_rap_done(rap);
2959c9af259SGordon Ross 	return (error);
2969c9af259SGordon Ross }
2979c9af259SGordon Ross 
2984bff34e3Sthurlow static int
2994bff34e3Sthurlow rap_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
3004bff34e3Sthurlow     struct share_info **entries_listp)
3014bff34e3Sthurlow {
3024bff34e3Sthurlow 	int error, bufsize, i, entries, total, nreturned;
3034bff34e3Sthurlow 	struct smb_share_info_1 *rpbuf, *ep;
3044bff34e3Sthurlow 	struct share_info *entry_list, *elp;
3054bff34e3Sthurlow 	char *cp;
3064bff34e3Sthurlow 	int lbound, rbound;
3074bff34e3Sthurlow 
3084bff34e3Sthurlow 	bufsize = 0xffe0;	/* samba notes win2k bug for 65535 */
3094bff34e3Sthurlow 	rpbuf = malloc(bufsize);
3104bff34e3Sthurlow 	if (rpbuf == NULL)
3114bff34e3Sthurlow 		return (errno);
3124bff34e3Sthurlow 
3134bff34e3Sthurlow 	error = smb_rap_NetShareEnum(ctx, 1, rpbuf, &bufsize, &entries, &total);
3144bff34e3Sthurlow 	if (error &&
315*148c5f43SAlan Wright 	    error != (ERROR_MORE_DATA | SMB_RAP_ERROR)) {
3164bff34e3Sthurlow 		free(rpbuf);
3174bff34e3Sthurlow 		return (error);
3184bff34e3Sthurlow 	}
3194bff34e3Sthurlow 	entry_list = malloc(entries * sizeof (struct share_info));
3204bff34e3Sthurlow 	if (entry_list == NULL) {
3214bff34e3Sthurlow 		error = errno;
3224bff34e3Sthurlow 		free(rpbuf);
3234bff34e3Sthurlow 		return (error);
3244bff34e3Sthurlow 	}
3254bff34e3Sthurlow 	lbound = entries * (sizeof (struct smb_share_info_1));
3264bff34e3Sthurlow 	rbound = bufsize;
3274bff34e3Sthurlow 	for (ep = rpbuf, elp = entry_list, i = 0, nreturned = 0; i < entries;
3284bff34e3Sthurlow 	    i++, ep++) {
3294bff34e3Sthurlow 		elp->type = letohs(ep->shi1_type);
3304bff34e3Sthurlow 		ep->shi1_pad = '\0'; /* ensure null termination */
3314bff34e3Sthurlow 		elp->netname = convert_wincs_to_utf8(ep->shi1_netname);
3324bff34e3Sthurlow 		if (elp->netname == NULL)
3334bff34e3Sthurlow 			continue;	/* punt on this entry */
3344bff34e3Sthurlow 		/*
3354bff34e3Sthurlow 		 * Check for validity of offset.
3364bff34e3Sthurlow 		 */
3374bff34e3Sthurlow 		if (ep->shi1_remark >= lbound && ep->shi1_remark < rbound) {
3384bff34e3Sthurlow 			cp = (char *)rpbuf + ep->shi1_remark;
3399c9af259SGordon Ross 			elp->remark = convert_wincs_to_utf8(cp);
3404bff34e3Sthurlow 		} else
3414bff34e3Sthurlow 			elp->remark = NULL;
3424bff34e3Sthurlow 		elp++;
3434bff34e3Sthurlow 		nreturned++;
3444bff34e3Sthurlow 	}
3454bff34e3Sthurlow 	*entriesp = nreturned;
3464bff34e3Sthurlow 	*totalp = total;
3474bff34e3Sthurlow 	*entries_listp = entry_list;
3484bff34e3Sthurlow 	free(rpbuf);
3494bff34e3Sthurlow 	return (0);
3504bff34e3Sthurlow }
3514bff34e3Sthurlow 
3524bff34e3Sthurlow /*
3534bff34e3Sthurlow  * First we try the RPC-based NetrShareEnum, and, if that fails, we fall
3544bff34e3Sthurlow  * back on the RAP-based NetShareEnum.
3554bff34e3Sthurlow  */
3564bff34e3Sthurlow int
3574bff34e3Sthurlow smb_netshareenum(struct smb_ctx *ctx, int *entriesp, int *totalp,
3584bff34e3Sthurlow     struct share_info **entry_listp)
3594bff34e3Sthurlow {
3604bff34e3Sthurlow 	int error;
3614bff34e3Sthurlow 
3624bff34e3Sthurlow #ifdef NOTYETDEFINED
3634bff34e3Sthurlow 	/*
3644bff34e3Sthurlow 	 * Try getting a list of shares with the SRVSVC RPC service.
3654bff34e3Sthurlow 	 */
3664bff34e3Sthurlow 	error = rpc_netshareenum(ctx, entriesp, totalp, entry_listp);
3674bff34e3Sthurlow 	if (error == 0)
3684bff34e3Sthurlow 		return (0);
3694bff34e3Sthurlow #endif
3704bff34e3Sthurlow 
3714bff34e3Sthurlow 	/*
3724bff34e3Sthurlow 	 * OK, that didn't work - try RAP.
3734bff34e3Sthurlow 	 * XXX - do so only if it failed because we couldn't open
3744bff34e3Sthurlow 	 * the pipe?
3754bff34e3Sthurlow 	 */
376613a2f6bSGordon Ross 	error = rap_netshareenum(ctx, entriesp, totalp, entry_listp);
377613a2f6bSGordon Ross 	return (error);
3784bff34e3Sthurlow }
379