cbf9c0aa2f9cec344000b65aeda6b0d7e68849a5
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / Tcp4Main.c
1 /** @file
2
3 Copyright (c) 2005 - 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13
14 Tcp4Main.c
15
16 Abstract:
17
18 Implementation of TCP4 protocol services.
19
20
21 **/
22
23 #include "Tcp4Main.h"
24
25
26 /**
27 Check the integrity of the data buffer.
28
29 @param DataLen The total length of the data buffer.
30 @param FragmentCount The fragment count of the fragment table.
31 @param FragmentTable Pointer to the fragment table of the data
32 buffer.
33
34 @retval EFI_SUCCESS The integrity check is passed.
35 @retval EFI_INVALID_PARAMETER The integrity check is failed.
36
37 **/
38 STATIC
39 EFI_STATUS
40 Tcp4ChkDataBuf (
41 IN UINT32 DataLen,
42 IN UINT32 FragmentCount,
43 IN EFI_TCP4_FRAGMENT_DATA *FragmentTable
44 )
45 {
46 UINT32 Index;
47
48 UINT32 Len;
49
50 for (Index = 0, Len = 0; Index < FragmentCount; Index++) {
51 Len = Len + (UINT32) FragmentTable[Index].FragmentLength;
52 }
53
54 if (DataLen != Len) {
55 return EFI_INVALID_PARAMETER;
56 }
57
58 return EFI_SUCCESS;
59 }
60
61
62 /**
63 Get the current operational status.
64
65 @param This Pointer to the EFI_TCP4_PROTOCOL instance.
66 @param Tcp4State Pointer to the buffer to receive the current TCP
67 state.
68 @param Tcp4ConfigData Pointer to the buffer to receive the current TCP
69 configuration.
70 @param Ip4ModeData Pointer to the buffer to receive the current
71 IPv4 configuration.
72 @param MnpConfigData Pointer to the buffer to receive the current MNP
73 configuration data indirectly used by the TCPv4
74 Instance.
75 @param SnpModeData Pointer to the buffer to receive the current SNP
76 configuration data indirectly used by the TCPv4
77 Instance.
78
79 @retval EFI_SUCCESS The mode data was read.
80 @retval EFI_NOT_STARTED No configuration data is available because this
81 instance hasn't been started.
82 @retval EFI_INVALID_PARAMETER This is NULL.
83
84 **/
85 EFI_STATUS
86 EFIAPI
87 Tcp4GetModeData (
88 IN CONST EFI_TCP4_PROTOCOL * This,
89 OUT EFI_TCP4_CONNECTION_STATE * Tcp4State OPTIONAL,
90 OUT EFI_TCP4_CONFIG_DATA * Tcp4ConfigData OPTIONAL,
91 OUT EFI_IP4_MODE_DATA * Ip4ModeData OPTIONAL,
92 OUT EFI_MANAGED_NETWORK_CONFIG_DATA * MnpConfigData OPTIONAL,
93 OUT EFI_SIMPLE_NETWORK_MODE * SnpModeData OPTIONAL
94 )
95 {
96 TCP4_MODE_DATA TcpMode;
97 SOCKET *Sock;
98
99 if (NULL == This) {
100 return EFI_INVALID_PARAMETER;
101 }
102
103 Sock = SOCK_FROM_THIS (This);
104
105 TcpMode.Tcp4State = Tcp4State;
106 TcpMode.Tcp4ConfigData = Tcp4ConfigData;
107 TcpMode.Ip4ModeData = Ip4ModeData;
108 TcpMode.MnpConfigData = MnpConfigData;
109 TcpMode.SnpModeData = SnpModeData;
110
111 return SockGetMode (Sock, &TcpMode);
112 }
113
114
115 /**
116 Initialize or brutally reset the operational parameters for
117 this EFI TCPv4 instance.
118
119 @param This Pointer to the EFI_TCP4_PROTOCOL instance.
120 @param TcpConfigData Pointer to the configure data to configure the
121 instance.
122
123 @retval EFI_SUCCESS The operational settings are set, changed, or
124 reset successfully.
125 @retval EFI_NO_MAPPING When using a default address, configuration
126 (through DHCP, BOOTP, RARP, etc.) is not
127 finished.
128 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
129 @retval EFI_ACCESS_DENIED Configuring TCP instance when it is already
130 configured.
131 @retval EFI_DEVICE_ERROR An unexpected network or system error occurred.
132 @retval EFI_UNSUPPORTED One or more of the control options are not
133 supported in the implementation.
134 @retval EFI_OUT_OF_RESOURCES Could not allocate enough system resources.
135
136 **/
137 EFI_STATUS
138 EFIAPI
139 Tcp4Configure (
140 IN EFI_TCP4_PROTOCOL * This,
141 IN EFI_TCP4_CONFIG_DATA * TcpConfigData OPTIONAL
142 )
143 {
144 EFI_TCP4_OPTION *Option;
145 SOCKET *Sock;
146 EFI_STATUS Status;
147 IP4_ADDR Ip;
148 IP4_ADDR SubnetMask;
149
150 // CpuBreakpoint ();
151 if (NULL == This) {
152 return EFI_INVALID_PARAMETER;
153 }
154
155 //
156 // Tcp protocol related parameter check will be conducted here
157 //
158 if (NULL != TcpConfigData) {
159
160 NetCopyMem (&Ip, &TcpConfigData->AccessPoint.RemoteAddress, sizeof (IP4_ADDR));
161 if ((Ip != 0) && !Ip4IsUnicast (NTOHL (Ip), 0)) {
162 return EFI_INVALID_PARAMETER;
163 }
164
165 if (TcpConfigData->AccessPoint.ActiveFlag &&
166 (0 == TcpConfigData->AccessPoint.RemotePort || (Ip == 0))) {
167 return EFI_INVALID_PARAMETER;
168 }
169
170 if (!TcpConfigData->AccessPoint.UseDefaultAddress) {
171
172 NetCopyMem (&Ip, &TcpConfigData->AccessPoint.StationAddress, sizeof (IP4_ADDR));
173 NetCopyMem (&SubnetMask, &TcpConfigData->AccessPoint.SubnetMask, sizeof (IP4_ADDR));
174 if (!Ip4IsUnicast (NTOHL (Ip), 0) || !IP4_IS_VALID_NETMASK (NTOHL (SubnetMask))) {
175 return EFI_INVALID_PARAMETER;
176 }
177 }
178
179 Option = TcpConfigData->ControlOption;
180 if ((NULL != Option) &&
181 (Option->EnableSelectiveAck || Option->EnablePathMtuDiscovery)) {
182 return EFI_UNSUPPORTED;
183 }
184 }
185
186 Sock = SOCK_FROM_THIS (This);
187
188 if (NULL == TcpConfigData) {
189 return SockFlush (Sock);
190 }
191
192 Status = SockConfigure (Sock, TcpConfigData);
193
194 if (EFI_NO_MAPPING == Status) {
195 Sock->ConfigureState = SO_NO_MAPPING;
196 }
197
198 return Status;
199 }
200
201
202 /**
203 Add or delete routing entries.
204
205 @param This Pointer to the EFI_TCP4_PROTOCOL instance.
206 @param DeleteRoute If TRUE, delete the specified route from routing
207 table; if FALSE, add the specified route to
208 routing table.
209 @param SubnetAddress The destination network.
210 @param SubnetMask The subnet mask for the destination network.
211 @param GatewayAddress The gateway address for this route.
212
213 @retval EFI_SUCCESS The operation completed successfully.
214 @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance has not been
215 configured.
216 @retval EFI_NO_MAPPING When using a default address, configuration
217 (through DHCP, BOOTP, RARP, etc.) is not
218 finished.
219 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
220 @retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to add the
221 entry to the routing table.
222 @retval EFI_NOT_FOUND This route is not in the routing table.
223 @retval EFI_ACCESS_DENIED This route is already in the routing table.
224 @retval EFI_UNSUPPORTED The TCP driver does not support this operation.
225
226 **/
227 EFI_STATUS
228 EFIAPI
229 Tcp4Routes (
230 IN EFI_TCP4_PROTOCOL *This,
231 IN BOOLEAN DeleteRoute,
232 IN EFI_IPv4_ADDRESS *SubnetAddress,
233 IN EFI_IPv4_ADDRESS *SubnetMask,
234 IN EFI_IPv4_ADDRESS *GatewayAddress
235 )
236 {
237 SOCKET *Sock;
238 TCP4_ROUTE_INFO RouteInfo;
239
240 if (NULL == This) {
241 return EFI_INVALID_PARAMETER;
242 }
243
244 Sock = SOCK_FROM_THIS (This);
245
246 RouteInfo.DeleteRoute = DeleteRoute;
247 RouteInfo.SubnetAddress = SubnetAddress;
248 RouteInfo.SubnetMask = SubnetMask;
249 RouteInfo.GatewayAddress = GatewayAddress;
250
251 return SockRoute (Sock, &RouteInfo);
252 }
253
254
255 /**
256 Initiate a nonblocking TCP connection request for an active TCP instance.
257
258 @param This Pointer to the EFI_TCP4_PROTOCOL instance
259 @param ConnectionToken Pointer to the connection token to return when
260 the TCP three way handshake finishes.
261
262 @retval EFI_SUCCESS The connection request is successfully
263 initiated.
264 @retval EFI_NOT_STARTED This EFI_TCP4_PROTOCOL instance hasn't been
265 configured.
266 @retval EFI_ACCESS_DENIED The instance is not configured as an active one
267 or it is not in Tcp4StateClosed state.
268 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
269 @retval EFI_OUT_OF_RESOURCES The driver can't allocate enough resource to
270 initiate the active open.
271 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
272
273 **/
274 EFI_STATUS
275 EFIAPI
276 Tcp4Connect (
277 IN EFI_TCP4_PROTOCOL *This,
278 IN EFI_TCP4_CONNECTION_TOKEN *ConnectionToken
279 )
280 {
281 SOCKET *Sock;
282
283 if (NULL == This ||
284 NULL == ConnectionToken ||
285 NULL == ConnectionToken->CompletionToken.Event) {
286 return EFI_INVALID_PARAMETER;
287 }
288
289 Sock = SOCK_FROM_THIS (This);
290
291 return SockConnect (Sock, ConnectionToken);
292 }
293
294
295 /**
296 Listen on the passive instance to accept an incoming connection request.
297
298 @param This Pointer to the EFI_TCP4_PROTOCOL instance
299 @param ListenToken Pointer to the listen token to return when
300 operation finishes.
301
302 @retval EFI_SUCCESS The listen token has been queued successfully.
303 @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
304 configured.
305 @retval EFI_ACCESS_DENIED The instatnce is not a passive one or it is not
306 in Tcp4StateListen state or a same listen token
307 has already existed in the listen token queue of
308 this TCP instance.
309 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
310 @retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to finish
311 the operation.
312 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
313
314 **/
315 EFI_STATUS
316 EFIAPI
317 Tcp4Accept (
318 IN EFI_TCP4_PROTOCOL *This,
319 IN EFI_TCP4_LISTEN_TOKEN *ListenToken
320 )
321 {
322 SOCKET *Sock;
323
324 if (NULL == This ||
325 NULL == ListenToken ||
326 NULL == ListenToken->CompletionToken.Event) {
327 return EFI_INVALID_PARAMETER;
328 }
329
330 Sock = SOCK_FROM_THIS (This);
331
332 return SockAccept (Sock, ListenToken);
333 }
334
335
336 /**
337 Queues outgoing data into the transmit queue
338
339 @param This Pointer to the EFI_TCP4_PROTOCOL instance
340 @param Token Pointer to the completion token to queue to the
341 transmit queue
342
343 @retval EFI_SUCCESS The data has been queued for transmission
344 @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
345 configured.
346 @retval EFI_NO_MAPPING When using a default address, configuration
347 (DHCP, BOOTP, RARP, etc.) is not finished yet.
348 @retval EFI_INVALID_PARAMETER One or more parameters are invalid
349 @retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:
350 * A transmit completion token with the same
351 Token-> CompletionToken.Event was already in the
352 transmission queue. * The current instance is in
353 Tcp4StateClosed state * The current instance is
354 a passive one and it is in Tcp4StateListen
355 state. * User has called Close() to disconnect
356 this connection.
357 @retval EFI_NOT_READY The completion token could not be queued because
358 the transmit queue is full.
359 @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data because of
360 resource shortage.
361 @retval EFI_NETWORK_UNREACHABLE There is no route to the destination network or
362 address.
363
364 **/
365 EFI_STATUS
366 EFIAPI
367 Tcp4Transmit (
368 IN EFI_TCP4_PROTOCOL *This,
369 IN EFI_TCP4_IO_TOKEN *Token
370 )
371 {
372 SOCKET *Sock;
373 EFI_STATUS Status;
374
375 if (NULL == This ||
376 NULL == Token ||
377 NULL == Token->CompletionToken.Event ||
378 NULL == Token->Packet.TxData ||
379 0 == Token->Packet.TxData->FragmentCount ||
380 0 == Token->Packet.TxData->DataLength
381 ) {
382 return EFI_INVALID_PARAMETER;
383 }
384
385 Status = Tcp4ChkDataBuf (
386 (UINT32) Token->Packet.TxData->DataLength,
387 (UINT32) Token->Packet.TxData->FragmentCount,
388 Token->Packet.TxData->FragmentTable
389 );
390 if (EFI_ERROR (Status)) {
391 return Status;
392 }
393
394 Sock = SOCK_FROM_THIS (This);
395
396 return SockSend (Sock, Token);
397
398 }
399
400
401 /**
402 Place an asynchronous receive request into the receiving queue.
403
404 @param This Pointer to the EFI_TCP4_PROTOCOL instance.
405 @param Token Pointer to a token that is associated with the
406 receive data descriptor.
407
408 @retval EFI_SUCCESS The receive completion token was cached
409 @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
410 configured.
411 @retval EFI_NO_MAPPING When using a default address, configuration
412 (DHCP, BOOTP, RARP, etc.) is not finished yet.
413 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
414 @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued
415 due to a lack of system resources.
416 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
417 @retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:
418 * A receive completion token with the same
419 Token->CompletionToken.Event was already in the
420 receive queue. * The current instance is in
421 Tcp4StateClosed state. * The current instance is
422 a passive one and it is in Tcp4StateListen
423 state. * User has called Close() to disconnect
424 this connection.
425 @retval EFI_CONNECTION_FIN The communication peer has closed the connection
426 and there is no any buffered data in the receive
427 buffer of this instance.
428 @retval EFI_NOT_READY The receive request could not be queued because
429 the receive queue is full.
430
431 **/
432 EFI_STATUS
433 EFIAPI
434 Tcp4Receive (
435 IN EFI_TCP4_PROTOCOL *This,
436 IN EFI_TCP4_IO_TOKEN *Token
437 )
438 {
439 SOCKET *Sock;
440 EFI_STATUS Status;
441
442 if (NULL == This ||
443 NULL == Token ||
444 NULL == Token->CompletionToken.Event ||
445 NULL == Token->Packet.RxData ||
446 0 == Token->Packet.RxData->FragmentCount ||
447 0 == Token->Packet.RxData->DataLength
448 ) {
449 return EFI_INVALID_PARAMETER;
450 }
451
452 Status = Tcp4ChkDataBuf (
453 (UINT32) Token->Packet.RxData->DataLength,
454 (UINT32) Token->Packet.RxData->FragmentCount,
455 Token->Packet.RxData->FragmentTable
456 );
457 if (EFI_ERROR (Status)) {
458 return Status;
459 }
460
461 Sock = SOCK_FROM_THIS (This);
462
463 return SockRcv (Sock, Token);
464
465 }
466
467
468 /**
469 Disconnecting a TCP connection gracefully or reset a TCP connection.
470
471 @param This Pointer to the EFI_TCP4_PROTOCOL instance
472 @param CloseToken Pointer to the close token to return when
473 operation finishes.
474
475 @retval EFI_SUCCESS The operation completed successfully
476 @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been
477 configured.
478 @retval EFI_ACCESS_DENIED One or more of the following are TRUE: *
479 Configure() has been called with TcpConfigData
480 set to NULL and this function has not returned.
481 * Previous Close() call on this instance has not
482 finished.
483 @retval EFI_INVALID_PARAMETER One ore more parameters are invalid
484 @retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the
485 operation
486 @retval EFI_DEVICE_ERROR Any unexpected and not belonged to above
487 category error.
488
489 **/
490 EFI_STATUS
491 EFIAPI
492 Tcp4Close (
493 IN EFI_TCP4_PROTOCOL *This,
494 IN EFI_TCP4_CLOSE_TOKEN *CloseToken
495 )
496 {
497 SOCKET *Sock;
498
499 if (NULL == This ||
500 NULL == CloseToken ||
501 NULL == CloseToken->CompletionToken.Event) {
502 return EFI_INVALID_PARAMETER;
503 }
504
505 Sock = SOCK_FROM_THIS (This);
506
507 return SockClose (Sock, CloseToken, CloseToken->AbortOnClose);
508 }
509
510
511 /**
512 Abort an asynchronous connection, listen, transmission or receive request.
513
514 @param This Pointer to the EFI_TCP4_PROTOCOL instance.
515 @param Token Pointer to a token that has been issued by
516 Connect(), Accept(), Transmit() or Receive(). If
517 NULL, all pending tokens issued by above four
518 functions will be aborted.
519
520 @retval EFI_UNSUPPORTED The operation is not supported in current
521 implementation.
522
523 **/
524 EFI_STATUS
525 EFIAPI
526 Tcp4Cancel (
527 IN EFI_TCP4_PROTOCOL * This,
528 IN EFI_TCP4_COMPLETION_TOKEN * Token OPTIONAL
529 )
530 {
531 return EFI_UNSUPPORTED;
532 }
533
534
535 /**
536 Poll to receive incoming data and transmit outgoing segments.
537
538 @param This Pointer to the EFI_TCP4_PROTOCOL instance.
539
540 @retval EFI_SUCCESS Incoming or outgoing data was processed.
541 @retval EFI_INVALID_PARAMETER This is NULL.
542 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
543 @retval EFI_NOT_READY No incoming or outgoing data was processed.
544 @retval EFI_TIMEOUT Data was dropped out of the transmission or
545 receive queue. Consider increasing the polling
546 rate.
547
548 **/
549 EFI_STATUS
550 EFIAPI
551 Tcp4Poll (
552 IN EFI_TCP4_PROTOCOL *This
553 )
554 {
555 SOCKET *Sock;
556 EFI_STATUS Status;
557
558 if (NULL == This) {
559 return EFI_INVALID_PARAMETER;
560 }
561
562 Sock = SOCK_FROM_THIS (This);
563
564 Status = Sock->ProtoHandler (Sock, SOCK_POLL, NULL);
565
566 return Status;
567 }