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
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
//! TCP segment sizing and option-budget helpers.
//!
//! These are pure, inspectable helper functions for packet builders. They size
//! correct TCP segments and document fragmentation-adjacent facts (MSS, option
//! budgeting, effective payload sizing) without implementing fragmentation,
//! path-MTU probing, reassembly, or any state machine. Every constant is backed
//! by an RFC and `docs/guide/tcp.md`, "Segment Sizing And
//! Fragmentation-Adjacent Guidance (Documentation Only)".
//!
//! Source anchors:
//! - RFC 9293 section 3.1 — TCP header layout and the 40-octet option budget
//! (Data Offset 4 bits, max 15 32-bit words).
//! - RFC 9293 section 3.7.1, RFC 1122, RFC 879 — the IPv4 default send MSS of
//! 536 octets when the path MTU is unknown.
//! - RFC 8200 section 5 / RFC 8201 — the 1280-octet IPv6 minimum link MTU.
//! - RFC 1191 / RFC 8201 / RFC 8899 — PMTUD / PLPMTUD guidance only; `crafter`
//! does not probe a path MTU. Callers supply `path_mtu`.
use ;
use ;
use TcpOption;
/// Round a raw TCP option-byte count up to the next 32-bit boundary.
///
/// TCP options are padded with zero/EOL bytes so the header length is a whole
/// number of 32-bit words (RFC 9293 section 3.1). Used when filling Data Offset
/// from unset option bytes during `compile()`.
pub
/// TCP header length in octets for a given raw option-byte count.
///
/// The fixed TCP header is 20 octets; options are padded to a 32-bit boundary
/// and added on top (RFC 9293 section 3.1). With no options this returns 20;
/// with the full 40-octet option budget it returns the 60-octet maximum.
///
/// This is a pure sizing helper. It does not validate that `option_bytes` fits
/// the 40-octet budget — deliberate over-budget values stay constructible for
/// stack testing; use [`option_budget`] to check the cap.
pub const
/// Maximum TCP option-byte budget: 40 octets (RFC 9293 section 3.1).
///
/// Data Offset is 4 bits, capping the TCP header at 15 32-bit words (60 octets);
/// after the 20-octet fixed header that leaves 40 octets for options. This is
/// the hard ceiling shared by MSS, Window Scale, SACK-Permitted, Timestamps, and
/// every other option on a SYN (see `docs/guide/tcp.md`).
pub const
/// Remaining TCP option-byte budget given `used` option bytes already consumed.
///
/// Returns how many more option octets fit under the 40-octet Data Offset cap
/// (RFC 9293 section 3.1). Saturates at zero: if `used` already meets or exceeds
/// the budget the result is 0, never a negative or wrapped value. This is the
/// inspectable form of "can another option still fit?" without modeling any
/// option layout.
pub const
/// A pure report on whether a planned TCP option set fits the base TCP header.
///
/// The TCP Data Offset is 4 bits, capping the TCP header at 15 32-bit words —
/// 60 octets total, of which 40 are available for options once the 20-octet
/// fixed header is subtracted (RFC 9293 section 3.1). When the Extended Data
/// Offset (EDO) experiment is not in use, that 40-octet ceiling is hard.
///
/// `TcpOptionBudget` lets a generated tool plan an option set *before* compiling
/// a segment: it sums the encoded length of each [`TcpOption`] (plus any raw
/// option byte counts the caller already knows about, e.g. pre-encoded bytes),
/// reports how the padded header lands, how many option octets remain under the
/// 40-octet cap, and whether the base TCP header limit is exceeded.
///
/// This is a pure report. It never drops, reorders, or rewrites options — the
/// caller decides what to do when [`TcpOptionBudget::exceeds`] is `true`.
/// Deliberately over-budget option sets stay constructible for stack testing.
///
/// ```rust
/// use crafter::prelude::*;
/// use crafter::protocols::transport::TcpOptionBudget;
///
/// // A common SYN option set: MSS + SACK-Permitted + Timestamps + Window Scale.
/// let options = [
/// TcpOption::maximum_segment_size(1460),
/// TcpOption::sack_permitted(),
/// TcpOption::timestamp(1, 0),
/// TcpOption::window_scale(7),
/// ];
/// let budget = TcpOptionBudget::for_options(&options);
/// assert!(budget.fits());
/// assert!(budget.remaining() > 0);
/// ```
/// Maximum TCP payload (user data) octets for a caller-provided path MTU.
///
/// Subtracts the IP header length and the TCP header length from the path MTU:
/// `path_mtu - ip_header_len - tcp_header_len`. `crafter` never discovers a path
/// MTU itself (RFC 1191 / RFC 8201 / RFC 8899 PMTUD/PLPMTUD are guidance only);
/// the caller supplies `path_mtu` from its own knowledge or a fixed assumption.
///
/// Saturating: if the headers meet or exceed the path MTU the result is 0, never
/// an underflow. This is a pure sizing helper and does not fragment, probe, or
/// emit a segment.
///
/// ```rust
/// use crafter::protocols::transport::{max_tcp_payload, option_budget, tcp_header_len};
///
/// // A 1500-octet path with a 20-octet IPv4 header and an options-laden
/// // 60-octet TCP header leaves room for 1420 payload octets.
/// let tcp_len = tcp_header_len(option_budget());
/// assert_eq!(tcp_len, 60);
/// assert_eq!(max_tcp_payload(1500, 20, tcp_len), 1420);
/// ```
pub const
/// Source-backed effective TCP MSS guidance for IPv4.
///
/// Returns the largest TCP payload an IPv4 sender should offer for a given path
/// MTU, derived as `path_mtu - IPv4 header - TCP header` over the fixed 20-octet
/// IPv4 and TCP headers (RFC 9293 section 3.7.1). When `path_mtu` is `None` (the
/// path MTU is unknown) this falls back to the RFC 9293 / RFC 1122 / RFC 879
/// default send MSS of 536 octets. The derived value is also floored at 536 so
/// guidance never recommends a smaller-than-default MSS for an unusually small
/// (but still IPv4-legal) MTU; callers that want the raw derivation can use
/// [`max_tcp_payload`] directly.
///
/// Pure guidance: it never sizes below the default, never probes, and never
/// fragments. Backed by `docs/guide/tcp.md`.
pub const
/// Source-backed effective TCP MSS guidance for IPv6.
///
/// Returns the largest TCP payload an IPv6 sender should offer for a given path
/// MTU, derived as `path_mtu - IPv6 header - TCP header` over the fixed 40-octet
/// IPv6 and 20-octet TCP headers (RFC 9293 section 3.7.1, RFC 8200). When
/// `path_mtu` is `None` (the path MTU is unknown) this uses the RFC 8200 / RFC
/// 8201 IPv6 minimum link MTU of 1280 octets, giving an effective MSS of
/// `1280 - 40 - 20 = 1220` octets. Any supplied MTU is also floored at the 1280
/// minimum before deriving, because IPv6 links must support at least 1280
/// octets, so guidance never drops below the minimum-MTU MSS.
///
/// Pure guidance: it never probes a path MTU and never fragments. Backed by
/// `docs/guide/tcp.md`.
pub const
/// Source-backed effective TCP MSS guidance for either IP version.
///
/// Dispatches to [`effective_mss_ipv4`] or [`effective_mss_ipv6`] based on
/// `is_ipv6`, applying the version-specific header sizes and unknown-`path_mtu`
/// defaults (IPv4 default MSS 536 per RFC 9293 / RFC 1122 / RFC 879; IPv6
/// derived from the 1280-octet minimum MTU per RFC 8200 / RFC 8201). This is the
/// single entry point a builder can call without branching on IP version
/// itself.
///
/// ```rust
/// use crafter::protocols::transport::effective_mss;
///
/// // A 1500-octet IPv4 path: 1500 - 20 (IPv4) - 20 (TCP) = 1460.
/// assert_eq!(effective_mss(false, Some(1500)), 1460);
///
/// // Unknown IPv4 path MTU falls back to the RFC default send MSS of 536.
/// assert_eq!(effective_mss(false, None), 536);
///
/// // Unknown IPv6 path MTU uses the 1280-octet minimum: 1280 - 40 - 20 = 1220.
/// assert_eq!(effective_mss(true, None), 1220);
/// ```
pub const
/// True when the SYN control bit is set in `flags`.
///
/// SYN occupies one octet of TCP sequence space (RFC 9293 section 3.4): the
/// sequence number of a SYN is the ISN, and the first data octet is ISN+1. This
/// is a pure flag predicate used by [`sequence_space_len`]; it models no
/// connection state.
pub const
/// True when the FIN control bit is set in `flags`.
///
/// FIN occupies one octet of TCP sequence space (RFC 9293 section 3.4): a FIN
/// is acknowledged like a data octet, so it advances the sequence number by one.
/// This is a pure flag predicate used by [`sequence_space_len`]; it models no
/// connection state.
pub const
/// Length of a TCP segment in *sequence space*, in octets.
///
/// TCP sequence numbers count payload octets plus the SYN and FIN control bits
/// (RFC 9293 section 3.4 "Sequence Numbers"): every payload octet consumes one
/// sequence number, a SYN consumes one, and a FIN consumes one. A pure ACK with
/// no payload and neither SYN nor FIN consumes zero sequence space.
///
/// `sequence_space_len = payload_len + (SYN ? 1 : 0) + (FIN ? 1 : 0)`
///
/// This is a pure helper for packet builders that need to compute the next
/// expected sequence/acknowledgment number for a crafted reply. It does **not**
/// implement a TCP state machine, retransmission, or reassembly; the caller
/// supplies `flags` and `payload_len` and decides how to use the result. Uses
/// saturating addition so the value never wraps a `u32`.
///
/// ```rust
/// use crafter::prelude::*;
/// use crafter::protocols::transport::sequence_space_len;
///
/// // A SYN with no payload consumes one octet of sequence space.
/// assert_eq!(sequence_space_len(TCP_FLAG_SYN, 0), 1);
///
/// // A pure ACK carrying 100 payload octets consumes exactly 100.
/// assert_eq!(sequence_space_len(TCP_FLAG_ACK, 100), 100);
/// ```
pub const