• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.5.8/source3/utils/
1/*
2   Unix SMB/CIFS implementation.
3   Network neighbourhood browser.
4
5   Copyright (C) Tim Potter      2000
6   Copyright (C) Jelmer Vernooij 2003
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 3 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program.  If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "includes.h"
23#include "../librpc/gen_ndr/cli_srvsvc.h"
24
25static int use_bcast;
26
27/* How low can we go? */
28
29enum tree_level {LEV_WORKGROUP, LEV_SERVER, LEV_SHARE};
30static enum tree_level level = LEV_SHARE;
31
32/* Holds a list of workgroups or servers */
33
34struct smb_name_list {
35        struct smb_name_list *prev, *next;
36        char *name, *comment;
37        uint32 server_type;
38};
39
40static struct smb_name_list *workgroups, *servers, *shares;
41
42static void free_name_list(struct smb_name_list *list)
43{
44        while(list)
45                DLIST_REMOVE(list, list);
46}
47
48static void add_name(const char *machine_name, uint32 server_type,
49                     const char *comment, void *state)
50{
51        struct smb_name_list **name_list = (struct smb_name_list **)state;
52        struct smb_name_list *new_name;
53
54        new_name = SMB_MALLOC_P(struct smb_name_list);
55
56        if (!new_name)
57                return;
58
59        ZERO_STRUCTP(new_name);
60
61	new_name->name = SMB_STRDUP(machine_name);
62	new_name->comment = SMB_STRDUP(comment);
63        new_name->server_type = server_type;
64
65	if (!new_name->name || !new_name->comment) {
66		SAFE_FREE(new_name->name);
67		SAFE_FREE(new_name->comment);
68		SAFE_FREE(new_name);
69		return;
70	}
71
72        DLIST_ADD(*name_list, new_name);
73}
74
75/****************************************************************************
76  display tree of smb workgroups, servers and shares
77****************************************************************************/
78static bool get_workgroups(struct user_auth_info *user_info)
79{
80        struct cli_state *cli;
81        struct sockaddr_storage server_ss;
82	TALLOC_CTX *ctx = talloc_tos();
83	char *master_workgroup = NULL;
84
85        /* Try to connect to a #1d name of our current workgroup.  If that
86           doesn't work broadcast for a master browser and then jump off
87           that workgroup. */
88
89	master_workgroup = talloc_strdup(ctx, lp_workgroup());
90	if (!master_workgroup) {
91		return false;
92	}
93
94        if (!use_bcast && !find_master_ip(lp_workgroup(), &server_ss)) {
95                DEBUG(4, ("Unable to find master browser for workgroup %s, falling back to broadcast\n",
96			  master_workgroup));
97				use_bcast = True;
98		} else if(!use_bcast) {
99			char addr[INET6_ADDRSTRLEN];
100			print_sockaddr(addr, sizeof(addr), &server_ss);
101			if (!(cli = get_ipc_connect(addr, &server_ss, user_info)))
102				return False;
103		}
104
105		if (!(cli = get_ipc_connect_master_ip_bcast(talloc_tos(),
106							user_info,
107							&master_workgroup))) {
108			DEBUG(4, ("Unable to find master browser by "
109				  "broadcast\n"));
110			return False;
111        }
112
113        if (!cli_NetServerEnum(cli, master_workgroup,
114                               SV_TYPE_DOMAIN_ENUM, add_name, &workgroups))
115                return False;
116
117        return True;
118}
119
120/* Retrieve the list of servers for a given workgroup */
121
122static bool get_servers(char *workgroup, struct user_auth_info *user_info)
123{
124        struct cli_state *cli;
125        struct sockaddr_storage server_ss;
126	char addr[INET6_ADDRSTRLEN];
127
128        /* Open an IPC$ connection to the master browser for the workgroup */
129
130        if (!find_master_ip(workgroup, &server_ss)) {
131                DEBUG(4, ("Cannot find master browser for workgroup %s\n",
132                          workgroup));
133                return False;
134        }
135
136	print_sockaddr(addr, sizeof(addr), &server_ss);
137        if (!(cli = get_ipc_connect(addr, &server_ss, user_info)))
138                return False;
139
140        if (!cli_NetServerEnum(cli, workgroup, SV_TYPE_ALL, add_name,
141                               &servers))
142                return False;
143
144        return True;
145}
146
147static bool get_rpc_shares(struct cli_state *cli,
148			   void (*fn)(const char *, uint32, const char *, void *),
149			   void *state)
150{
151	NTSTATUS status;
152	struct rpc_pipe_client *pipe_hnd = NULL;
153	TALLOC_CTX *mem_ctx;
154	WERROR werr;
155	struct srvsvc_NetShareInfoCtr info_ctr;
156	struct srvsvc_NetShareCtr1 ctr1;
157	int i;
158	uint32_t resume_handle = 0;
159	uint32_t total_entries = 0;
160
161	mem_ctx = talloc_new(NULL);
162	if (mem_ctx == NULL) {
163		DEBUG(0, ("talloc_new failed\n"));
164		return False;
165	}
166
167	status = cli_rpc_pipe_open_noauth(cli, &ndr_table_srvsvc.syntax_id,
168					  &pipe_hnd);
169
170	if (!NT_STATUS_IS_OK(status)) {
171		DEBUG(10, ("Could not connect to srvsvc pipe: %s\n",
172			   nt_errstr(status)));
173		TALLOC_FREE(mem_ctx);
174		return False;
175	}
176
177	ZERO_STRUCT(info_ctr);
178	ZERO_STRUCT(ctr1);
179
180	info_ctr.level = 1;
181	info_ctr.ctr.ctr1 = &ctr1;
182
183	status = rpccli_srvsvc_NetShareEnumAll(pipe_hnd, mem_ctx,
184					       pipe_hnd->desthost,
185					       &info_ctr,
186					       0xffffffff,
187					       &total_entries,
188					       &resume_handle,
189					       &werr);
190
191	if (!NT_STATUS_IS_OK(status) || !W_ERROR_IS_OK(werr)) {
192		TALLOC_FREE(mem_ctx);
193		TALLOC_FREE(pipe_hnd);
194		return False;
195	}
196
197	for (i=0; i<total_entries; i++) {
198		struct srvsvc_NetShareInfo1 info = info_ctr.ctr.ctr1->array[i];
199		fn(info.name, info.type, info.comment, state);
200	}
201
202	TALLOC_FREE(mem_ctx);
203	TALLOC_FREE(pipe_hnd);
204	return True;
205}
206
207
208static bool get_shares(char *server_name, struct user_auth_info *user_info)
209{
210        struct cli_state *cli;
211
212        if (!(cli = get_ipc_connect(server_name, NULL, user_info)))
213                return False;
214
215	if (get_rpc_shares(cli, add_name, &shares))
216		return True;
217
218        if (!cli_RNetShareEnum(cli, add_name, &shares))
219                return False;
220
221        return True;
222}
223
224static bool print_tree(struct user_auth_info *user_info)
225{
226        struct smb_name_list *wg, *sv, *sh;
227
228        /* List workgroups */
229
230        if (!get_workgroups(user_info))
231                return False;
232
233        for (wg = workgroups; wg; wg = wg->next) {
234
235                printf("%s\n", wg->name);
236
237                /* List servers */
238
239                free_name_list(servers);
240                servers = NULL;
241
242                if (level == LEV_WORKGROUP ||
243                    !get_servers(wg->name, user_info))
244                        continue;
245
246                for (sv = servers; sv; sv = sv->next) {
247
248                        printf("\t\\\\%-15s\t\t%s\n",
249			       sv->name, sv->comment);
250
251                        /* List shares */
252
253                        free_name_list(shares);
254                        shares = NULL;
255
256                        if (level == LEV_SERVER ||
257                            !get_shares(sv->name, user_info))
258                                continue;
259
260                        for (sh = shares; sh; sh = sh->next) {
261                                printf("\t\t\\\\%s\\%-15s\t%s\n",
262				       sv->name, sh->name, sh->comment);
263                        }
264                }
265        }
266
267        return True;
268}
269
270/****************************************************************************
271  main program
272****************************************************************************/
273 int main(int argc,char *argv[])
274{
275	TALLOC_CTX *frame = talloc_stackframe();
276	struct user_auth_info *auth_info;
277	struct poptOption long_options[] = {
278		POPT_AUTOHELP
279		{ "broadcast", 'b', POPT_ARG_VAL, &use_bcast, True, "Use broadcast instead of using the master browser" },
280		{ "domains", 'D', POPT_ARG_VAL, &level, LEV_WORKGROUP, "List only domains (workgroups) of tree" },
281		{ "servers", 'S', POPT_ARG_VAL, &level, LEV_SERVER, "List domains(workgroups) and servers of tree" },
282		POPT_COMMON_SAMBA
283		POPT_COMMON_CREDENTIALS
284		POPT_TABLEEND
285	};
286	poptContext pc;
287
288	/* Initialise samba stuff */
289	load_case_tables();
290
291	setlinebuf(stdout);
292
293	dbf = x_stderr;
294
295	setup_logging(argv[0],True);
296
297	auth_info = user_auth_info_init(frame);
298	if (auth_info == NULL) {
299		exit(1);
300	}
301	popt_common_set_auth_info(auth_info);
302
303	pc = poptGetContext("smbtree", argc, (const char **)argv, long_options,
304						POPT_CONTEXT_KEEP_FIRST);
305	while(poptGetNextOpt(pc) != -1);
306	poptFreeContext(pc);
307
308	lp_load(get_dyn_CONFIGFILE(),True,False,False,True);
309	load_interfaces();
310
311	/* Parse command line args */
312
313	if (get_cmdline_auth_info_use_machine_account(auth_info) &&
314	    !set_cmdline_auth_info_machine_account_creds(auth_info)) {
315		TALLOC_FREE(frame);
316		return 1;
317	}
318
319	set_cmdline_auth_info_getpass(auth_info);
320
321	/* Now do our stuff */
322
323        if (!print_tree(auth_info)) {
324		TALLOC_FREE(frame);
325                return 1;
326	}
327
328	TALLOC_FREE(frame);
329	return 0;
330}
331