2 Unix SMB/CIFS implementation.
3 Manage connections_struct structures
4 Copyright (C) Andrew Tridgell 1998
5 Copyright (C) Alexander Bokovoy 2002
6 Copyright (C) Jeremy Allison 2010
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 "smbd/smbd.h"
24 #include "smbd/globals.h"
25 #include "rpc_server/rpc_ncacn_np.h"
27 /* The connections bitmap is expanded in increments of BITMAP_BLOCK_SZ. The
28 * maximum size of the bitmap is the largest positive integer, but you will hit
29 * the "max connections" limit, looong before that.
32 #define BITMAP_BLOCK_SZ 128
34 /****************************************************************************
35 Init the conn structures.
36 ****************************************************************************/
38 void conn_init(struct smbd_server_connection
*sconn
)
40 sconn
->smb1
.tcons
.Connections
= NULL
;
41 sconn
->smb1
.tcons
.bmap
= bitmap_talloc(sconn
, BITMAP_BLOCK_SZ
);
44 /****************************************************************************
45 Return the number of open connections.
46 ****************************************************************************/
48 int conn_num_open(struct smbd_server_connection
*sconn
)
50 return sconn
->num_tcons_open
;
53 /****************************************************************************
54 Check if a snum is in use.
55 ****************************************************************************/
57 bool conn_snum_used(int snum
)
59 struct smbd_server_connection
*sconn
= smbd_server_conn
;
61 if (sconn
->using_smb2
) {
63 struct smbd_smb2_session
*sess
;
64 for (sess
= sconn
->smb2
.sessions
.list
; sess
; sess
= sess
->next
) {
65 struct smbd_smb2_tcon
*ptcon
;
67 for (ptcon
= sess
->tcons
.list
; ptcon
; ptcon
= ptcon
->next
) {
68 if (ptcon
->compat_conn
&&
69 ptcon
->compat_conn
->params
&&
70 (ptcon
->compat_conn
->params
->service
= snum
)) {
77 connection_struct
*conn
;
78 for (conn
=sconn
->smb1
.tcons
.Connections
;conn
;conn
=conn
->next
) {
79 if (conn
->params
->service
== snum
) {
87 /****************************************************************************
88 Find a conn given a cnum.
89 ****************************************************************************/
91 connection_struct
*conn_find(struct smbd_server_connection
*sconn
,unsigned cnum
)
93 if (sconn
->using_smb2
) {
95 struct smbd_smb2_session
*sess
;
96 for (sess
= sconn
->smb2
.sessions
.list
; sess
; sess
= sess
->next
) {
97 struct smbd_smb2_tcon
*ptcon
;
99 for (ptcon
= sess
->tcons
.list
; ptcon
; ptcon
= ptcon
->next
) {
100 if (ptcon
->compat_conn
&&
101 ptcon
->compat_conn
->cnum
== cnum
) {
102 return ptcon
->compat_conn
;
109 connection_struct
*conn
;
110 for (conn
=sconn
->smb1
.tcons
.Connections
;conn
;conn
=conn
->next
,count
++) {
111 if (conn
->cnum
== cnum
) {
113 DLIST_PROMOTE(sconn
->smb1
.tcons
.Connections
,
124 /****************************************************************************
125 Find first available connection slot, starting from a random position.
126 The randomisation stops problems with the server dieing and clients
127 thinking the server is still available.
128 ****************************************************************************/
130 connection_struct
*conn_new(struct smbd_server_connection
*sconn
)
132 connection_struct
*conn
;
136 if (sconn
->using_smb2
) {
138 if (!(conn
=TALLOC_ZERO_P(NULL
, connection_struct
)) ||
139 !(conn
->params
= TALLOC_P(conn
, struct share_params
))) {
140 DEBUG(0,("TALLOC_ZERO() failed!\n"));
150 i
= bitmap_find(sconn
->smb1
.tcons
.bmap
, find_offset
);
153 /* Expand the connections bitmap. */
154 int oldsz
= sconn
->smb1
.tcons
.bmap
->n
;
155 int newsz
= sconn
->smb1
.tcons
.bmap
->n
+
157 struct bitmap
* nbmap
;
159 if (newsz
<= oldsz
) {
161 DEBUG(0,("ERROR! Out of connection structures\n"));
165 DEBUG(4,("resizing connections bitmap from %d to %d\n",
168 nbmap
= bitmap_talloc(sconn
, newsz
);
170 DEBUG(0,("ERROR! malloc fail.\n"));
174 bitmap_copy(nbmap
, sconn
->smb1
.tcons
.bmap
);
175 TALLOC_FREE(sconn
->smb1
.tcons
.bmap
);
177 sconn
->smb1
.tcons
.bmap
= nbmap
;
178 find_offset
= oldsz
; /* Start next search in the new portion. */
183 /* The bitmap position is used below as the connection number
184 * conn->cnum). This ends up as the TID field in the SMB header,
185 * which is limited to 16 bits (we skip 0xffff which is the
189 DEBUG(0, ("Maximum connection limit reached\n"));
193 if (!(conn
=TALLOC_ZERO_P(NULL
, connection_struct
)) ||
194 !(conn
->params
= TALLOC_P(conn
, struct share_params
))) {
195 DEBUG(0,("TALLOC_ZERO() failed!\n"));
201 conn
->force_group_gid
= (gid_t
)-1;
203 bitmap_set(sconn
->smb1
.tcons
.bmap
, i
);
205 sconn
->num_tcons_open
++;
207 string_set(&conn
->connectpath
,"");
208 string_set(&conn
->origpath
,"");
210 DLIST_ADD(sconn
->smb1
.tcons
.Connections
, conn
);
215 /****************************************************************************
216 Close all conn structures.
217 Return true if any were closed.
218 ****************************************************************************/
220 bool conn_close_all(struct smbd_server_connection
*sconn
)
223 if (sconn
->using_smb2
) {
225 struct smbd_smb2_session
*sess
;
226 for (sess
= sconn
->smb2
.sessions
.list
; sess
; sess
= sess
->next
) {
227 struct smbd_smb2_tcon
*tcon
, *tc_next
;
229 for (tcon
= sess
->tcons
.list
; tcon
; tcon
= tc_next
) {
230 tc_next
= tcon
->next
;
237 connection_struct
*conn
, *next
;
239 for (conn
=sconn
->smb1
.tcons
.Connections
;conn
;conn
=next
) {
241 set_current_service(conn
, 0, True
);
242 close_cnum(conn
, conn
->vuid
);
249 /****************************************************************************
250 Update last used timestamps.
251 ****************************************************************************/
253 static void conn_lastused_update(struct smbd_server_connection
*sconn
,time_t t
)
255 if (sconn
->using_smb2
) {
257 struct smbd_smb2_session
*sess
;
258 for (sess
= sconn
->smb2
.sessions
.list
; sess
; sess
= sess
->next
) {
259 struct smbd_smb2_tcon
*ptcon
;
261 for (ptcon
= sess
->tcons
.list
; ptcon
; ptcon
= ptcon
->next
) {
262 connection_struct
*conn
= ptcon
->compat_conn
;
263 /* Update if connection wasn't idle. */
264 if (conn
&& conn
->lastused
!= conn
->lastused_count
) {
266 conn
->lastused_count
= t
;
272 connection_struct
*conn
;
273 for (conn
=sconn
->smb1
.tcons
.Connections
;conn
;conn
=conn
->next
) {
274 /* Update if connection wasn't idle. */
275 if (conn
->lastused
!= conn
->lastused_count
) {
277 conn
->lastused_count
= t
;
283 /****************************************************************************
284 Idle inactive connections.
285 ****************************************************************************/
287 bool conn_idle_all(struct smbd_server_connection
*sconn
, time_t t
)
289 int deadtime
= lp_deadtime()*60;
291 conn_lastused_update(sconn
, t
);
294 deadtime
= DEFAULT_SMBD_TIMEOUT
;
297 if (sconn
->using_smb2
) {
299 struct smbd_smb2_session
*sess
;
300 for (sess
= sconn
->smb2
.sessions
.list
; sess
; sess
= sess
->next
) {
301 struct smbd_smb2_tcon
*ptcon
;
303 for (ptcon
= sess
->tcons
.list
; ptcon
; ptcon
= ptcon
->next
) {
305 connection_struct
*conn
= ptcon
->compat_conn
;
311 age
= t
- conn
->lastused
;
312 /* close dirptrs on connections that are idle */
313 if (age
> DPTR_IDLE_TIMEOUT
) {
317 if (conn
->num_files_open
> 0 || age
< deadtime
) {
324 connection_struct
*conn
;
325 for (conn
=sconn
->smb1
.tcons
.Connections
;conn
;conn
=conn
->next
) {
326 time_t age
= t
- conn
->lastused
;
328 /* close dirptrs on connections that are idle */
329 if (age
> DPTR_IDLE_TIMEOUT
) {
333 if (conn
->num_files_open
> 0 || age
< deadtime
) {
340 * Check all pipes for any open handles. We cannot
341 * idle with a handle open.
343 if (check_open_pipes()) {
350 /****************************************************************************
351 Clear a vuid out of the validity cache, and as the 'owner' of a connection.
352 ****************************************************************************/
354 void conn_clear_vuid_caches(struct smbd_server_connection
*sconn
,uint16_t vuid
)
356 connection_struct
*conn
;
358 if (sconn
->using_smb2
) {
360 struct smbd_smb2_session
*sess
;
361 for (sess
= sconn
->smb2
.sessions
.list
; sess
; sess
= sess
->next
) {
362 struct smbd_smb2_tcon
*ptcon
;
364 for (ptcon
= sess
->tcons
.list
; ptcon
; ptcon
= ptcon
->next
) {
365 if (ptcon
->compat_conn
) {
366 if (ptcon
->compat_conn
->vuid
== vuid
) {
367 ptcon
->compat_conn
->vuid
= UID_FIELD_INVALID
;
369 conn_clear_vuid_cache(ptcon
->compat_conn
, vuid
);
375 for (conn
=sconn
->smb1
.tcons
.Connections
;conn
;conn
=conn
->next
) {
376 if (conn
->vuid
== vuid
) {
377 conn
->vuid
= UID_FIELD_INVALID
;
379 conn_clear_vuid_cache(conn
, vuid
);
384 /****************************************************************************
385 Free a conn structure - internal part.
386 ****************************************************************************/
388 static void conn_free_internal(connection_struct
*conn
)
390 vfs_handle_struct
*handle
= NULL
, *thandle
= NULL
;
391 struct trans_state
*state
= NULL
;
393 /* Free vfs_connection_struct */
394 handle
= conn
->vfs_handles
;
396 thandle
= handle
->next
;
397 DLIST_REMOVE(conn
->vfs_handles
, handle
);
398 if (handle
->free_data
)
399 handle
->free_data(&handle
->data
);
403 /* Free any pending transactions stored on this conn. */
404 for (state
= conn
->pending_trans
; state
; state
= state
->next
) {
405 /* state->setup is a talloc child of state. */
406 SAFE_FREE(state
->param
);
407 SAFE_FREE(state
->data
);
410 free_namearray(conn
->veto_list
);
411 free_namearray(conn
->hide_list
);
412 free_namearray(conn
->veto_oplock_list
);
413 free_namearray(conn
->aio_write_behind_list
);
415 string_free(&conn
->connectpath
);
416 string_free(&conn
->origpath
);
419 talloc_destroy(conn
);
422 /****************************************************************************
423 Free a conn structure.
424 ****************************************************************************/
426 void conn_free(connection_struct
*conn
)
428 if (conn
->sconn
== NULL
) {
429 conn_free_internal(conn
);
433 if (conn
->sconn
->using_smb2
) {
435 conn_free_internal(conn
);
440 DLIST_REMOVE(conn
->sconn
->smb1
.tcons
.Connections
, conn
);
442 if (conn
->sconn
->smb1
.tcons
.bmap
!= NULL
) {
444 * Can be NULL for fake connections created by
445 * create_conn_struct()
447 bitmap_clear(conn
->sconn
->smb1
.tcons
.bmap
, conn
->cnum
);
450 SMB_ASSERT(conn
->sconn
->num_tcons_open
> 0);
451 conn
->sconn
->num_tcons_open
--;
453 conn_free_internal(conn
);
456 /****************************************************************************
457 Receive a smbcontrol message to forcibly unmount a share.
458 The message contains just a share name and all instances of that
460 The special sharename '*' forces unmount of all shares.
461 ****************************************************************************/
463 void msg_force_tdis(struct messaging_context
*msg
,
466 struct server_id server_id
,
469 struct smbd_server_connection
*sconn
;
470 connection_struct
*conn
, *next
;
473 sconn
= msg_ctx_to_sconn(msg
);
475 DEBUG(1, ("could not find sconn\n"));
479 fstrcpy(sharename
, (const char *)data
->data
);
481 if (strcmp(sharename
, "*") == 0) {
482 DEBUG(1,("Forcing close of all shares\n"));
483 conn_close_all(sconn
);
487 if (sconn
->using_smb2
) {
489 struct smbd_smb2_session
*sess
;
490 for (sess
= sconn
->smb2
.sessions
.list
; sess
; sess
= sess
->next
) {
491 struct smbd_smb2_tcon
*tcon
, *tc_next
;
493 for (tcon
= sess
->tcons
.list
; tcon
; tcon
= tc_next
) {
494 tc_next
= tcon
->next
;
495 if (tcon
->compat_conn
&&
496 strequal(lp_servicename(SNUM(tcon
->compat_conn
)),
498 DEBUG(1,("Forcing close of share %s cnum=%d\n",
499 sharename
, tcon
->compat_conn
->cnum
));
506 for (conn
=sconn
->smb1
.tcons
.Connections
;conn
;conn
=next
) {
508 if (strequal(lp_servicename(SNUM(conn
)), sharename
)) {
509 DEBUG(1,("Forcing close of share %s cnum=%d\n",
510 sharename
, conn
->cnum
));
511 close_cnum(conn
, (uint16
)-1);