]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Tcp4Dxe/Tcp4Main.c
1. Add DPC protocol and DpcLib library in MdeModulePkg.
[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
36ee91ca 150// CpuBreakpoint ();\r
8a67d61d 151 if (NULL == This) {\r
152 return EFI_INVALID_PARAMETER;\r
153 }\r
154\r
155 //\r
156 // Tcp protocol related parameter check will be conducted here\r
157 //\r
158 if (NULL != TcpConfigData) {\r
772db4bb 159\r
160 NetCopyMem (&Ip, &TcpConfigData->AccessPoint.RemoteAddress, sizeof (IP4_ADDR));\r
161 if ((Ip != 0) && !Ip4IsUnicast (NTOHL (Ip), 0)) {\r
162 return EFI_INVALID_PARAMETER;\r
163 }\r
164\r
165 if (TcpConfigData->AccessPoint.ActiveFlag &&\r
166 (0 == TcpConfigData->AccessPoint.RemotePort || (Ip == 0))) {\r
8a67d61d 167 return EFI_INVALID_PARAMETER;\r
168 }\r
169\r
170 if (!TcpConfigData->AccessPoint.UseDefaultAddress) {\r
772db4bb 171\r
172 NetCopyMem (&Ip, &TcpConfigData->AccessPoint.StationAddress, sizeof (IP4_ADDR));\r
687a2e5f 173 NetCopyMem (&SubnetMask, &TcpConfigData->AccessPoint.SubnetMask, sizeof (IP4_ADDR));\r
174 if (!Ip4IsUnicast (NTOHL (Ip), 0) || !IP4_IS_VALID_NETMASK (NTOHL (SubnetMask))) {\r
8a67d61d 175 return EFI_INVALID_PARAMETER;\r
176 }\r
177 }\r
178\r
8a67d61d 179 Option = TcpConfigData->ControlOption;\r
180 if ((NULL != Option) &&\r
181 (Option->EnableSelectiveAck || Option->EnablePathMtuDiscovery)) {\r
182 return EFI_UNSUPPORTED;\r
183 }\r
184 }\r
185\r
186 Sock = SOCK_FROM_THIS (This);\r
187\r
188 if (NULL == TcpConfigData) {\r
189 return SockFlush (Sock);\r
190 }\r
191\r
192 Status = SockConfigure (Sock, TcpConfigData);\r
193\r
194 if (EFI_NO_MAPPING == Status) {\r
195 Sock->ConfigureState = SO_NO_MAPPING;\r
196 }\r
197\r
198 return Status;\r
199}\r
200\r
201\r
202/**\r
203 Add or delete routing entries.\r
204\r
205 @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
206 @param DeleteRoute If TRUE, delete the specified route from routing\r
207 table; if FALSE, add the specified route to\r
208 routing table.\r
209 @param SubnetAddress The destination network.\r
210 @param SubnetMask The subnet mask for the destination network.\r
211 @param GatewayAddress The gateway address for this route.\r
212\r
213 @retval EFI_SUCCESS The operation completed successfully.\r
214 @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance has not been\r
215 configured.\r
216 @retval EFI_NO_MAPPING When using a default address, configuration\r
217 (through DHCP, BOOTP, RARP, etc.) is not\r
218 finished.\r
219 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
220 @retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to add the\r
221 entry to the routing table.\r
222 @retval EFI_NOT_FOUND This route is not in the routing table.\r
223 @retval EFI_ACCESS_DENIED This route is already in the routing table.\r
224 @retval EFI_UNSUPPORTED The TCP driver does not support this operation.\r
225\r
226**/\r
227EFI_STATUS\r
228EFIAPI\r
229Tcp4Routes (\r
230 IN EFI_TCP4_PROTOCOL *This,\r
231 IN BOOLEAN DeleteRoute,\r
232 IN EFI_IPv4_ADDRESS *SubnetAddress,\r
233 IN EFI_IPv4_ADDRESS *SubnetMask,\r
234 IN EFI_IPv4_ADDRESS *GatewayAddress\r
235 )\r
236{\r
237 SOCKET *Sock;\r
238 TCP4_ROUTE_INFO RouteInfo;\r
239\r
240 if (NULL == This) {\r
241 return EFI_INVALID_PARAMETER;\r
242 }\r
243\r
244 Sock = SOCK_FROM_THIS (This);\r
245\r
246 RouteInfo.DeleteRoute = DeleteRoute;\r
247 RouteInfo.SubnetAddress = SubnetAddress;\r
248 RouteInfo.SubnetMask = SubnetMask;\r
249 RouteInfo.GatewayAddress = GatewayAddress;\r
250\r
251 return SockRoute (Sock, &RouteInfo);\r
252}\r
253\r
254\r
255/**\r
256 Initiate a nonblocking TCP connection request for an active TCP instance.\r
257\r
258 @param This Pointer to the EFI_TCP4_PROTOCOL instance\r
259 @param ConnectionToken Pointer to the connection token to return when\r
260 the TCP three way handshake finishes.\r
261\r
262 @retval EFI_SUCCESS The connection request is successfully\r
263 initiated.\r
264 @retval EFI_NOT_STARTED This EFI_TCP4_PROTOCOL instance hasn't been\r
265 configured.\r
266 @retval EFI_ACCESS_DENIED The instance is not configured as an active one\r
267 or it is not in Tcp4StateClosed state.\r
268 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
269 @retval EFI_OUT_OF_RESOURCES The driver can't allocate enough resource to\r
270 initiate the active open.\r
271 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
272\r
273**/\r
274EFI_STATUS\r
275EFIAPI\r
276Tcp4Connect (\r
277 IN EFI_TCP4_PROTOCOL *This,\r
278 IN EFI_TCP4_CONNECTION_TOKEN *ConnectionToken\r
279 )\r
280{\r
281 SOCKET *Sock;\r
282\r
283 if (NULL == This ||\r
284 NULL == ConnectionToken ||\r
285 NULL == ConnectionToken->CompletionToken.Event) {\r
286 return EFI_INVALID_PARAMETER;\r
287 }\r
288\r
289 Sock = SOCK_FROM_THIS (This);\r
290\r
291 return SockConnect (Sock, ConnectionToken);\r
292}\r
293\r
294\r
295/**\r
296 Listen on the passive instance to accept an incoming connection request.\r
297\r
298 @param This Pointer to the EFI_TCP4_PROTOCOL instance\r
299 @param ListenToken Pointer to the listen token to return when\r
300 operation finishes.\r
301\r
302 @retval EFI_SUCCESS The listen token has been queued successfully.\r
303 @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been\r
304 configured.\r
305 @retval EFI_ACCESS_DENIED The instatnce is not a passive one or it is not\r
306 in Tcp4StateListen state or a same listen token\r
307 has already existed in the listen token queue of\r
308 this TCP instance.\r
309 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
310 @retval EFI_OUT_OF_RESOURCES Could not allocate enough resources to finish\r
311 the operation.\r
312 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
313\r
314**/\r
315EFI_STATUS\r
316EFIAPI\r
317Tcp4Accept (\r
318 IN EFI_TCP4_PROTOCOL *This,\r
319 IN EFI_TCP4_LISTEN_TOKEN *ListenToken\r
320 )\r
321{\r
322 SOCKET *Sock;\r
323\r
324 if (NULL == This ||\r
325 NULL == ListenToken ||\r
326 NULL == ListenToken->CompletionToken.Event) {\r
327 return EFI_INVALID_PARAMETER;\r
328 }\r
329\r
330 Sock = SOCK_FROM_THIS (This);\r
331\r
332 return SockAccept (Sock, ListenToken);\r
333}\r
334\r
335\r
336/**\r
337 Queues outgoing data into the transmit queue\r
338\r
339 @param This Pointer to the EFI_TCP4_PROTOCOL instance\r
340 @param Token Pointer to the completion token to queue to the\r
341 transmit queue\r
342\r
343 @retval EFI_SUCCESS The data has been queued for transmission\r
344 @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been\r
345 configured.\r
346 @retval EFI_NO_MAPPING When using a default address, configuration\r
347 (DHCP, BOOTP, RARP, etc.) is not finished yet.\r
348 @retval EFI_INVALID_PARAMETER One or more parameters are invalid\r
349 @retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:\r
350 * A transmit completion token with the same\r
351 Token-> CompletionToken.Event was already in the\r
352 transmission queue. * The current instance is in\r
353 Tcp4StateClosed state * The current instance is\r
354 a passive one and it is in Tcp4StateListen\r
355 state. * User has called Close() to disconnect\r
356 this connection.\r
357 @retval EFI_NOT_READY The completion token could not be queued because\r
358 the transmit queue is full.\r
359 @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data because of\r
360 resource shortage.\r
361 @retval EFI_NETWORK_UNREACHABLE There is no route to the destination network or\r
362 address.\r
363\r
364**/\r
365EFI_STATUS\r
366EFIAPI\r
367Tcp4Transmit (\r
368 IN EFI_TCP4_PROTOCOL *This,\r
369 IN EFI_TCP4_IO_TOKEN *Token\r
370 )\r
371{\r
372 SOCKET *Sock;\r
373 EFI_STATUS Status;\r
374\r
375 if (NULL == This ||\r
376 NULL == Token ||\r
377 NULL == Token->CompletionToken.Event ||\r
378 NULL == Token->Packet.TxData ||\r
379 0 == Token->Packet.TxData->FragmentCount ||\r
380 0 == Token->Packet.TxData->DataLength\r
381 ) {\r
382 return EFI_INVALID_PARAMETER;\r
383 }\r
384\r
385 Status = Tcp4ChkDataBuf (\r
4eb65aff 386 (UINT32) Token->Packet.TxData->DataLength,\r
387 (UINT32) Token->Packet.TxData->FragmentCount,\r
8a67d61d 388 Token->Packet.TxData->FragmentTable\r
389 );\r
390 if (EFI_ERROR (Status)) {\r
391 return Status;\r
392 }\r
393\r
394 Sock = SOCK_FROM_THIS (This);\r
395\r
396 return SockSend (Sock, Token);\r
397\r
398}\r
399\r
400\r
401/**\r
402 Place an asynchronous receive request into the receiving queue.\r
403\r
404 @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
405 @param Token Pointer to a token that is associated with the\r
406 receive data descriptor.\r
407\r
408 @retval EFI_SUCCESS The receive completion token was cached\r
409 @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been\r
410 configured.\r
411 @retval EFI_NO_MAPPING When using a default address, configuration\r
412 (DHCP, BOOTP, RARP, etc.) is not finished yet.\r
413 @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
414 @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued\r
415 due to a lack of system resources.\r
416 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
417 @retval EFI_ACCESS_DENIED One or more of the following conditions is TRUE:\r
418 * A receive completion token with the same\r
419 Token->CompletionToken.Event was already in the\r
420 receive queue. * The current instance is in\r
421 Tcp4StateClosed state. * The current instance is\r
422 a passive one and it is in Tcp4StateListen\r
423 state. * User has called Close() to disconnect\r
424 this connection.\r
425 @retval EFI_CONNECTION_FIN The communication peer has closed the connection\r
426 and there is no any buffered data in the receive\r
427 buffer of this instance.\r
428 @retval EFI_NOT_READY The receive request could not be queued because\r
429 the receive queue is full.\r
430\r
431**/\r
432EFI_STATUS\r
433EFIAPI\r
434Tcp4Receive (\r
435 IN EFI_TCP4_PROTOCOL *This,\r
436 IN EFI_TCP4_IO_TOKEN *Token\r
437 )\r
438{\r
439 SOCKET *Sock;\r
440 EFI_STATUS Status;\r
441\r
442 if (NULL == This ||\r
443 NULL == Token ||\r
444 NULL == Token->CompletionToken.Event ||\r
445 NULL == Token->Packet.RxData ||\r
446 0 == Token->Packet.RxData->FragmentCount ||\r
447 0 == Token->Packet.RxData->DataLength\r
448 ) {\r
449 return EFI_INVALID_PARAMETER;\r
450 }\r
451\r
452 Status = Tcp4ChkDataBuf (\r
4eb65aff 453 (UINT32) Token->Packet.RxData->DataLength,\r
454 (UINT32) Token->Packet.RxData->FragmentCount,\r
8a67d61d 455 Token->Packet.RxData->FragmentTable\r
456 );\r
457 if (EFI_ERROR (Status)) {\r
458 return Status;\r
459 }\r
460\r
461 Sock = SOCK_FROM_THIS (This);\r
462\r
463 return SockRcv (Sock, Token);\r
464\r
465}\r
466\r
467\r
468/**\r
469 Disconnecting a TCP connection gracefully or reset a TCP connection.\r
470\r
471 @param This Pointer to the EFI_TCP4_PROTOCOL instance\r
472 @param CloseToken Pointer to the close token to return when\r
473 operation finishes.\r
474\r
475 @retval EFI_SUCCESS The operation completed successfully\r
476 @retval EFI_NOT_STARTED The EFI_TCP4_PROTOCOL instance hasn't been\r
477 configured.\r
478 @retval EFI_ACCESS_DENIED One or more of the following are TRUE: *\r
479 Configure() has been called with TcpConfigData\r
480 set to NULL and this function has not returned.\r
481 * Previous Close() call on this instance has not\r
482 finished.\r
483 @retval EFI_INVALID_PARAMETER One ore more parameters are invalid\r
484 @retval EFI_OUT_OF_RESOURCES Could not allocate enough resource to finish the\r
485 operation\r
486 @retval EFI_DEVICE_ERROR Any unexpected and not belonged to above\r
487 category error.\r
488\r
489**/\r
490EFI_STATUS\r
491EFIAPI\r
492Tcp4Close (\r
493 IN EFI_TCP4_PROTOCOL *This,\r
494 IN EFI_TCP4_CLOSE_TOKEN *CloseToken\r
495 )\r
496{\r
497 SOCKET *Sock;\r
498\r
499 if (NULL == This ||\r
500 NULL == CloseToken ||\r
501 NULL == CloseToken->CompletionToken.Event) {\r
502 return EFI_INVALID_PARAMETER;\r
503 }\r
504\r
505 Sock = SOCK_FROM_THIS (This);\r
506\r
507 return SockClose (Sock, CloseToken, CloseToken->AbortOnClose);\r
508}\r
509\r
510\r
511/**\r
512 Abort an asynchronous connection, listen, transmission or receive request.\r
513\r
514 @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
515 @param Token Pointer to a token that has been issued by\r
516 Connect(), Accept(), Transmit() or Receive(). If\r
517 NULL, all pending tokens issued by above four\r
518 functions will be aborted.\r
519\r
520 @retval EFI_UNSUPPORTED The operation is not supported in current\r
521 implementation.\r
522\r
523**/\r
524EFI_STATUS\r
525EFIAPI\r
526Tcp4Cancel (\r
527 IN EFI_TCP4_PROTOCOL * This,\r
528 IN EFI_TCP4_COMPLETION_TOKEN * Token OPTIONAL\r
529 )\r
530{\r
531 return EFI_UNSUPPORTED;\r
532}\r
533\r
534\r
535/**\r
536 Poll to receive incoming data and transmit outgoing segments.\r
537\r
538 @param This Pointer to the EFI_TCP4_PROTOCOL instance.\r
539\r
540 @retval EFI_SUCCESS Incoming or outgoing data was processed.\r
541 @retval EFI_INVALID_PARAMETER This is NULL.\r
542 @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r
543 @retval EFI_NOT_READY No incoming or outgoing data was processed.\r
544 @retval EFI_TIMEOUT Data was dropped out of the transmission or\r
545 receive queue. Consider increasing the polling\r
546 rate.\r
547\r
548**/\r
549EFI_STATUS\r
550EFIAPI\r
551Tcp4Poll (\r
552 IN EFI_TCP4_PROTOCOL *This\r
553 )\r
554{\r
555 SOCKET *Sock;\r
556 EFI_STATUS Status;\r
557\r
558 if (NULL == This) {\r
559 return EFI_INVALID_PARAMETER;\r
560 }\r
561\r
562 Sock = SOCK_FROM_THIS (This);\r
563\r
564 Status = Sock->ProtoHandler (Sock, SOCK_POLL, NULL);\r
565\r
566 return Status;\r
567}\r