1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
//! Connection configuration settings.
use std::time::Duration;
use smb_msg::Dialect;
use smb_transport::config::*;
/// Specifies the encryption mode for the connection.
/// Use this as part of the [ConnectionConfig] to specify the encryption mode for the connection.
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum EncryptionMode {
/// Encryption is allowed but not required, it's up to the server to decide.
#[default]
Allowed,
/// Encryption is required, and connection will fail if the server does not support it.
Required,
/// Encryption is disabled, server might fail the connection if it requires encryption.
Disabled,
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub enum MultiChannelConfig {
/// Multi-channel is disabled.
#[default]
Disabled,
/// Multi-channel is always enabled, if supported by the server and client.
Always,
/// Multi-channel is enabled only if using RDMA transport, and if supported by the server and client.
#[cfg(feature = "rdma")]
RdmaOnly,
}
impl MultiChannelConfig {
/// Returns whether multichannel of any form is enabled.
pub fn is_enabled(&self) -> bool {
match self {
MultiChannelConfig::Always => true,
#[cfg(feature = "rdma")]
MultiChannelConfig::RdmaOnly => true,
MultiChannelConfig::Disabled => false,
}
}
/// Returns whether multichannel is enabled only for RDMA transport.
pub fn is_rdma_only(&self) -> bool {
#[cfg(feature = "rdma")]
return matches!(self, MultiChannelConfig::RdmaOnly);
#[cfg(not(feature = "rdma"))]
return false;
}
}
impl EncryptionMode {
/// Returns true if encryption is required.
pub fn is_required(&self) -> bool {
matches!(self, Self::Required)
}
/// Returns true if encryption is disabled.
pub fn is_disabled(&self) -> bool {
matches!(self, Self::Disabled)
}
}
/// Specifies the authentication methods (SSPs) to be used for the connection.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct AuthMethodsConfig {
/// Whether to try using NTLM authentication.
/// This is enabled by default.
pub ntlm: bool,
/// Whether to try using Kerberos authentication.
/// This is supported only if the `kerberos` feature is enabled,
/// and if so, enabled by default.
pub kerberos: bool,
}
impl Default for AuthMethodsConfig {
fn default() -> Self {
Self {
ntlm: true,
kerberos: cfg!(feature = "kerberos"),
}
}
}
/// Specifies the configuration for a connection.
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct ConnectionConfig {
/// Specifies the server port to connect to.
/// If unset, defaults to the default port for the selected transport protocol.
pub port: Option<u16>,
/// Specifies the timeout for the connection.
/// If unset, defaults to [`ConnectionConfig::DEFAULT_TIMEOUT`].
/// 0 means wait forever.
/// Access the timeout using the [`ConnectionConfig::timeout()`] method.
pub timeout: Option<Duration>,
/// Specifies the minimum and maximum dialects to be used in the connection.
///
/// Note, that if set, the minimum dialect must be less than or equal to the maximum dialect.
pub min_dialect: Option<Dialect>,
/// Specifies the minimum and maximum dialects to be used in the connection.
///
/// Note, that if set, the minimum dialect must be less than or equal to the maximum dialect.
pub max_dialect: Option<Dialect>,
/// Sets the encryption mode for the connection.
/// See [EncryptionMode] for more information.
pub encryption_mode: EncryptionMode,
/// Sets whether signing may be skipped for guest or anonymous access.
pub allow_unsigned_guest_access: bool,
/// Whether to enable compression, if supported by the server and specified connection dialects.
///
/// Note: you must also have compression features enabled when building the crate, otherwise compression
/// would not be available. *The compression feature is enabled by default.*
pub compression_enabled: bool,
/// Multi-channel configuration
pub multichannel: MultiChannelConfig,
/// Specifies the client host name to be used in the SMB2 negotiation & session setup.
pub client_name: Option<String>,
/// Specifies whether to disable support for Server-to-client notifications.
/// If set to true, the client will NOT support notifications.
pub disable_notifications: bool,
/// Whether to avoid multi-protocol negotiation,
/// and perform smb2-only negotiation. This results in a
/// faster negotiation process, but it might fail with some servers,
pub smb2_only_negotiate: bool,
/// Specifies the transport protocol to be used for the connection.
pub transport: TransportConfig,
/// Configures valid authentication methods (SSPs) for the connection.
/// See [`AuthMethodsConfig`] for more information.
pub auth_methods: AuthMethodsConfig,
/// The number of SMB2 credits to request for the connection.
/// If not configured, uses a default value.
///
/// The higher number of credits, the more concurrent requests can be sent on the connection.
/// However, some servers may not issue such high number of credits.
///
/// This is the somewhat similar to the [`-Smb2MaxCredits`](<https://learn.microsoft.com/en-us/powershell/module/smbshare/set-smbserverconfiguration?view=windowsserver2025-ps#-smb2creditsmax>)
/// parameter in the `Set-SmbServerConfiguration` PowerShell cmdlet, but from the client's side.
pub credits_backlog: Option<u16>,
/// The default size, in bytes, of the buffer that can be used for
/// [`ResourceHandle::query_info`][crate::ResourceHandle::query_info], [`ResourceHandle::query_fs_info`][crate::ResourceHandle::query_fs_info],
/// [`ResourceHandle::query_security_info`][crate::ResourceHandle::query_security_info], [`Directory::query_quota_info`][crate::Directory::query_quota_info],
/// their respective `set_*_info` counterparts (such as [`ResourceHandle::set_info`][crate::ResourceHandle::set_info]),
/// [`Directory::query`][crate::Directory::query] and [`Directory::watch`][crate::Directory::watch] operations.
pub default_transaction_size: Option<u32>,
}
impl ConnectionConfig {
pub const DEFAULT_TIMEOUT: Duration = Duration::from_secs(10);
/// Validates common configuration settings.
pub fn validate(&self) -> crate::Result<()> {
// Make sure dialects min <= max.
if let (Some(min), Some(max)) = (self.min_dialect, self.max_dialect)
&& min > max
{
return Err(crate::Error::InvalidConfiguration(
"Minimum dialect is greater than maximum dialect".to_string(),
));
}
// Make sure transport is supported by the dialects.
#[cfg(feature = "quic")]
if let Some(min) = self.min_dialect
&& min < Dialect::Smb0311
&& matches!(self.transport, TransportConfig::Quic(_))
{
return Err(crate::Error::InvalidConfiguration(
"SMB over QUIC is not supported by the selected dialect".to_string(),
));
}
if let Some(default_transaction_size) = self.default_transaction_size
&& default_transaction_size == 0
{
return Err(crate::Error::InvalidConfiguration(
"Default transaction size cannot be zero".to_string(),
));
}
Ok(())
}
/// Returns the effective timeout to be used if [`timeout`][`Self::timeout`] is not set.
pub fn timeout(&self) -> Duration {
self.timeout.unwrap_or(Self::DEFAULT_TIMEOUT)
}
pub const DEFAULT_TRANSACTION_SIZE: u32 = 0x10_000;
/// Returns the effective value to be used if [`default_transaction_size`][`Self::default_transaction_size`] is not set.
pub fn default_transaction_size(&self) -> u32 {
self.default_transaction_size
.unwrap_or(Self::DEFAULT_TRANSACTION_SIZE)
}
}