~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/utils/smbtree.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

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