]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Tcp4Dxe/SockInterface.c
fixed potential NULL pointer reference issue.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Tcp4Dxe / SockInterface.c
CommitLineData
8a67d61d 1/** @file\r
2\r
dfc1f033 3Copyright (c) 2005 - 2006, Intel Corporation<BR>\r
8a67d61d 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
dfc1f033 7http://opensource.org/licenses/bsd-license.php<BR>\r
8a67d61d 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
8a67d61d 12**/\r
13\r
14\r
15#include "SockImpl.h"\r
16\r
17\r
18/**\r
19 Check whether the Event is in the List.\r
20\r
21 @param List Pointer to the token list to be searched.\r
22 @param Event The event to be checked.\r
23\r
120db52c 24 @retval TRUE The specific Event exists in the List. \r
25 @retval False The specific Event is not in the List.\r
8a67d61d 26\r
27**/\r
8a67d61d 28BOOLEAN\r
29SockTokenExistedInList (\r
e48e37fc 30 IN LIST_ENTRY *List,\r
8a67d61d 31 IN EFI_EVENT Event\r
32 )\r
33{\r
e48e37fc 34 LIST_ENTRY *ListEntry;\r
8a67d61d 35 SOCK_TOKEN *SockToken;\r
36\r
37 NET_LIST_FOR_EACH (ListEntry, List) {\r
38 SockToken = NET_LIST_USER_STRUCT (\r
39 ListEntry,\r
40 SOCK_TOKEN,\r
41 TokenList\r
42 );\r
43\r
44 if (Event == SockToken->Token->Event) {\r
45 return TRUE;\r
46 }\r
47 }\r
48\r
49 return FALSE;\r
50}\r
51\r
52\r
53/**\r
54 Call SockTokenExistedInList() to check whether the Event is\r
55 in the related socket's lists.\r
56\r
57 @param Sock Pointer to the instance's socket.\r
58 @param Event The event to be checked.\r
59\r
60 @return The specific Event exists in one of socket's lists or not.\r
61\r
62**/\r
63BOOLEAN\r
64SockTokenExisted (\r
65 IN SOCKET *Sock,\r
66 IN EFI_EVENT Event\r
67 )\r
68{\r
69\r
70 if (SockTokenExistedInList (&Sock->SndTokenList, Event) ||\r
71 SockTokenExistedInList (&Sock->ProcessingSndTokenList, Event) ||\r
72 SockTokenExistedInList (&Sock->RcvTokenList, Event) ||\r
120db52c 73 SockTokenExistedInList (&Sock->ListenTokenList, Event)) {\r
8a67d61d 74\r
75 return TRUE;\r
76 }\r
77\r
78 if ((Sock->ConnectionToken != NULL) &&\r
79 (Sock->ConnectionToken->Event == Event)) {\r
80\r
81 return TRUE;\r
82 }\r
83\r
84 if ((Sock->CloseToken != NULL) && (Sock->CloseToken->Event == Event)) {\r
85 return TRUE;\r
86 }\r
87\r
88 return FALSE;\r
89}\r
90\r
91\r
92/**\r
93 Buffer a token into the specific list of socket Sock.\r
94\r
95 @param Sock Pointer to the instance's socket.\r
96 @param List Pointer to the list to store the token.\r
97 @param Token Pointer to the token to be buffered.\r
98 @param DataLen The data length of the buffer contained in Token.\r
99\r
100 @return Pointer to the token that wraps Token. If NULL, error condition occurred.\r
101\r
102**/\r
103SOCK_TOKEN *\r
104SockBufferToken (\r
105 IN SOCKET *Sock,\r
e48e37fc 106 IN LIST_ENTRY *List,\r
8a67d61d 107 IN VOID *Token,\r
108 IN UINT32 DataLen\r
109 )\r
110{\r
111 SOCK_TOKEN *SockToken;\r
112\r
e48e37fc 113 SockToken = AllocatePool (sizeof (SOCK_TOKEN));\r
8a67d61d 114 if (NULL == SockToken) {\r
115\r
e48e37fc 116 DEBUG ((EFI_D_ERROR, "SockBufferIOToken: No Memory "\r
8a67d61d 117 "to allocate SockToken\n"));\r
118\r
119 return NULL;\r
120 }\r
121\r
122 SockToken->Sock = Sock;\r
123 SockToken->Token = (SOCK_COMPLETION_TOKEN *) Token;\r
124 SockToken->RemainDataLen = DataLen;\r
e48e37fc 125 InsertTailList (List, &SockToken->TokenList);\r
8a67d61d 126\r
127 return SockToken;\r
128}\r
129\r
130\r
131/**\r
132 Destory the socket Sock and its associated protocol control block.\r
133\r
134 @param Sock The socket to be destroyed.\r
135\r
136 @retval EFI_SUCCESS The socket Sock is destroyed successfully.\r
137 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
138\r
139**/\r
140EFI_STATUS\r
141SockDestroyChild (\r
142 IN SOCKET *Sock\r
143 )\r
144{\r
145 EFI_STATUS Status;\r
146\r
120db52c 147 ASSERT ((Sock != NULL) && (Sock->ProtoHandler != NULL));\r
8a67d61d 148\r
149 if (Sock->IsDestroyed) {\r
150 return EFI_SUCCESS;\r
151 }\r
152\r
153 Sock->IsDestroyed = TRUE;\r
154\r
e48e37fc 155 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 156 if (EFI_ERROR (Status)) {\r
157\r
e48e37fc 158 DEBUG ((EFI_D_ERROR, "SockDestroyChild: Get the lock to "\r
8a67d61d 159 "access socket failed with %r\n", Status));\r
160\r
161 return EFI_ACCESS_DENIED;\r
162 }\r
163\r
164 //\r
165 // force protocol layer to detach the PCB\r
166 //\r
167 Status = Sock->ProtoHandler (Sock, SOCK_DETACH, NULL);\r
168\r
169 if (EFI_ERROR (Status)) {\r
170\r
e48e37fc 171 DEBUG ((EFI_D_ERROR, "SockDestroyChild: Protocol detach socket"\r
8a67d61d 172 " failed with %r\n", Status));\r
173\r
174 Sock->IsDestroyed = FALSE;\r
175 } else if (SOCK_IS_CONFIGURED (Sock)) {\r
176\r
177 SockConnFlush (Sock);\r
178 SockSetState (Sock, SO_CLOSED);\r
179\r
180 Sock->ConfigureState = SO_UNCONFIGURED;\r
181 }\r
182\r
e48e37fc 183 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 184\r
185 if (EFI_ERROR (Status)) {\r
186 return Status;\r
187 }\r
188\r
189 SockDestroy (Sock);\r
190 return EFI_SUCCESS;\r
191}\r
192\r
193\r
194/**\r
195 Create a socket and its associated protocol control block\r
196 with the intial data SockInitData and protocol specific\r
197 data ProtoData.\r
198\r
199 @param SockInitData Inital data to setting the socket.\r
85511ddf 200 \r
8a67d61d 201 @return Pointer to the newly created socket. If NULL, error condition occured.\r
202\r
203**/\r
204SOCKET *\r
205SockCreateChild (\r
4f6e31e4 206 IN SOCK_INIT_DATA *SockInitData\r
8a67d61d 207 )\r
208{\r
209 SOCKET *Sock;\r
210 EFI_STATUS Status;\r
211\r
8a67d61d 212 //\r
213 // create a new socket\r
214 //\r
215 Sock = SockCreate (SockInitData);\r
216 if (NULL == Sock) {\r
217\r
e48e37fc 218 DEBUG ((EFI_D_ERROR, "SockCreateChild: No resource to "\r
8a67d61d 219 "create a new socket\n"));\r
220\r
221 return NULL;\r
222 }\r
223\r
e48e37fc 224 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 225 if (EFI_ERROR (Status)) {\r
226\r
e48e37fc 227 DEBUG ((EFI_D_ERROR, "SockCreateChild: Get the lock to "\r
8a67d61d 228 "access socket failed with %r\n", Status));\r
229\r
230 SockDestroy (Sock);\r
231 return NULL;\r
232 }\r
233 //\r
234 // inform the protocol layer to attach the socket\r
235 // with a new protocol control block\r
236 //\r
237 Status = Sock->ProtoHandler (Sock, SOCK_ATTACH, NULL);\r
238 if (EFI_ERROR (Status)) {\r
239\r
e48e37fc 240 DEBUG ((EFI_D_ERROR, "SockCreateChild: Protocol failed to"\r
8a67d61d 241 " attach a socket with %r\n", Status));\r
242\r
243 SockDestroy (Sock);\r
244 Sock = NULL;\r
245 }\r
246\r
e48e37fc 247 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 248 return Sock;\r
249}\r
250\r
251\r
252/**\r
120db52c 253 Configure the specific socket Sock using configuration data ConfigData.\r
8a67d61d 254\r
255 @param Sock Pointer to the socket to be configured.\r
256 @param ConfigData Pointer to the configuration data.\r
257\r
258 @retval EFI_SUCCESS The socket is configured successfully.\r
259 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket or the\r
260 socket is already configured.\r
261\r
262**/\r
263EFI_STATUS\r
264SockConfigure (\r
265 IN SOCKET *Sock,\r
266 IN VOID *ConfigData\r
267 )\r
268{\r
269 EFI_STATUS Status;\r
270\r
e48e37fc 271 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 272 if (EFI_ERROR (Status)) {\r
273\r
e48e37fc 274 DEBUG ((EFI_D_ERROR, "SockConfigure: Get the access for "\r
8a67d61d 275 "socket failed with %r", Status));\r
276\r
277 return EFI_ACCESS_DENIED;\r
278 }\r
279\r
280 if (SOCK_IS_CONFIGURED (Sock)) {\r
281 Status = EFI_ACCESS_DENIED;\r
282 goto OnExit;\r
283 }\r
284\r
285 ASSERT (Sock->State == SO_CLOSED);\r
286\r
287 Status = Sock->ProtoHandler (Sock, SOCK_CONFIGURE, ConfigData);\r
288\r
289OnExit:\r
e48e37fc 290 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 291\r
292 return Status;\r
293}\r
294\r
295\r
296/**\r
297 Initiate a connection establishment process.\r
298\r
299 @param Sock Pointer to the socket to initiate the initate the\r
300 connection.\r
301 @param Token Pointer to the token used for the connection\r
302 operation.\r
303\r
304 @retval EFI_SUCCESS The connection is initialized successfully.\r
305 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
306 socket is closed, or the socket is not configured to\r
307 be an active one, or the token is already in one of\r
308 this socket's lists.\r
309 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
310 finished.\r
311 @retval EFI_NOT_STARTED The socket is not configured.\r
312\r
313**/\r
314EFI_STATUS\r
315SockConnect (\r
316 IN SOCKET *Sock,\r
317 IN VOID *Token\r
318 )\r
319{\r
320 EFI_STATUS Status;\r
321 EFI_EVENT Event;\r
322\r
e48e37fc 323 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 324 if (EFI_ERROR (Status)) {\r
325\r
e48e37fc 326 DEBUG ((EFI_D_ERROR, "SockConnect: Get the access for "\r
8a67d61d 327 "socket failed with %r", Status));\r
328\r
329 return EFI_ACCESS_DENIED;\r
330 }\r
331\r
332 if (SOCK_IS_NO_MAPPING (Sock)) {\r
333 Status = EFI_NO_MAPPING;\r
334 goto OnExit;\r
335 }\r
336\r
337 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
338\r
339 Status = EFI_NOT_STARTED;\r
340 goto OnExit;\r
341 }\r
342\r
343 if (!SOCK_IS_CLOSED (Sock) || !SOCK_IS_CONFIGURED_ACTIVE (Sock)) {\r
344\r
345 Status = EFI_ACCESS_DENIED;\r
346 goto OnExit;\r
347 }\r
348\r
349 Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;\r
350\r
351 if (SockTokenExisted (Sock, Event)) {\r
352\r
353 Status = EFI_ACCESS_DENIED;\r
354 goto OnExit;\r
355 }\r
356\r
357 Sock->ConnectionToken = (SOCK_COMPLETION_TOKEN *) Token;\r
358 SockSetState (Sock, SO_CONNECTING);\r
359 Status = Sock->ProtoHandler (Sock, SOCK_CONNECT, NULL);\r
360\r
361OnExit:\r
e48e37fc 362 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 363 return Status;\r
364}\r
365\r
366\r
367/**\r
368 Issue a listen token to get an existed connected network instance\r
369 or wait for a connection if there is none.\r
370\r
371 @param Sock Pointer to the socket to accept connections.\r
372 @param Token The token to accept a connection.\r
373\r
374 @retval EFI_SUCCESS Either a connection is accpeted or the Token is\r
375 buffered for further acception.\r
376 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
377 socket is closed, or the socket is not configured to\r
378 be a passive one, or the token is already in one of\r
379 this socket's lists.\r
380 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
381 finished.\r
382 @retval EFI_NOT_STARTED The socket is not configured.\r
383 @retval EFI_OUT_OF_RESOURCE Failed to buffer the Token due to memory limit.\r
384\r
385**/\r
386EFI_STATUS\r
387SockAccept (\r
388 IN SOCKET *Sock,\r
389 IN VOID *Token\r
390 )\r
391{\r
392 EFI_TCP4_LISTEN_TOKEN *ListenToken;\r
e48e37fc 393 LIST_ENTRY *ListEntry;\r
8a67d61d 394 EFI_STATUS Status;\r
395 SOCKET *Socket;\r
396 EFI_EVENT Event;\r
397\r
398 ASSERT (SOCK_STREAM == Sock->Type);\r
399\r
e48e37fc 400 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 401 if (EFI_ERROR (Status)) {\r
402\r
e48e37fc 403 DEBUG ((EFI_D_ERROR, "SockAccept: Get the access for socket"\r
8a67d61d 404 " failed with %r", Status));\r
405\r
406 return EFI_ACCESS_DENIED;\r
407 }\r
408\r
409 if (SOCK_IS_NO_MAPPING (Sock)) {\r
410 Status = EFI_NO_MAPPING;\r
411 goto Exit;\r
412 }\r
413\r
414 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
415\r
416 Status = EFI_NOT_STARTED;\r
417 goto Exit;\r
418 }\r
419\r
420 if (!SOCK_IS_LISTENING (Sock)) {\r
421\r
422 Status = EFI_ACCESS_DENIED;\r
423 goto Exit;\r
424 }\r
425\r
426 Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;\r
427\r
428 if (SockTokenExisted (Sock, Event)) {\r
429\r
430 Status = EFI_ACCESS_DENIED;\r
431 goto Exit;\r
432 }\r
433\r
434 ListenToken = (EFI_TCP4_LISTEN_TOKEN *) Token;\r
435\r
436 //\r
437 // Check if a connection has already in this Sock->ConnectionList\r
438 //\r
439 NET_LIST_FOR_EACH (ListEntry, &Sock->ConnectionList) {\r
440\r
441 Socket = NET_LIST_USER_STRUCT (ListEntry, SOCKET, ConnectionList);\r
442\r
443 if (SOCK_IS_CONNECTED (Socket)) {\r
444 ListenToken->NewChildHandle = Socket->SockHandle;\r
445 SIGNAL_TOKEN (&(ListenToken->CompletionToken), EFI_SUCCESS);\r
446\r
e48e37fc 447 RemoveEntryList (ListEntry);\r
8a67d61d 448\r
120db52c 449 ASSERT (Socket->Parent != NULL);\r
8a67d61d 450\r
451 Socket->Parent->ConnCnt--;\r
452\r
e48e37fc 453 DEBUG (\r
dfc1f033 454 (EFI_D_INFO,\r
e48e37fc 455 "SockAccept: Accept a socket, now conncount is %d",\r
456 Socket->Parent->ConnCnt)\r
8a67d61d 457 );\r
458 Socket->Parent = NULL;\r
459\r
460 goto Exit;\r
461 }\r
462 }\r
463\r
464 //\r
465 // Buffer this token for latter incoming connection request\r
466 //\r
467 if (NULL == SockBufferToken (Sock, &(Sock->ListenTokenList), Token, 0)) {\r
468\r
469 Status = EFI_OUT_OF_RESOURCES;\r
470 }\r
471\r
472Exit:\r
e48e37fc 473 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 474\r
475 return Status;\r
476}\r
477\r
478\r
479/**\r
480 Issue a token with data to the socket to send out.\r
481\r
482 @param Sock Pointer to the socket to process the token with\r
483 data.\r
484 @param Token The token with data that needs to send out.\r
485\r
486 @retval EFI_SUCCESS The token is processed successfully.\r
487 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
488 socket is closed, or the socket is not in a\r
489 synchronized state , or the token is already in one\r
490 of this socket's lists.\r
491 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
492 finished.\r
493 @retval EFI_NOT_STARTED The socket is not configured.\r
494 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.\r
495\r
496**/\r
497EFI_STATUS\r
498SockSend (\r
499 IN SOCKET *Sock,\r
500 IN VOID *Token\r
501 )\r
502{\r
503 SOCK_IO_TOKEN *SndToken;\r
504 EFI_EVENT Event;\r
505 UINT32 FreeSpace;\r
506 EFI_TCP4_TRANSMIT_DATA *TxData;\r
507 EFI_STATUS Status;\r
508 SOCK_TOKEN *SockToken;\r
509 UINT32 DataLen;\r
510\r
511 ASSERT (SOCK_STREAM == Sock->Type);\r
512\r
e48e37fc 513 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 514 if (EFI_ERROR (Status)) {\r
515\r
e48e37fc 516 DEBUG ((EFI_D_ERROR, "SockSend: Get the access for socket"\r
8a67d61d 517 " failed with %r", Status));\r
518\r
519 return EFI_ACCESS_DENIED;\r
520 }\r
521\r
522 if (SOCK_IS_NO_MAPPING (Sock)) {\r
523 Status = EFI_NO_MAPPING;\r
524 goto Exit;\r
525 }\r
526\r
527 SndToken = (SOCK_IO_TOKEN *) Token;\r
528 TxData = (EFI_TCP4_TRANSMIT_DATA *) SndToken->Packet.TxData;\r
529\r
530 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
531 Status = EFI_NOT_STARTED;\r
532 goto Exit;\r
533 }\r
534\r
535 if (!(SOCK_IS_CONNECTING (Sock) || SOCK_IS_CONNECTED (Sock))) {\r
536\r
537 Status = EFI_ACCESS_DENIED;\r
538 goto Exit;\r
539 }\r
540\r
541 //\r
542 // check if a token is already in the token buffer\r
543 //\r
544 Event = SndToken->Token.Event;\r
545\r
546 if (SockTokenExisted (Sock, Event)) {\r
547 Status = EFI_ACCESS_DENIED;\r
548 goto Exit;\r
549 }\r
550\r
4eb65aff 551 DataLen = (UINT32) TxData->DataLength;\r
8a67d61d 552\r
553 //\r
554 // process this sending token now or buffer it only?\r
555 //\r
556 FreeSpace = SockGetFreeSpace (Sock, SOCK_SND_BUF);\r
557\r
558 if ((FreeSpace < Sock->SndBuffer.LowWater) || !SOCK_IS_CONNECTED (Sock)) {\r
559\r
560 SockToken = SockBufferToken (\r
561 Sock,\r
562 &Sock->SndTokenList,\r
563 SndToken,\r
564 DataLen\r
565 );\r
566\r
567 if (NULL == SockToken) {\r
568 Status = EFI_OUT_OF_RESOURCES;\r
569 }\r
570 } else {\r
571\r
572 SockToken = SockBufferToken (\r
573 Sock,\r
574 &Sock->ProcessingSndTokenList,\r
575 SndToken,\r
576 DataLen\r
577 );\r
578\r
579 if (NULL == SockToken) {\r
e48e37fc 580 DEBUG ((EFI_D_ERROR, "SockSend: Failed to buffer IO token into"\r
8a67d61d 581 " socket processing SndToken List\n", Status));\r
582\r
583 Status = EFI_OUT_OF_RESOURCES;\r
584 goto Exit;\r
585 }\r
586\r
587 Status = SockProcessTcpSndData (Sock, TxData);\r
588\r
589 if (EFI_ERROR (Status)) {\r
e48e37fc 590 DEBUG ((EFI_D_ERROR, "SockSend: Failed to process "\r
8a67d61d 591 "Snd Data\n", Status));\r
592\r
e48e37fc 593 RemoveEntryList (&(SockToken->TokenList));\r
594 gBS->FreePool (SockToken);\r
8a67d61d 595 }\r
596 }\r
597\r
598Exit:\r
e48e37fc 599 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 600 return Status;\r
601}\r
602\r
603\r
604/**\r
605 Issue a token to get data from the socket.\r
606\r
607 @param Sock Pointer to the socket to get data from.\r
608 @param Token The token to store the received data from the\r
609 socket.\r
610\r
611 @retval EFI_SUCCESS The token is processed successfully.\r
612 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
613 socket is closed, or the socket is not in a\r
614 synchronized state , or the token is already in one\r
615 of this socket's lists.\r
616 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
617 finished.\r
618 @retval EFI_NOT_STARTED The socket is not configured.\r
619 @retval EFI_CONNECTION_FIN The connection is closed and there is no more data.\r
620 @retval EFI_OUT_OF_RESOURCE Failed to buffer the token due to memory limit.\r
621\r
622**/\r
623EFI_STATUS\r
624SockRcv (\r
625 IN SOCKET *Sock,\r
626 IN VOID *Token\r
627 )\r
628{\r
629 SOCK_IO_TOKEN *RcvToken;\r
630 UINT32 RcvdBytes;\r
631 EFI_STATUS Status;\r
632 EFI_EVENT Event;\r
633\r
634 ASSERT (SOCK_STREAM == Sock->Type);\r
635\r
e48e37fc 636 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 637 if (EFI_ERROR (Status)) {\r
638\r
e48e37fc 639 DEBUG ((EFI_D_ERROR, "SockRcv: Get the access for socket"\r
8a67d61d 640 " failed with %r", Status));\r
641\r
642 return EFI_ACCESS_DENIED;\r
643 }\r
644\r
645 if (SOCK_IS_NO_MAPPING (Sock)) {\r
646\r
647 Status = EFI_NO_MAPPING;\r
648 goto Exit;\r
649 }\r
650\r
651 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
652\r
653 Status = EFI_NOT_STARTED;\r
654 goto Exit;\r
655 }\r
656\r
657 if (!(SOCK_IS_CONNECTED (Sock) || SOCK_IS_CONNECTING (Sock))) {\r
658\r
659 Status = EFI_ACCESS_DENIED;\r
660 goto Exit;\r
661 }\r
662\r
663 RcvToken = (SOCK_IO_TOKEN *) Token;\r
664\r
665 //\r
666 // check if a token is already in the token buffer of this socket\r
667 //\r
668 Event = RcvToken->Token.Event;\r
669 if (SockTokenExisted (Sock, Event)) {\r
670 Status = EFI_ACCESS_DENIED;\r
671 goto Exit;\r
672 }\r
673\r
674 RcvToken = (SOCK_IO_TOKEN *) Token;\r
675 RcvdBytes = GET_RCV_DATASIZE (Sock);\r
676\r
677 //\r
678 // check whether an error has happened before\r
679 //\r
680 if (EFI_ABORTED != Sock->SockError) {\r
681\r
682 SIGNAL_TOKEN (&(RcvToken->Token), Sock->SockError);\r
683 Sock->SockError = EFI_ABORTED;\r
684 goto Exit;\r
685 }\r
686\r
687 //\r
688 // check whether can not receive and there is no any\r
689 // data buffered in Sock->RcvBuffer\r
690 //\r
691 if (SOCK_IS_NO_MORE_DATA (Sock) && (0 == RcvdBytes)) {\r
692\r
693 Status = EFI_CONNECTION_FIN;\r
694 goto Exit;\r
695 }\r
696\r
697 if (RcvdBytes != 0) {\r
698 Status = SockProcessRcvToken (Sock, RcvToken);\r
699\r
700 if (EFI_ERROR (Status)) {\r
701 goto Exit;\r
702 }\r
703\r
704 Status = Sock->ProtoHandler (Sock, SOCK_CONSUMED, NULL);\r
705 } else {\r
706\r
707 if (NULL == SockBufferToken (Sock, &Sock->RcvTokenList, RcvToken, 0)) {\r
708 Status = EFI_OUT_OF_RESOURCES;\r
709 }\r
710 }\r
711\r
712Exit:\r
e48e37fc 713 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 714 return Status;\r
715}\r
716\r
717\r
718/**\r
719 Reset the socket and its associated protocol control block.\r
720\r
721 @param Sock Pointer to the socket to be flushed.\r
722\r
723 @retval EFI_SUCCESS The socket is flushed successfully.\r
724 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
725\r
726**/\r
727EFI_STATUS\r
728SockFlush (\r
729 IN SOCKET *Sock\r
730 )\r
731{\r
732 EFI_STATUS Status;\r
733\r
734 ASSERT (SOCK_STREAM == Sock->Type);\r
735\r
e48e37fc 736 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 737 if (EFI_ERROR (Status)) {\r
738\r
e48e37fc 739 DEBUG ((EFI_D_ERROR, "SockFlush: Get the access for socket"\r
8a67d61d 740 " failed with %r", Status));\r
741\r
742 return EFI_ACCESS_DENIED;\r
743 }\r
744\r
745 if (!SOCK_IS_CONFIGURED (Sock)) {\r
746 goto Exit;\r
747 }\r
748\r
749 Status = Sock->ProtoHandler (Sock, SOCK_FLUSH, NULL);\r
750 if (EFI_ERROR (Status)) {\r
751\r
e48e37fc 752 DEBUG ((EFI_D_ERROR, "SockFlush: Protocol failed handling"\r
8a67d61d 753 " SOCK_FLUSH with %r", Status));\r
754\r
755 goto Exit;\r
756 }\r
757\r
758 SOCK_ERROR (Sock, EFI_ABORTED);\r
759 SockConnFlush (Sock);\r
760 SockSetState (Sock, SO_CLOSED);\r
761\r
762 Sock->ConfigureState = SO_UNCONFIGURED;\r
763\r
764Exit:\r
e48e37fc 765 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 766 return Status;\r
767}\r
768\r
769\r
770/**\r
771 Close or abort the socket associated connection.\r
772\r
773 @param Sock Pointer to the socket of the connection to close or\r
774 abort.\r
775 @param Token The token for close operation.\r
776 @param OnAbort TRUE for aborting the connection, FALSE to close it.\r
777\r
778 @retval EFI_SUCCESS The close or abort operation is initialized\r
779 successfully.\r
780 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket, or the\r
781 socket is closed, or the socket is not in a\r
782 synchronized state , or the token is already in one\r
783 of this socket's lists.\r
784 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
785 finished.\r
786 @retval EFI_NOT_STARTED The socket is not configured.\r
787\r
788**/\r
789EFI_STATUS\r
790SockClose (\r
791 IN SOCKET *Sock,\r
792 IN VOID *Token,\r
793 IN BOOLEAN OnAbort\r
794 )\r
795{\r
796 EFI_STATUS Status;\r
797 EFI_EVENT Event;\r
798\r
799 ASSERT (SOCK_STREAM == Sock->Type);\r
800\r
e48e37fc 801 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 802 if (EFI_ERROR (Status)) {\r
e48e37fc 803 DEBUG ((EFI_D_ERROR, "SockClose: Get the access for socket"\r
8a67d61d 804 " failed with %r", Status));\r
805\r
806 return EFI_ACCESS_DENIED;\r
807 }\r
808\r
809 if (SOCK_IS_NO_MAPPING (Sock)) {\r
810 Status = EFI_NO_MAPPING;\r
811 goto Exit;\r
812 }\r
813\r
814 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
815 Status = EFI_NOT_STARTED;\r
816 goto Exit;\r
817 }\r
818\r
819 if (SOCK_IS_DISCONNECTING (Sock)) {\r
820 Status = EFI_ACCESS_DENIED;\r
821 goto Exit;\r
822 }\r
823\r
824 Event = ((SOCK_COMPLETION_TOKEN *) Token)->Event;\r
825\r
826 if (SockTokenExisted (Sock, Event)) {\r
827 Status = EFI_ACCESS_DENIED;\r
828 goto Exit;\r
829 }\r
830\r
831 Sock->CloseToken = Token;\r
832 SockSetState (Sock, SO_DISCONNECTING);\r
833\r
834 if (OnAbort) {\r
835 Status = Sock->ProtoHandler (Sock, SOCK_ABORT, NULL);\r
836 } else {\r
837 Status = Sock->ProtoHandler (Sock, SOCK_CLOSE, NULL);\r
838 }\r
839\r
840Exit:\r
e48e37fc 841 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 842 return Status;\r
843}\r
844\r
845\r
846/**\r
847 Get the mode data of the low layer protocol.\r
848\r
849 @param Sock Pointer to the socket to get mode data from.\r
850 @param Mode Pointer to the data to store the low layer mode\r
851 information.\r
852\r
853 @retval EFI_SUCCESS The mode data is got successfully.\r
854 @retval EFI_NOT_STARTED The socket is not configured.\r
855\r
856**/\r
857EFI_STATUS\r
858SockGetMode (\r
276dcc1b 859 IN SOCKET *Sock,\r
860 IN OUT VOID *Mode\r
8a67d61d 861 )\r
862{\r
863 return Sock->ProtoHandler (Sock, SOCK_MODE, Mode);\r
864}\r
865\r
866\r
867/**\r
868 Configure the low level protocol to join a multicast group for\r
869 this socket's connection.\r
870\r
871 @param Sock Pointer to the socket of the connection to join the\r
872 specific multicast group.\r
873 @param GroupInfo Pointer to the multicast group info.\r
874\r
875 @retval EFI_SUCCESS The configuration is done successfully.\r
876 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
877 @retval EFI_NOT_STARTED The socket is not configured.\r
878\r
879**/\r
880EFI_STATUS\r
881SockGroup (\r
882 IN SOCKET *Sock,\r
883 IN VOID *GroupInfo\r
884 )\r
885{\r
886 EFI_STATUS Status;\r
887\r
e48e37fc 888 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 889\r
890 if (EFI_ERROR (Status)) {\r
891\r
e48e37fc 892 DEBUG ((EFI_D_ERROR, "SockGroup: Get the access for socket"\r
8a67d61d 893 " failed with %r", Status));\r
894\r
895 return EFI_ACCESS_DENIED;\r
896 }\r
897\r
898 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
899 Status = EFI_NOT_STARTED;\r
900 goto Exit;\r
901 }\r
902\r
903 Status = Sock->ProtoHandler (Sock, SOCK_GROUP, GroupInfo);\r
904\r
905Exit:\r
e48e37fc 906 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 907 return Status;\r
908}\r
909\r
910\r
911/**\r
912 Add or remove route information in IP route table associated\r
913 with this socket.\r
914\r
915 @param Sock Pointer to the socket associated with the IP route\r
916 table to operate on.\r
917 @param RouteInfo Pointer to the route information to be processed.\r
918\r
919 @retval EFI_SUCCESS The route table is updated successfully.\r
920 @retval EFI_ACCESS_DENIED Failed to get the lock to access the socket.\r
921 @retval EFI_NO_MAPPING The IP address configuration operation is not\r
922 finished.\r
923 @retval EFI_NOT_STARTED The socket is not configured.\r
924\r
925**/\r
926EFI_STATUS\r
927SockRoute (\r
928 IN SOCKET *Sock,\r
929 IN VOID *RouteInfo\r
930 )\r
931{\r
932 EFI_STATUS Status;\r
933\r
e48e37fc 934 Status = EfiAcquireLockOrFail (&(Sock->Lock));\r
8a67d61d 935 if (EFI_ERROR (Status)) {\r
e48e37fc 936 DEBUG ((EFI_D_ERROR, "SockRoute: Get the access for socket"\r
8a67d61d 937 " failed with %r", Status));\r
938\r
939 return EFI_ACCESS_DENIED;\r
940 }\r
941\r
942 if (SOCK_IS_NO_MAPPING (Sock)) {\r
943 Status = EFI_NO_MAPPING;\r
944 goto Exit;\r
945 }\r
946\r
947 if (SOCK_IS_UNCONFIGURED (Sock)) {\r
948 Status = EFI_NOT_STARTED;\r
949 goto Exit;\r
950 }\r
951\r
952 Status = Sock->ProtoHandler (Sock, SOCK_ROUTE, RouteInfo);\r
953\r
954Exit:\r
e48e37fc 955 EfiReleaseLock (&(Sock->Lock));\r
8a67d61d 956 return Status;\r
957}\r