uefi_raw/protocol/network/tcp4.rs
1// SPDX-License-Identifier: MIT OR Apache-2.0
2
3//! TCPv4 Protocol
4//!
5//! This module provides the TCPv4 Protocol interface definitions. The
6//! TCPv4 Protocol provides services to send and receive data streams
7//! over IPv4 networks.
8//!
9//! The protocol is defined in the [UEFI Specification, Section 28.1](https://uefi.org/specs/UEFI/2.11/28_Network_Protocols_TCP_IP_and_Configuration.html#efi-tcpv4-protocol).
10
11use crate::protocol::network::ip4::Ip4ModeData;
12use crate::protocol::network::snp::NetworkMode;
13use crate::{Boolean, Event, Guid, Handle, Ipv4Address, Status, guid, newtype_enum};
14use core::ffi::c_void;
15use core::fmt::{Debug, Formatter};
16
17#[derive(Debug)]
18#[repr(C)]
19pub struct Tcp4Protocol {
20 /// Get the current operational status.
21 ///
22 /// `get_mode_data` copies the current operational settings of
23 /// this instance into user-supplied structs. This function can
24 /// also be used to retrieve the operational setting of underlying
25 /// drivers such as IPv4, MNP, or SNP.
26 #[allow(clippy::type_complexity)]
27 pub get_mode_data: unsafe extern "efiapi" fn(
28 this: *mut Self,
29 connection_state: *mut Tcp4ConnectionState,
30 config_data: *mut Tcp4ConfigData,
31 ip4_mode_data: *mut Ip4ModeData,
32 managed_network_config_data: *mut c_void,
33 simple_network_mode: *mut NetworkMode,
34 ) -> Status,
35
36 /// Initialize or brutally reset the operational parameters for
37 /// this instance.
38 ///
39 /// No other [`Tcp4Protocol`] operation can be executed by this
40 /// instance until it is configured properly. For an active
41 /// [`Tcp4Protocol`] instance, after a proper configuration it may
42 /// call [`Tcp4Protocol::connect`] to initiates the three-way
43 /// handshake. For a passive [`Tcp4Protocol`] instance, its state
44 /// will transition to [`Tcp4ConnectionState::LISTEN`] after
45 /// configuration, and [`accept`][Self::accept] may be called to
46 /// listen for incoming TCP connection requests. If `config_data`
47 /// is set to `NULL`, the instance is reset. Resetting process
48 /// will be done brutally; the state machine will be set to
49 /// [`Tcp4ConnectionState::CLOSED`] directly, the receive queue
50 /// and transmit queue will be flushed, and no traffic will be
51 /// allowed through this instance.
52 pub configure:
53 unsafe extern "efiapi" fn(this: *mut Self, config_data: *const Tcp4ConfigData) -> Status,
54
55 /// Add or delete routing entries.
56 ///
57 /// The most specific route is selected by comparing the
58 /// `subnet_address` with the destination IP address
59 /// arithmetically ANDed with the `subnet_mask`.
60 ///
61 /// The default route is added with both `subnet_address` and
62 /// `subnet_mask` set to `0.0.0.0`. The default route matches all
63 /// destination IP addresses if there is no more specific route.
64 ///
65 /// A direct route is added with `gateway_address` set to
66 /// `0.0.0.0`. Packets are sent to the destination host if its
67 /// address can be found in the Address Resolution Protocol (ARP)
68 /// cache or it is on the local subnet. If the instance is
69 /// configured to use default address, a direct route to the local
70 /// network will be added automatically.
71 ///
72 /// Each TCP instance has its own independent routing table. An
73 /// instance that uses the default IP address will have a copy of
74 /// the
75 /// [`Ipv4Config2Protocol`][super::ip4_config2::Ip4Config2Protocol]'s
76 /// routing table. The copy will be updated automatically whenever
77 /// the IP driver reconfigures its instance. As a result, the
78 /// previous modification to the instance's local copy will be
79 /// lost.
80 ///
81 /// The priority of checking the route table is specific to the IP
82 /// implementation, and every IP implementation must comply with
83 /// RFC 1122.
84 ///
85 /// Note: There is no way to set up routes to other network
86 /// interface cards (NICs) because each NIC has its own
87 /// independent network stack that shares information only through
88 /// EFI TCPv4 variable.
89 pub routes: unsafe extern "efiapi" fn(
90 this: *mut Self,
91 delete_route: Boolean,
92 subnet_address: *const Ipv4Address,
93 subnet_mask: *const Ipv4Address,
94 gateway_address: *const Ipv4Address,
95 ) -> Status,
96
97 /// Initiate a nonblocking TCP connection request for an active
98 /// TCP instance.
99 ///
100 /// `connect` initiates an active open to the remote peer
101 /// configured in the current TCP instance if it is configured as
102 /// active. If the connection succeeds or fails due to any error,
103 /// the [`token.completion_token.event`][Tcp4CompletionToken::event]
104 /// will be signaled and `token.completion_token.status` will be
105 /// updated accordingly. This function can only be called for the
106 /// TCP instance in the [`Tcp4ConnectionState::CLOSED`] state. The
107 /// instance will transition to [`Tcp4ConnectionState::SYN_SENT`]
108 /// if the function returns [`Status::SUCCESS`]. If the TCP
109 /// three-way handshake succeeds, its state will become
110 /// [`Tcp4ConnectionState::ESTABLISHED`], otherwise, the state
111 /// will return to [`Tcp4ConnectionState::CLOSED`].
112 pub connect:
113 unsafe extern "efiapi" fn(this: *mut Self, token: *mut Tcp4ConnectionToken) -> Status,
114
115 /// Listen on the passive instance to accept an incoming
116 /// connection request. This is a nonblocking operation.
117 ///
118 /// The `accept` function initiates an asynchronous accept request
119 /// to wait for an incoming connection on the passive TCP
120 /// instance. If a remote peer successfully establishes a
121 /// connection with this instance, a new TCP instance will be
122 /// created and its handle will be returned in
123 /// [`new_child_handle`][Tcp4ListenToken::new_child_handle]. The
124 /// newly created instance is configured by inheriting the passive
125 /// instance's configuration and is ready for use upon return. The
126 /// instance is in the [`Tcp4ConnectionState::ESTABLISHED`]
127 /// state.
128 ///
129 /// The [`new_child_handle`][Tcp4ListenToken::new_child_handle]
130 /// will be signaled when a new connection is accepted, the user
131 /// aborts the listen, or the connection is reset.
132 ///
133 /// This function can only be called when the current TCP instance
134 /// is in [`Tcp4ConnectionState::LISTEN`] state.
135 pub accept:
136 unsafe extern "efiapi" fn(this: *mut Self, listen_token: *mut Tcp4ListenToken) -> Status,
137
138 /// Queues outgoing data into the transmit queue.
139 ///
140 /// The `transmit` function queues a sending request to this
141 /// instance along with the user data. The status of the token is
142 /// updated and the event in the token will be signaled once the
143 /// data is sent out or some error occurs.
144 pub transmit: unsafe extern "efiapi" fn(this: *mut Self, token: *mut Tcp4IoToken) -> Status,
145
146 /// Places an asynchronous receive request into the receiving
147 /// queue.
148 ///
149 /// `receive` places a completion token into the receive packet
150 /// queue. This function is always asynchronous. The caller must
151 /// allocate the
152 /// [`token.completion_token.event`][Tcp4CompletionToken::event]
153 /// and the `fragment_buffer` used to receive data. They also must
154 /// fill [`data_length`][Tcp4ReceiveData::data_length] which
155 /// represents the whole length of all `fragment_buffer`. When the
156 /// receive operation completes, the driver updates the
157 /// [`token.completion_token.status`][Tcp4CompletionToken::status]
158 /// and [`token.packet.rx_data`][Tcp4Packet::rx_data] fields and
159 /// and the `token.completion_token.event` is signaled. If data
160 /// was received, the data and its length will be copied into the
161 /// `fragment_table`. At the same time, the full length of
162 /// received data will be recorded in the `data_length`
163 /// fields. Providing a proper notification function and context
164 /// for the event will enable the user to receive the notification
165 /// and receiving status. That notification function is guaranteed
166 /// to not be re-entered.
167 pub receive: unsafe extern "efiapi" fn(this: *mut Self, token: *mut Tcp4IoToken) -> Status,
168
169 /// Disconnect a TCP connection gracefully or reset a TCP
170 /// connection. This function is a nonblocking operation.
171 ///
172 /// Initiate an asynchronous close token to TCP driver. After
173 /// `close` is called, any buffered transmission data will be sent
174 /// by TCP driver and the current instance will have a graceful
175 /// close working flow described as RFC 793 if `abort_on_close` is
176 /// set to `false`, otherwise, a reset packet will be sent by the
177 /// TCP driver to quickly disconnect this connection. When the
178 /// close operation completes successfully the TCP instance is in
179 /// [`Tcp4ConnectionState::CLOSED`] state, all pending
180 /// asynchronous operations are signaled, and any buffers used for
181 /// TCP network traffic are flushed.
182 pub close:
183 unsafe extern "efiapi" fn(this: *mut Self, close_token: *mut Tcp4CloseToken) -> Status,
184
185 /// Abort an asynchronous connection, listen, transmission or
186 /// receive request.
187 ///
188 /// The `cancel` function aborts a pending connection, listen,
189 /// transmit or receive request. If `completion_token` is not
190 /// `NULL` and the token is in the connection, listen,
191 /// transmission or receive queue when it is being cancelled, its
192 /// `status` will be set to [`Status::ABORTED`] and then `event`
193 /// will be signaled. If the token is not in one of the queues,
194 /// which usually means that the asynchronous operation has
195 /// completed, [`Status::NOT_FOUND`] is returned. If
196 /// `completion_token` is `NULL`, all asynchronous tokens issued
197 /// by [`Tcp4Protocol::connect`], [`Tcp4Protocol::accept`],
198 /// [`Tcp4Protocol::transmit`] and [`Tcp4Protocol::receive`]
199 /// will be aborted.
200 pub cancel: unsafe extern "efiapi" fn(
201 this: *mut Self,
202 completion_token: *mut Tcp4CompletionToken,
203 ) -> Status,
204
205 /// Poll to receive incoming data and transmit outgoing segments.
206 ///
207 /// The `poll` function increases the rate that data is moved
208 /// between the network and application and can be called when the
209 /// TCP instance is created successfully. Its use is optional.
210 ///
211 /// In some implementations, the periodical timer in the MNP
212 /// driver may not poll the underlying communications device fast
213 /// enough to avoid dropping packets. Drivers and applications
214 /// that are experiencing packet loss should try calling the
215 /// `poll` function at a high frequency.
216 pub poll: unsafe extern "efiapi" fn(this: *mut Self) -> Status,
217}
218
219impl Tcp4Protocol {
220 /// The GUID for the TCPv4 protocol.
221 ///
222 /// Defined in the [UEFI Specification, Section 28.1.4](https://uefi.org/specs/UEFI/2.11/28_Network_Protocols_TCP_IP_and_Configuration.html#efi-tcp4-protocol).
223 pub const GUID: Guid = guid!("65530BC7-A359-410F-B010-5AADC7EC2B62");
224
225 /// The GUID for the TCPv4 service binding protocol.
226 ///
227 /// Defined in the [UEFI Specification, Section 28.1.2](https://uefi.org/specs/UEFI/2.11/28_Network_Protocols_TCP_IP_and_Configuration.html#efi-tcp4-service-binding-protocol).
228 pub const SERVICE_BINDING_GUID: Guid = guid!("00720665-67EB-4a99-BAF7-D3C33A1C7CC9");
229}
230
231newtype_enum! {
232 pub enum Tcp4ConnectionState: i32 => {
233 CLOSED = 0,
234 LISTEN = 1,
235 SYN_SENT = 2,
236 SYN_RECEIVED = 3,
237 ESTABLISHED = 4,
238 FIN_WAIT1 = 5,
239 FIN_WAIT2 = 6,
240 CLOSING = 7,
241 TIME_WAIT = 8,
242 CLOSE_WAIT = 9,
243 LAST_ACK = 10,
244 }
245}
246
247#[derive(Debug)]
248#[repr(C)]
249pub struct Tcp4ConfigData {
250 /// Type of service field in transmitted IPv4 packets.
251 pub type_of_service: u8,
252 /// Time to live field in transmitted IPv4 packets.
253 pub time_to_live: u8,
254 /// Access point configuration.
255 pub access_point: Tcp4AccessPoint,
256 /// Optional TCP configuration parameters.
257 pub control_option: *mut Tcp4Option,
258}
259
260#[derive(Debug, Clone)]
261#[repr(C)]
262pub struct Tcp4AccessPoint {
263 /// Set to `TRUE` to use the default IP address.
264 pub use_default_address: Boolean,
265 /// The local IP address assigned to this TCP instance.
266 pub station_address: Ipv4Address,
267 /// The subnet mask associated with the station address.
268 pub subnet_mask: Ipv4Address,
269 /// The local port number.
270 pub station_port: u16,
271 /// The remote IP address.
272 pub remote_address: Ipv4Address,
273 /// The remote port number.
274 pub remote_port: u16,
275 /// Set to `TRUE` for active open, `FALSE` for passive open.
276 pub active_flag: Boolean,
277}
278
279#[derive(Debug)]
280#[repr(C)]
281pub struct Tcp4Option {
282 /// Size of the TCP receive buffer.
283 pub receive_buffer_size: u32,
284 /// Size of the TCP send buffer.
285 pub send_buffer_size: u32,
286 /// Maximum number of pending connections for passive instances.
287 pub max_syn_back_log: u32,
288 /// Connection timeout in seconds.
289 pub connection_timeout: u32,
290 /// Number of data retransmission attempts.
291 pub data_retries: u32,
292 /// FIN timeout in seconds.
293 pub fin_timeout: u32,
294 /// TIME_WAIT timeout in seconds.
295 pub time_wait_timeout: u32,
296 /// Number of keep-alive probes.
297 pub keep_alive_probes: u32,
298 /// Time before sending keep-alive probes in seconds.
299 pub keep_alive_time: u32,
300 /// Interval between keep-alive probes in seconds.
301 pub keep_alive_interval: u32,
302 /// Set to `TRUE` to enable Nagle algorithm.
303 pub enable_nagle: Boolean,
304 /// Set to `TRUE` to enable TCP timestamps.
305 pub enable_time_stamp: Boolean,
306 /// Set to `TRUE` to enable window scaling.
307 pub enable_window_scaling: Boolean,
308 /// Set to `TRUE` to enable selective acknowledgment.
309 pub enable_selective_ack: Boolean,
310 /// Set to `TRUE` to enable path MTU discovery.
311 pub enable_path_mtu_discovery: Boolean,
312}
313
314#[derive(Debug)]
315#[repr(C)]
316pub struct Tcp4CompletionToken {
317 /// Event to signal when the operation completes.
318 pub event: Event,
319 /// Status of the completed operation.
320 pub status: Status,
321}
322
323#[derive(Debug)]
324#[repr(C)]
325pub struct Tcp4ConnectionToken {
326 pub completion_token: Tcp4CompletionToken,
327}
328
329#[derive(Debug)]
330#[repr(C)]
331pub struct Tcp4ListenToken {
332 /// Completion token for the listen operation.
333 pub completion_token: Tcp4CompletionToken,
334 /// The new TCP instance handle created for the established
335 /// connection.
336 pub new_child_handle: Handle,
337}
338
339#[derive(Debug)]
340#[repr(C)]
341pub struct Tcp4IoToken {
342 /// Completion token for the I/O operation.
343 pub completion_token: Tcp4CompletionToken,
344 /// Packet data for the I/O operation.
345 pub packet: Tcp4Packet,
346}
347
348#[derive(Debug)]
349#[repr(C)]
350pub struct Tcp4CloseToken {
351 /// Completion token for the close operation.
352 pub completion_token: Tcp4CompletionToken,
353 /// Abort the TCP connection on close instead of the standard TCP
354 /// close process when it is set to TRUE. This option can be used
355 /// to satisfy a fast disconnect.
356 pub abort_on_close: Boolean,
357}
358
359#[repr(C)]
360pub union Tcp4Packet {
361 /// Pointer to receive data structure.
362 pub rx_data: *mut Tcp4ReceiveData,
363 /// Pointer to transmit data structure.
364 pub tx_data: *mut Tcp4TransmitData,
365}
366
367impl Debug for Tcp4Packet {
368 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
369 f.debug_struct("Tcp4Packet").finish()
370 }
371}
372
373#[derive(Debug)]
374#[repr(C)]
375pub struct Tcp4FragmentData {
376 /// Length of the fragment in bytes.
377 pub fragment_length: u32,
378 /// Pointer to an array of contiguous bytes, at least
379 /// `fragment_length` in length.
380 pub fragment_buf: *mut u8,
381}
382
383#[derive(Debug)]
384#[repr(C)]
385pub struct Tcp4ReceiveData {
386 /// When `TRUE`, the instance is in urgent mode. The
387 /// implementations of this specification should follow RFC793 to
388 /// process urgent data, and should NOT mix the data across the
389 /// urgent point in one token.
390 pub urgent: Boolean,
391 /// When calling [`receive`][Tcp4Protocol::receive], the caller
392 /// is responsible for setting it to the byte counts of all
393 /// fragment buffers. When the token is signaled by the driver
394 /// it is the length of received data in the fragments.
395 pub data_length: u32,
396 /// Number of fragments in the following fragment table.
397 pub fragment_count: u32,
398 /// Variable-length array of fragment descriptors.
399 ///
400 /// NOTE: this is a flexible array member.
401 pub fragment_table: [Tcp4FragmentData; 0],
402}
403
404#[derive(Debug)]
405#[repr(C)]
406pub struct Tcp4TransmitData {
407 /// If `TRUE`, data must be transmitted promptly, and the PUSH bit
408 /// in the last TCP segment created will be set. If `FALSE`, data
409 /// transmission may be delayed to combine with data from
410 /// subsequent [`transmit`][Tcp4Protocol::transmit] for
411 /// efficiency.
412 pub push: Boolean,
413 /// The data in the fragment table are urgent and urgent point is
414 /// in effect if `TRUE`. Otherwise those data are NOT considered
415 /// urgent.
416 pub urgent: Boolean,
417 /// Total length of data to transmit.
418 pub data_length: u32,
419 /// Number of fragments in the following fragment table.
420 pub fragment_count: u32,
421 /// Variable-length array of fragment descriptors.
422 ///
423 /// NOTE: this is a flexible array member.
424 pub fragment_table: [Tcp4FragmentData; 0],
425}
426
427#[derive(Debug)]
428#[repr(C)]
429pub struct Tcp4ClientConnectionModeParams {
430 /// Remote IP address for the connection.
431 pub remote_ip: Ipv4Address,
432 /// Remote port for the connection.
433 pub remote_port: u16,
434}