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