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.
28 extern int DEBUGLEVEL
;
30 extern pstring global_myname
;
34 struct cli_state
*cli
;
38 static struct cli_use
**clis
= NULL
;
39 static uint32 num_clis
= 0;
41 /****************************************************************************
42 terminate client connection
43 ****************************************************************************/
44 static void cli_use_free(struct cli_use
*cli
)
48 if (cli
->cli
->initialised
)
50 /* only logoff if we have a valid socket */
51 if (cli
->cli
->fd
!= -1)
52 cli_ulogoff(cli
->cli
);
53 cli_shutdown(cli
->cli
);
61 /****************************************************************************
63 ****************************************************************************/
64 static void free_cli_array(uint32 num_entries
, struct cli_use
**entries
)
66 void (*fn
) (void *) = (void (*)(void *))&cli_use_free
;
67 free_void_array(num_entries
, (void **)entries
, *fn
);
70 /****************************************************************************
71 add a client state to the array
72 ****************************************************************************/
73 static struct cli_use
*add_cli_to_array(uint32
*len
,
74 struct cli_use
***array
,
78 for (i
= 0; i
< num_clis
; i
++)
87 return (struct cli_use
*)add_item_to_array(len
,
93 /****************************************************************************
95 ****************************************************************************/
96 void init_cli_use(void)
102 /****************************************************************************
103 terminate client array
104 ****************************************************************************/
105 void free_cli_use(void)
107 free_cli_array(num_clis
, clis
);
111 /****************************************************************************
112 find client state. server name, user name, domain name and password must all
114 ****************************************************************************/
115 static struct cli_use
*cli_find(const char *srv_name
,
116 const struct ntuser_creds
*usr_creds
,
120 const char *sv_name
= srv_name
;
121 struct ntuser_creds null_usr
;
123 if (usr_creds
== NULL
)
125 copy_nt_creds(&null_usr
, usr_creds
);
126 usr_creds
= &null_usr
;
129 if (strnequal("\\\\", sv_name
, 2))
131 sv_name
= &sv_name
[2];
134 DEBUG(10, ("cli_find: %s %s %s reuse: %s\n",
135 srv_name
, usr_creds
->user_name
, usr_creds
->domain
,
139 for (i
= 0; i
< num_clis
; i
++)
141 char *cli_name
= NULL
;
142 struct cli_use
*c
= clis
[i
];
144 if (c
== NULL
|| !c
->cli
->initialised
|| c
->cli
->fd
== -1)
149 cli_name
= c
->cli
->desthost
;
151 DEBUG(10, ("cli_find[%d]: %s %s %s\n",
153 c
->cli
->user_name
, c
->cli
->domain
));
155 if (strnequal("\\\\", cli_name
, 2))
157 cli_name
= &cli_name
[2];
160 if (!strequal(cli_name
, sv_name
))
164 if (strequal(usr_creds
->user_name
, "") &&
165 strequal(usr_creds
->domain
, "") &&
166 pwd_is_nullpwd(&usr_creds
->pwd
))
170 if (!strequal(usr_creds
->user_name
, c
->cli
->user_name
))
174 if (!reuse
&& !pwd_compare((struct pwd_info
*)&usr_creds
->pwd
, &c
->cli
->pwd
))
176 DEBUG(100, ("password doesn't match\n"));
179 if (usr_creds
->domain
[0] == 0)
183 if (strequal(usr_creds
->domain
, c
->cli
->domain
))
192 /****************************************************************************
193 create a new client state from user credentials
194 ****************************************************************************/
195 static struct cli_use
*cli_use_get(const char *srv_name
,
196 const struct ntuser_creds
*usr_creds
)
198 struct cli_use
*cli
= (struct cli_use
*)malloc(sizeof(*cli
));
205 memset(cli
, 0, sizeof(*cli
));
207 cli
->cli
= cli_initialise(NULL
);
209 if (cli
->cli
== NULL
)
214 cli_init_creds(cli
->cli
, usr_creds
);
219 /****************************************************************************
221 ****************************************************************************/
222 struct cli_state
*cli_net_use_add(const char *srv_name
,
223 const struct ntuser_creds
*usr_creds
,
224 BOOL reuse
, BOOL
*is_new
)
226 struct nmb_name calling
;
227 struct nmb_name called
;
228 struct in_addr
*dest_ip
= NULL
;
233 DEBUG(10, ("cli_net_use_add\n"));
235 cli
= cli_find(srv_name
, usr_creds
, reuse
);
241 ("cli_net_use_add: num_users: %d\n", cli
->num_users
));
246 /* reuse an existing connection requested, and one was not found */
247 if (usr_creds
!= NULL
&& reuse
)
256 cli
= cli_use_get(srv_name
, usr_creds
);
258 if (resolve_srv_name(srv_name
, dest_host
, &ip
))
268 make_nmb_name(&called
, dns_to_netbios_name(dest_host
), 0x20);
269 make_nmb_name(&calling
, dns_to_netbios_name(global_myname
), 0);
275 if (!cli_establish_connection(cli
->cli
,
278 "IPC$", "IPC", False
, True
))
280 DEBUG(0, ("cli_net_use_add: connection failed\n"));
285 add_cli_to_array(&num_clis
, &clis
, cli
);
288 DEBUG(10, ("cli_net_use_add: num_users: %d\n", cli
->num_users
));
295 /****************************************************************************
296 delete a client state
297 ****************************************************************************/
298 BOOL
cli_net_use_del(const char *srv_name
,
299 const struct ntuser_creds
*usr_creds
,
300 BOOL force_close
, BOOL
*connection_closed
)
303 const char *sv_name
= srv_name
;
305 DEBUG(10, ("cli_net_use_del: %s. %s. %s. force close: %s\n",
307 usr_creds
? usr_creds
->user_name
: "",
308 usr_creds
? usr_creds
->domain
: "", BOOLSTR(force_close
)));
310 if (strnequal("\\\\", sv_name
, 2))
312 sv_name
= &sv_name
[2];
315 if (connection_closed
!= NULL
)
317 *connection_closed
= False
;
320 for (i
= 0; i
< num_clis
; i
++)
322 char *cli_name
= NULL
;
326 if (clis
[i
]->cli
== NULL
)
329 cli_name
= clis
[i
]->cli
->desthost
;
331 DEBUG(10, ("connection: %s %s %s\n", cli_name
,
332 clis
[i
]->cli
->user_name
,
333 clis
[i
]->cli
->domain
));
335 if (strnequal("\\\\", cli_name
, 2))
337 cli_name
= &cli_name
[2];
340 if (!strequal(cli_name
, sv_name
))
343 if (strequal(usr_creds
? usr_creds
->user_name
: "",
344 clis
[i
]->cli
->user_name
) &&
345 strequal(usr_creds
? usr_creds
->domain
: "",
346 clis
[i
]->cli
->domain
))
348 /* decrement number of users */
349 clis
[i
]->num_users
--;
351 DEBUG(10, ("idx: %i num_users now: %d\n",
352 i
, clis
[i
]->num_users
));
354 if (force_close
|| clis
[i
]->num_users
== 0)
356 cli_use_free(clis
[i
]);
358 if (connection_closed
!= NULL
)
360 *connection_closed
= True
;
370 /****************************************************************************
371 enumerate client states
372 ****************************************************************************/
373 void cli_net_use_enum(uint32
*num_cons
, struct use_info
***use
)
380 for (i
= 0; i
< num_clis
; i
++)
382 struct use_info item
;
389 item
.connected
= clis
[i
]->cli
!= NULL
? True
: False
;
393 item
.srv_name
= clis
[i
]->cli
->desthost
;
394 item
.user_name
= clis
[i
]->cli
->user_name
;
395 item
.key
= clis
[i
]->cli
->key
;
396 item
.domain
= clis
[i
]->cli
->domain
;
399 add_use_info_to_array(num_cons
, use
, &item
);
404 /****************************************************************************
405 wait for keyboard activity, swallowing network packets on all client states.
406 ****************************************************************************/
407 void cli_use_wait_keyboard(void)
410 struct timeval timeout
;
415 int maxfd
= fileno(stdin
);
417 FD_SET(fileno(stdin
), &fds
);
418 for (i
= 0; i
< num_clis
; i
++)
420 if (clis
[i
] != NULL
&& clis
[i
]->cli
!= NULL
)
422 int fd
= clis
[i
]->cli
->fd
;
424 maxfd
= MAX(fd
, maxfd
);
430 sys_select(maxfd
+ 1, &fds
, &timeout
);
432 if (FD_ISSET(fileno(stdin
), &fds
))
435 /* We deliberately use receive_smb instead of
436 client_receive_smb as we want to receive
437 session keepalives and then drop them here.
439 for (i
= 0; i
< num_clis
; i
++)
442 if (clis
[i
] == NULL
|| clis
[i
]->cli
== NULL
)
444 fd
= clis
[i
]->cli
->fd
;
445 if (FD_ISSET(fd
, &fds
))
446 receive_smb(fd
, clis
[i
]->cli
->inbuf
, 0);