2 Unix SMB/CIFS implementation.
3 Network neighbourhood browser.
5 Copyright (C) Tim Potter 2000
6 Copyright (C) Jelmer Vernooij 2003
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.
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.
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/>.
23 #include "lib/cmdline/cmdline.h"
24 #include "rpc_client/cli_pipe.h"
25 #include "../librpc/gen_ndr/ndr_srvsvc_c.h"
26 #include "libsmb/libsmb.h"
27 #include "libsmb/namequery.h"
28 #include "libsmb/clirap.h"
29 #include "../libcli/smb/smbXcli_base.h"
31 #include "libsmbclient.h"
33 /* How low can we go? */
35 enum tree_level {LEV_WORKGROUP, LEV_SERVER, LEV_SHARE};
36 static enum tree_level level = LEV_SHARE;
38 static void get_auth_data_with_context_fn(
49 struct cli_credentials *creds = samba_cmdline_get_creds();
52 len = strlcpy(domain, cli_credentials_get_domain(creds), domain_len);
53 if ((int)len >= domain_len) {
57 user, cli_credentials_get_username(creds), user_len);
58 if ((int)len >= user_len) {
62 password, cli_credentials_get_password(creds), password_len);
63 if ((int)len >= password_len) {
64 /* pointless, but what can you do... */
69 /****************************************************************************
71 ****************************************************************************/
72 int main(int argc, char *argv[])
74 TALLOC_CTX *frame = talloc_stackframe();
75 const char **argv_const = discard_const_p(const char *, argv);
76 struct poptOption long_options[] = {
79 .longName = "domains",
81 .argInfo = POPT_ARG_VAL,
84 .descrip = "List only domains (workgroups) of tree" ,
87 .longName = "servers",
89 .argInfo = POPT_ARG_VAL,
92 .descrip = "List domains(workgroups) and servers of tree" ,
95 POPT_COMMON_CREDENTIALS
101 SMBCFILE *workgroups = NULL;
102 struct smbc_dirent *dirent = NULL;
108 /* Initialise samba stuff */
113 ok = samba_cmdline_init(frame,
114 SAMBA_CMDLINE_CONFIG_CLIENT,
115 false /* require_smbconf */);
117 DBG_ERR("Failed to init cmdline parser!\n");
122 pc = samba_popt_get_context(getprogname(),
126 POPT_CONTEXT_KEEP_FIRST);
128 DBG_ERR("Failed to setup popt context!\n");
133 while((opt = poptGetNextOpt(pc)) != -1) {
135 case POPT_ERROR_BADOPT:
136 fprintf(stderr, "\nInvalid option %s: %s\n\n",
137 poptBadOption(pc, 0), poptStrerror(opt));
138 poptPrintUsage(pc, stderr, 0);
143 samba_cmdline_burn(argc, argv);
145 debuglevel = DEBUGLEVEL;
147 ctx = smbc_new_context();
149 perror("smbc_new_context");
152 ret = smbc_setConfiguration(ctx, get_dyn_CONFIGFILE());
154 perror("smbc_setConfiguration");
157 smbc_setDebug(ctx, debuglevel);
158 ok = smbc_setOptionProtocols(ctx, NULL, "NT1");
160 perror("smbc_setOptionProtocols");
163 smbc_setFunctionAuthDataWithContext(
164 ctx, get_auth_data_with_context_fn);
166 ok = smbc_init_context(ctx);
168 perror("smbc_init_context");
172 workgroups = smbc_getFunctionOpendir(ctx)(ctx, "smb://");
173 if (workgroups == NULL) {
174 DBG_ERR("This is utility doesn't work if netbios name "
175 "resolution is not configured.\n"
176 "If you are using SMB2 or SMB3, network browsing uses "
177 "WSD/LLMNR, which is not yet supported by Samba. SMB1 "
178 "is disabled by default on the latest Windows versions "
179 "for security reasons. It is still possible to access "
180 "the Samba resources directly via \\name or "
185 while ((dirent = smbc_getFunctionReaddir(ctx)(ctx, workgroups))
188 SMBCFILE *servers = NULL;
190 if (dirent->smbc_type != SMBC_WORKGROUP) {
194 printf("%s\n", dirent->name);
196 if (level == LEV_WORKGROUP) {
200 url = talloc_asprintf(
201 talloc_tos(), "smb://%s/", dirent->name);
203 perror("talloc_asprintf");
207 servers = smbc_getFunctionOpendir(ctx)(ctx, url);
208 if (servers == NULL) {
209 perror("smbc_opendir");
214 while ((dirent = smbc_getFunctionReaddir(ctx)(ctx, servers))
216 SMBCFILE *shares = NULL;
217 char *servername = NULL;
219 if (dirent->smbc_type != SMBC_SERVER) {
223 printf("\t\\\\%-15s\t\t%s\n",
227 if (level == LEV_SERVER) {
232 * The subsequent readdir for shares will
233 * overwrite the "server" readdir
235 servername = talloc_strdup(talloc_tos(), dirent->name);
236 if (servername == NULL) {
240 url = talloc_asprintf(
241 talloc_tos(), "smb://%s/", servername);
243 perror("talloc_asprintf");
247 shares = smbc_getFunctionOpendir(ctx)(ctx, url);
248 if (shares == NULL) {
249 perror("smbc_opendir");
253 while ((dirent = smbc_getFunctionReaddir(
256 printf("\t\t\\\\%s\\%-15s\t%s\n",
262 ret = smbc_getFunctionClosedir(ctx)(ctx, shares);
264 perror("smbc_closedir");
268 TALLOC_FREE(servername);
272 ret = smbc_getFunctionClosedir(ctx)(ctx, servers);
274 perror("smbc_closedir");
279 ret = smbc_getFunctionClosedir(ctx)(ctx, workgroups);
281 perror("smbc_closedir");
288 smbc_free_context(ctx, 0);