xref: /illumos-gate/usr/src/uts/common/fs/smbclnt/netsmb/smb_conn.h (revision fb217153ae25423b48522eea4456af6b24de0a3c)
1 /*
2  * Copyright (c) 2000-2001 Boris Popov
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *    This product includes software developed by Boris Popov.
16  * 4. Neither the name of the author nor the names of any co-contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  *
32  * $Id: smb_conn.h,v 1.32.42.1 2005/05/27 02:35:29 lindak Exp $
33  */
34 
35 /*
36  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
37  * Use is subject to license terms.
38  *
39  * Portions Copyright (C) 2001 - 2013 Apple Inc. All rights reserved.
40  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
41  * Copyright 2024 RackTop Systems, Inc.
42  */
43 
44 #ifndef _SMB_CONN_H
45 #define	_SMB_CONN_H
46 
47 #include <sys/dditypes.h>
48 #include <sys/t_lock.h>
49 #include <sys/queue.h> /* for SLIST below */
50 #include <sys/uio.h>
51 #include <netsmb/smb_dev.h>
52 #include <netsmb/nsmb_kcrypt.h>
53 
54 /*
55  * Credentials of user/process for processing in the connection procedures
56  */
57 typedef struct smb_cred {
58 	struct cred *scr_cred;
59 } smb_cred_t;
60 
61 /*
62  * Common object flags
63  */
64 #define	SMBO_GONE		0x1000000
65 
66 /*
67  * Bits in vc_flags (a.k.a. vc_co.co_flags)
68  * Note: SMBO_GONE is also in vc_flags
69  */
70 #define	SMBV_UNICODE		0x0040	/* conn configured to use Unicode */
71 #define	SMBV_EXT_SEC		0x0080	/* conn to use extended security */
72 #define	SMBV_SIGNING		0x0100	/* negotiated signing */
73 #define	SMBV_SMB2		0x0200	/* VC using SMB 2 or 3 */
74 #define	SMBV_HAS_FILEIDS	0x0400	/* Use File IDs for hash and inums */
75 #define	SMBV_NO_WRITE_THRU	0x0800	/* Can't use ... */
76 
77 /*
78  * Note: the common "obj" level uses this GONE flag by
79  * the name SMBO_GONE.  Keep this alias as a reminder.
80  */
81 #define	SMBV_GONE		SMBO_GONE
82 
83 /*
84  * bits in smb_share ss_flags (a.k.a. ss_co.co_flags)
85  */
86 #define	SMBS_RECONNECTING	0x0002
87 #define	SMBS_CONNECTED		0x0004
88 #define	SMBS_TCON_WAIT		0x0008
89 #define	SMBS_FST_FAT		0x0010	/* share FS Type is FAT */
90 /*
91  * Note: the common "obj" level uses this GONE flag by
92  * the name SMBO_GONE.  Keep this alias as a reminder.
93  */
94 #define	SMBS_GONE		SMBO_GONE
95 
96 /*
97  * bits in smb_fh fh_flags (a.k.a. ss_co.co_flags)
98  */
99 #define	SMBFH_VALID		0x0002	/* FID is valid */
100 /*
101  * Note: the common "obj" level uses this GONE flag by
102  * the name SMBO_GONE.  Keep this alias as a reminder.
103  */
104 #define	SMBFH_GONE		SMBO_GONE
105 
106 struct smb_rq;
107 /* This declares struct smb_rqhead */
108 TAILQ_HEAD(smb_rqhead, smb_rq);
109 
110 #define	SMB_NBTIMO	15
111 #define	SMB_DEFRQTIMO	30	/* 30 for oplock revoke/writeback */
112 #define	SMBWRTTIMO	60
113 #define	SMBSSNSETUPTIMO	60
114 #define	SMBNOREPLYWAIT (0)
115 
116 #define	SMB_DIALECT(vcp)	((vcp)->vc_sopt.sv_proto)
117 
118 /*
119  * Connection object
120  */
121 
122 #define	SMB_CO_LOCK(cp)		mutex_enter(&(cp)->co_lock)
123 #define	SMB_CO_UNLOCK(cp)	mutex_exit(&(cp)->co_lock)
124 
125 /*
126  * Common part of smb_vc, smb_share
127  * Locking: co_lock protects most
128  * fields in this struct, except
129  * as noted below:
130  */
131 struct smb_connobj {
132 	kmutex_t		co_lock;
133 	int			co_level;	/* SMBL_ */
134 	int			co_flags;
135 	int			co_usecount;
136 
137 	/* Note: must lock co_parent before child. */
138 	struct smb_connobj	*co_parent;
139 
140 	/* this.co_lock protects the co_children list */
141 	SLIST_HEAD(, smb_connobj) co_children;
142 
143 	/*
144 	 * Linkage in parent's list of children.
145 	 * Must hold parent.co_lock to traverse.
146 	 */
147 	SLIST_ENTRY(smb_connobj) co_next;
148 
149 	/* These two are set only at creation. */
150 	void (*co_gone)(struct smb_connobj *);
151 	void (*co_free)(struct smb_connobj *);
152 };
153 typedef struct smb_connobj smb_connobj_t;
154 
155 /*
156  * "Level" in the connection object hierarchy
157  */
158 enum smbco_level {
159 	SMBL_SM = 0,
160 	SMBL_VC = 1,
161 	SMBL_SHARE = 2,
162 	SMBL_FH = 3
163 };
164 
165 /*
166  * SMB1 Negotiated protocol parameters
167  * Note:  All set to zero at start of nsmb_iod_negotiate
168  */
169 struct smb_sopt {
170 	uint16_t	sv_proto;	/* protocol dialect */
171 	uchar_t		sv_sm;		/* security mode */
172 	int16_t		sv_tz;		/* offset in min relative to UTC */
173 	uint16_t	sv_maxmux;	/* max number of outstanding rq's */
174 	uint16_t	sv_maxvcs;	/* max number of VCs */
175 	uint16_t	sv_rawmode;
176 	uint32_t	sv_maxtx;	/* maximum transmit buf size */
177 	uint32_t	sv_maxraw;	/* maximum raw-buffer size */
178 	uint32_t	sv_skey;	/* session key */
179 	uint32_t	sv_caps;	/* capabilites SMB_CAP_ */
180 
181 	/* SMB2+ fields */
182 	uint32_t	sv2_capabilities;	/* capabilities */
183 	uint32_t	sv2_maxtransact;	/* max transact size */
184 	uint32_t	sv2_maxread;	/* max read size */
185 	uint32_t	sv2_maxwrite;	/* max write size */
186 	uint16_t	sv2_security_mode;	/* security mode */
187 	uint16_t	sv2_sessflags;	/* final session setup reply flags */
188 	uint8_t		sv2_guid[16];	/* GUID */
189 };
190 typedef struct smb_sopt smb_sopt_t;
191 
192 /*
193  * SMB1 I/O Deamon state
194  */
195 struct smb_iods {
196 	uint8_t		is_hflags;	/* SMB header flags */
197 	uint16_t	is_hflags2;	/* SMB header flags2 */
198 	uint16_t	is_smbuid;	/* SMB header UID */
199 	uint16_t	is_next_mid;	/* SMB header MID */
200 	uint32_t	is_txmax;	/* max tx/rx packet size */
201 	uint32_t	is_rwmax;	/* max read/write data size */
202 	uint32_t	is_rxmax;	/* max readx data size */
203 	uint32_t	is_wxmax;	/* max writex data size */
204 	/* Signing state */
205 	uint32_t	is_next_seq;	/* my next sequence number */
206 
207 };
208 typedef struct smb_iods smb_iods_t;
209 
210 /*
211  * Virtual Circuit to a server (really connection + session).
212  * Yes, calling this a "Virtual Circuit" is confusining,
213  * because it has nothing to do with the SMB notion of a
214  * "Virtual Circuit".
215  */
216 typedef struct smb_vc {
217 	struct smb_connobj	vc_co;	/* keep first! See CPTOVC */
218 	enum smbiod_state	vc_state;
219 	kcondvar_t		vc_statechg;
220 
221 	zoneid_t		vc_zoneid;
222 	uid_t			vc_owner;	/* Unix owner */
223 	int			vc_genid;	/* "generation" ID */
224 
225 	int			vc_mackeylen;	/* MAC key length */
226 	int			vc_ssnkeylen;	/* session key length */
227 	uint8_t			*vc_mackey;	/* MAC key buffer */
228 	uint8_t			*vc_ssnkey;	/* session key buffer */
229 	smb_crypto_mech_t	vc_signmech;
230 	struct smb_mac_ops	*vc_sign_ops;
231 
232 	struct smb_tran_desc	*vc_tdesc;	/* transport ops. vector */
233 	void			*vc_tdata;	/* transport control block */
234 
235 	/* SMB2+ fields */
236 	uint64_t	vc2_oldest_message_id;
237 	uint64_t	vc2_next_message_id;
238 	uint64_t	vc2_limit_message_id;
239 	uint64_t	vc2_session_id;		/* session id */
240 	uint64_t	vc2_prev_session_id;	/* for reconnect */
241 	uint32_t	vc2_lease_key;		/* lease key gen */
242 
243 	/* SMB3+ fields */
244 	smb_crypto_mech_t vc3_preauthmech;
245 	smb_crypto_mech_t vc3_crypt_mech;
246 
247 	uint16_t	vc3_enc_cipherid;
248 	uint16_t	vc3_preauth_hashid;
249 	uint8_t		vc3_preauth_hashval[SHA512_DIGEST_LENGTH];
250 	uint_t		vc3_preauth_hashfails;
251 
252 	/* Encrypt/decrypt keys can be 128 bit or 256 bit */
253 	uint8_t		vc3_encrypt_key[AES256_KEY_LENGTH];
254 	uint32_t	vc3_encrypt_key_len;
255 
256 	uint8_t		vc3_decrypt_key[AES256_KEY_LENGTH];
257 	uint32_t	vc3_decrypt_key_len;
258 
259 	/* SMB 3 Nonce used for encryption */
260 	uint64_t	vc3_nonce_high;
261 	uint64_t	vc3_nonce_low;
262 
263 	kcondvar_t		iod_idle;	/* IOD thread idle CV */
264 	krwlock_t		iod_rqlock;	/* iod_rqlist */
265 	struct smb_rqhead	iod_rqlist;	/* list of active reqs */
266 	struct _kthread		*iod_thr;	/* the IOD (reader) thread */
267 	int			iod_flags;	/* see SMBIOD_* below */
268 	uint_t			iod_muxcnt;	/* num. active requests */
269 	uint_t			iod_muxwant;	/* waiting to be active */
270 	kcondvar_t		iod_muxwait;
271 	boolean_t		iod_noresp;	/* Logged "not responding" */
272 
273 	smb_iods_t		vc_iods;
274 	smb_sopt_t		vc_sopt;
275 
276 	/* This is copied in/out when IOD enters/returns */
277 	smbioc_ssn_work_t	vc_work;
278 
279 	/* session identity, etc. */
280 	smbioc_ossn_t		vc_ssn;
281 } smb_vc_t;
282 
283 #define	vc_lock		vc_co.co_lock
284 #define	vc_flags	vc_co.co_flags
285 
286 /* defines for members in vc_ssn */
287 #define	vc_owner	vc_ssn.ssn_owner
288 #define	vc_vopt		vc_ssn.ssn_vopt
289 #define	vc_minver	vc_ssn.ssn_minver
290 #define	vc_maxver	vc_ssn.ssn_maxver
291 #define	vc_srvname	vc_ssn.ssn_srvname
292 #define	vc_srvaddr	vc_ssn.ssn_id.id_srvaddr
293 #define	vc_domain	vc_ssn.ssn_id.id_domain
294 #define	vc_username	vc_ssn.ssn_id.id_user
295 
296 /* defines for members in vc_work */
297 #define	vc_cl_guid	vc_work.wk_cl_guid
298 
299 /* defines for members in vc_sopt ? */
300 #define	vc_maxmux	vc_sopt.sv_maxmux
301 
302 /* defines for members in vc_iods */
303 #define	vc_hflags	vc_iods.is_hflags
304 #define	vc_hflags2	vc_iods.is_hflags2
305 #define	vc_smbuid	vc_iods.is_smbuid
306 #define	vc_next_mid	vc_iods.is_next_mid
307 #define	vc_txmax	vc_iods.is_txmax
308 #define	vc_rwmax	vc_iods.is_rwmax
309 #define	vc_rxmax	vc_iods.is_rxmax
310 #define	vc_wxmax	vc_iods.is_wxmax
311 #define	vc_next_seq	vc_iods.is_next_seq
312 
313 #define	SMB_VC_LOCK(vcp)	mutex_enter(&(vcp)->vc_lock)
314 #define	SMB_VC_UNLOCK(vcp)	mutex_exit(&(vcp)->vc_lock)
315 
316 #define	CPTOVC(cp)	((struct smb_vc *)((void *)(cp)))
317 #define	VCTOCP(vcp)	(&(vcp)->vc_co)
318 
319 #define	SMB_UNICODE_STRINGS(vcp) \
320 	(((vcp)->vc_flags & SMBV_SMB2) != 0 ||	\
321 	((vcp)->vc_hflags2 & SMB_FLAGS2_UNICODE) != 0)
322 
323 /* Bits in iod_flags */
324 #define	SMBIOD_RUNNING		0x0001
325 #define	SMBIOD_SHUTDOWN		0x0002
326 
327 /*
328  * smb_share structure describes connection to the given SMB share (tree).
329  * Connection to share is always built on top of the VC.
330  */
331 
332 typedef struct smb_share {
333 	struct smb_connobj ss_co;	/* keep first! See CPTOSS */
334 	kcondvar_t	ss_conn_done;	/* wait for reconnect */
335 	int		ss_conn_waiters;
336 	int		ss_vcgenid;	/* check VC generation ID */
337 	uint16_t	ss_tid;		/* TID */
338 	uint16_t	ss_options;	/* option support bits */
339 	uint32_t	ss2_tree_id;
340 	uint32_t	ss2_share_flags;
341 	uint32_t	ss2_share_caps;
342 	smbioc_oshare_t ss_ioc;
343 } smb_share_t;
344 
345 #define	ss_lock		ss_co.co_lock
346 #define	ss_flags	ss_co.co_flags
347 
348 #define	ss_use		ss_ioc.sh_use
349 #define	ss_type		ss_ioc.sh_type
350 #define	ss_name		ss_ioc.sh_name
351 #define	ss_pass		ss_ioc.sh_pass
352 
353 #define	SMB_SS_LOCK(ssp)	mutex_enter(&(ssp)->ss_lock)
354 #define	SMB_SS_UNLOCK(ssp)	mutex_exit(&(ssp)->ss_lock)
355 
356 #define	CPTOSS(cp)	((struct smb_share *)((void *)(cp)))
357 #define	SSTOCP(ssp)	(&(ssp)->ss_co)
358 #define	SSTOVC(ssp)	CPTOVC(((ssp)->ss_co.co_parent))
359 
360 typedef struct smb2fid {
361 	uint64_t fid_persistent;
362 	uint64_t fid_volatile;
363 } smb2fid_t;
364 
365 /*
366  * smb_fh struct describes an open file handle under some share.
367  */
368 typedef struct smb_fh {
369 	struct smb_connobj fh_co;	/* keep first! See CPTOSS */
370 	int	fh_vcgenid;		/* check VC generation ID */
371 	uint32_t fh_rights;		/* granted access */
372 	smb2fid_t fh_fid2;
373 	uint16_t fh_fid1;
374 } smb_fh_t;
375 
376 #define	fh_lock		fh_co.co_lock
377 #define	fh_flags	fh_co.co_flags
378 
379 #define	SMB_FH_LOCK(fhp)	mutex_enter(&(fhp)->fh_lock)
380 #define	SMB_FH_UNLOCK(fhp)	mutex_exit(&(fhp)->fh_lock)
381 
382 #define	CPTOFH(cp)	((struct smb_fh *)((void *)(cp)))
383 #define	FHTOCP(fhp)	(&(fhp)->fh_co)
384 #define	FHTOSS(fhp)	CPTOSS(((fhp)->fh_co.co_parent))
385 
386 /*
387  * Call-back operations vector, so the netsmb module
388  * can notify smbfs about events affecting mounts.
389  * Installed in netsmb after smbfs loads.
390  * Note: smbfs only uses the fscb_discon hook.
391  */
392 typedef struct smb_fscb {
393 	/* Called when the VC has disconnected. */
394 	void (*fscb_disconn)(smb_share_t *);
395 	/* Called when the VC has reconnected. */
396 	void (*fscb_connect)(smb_share_t *);
397 } smb_fscb_t;
398 /* Install the above vector, or pass NULL to clear it. */
399 void smb_fscb_set(smb_fscb_t *);
400 
401 /*
402  * The driver per open instance object.
403  * Mostly used in: smb_dev.c, smb_usr.c
404  */
405 typedef struct smb_dev {
406 	kmutex_t	sd_lock;
407 	struct smb_vc	*sd_vc;		/* Reference to VC */
408 	struct smb_share *sd_share;	/* Reference to share if any */
409 	struct smb_fh	*sd_fh;		/* Reference to FH, if any */
410 	int		sd_level;	/* SMBL_VC, ... */
411 	int		sd_vcgenid;	/* Generation of share or VC */
412 	int		sd_poll;	/* Future use */
413 	int		sd_flags;	/* State of connection */
414 #define	NSMBFL_OPEN		0x0001	/* Device minor is open */
415 #define	NSMBFL_IOD		0x0004	/* Open by IOD */
416 #define	NSMBFL_IOCTL		0x0010	/* Serialize ioctl calls */
417 	zoneid_t	zoneid;		/* Zone id */
418 } smb_dev_t;
419 
420 extern const uint32_t nsmb_version;
421 
422 /*
423  * smb_dev.c
424  */
425 int  smb_dev2share(int fd, struct smb_share **sspp);
426 
427 
428 /*
429  * smb_usr.c
430  */
431 int smb_usr_ioctl(smb_dev_t *, int, intptr_t, int, cred_t *);
432 
433 int smb_usr_get_flags2(smb_dev_t *sdp, intptr_t arg, int flags);
434 int smb_usr_get_ssnkey(smb_dev_t *sdp, intptr_t arg, int flags);
435 int smb_usr_dup_dev(smb_dev_t *sdp, intptr_t arg, int flags);
436 
437 int smb_usr_simplerq(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr);
438 int smb_usr_t2request(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr);
439 
440 int smb_usr_closefh(smb_dev_t *, cred_t *);
441 int smb_usr_rw(smb_dev_t *sdp, int cmd, intptr_t arg, int flags, cred_t *cr);
442 int smb_usr_ntcreate(smb_dev_t *, intptr_t, int, cred_t *);
443 int smb_usr_printjob(smb_dev_t *, intptr_t, int, cred_t *);
444 
445 int smb_usr_get_ssn(smb_dev_t *, int, intptr_t, int, cred_t *);
446 int smb_usr_drop_ssn(smb_dev_t *sdp, int cmd);
447 
448 int smb_usr_get_tree(smb_dev_t *, int, intptr_t, int, cred_t *);
449 int smb_usr_drop_tree(smb_dev_t *sdp, int cmd);
450 
451 int smb_usr_iod_work(smb_dev_t *sdp, intptr_t arg, int flags, cred_t *cr);
452 int smb_usr_iod_ioctl(smb_dev_t *sdp, int cmd, intptr_t arg, int flags,
453     cred_t *cr);
454 
455 int smb_pkey_ioctl(int, intptr_t, int, cred_t *);
456 
457 
458 /*
459  * IOD functions
460  */
461 int  smb_iod_create(smb_vc_t *vcp);
462 int  smb_iod_destroy(smb_vc_t *vcp);
463 void smb_iod_disconnect(smb_vc_t *vcp);
464 int  smb2_iod_addrq(struct smb_rq *rqp);
465 int  smb1_iod_addrq(struct smb_rq *rqp);
466 int  smb1_iod_multirq(struct smb_rq *rqp);
467 int  smb_iod_waitrq(struct smb_rq *rqp);
468 int  smb_iod_waitrq_int(struct smb_rq *rqp);
469 void smb_iod_removerq(struct smb_rq *rqp);
470 int  smb_iod_sendrecv(struct smb_rq *, int);
471 void smb_iod_shutdown_share(smb_share_t *ssp);
472 
473 void smb_iod_sendall(smb_vc_t *);
474 int smb_iod_recvall(smb_vc_t *, boolean_t);
475 
476 int nsmb_iod_connect(smb_vc_t *vcp, cred_t *cr);
477 int nsmb_iod_negotiate(smb_vc_t *vcp, cred_t *cr);
478 int nsmb_iod_ssnsetup(smb_vc_t *vcp, cred_t *cr);
479 int smb_iod_vc_work(smb_vc_t *, int, cred_t *);
480 int smb_iod_vc_idle(smb_vc_t *);
481 int smb_iod_vc_rcfail(smb_vc_t *);
482 int smb_iod_reconnect(smb_vc_t *);
483 
484 /*
485  * Session level functions
486  */
487 int  smb_sm_init(void);
488 int  smb_sm_idle(void);
489 void smb_sm_done(void);
490 
491 /*
492  * VC level functions
493  */
494 void smb_vc_hold(smb_vc_t *vcp);
495 void smb_vc_rele(smb_vc_t *vcp);
496 void smb_vc_kill(smb_vc_t *vcp);
497 
498 int smb_vc_findcreate(smbioc_ossn_t *, smb_cred_t *, smb_vc_t **);
499 int smb_vc_create(smbioc_ossn_t *ossn, smb_cred_t *scred, smb_vc_t **vcpp);
500 
501 const char *smb_vc_getpass(smb_vc_t *vcp);
502 uint16_t smb_vc_nextmid(smb_vc_t *vcp);
503 void *smb_vc_getipaddr(smb_vc_t *vcp, int *ipvers);
504 
505 typedef void (*walk_share_func_t)(smb_share_t *);
506 void smb_vc_walkshares(struct smb_vc *,	walk_share_func_t);
507 
508 /*
509  * share level functions
510  */
511 
512 int smb_share_findcreate(smbioc_tcon_t *, smb_vc_t *,
513 	smb_share_t **, smb_cred_t *);
514 
515 void smb_share_hold(smb_share_t *ssp);
516 void smb_share_rele(smb_share_t *ssp);
517 void smb_share_kill(smb_share_t *ssp);
518 
519 void smb_share_invalidate(smb_share_t *ssp);
520 int  smb_share_tcon(smb_share_t *, smb_cred_t *);
521 
522 /*
523  * File handle level functions
524  */
525 int smb_fh_create(smb_share_t *ssp, struct smb_fh **fhpp);
526 void smb_fh_opened(struct smb_fh *fhp);
527 void smb_fh_close(struct smb_fh *fhp);
528 void smb_fh_hold(struct smb_fh *fhp);
529 void smb_fh_rele(struct smb_fh *fhp);
530 
531 #endif /* _SMB_CONN_H */
532