2 Unix SMB/Netbios implementation.
4 SMB client generic functions
5 Copyright (C) Andrew Tridgell 1994-1999
6 Copyright (C) Luke Kenneth Casson Leighton 1996-1999
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 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 extern pstring global_myname;
33 struct cli_state *cli;
37 static struct cli_use **clis = NULL;
38 static uint32 num_clis = 0;
40 /****************************************************************************
41 terminate client connection
42 ****************************************************************************/
43 static void cli_use_free(struct cli_use *cli)
47 if (cli->cli->initialised)
49 /* only logoff if we have a valid socket */
50 if (cli->cli->fd != -1)
51 cli_ulogoff(cli->cli);
52 cli_shutdown(cli->cli);
60 /****************************************************************************
62 ****************************************************************************/
63 static void free_cli_array(uint32 num_entries, struct cli_use **entries)
65 void (*fn) (void *) = (void (*)(void *))&cli_use_free;
66 free_void_array(num_entries, (void **)entries, *fn);
69 /****************************************************************************
70 add a client state to the array
71 ****************************************************************************/
72 static struct cli_use *add_cli_to_array(uint32 *len,
73 struct cli_use ***array,
77 for (i = 0; i < num_clis; i++)
86 return (struct cli_use *)add_item_to_array(len,
92 /****************************************************************************
94 ****************************************************************************/
95 void init_cli_use(void)
101 /****************************************************************************
102 terminate client array
103 ****************************************************************************/
104 void free_cli_use(void)
106 free_cli_array(num_clis, clis);
110 /****************************************************************************
111 find client state. server name, user name, domain name and password must all
113 ****************************************************************************/
114 static struct cli_use *cli_find(const char *srv_name,
115 const struct ntuser_creds *usr_creds,
119 const char *sv_name = srv_name;
120 struct ntuser_creds null_usr;
122 if (usr_creds == NULL)
124 copy_nt_creds(&null_usr, usr_creds);
125 usr_creds = &null_usr;
128 if (strnequal("\\\\", sv_name, 2))
130 sv_name = &sv_name[2];
133 DEBUG(10, ("cli_find: %s %s %s reuse: %s\n",
134 srv_name, usr_creds->user_name, usr_creds->domain,
138 for (i = 0; i < num_clis; i++)
140 char *cli_name = NULL;
141 struct cli_use *c = clis[i];
143 if (c == NULL || !c->cli->initialised || c->cli->fd == -1)
148 cli_name = c->cli->desthost;
150 DEBUG(10, ("cli_find[%d]: %s %s %s\n",
152 c->cli->user_name, c->cli->domain));
154 if (strnequal("\\\\", cli_name, 2))
156 cli_name = &cli_name[2];
159 if (!strequal(cli_name, sv_name))
163 if (strequal(usr_creds->user_name, "") &&
164 strequal(usr_creds->domain, "") &&
165 pwd_is_nullpwd(&usr_creds->pwd))
169 if (!strequal(usr_creds->user_name, c->cli->user_name))
173 if (!reuse && !pwd_compare((struct pwd_info *)&usr_creds->pwd, &c->cli->pwd))
175 DEBUG(100, ("password doesn't match\n"));
178 if (usr_creds->domain[0] == 0)
182 if (strequal(usr_creds->domain, c->cli->domain))
191 /****************************************************************************
192 create a new client state from user credentials
193 ****************************************************************************/
194 static struct cli_use *cli_use_get(const char *srv_name,
195 const struct ntuser_creds *usr_creds)
197 struct cli_use *cli = (struct cli_use *)malloc(sizeof(*cli));
204 memset(cli, 0, sizeof(*cli));
206 cli->cli = cli_initialise(NULL);
208 if (cli->cli == NULL)
213 cli_init_creds(cli->cli, usr_creds);
218 /****************************************************************************
220 ****************************************************************************/
221 struct cli_state *cli_net_use_add(const char *srv_name,
222 const struct ntuser_creds *usr_creds,
223 BOOL reuse, BOOL *is_new)
225 struct nmb_name calling;
226 struct nmb_name called;
227 struct in_addr *dest_ip = NULL;
232 DEBUG(10, ("cli_net_use_add\n"));
234 cli = cli_find(srv_name, usr_creds, reuse);
240 ("cli_net_use_add: num_users: %d\n", cli->num_users));
245 /* reuse an existing connection requested, and one was not found */
246 if (usr_creds != NULL && reuse)
255 cli = cli_use_get(srv_name, usr_creds);
257 if (resolve_srv_name(srv_name, dest_host, &ip))
267 make_nmb_name(&called, dns_to_netbios_name(dest_host), 0x20);
268 make_nmb_name(&calling, dns_to_netbios_name(global_myname), 0);
274 if (!cli_establish_connection(cli->cli,
277 "IPC$", "IPC", False, True))
279 DEBUG(0, ("cli_net_use_add: connection failed\n"));
284 add_cli_to_array(&num_clis, &clis, cli);
287 DEBUG(10, ("cli_net_use_add: num_users: %d\n", cli->num_users));
294 /****************************************************************************
295 delete a client state
296 ****************************************************************************/
297 BOOL cli_net_use_del(const char *srv_name,
298 const struct ntuser_creds *usr_creds,
299 BOOL force_close, BOOL *connection_closed)
302 const char *sv_name = srv_name;
304 DEBUG(10, ("cli_net_use_del: %s. %s. %s. force close: %s\n",
306 usr_creds ? usr_creds->user_name : "",
307 usr_creds ? usr_creds->domain : "", BOOLSTR(force_close)));
309 if (strnequal("\\\\", sv_name, 2))
311 sv_name = &sv_name[2];
314 if (connection_closed != NULL)
316 *connection_closed = False;
319 for (i = 0; i < num_clis; i++)
321 char *cli_name = NULL;
325 if (clis[i]->cli == NULL)
328 cli_name = clis[i]->cli->desthost;
330 DEBUG(10, ("connection: %s %s %s\n", cli_name,
331 clis[i]->cli->user_name,
332 clis[i]->cli->domain));
334 if (strnequal("\\\\", cli_name, 2))
336 cli_name = &cli_name[2];
339 if (!strequal(cli_name, sv_name))
342 if (strequal(usr_creds ? usr_creds->user_name : "",
343 clis[i]->cli->user_name) &&
344 strequal(usr_creds ? usr_creds->domain : "",
345 clis[i]->cli->domain))
347 /* decrement number of users */
348 clis[i]->num_users--;
350 DEBUG(10, ("idx: %i num_users now: %d\n",
351 i, clis[i]->num_users));
353 if (force_close || clis[i]->num_users == 0)
355 cli_use_free(clis[i]);
357 if (connection_closed != NULL)
359 *connection_closed = True;
369 /****************************************************************************
370 enumerate client states
371 ****************************************************************************/
372 void cli_net_use_enum(uint32 *num_cons, struct use_info ***use)
379 for (i = 0; i < num_clis; i++)
381 struct use_info item;
388 item.connected = clis[i]->cli != NULL ? True : False;
392 item.srv_name = clis[i]->cli->desthost;
393 item.user_name = clis[i]->cli->user_name;
394 item.key = clis[i]->cli->key;
395 item.domain = clis[i]->cli->domain;
398 add_use_info_to_array(num_cons, use, &item);
403 /****************************************************************************
404 wait for keyboard activity, swallowing network packets on all client states.
405 ****************************************************************************/
406 void cli_use_wait_keyboard(void)
409 struct timeval timeout;
414 int maxfd = fileno(stdin);
416 FD_SET(fileno(stdin), &fds);
417 for (i = 0; i < num_clis; i++)
419 if (clis[i] != NULL && clis[i]->cli != NULL)
421 int fd = clis[i]->cli->fd;
423 maxfd = MAX(fd, maxfd);
429 sys_select(maxfd + 1, &fds, &timeout);
431 if (FD_ISSET(fileno(stdin), &fds))
434 /* We deliberately use receive_smb instead of
435 client_receive_smb as we want to receive
436 session keepalives and then drop them here.
438 for (i = 0; i < num_clis; i++)
441 if (clis[i] == NULL || clis[i]->cli == NULL)
443 fd = clis[i]->cli->fd;
444 if (FD_ISSET(fd, &fds))
445 receive_smb(fd, clis[i]->cli->inbuf, 0);