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);