]> git.proxmox.com Git - mirror_edk2.git/blame - StdLib/EfiSocketLib/Ip4.c
StdLib: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / StdLib / EfiSocketLib / Ip4.c
CommitLineData
a88c3163 1/** @file\r
2 Implement the IP4 driver support for the socket layer.\r
3\r
c581e503 4 Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>\r
0a2530ea 5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
a88c3163 6**/\r
a88c3163 7#include "Socket.h"\r
8\r
9\r
beaaa3b7 10/** Get the local socket address.\r
a88c3163 11\r
12 This routine returns the IPv4 address associated with the local\r
13 socket.\r
14\r
15 This routine is called by ::EslSocketGetLocalAddress to determine the\r
16 network address for the SOCK_RAW socket.\r
17\r
18 @param [in] pPort Address of an ::ESL_PORT structure.\r
a88c3163 19 @param [out] pAddress Network address to receive the local system address\r
a88c3163 20**/\r
21VOID\r
22EslIp4LocalAddressGet (\r
23 IN ESL_PORT * pPort,\r
24 OUT struct sockaddr * pAddress\r
25 )\r
26{\r
27 struct sockaddr_in * pLocalAddress;\r
28 ESL_IP4_CONTEXT * pIp4;\r
29\r
30 DBG_ENTER ( );\r
31\r
a88c3163 32 // Return the local address\r
a88c3163 33 pIp4 = &pPort->Context.Ip4;\r
34 pLocalAddress = (struct sockaddr_in *)pAddress;\r
35 pLocalAddress->sin_family = AF_INET;\r
36 CopyMem ( &pLocalAddress->sin_addr,\r
37 &pIp4->ModeData.ConfigData.StationAddress.Addr[0],\r
38 sizeof ( pLocalAddress->sin_addr ));\r
39\r
40 DBG_EXIT ( );\r
41}\r
42\r
43\r
beaaa3b7 44/** Set the local port address.\r
a88c3163 45\r
46 This routine sets the local port address.\r
47\r
48 This support routine is called by ::EslSocketPortAllocate.\r
49\r
50 @param [in] pPort Address of an ESL_PORT structure\r
51 @param [in] pSockAddr Address of a sockaddr structure that contains the\r
52 connection point on the local machine. An IPv4 address\r
53 of INADDR_ANY specifies that the connection is made to\r
54 all of the network stacks on the platform. Specifying a\r
55 specific IPv4 address restricts the connection to the\r
56 network stack supporting that address. Specifying zero\r
57 for the port causes the network layer to assign a port\r
58 number from the dynamic range. Specifying a specific\r
59 port number causes the network layer to use that port.\r
60\r
61 @param [in] bBindTest TRUE = run bind testing\r
62\r
63 @retval EFI_SUCCESS The operation was successful\r
a88c3163 64 **/\r
65EFI_STATUS\r
66EslIp4LocalAddressSet (\r
67 IN ESL_PORT * pPort,\r
68 IN CONST struct sockaddr * pSockAddr,\r
69 IN BOOLEAN bBindTest\r
70 )\r
71{\r
72 EFI_IP4_CONFIG_DATA * pConfig;\r
73 CONST struct sockaddr_in * pIpAddress;\r
74 CONST UINT8 * pIpv4Address;\r
75 EFI_STATUS Status;\r
76\r
77 DBG_ENTER ( );\r
78\r
a88c3163 79 // Validate the address\r
a88c3163 80 pIpAddress = (struct sockaddr_in *)pSockAddr;\r
81 if ( INADDR_BROADCAST == pIpAddress->sin_addr.s_addr ) {\r
a88c3163 82 // The local address must not be the broadcast address\r
a88c3163 83 Status = EFI_INVALID_PARAMETER;\r
84 pPort->pSocket->errno = EADDRNOTAVAIL;\r
85 }\r
86 else {\r
87 Status = EFI_SUCCESS;\r
88\r
a88c3163 89 // Set the local address\r
a88c3163 90 pIpAddress = (struct sockaddr_in *)pSockAddr;\r
91 pIpv4Address = (UINT8 *)&pIpAddress->sin_addr.s_addr;\r
92 pConfig = &pPort->Context.Ip4.ModeData.ConfigData;\r
93 pConfig->StationAddress.Addr[0] = pIpv4Address[0];\r
94 pConfig->StationAddress.Addr[1] = pIpv4Address[1];\r
95 pConfig->StationAddress.Addr[2] = pIpv4Address[2];\r
96 pConfig->StationAddress.Addr[3] = pIpv4Address[3];\r
97\r
a88c3163 98 // Determine if the default address is used\r
a88c3163 99 pConfig->UseDefaultAddress = (BOOLEAN)( 0 == pIpAddress->sin_addr.s_addr );\r
100\r
a88c3163 101 // Display the local address\r
a88c3163 102 DEBUG (( DEBUG_BIND,\r
103 "0x%08x: Port, Local IP4 Address: %d.%d.%d.%d\r\n",\r
104 pPort,\r
105 pConfig->StationAddress.Addr[0],\r
106 pConfig->StationAddress.Addr[1],\r
107 pConfig->StationAddress.Addr[2],\r
108 pConfig->StationAddress.Addr[3]));\r
109\r
a88c3163 110 // Set the subnet mask\r
a88c3163 111 if ( pConfig->UseDefaultAddress ) {\r
112 pConfig->SubnetMask.Addr[0] = 0;\r
113 pConfig->SubnetMask.Addr[1] = 0;\r
114 pConfig->SubnetMask.Addr[2] = 0;\r
115 pConfig->SubnetMask.Addr[3] = 0;\r
116 }\r
117 else {\r
118 pConfig->SubnetMask.Addr[0] = 0xff;\r
6e1450f3 119 pConfig->SubnetMask.Addr[1] = ( 128 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;\r
120 pConfig->SubnetMask.Addr[2] = ( 192 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;\r
121 pConfig->SubnetMask.Addr[3] = ( 224 <= pConfig->StationAddress.Addr[0]) ? 0xff : 0;\r
a88c3163 122 }\r
123 }\r
a88c3163 124 // Return the operation status\r
a88c3163 125 DBG_EXIT_STATUS ( Status );\r
126 return Status;\r
127}\r
128\r
129\r
beaaa3b7 130/** Get the option value.\r
a88c3163 131\r
132 This routine handles the IPv4 level options.\r
133\r
134 The ::EslSocketOptionGet routine calls this routine to retrieve\r
135 the IPv4 options one at a time by name.\r
136\r
137 @param [in] pSocket Address of an ::ESL_SOCKET structure\r
138 @param [in] OptionName Name of the option\r
139 @param [out] ppOptionData Buffer to receive address of option value\r
140 @param [out] pOptionLength Buffer to receive the option length\r
141\r
142 @retval EFI_SUCCESS - Socket data successfully received\r
a88c3163 143 **/\r
144EFI_STATUS\r
145EslIp4OptionGet (\r
146 IN ESL_SOCKET * pSocket,\r
147 IN int OptionName,\r
148 OUT CONST void ** __restrict ppOptionData,\r
149 OUT socklen_t * __restrict pOptionLength\r
150 )\r
151{\r
152 EFI_STATUS Status;\r
153\r
154 DBG_ENTER ( );\r
155\r
a88c3163 156 // Assume success\r
a88c3163 157 pSocket->errno = 0;\r
158 Status = EFI_SUCCESS;\r
159\r
a88c3163 160 // Attempt to get the option\r
a88c3163 161 switch ( OptionName ) {\r
162 default:\r
a88c3163 163 // Option not supported\r
a88c3163 164 pSocket->errno = ENOPROTOOPT;\r
165 Status = EFI_INVALID_PARAMETER;\r
166 break;\r
167\r
168 case IP_HDRINCL:\r
58081f2c 169 *ppOptionData = (void *)&pSocket->bIncludeHeader;\r
a88c3163 170 *pOptionLength = sizeof ( pSocket->bIncludeHeader );\r
171 break;\r
172 }\r
a88c3163 173 // Return the operation status\r
a88c3163 174 DBG_EXIT_STATUS ( Status );\r
175 return Status;\r
176}\r
177\r
178\r
beaaa3b7 179/** Set the option value.\r
a88c3163 180\r
181 This routine handles the IPv4 level options.\r
182\r
183 The ::EslSocketOptionSet routine calls this routine to adjust\r
184 the IPv4 options one at a time by name.\r
185\r
186 @param [in] pSocket Address of an ::ESL_SOCKET structure\r
187 @param [in] OptionName Name of the option\r
188 @param [in] pOptionValue Buffer containing the option value\r
189 @param [in] OptionLength Length of the buffer in bytes\r
190\r
191 @retval EFI_SUCCESS - Option successfully set\r
a88c3163 192 **/\r
193EFI_STATUS\r
194EslIp4OptionSet (\r
195 IN ESL_SOCKET * pSocket,\r
196 IN int OptionName,\r
197 IN CONST void * pOptionValue,\r
198 IN socklen_t OptionLength\r
199 )\r
200{\r
201 BOOLEAN bTrueFalse;\r
beaaa3b7
OM
202 //socklen_t LengthInBytes;\r
203 //UINT8 * pOptionData;\r
a88c3163 204 EFI_STATUS Status;\r
205\r
206 DBG_ENTER ( );\r
207\r
a88c3163 208 // Assume success\r
a88c3163 209 pSocket->errno = 0;\r
210 Status = EFI_SUCCESS;\r
211\r
a88c3163 212 // Determine if the option protocol matches\r
beaaa3b7
OM
213 //LengthInBytes = 0;\r
214 //pOptionData = NULL;\r
a88c3163 215 switch ( OptionName ) {\r
216 default:\r
a88c3163 217 // Protocol level not supported\r
a88c3163 218 DEBUG (( DEBUG_INFO | DEBUG_OPTION, "ERROR - Invalid protocol option\r\n" ));\r
219 pSocket->errno = ENOTSUP;\r
220 Status = EFI_UNSUPPORTED;\r
221 break;\r
222\r
223 case IP_HDRINCL:\r
224\r
a88c3163 225 // Validate the option length\r
a88c3163 226 if ( sizeof ( UINT32 ) == OptionLength ) {\r
a88c3163 227 // Restrict the input to TRUE or FALSE\r
a88c3163 228 bTrueFalse = TRUE;\r
229 if ( 0 == *(UINT32 *)pOptionValue ) {\r
230 bTrueFalse = FALSE;\r
231 }\r
232 pOptionValue = &bTrueFalse;\r
233\r
a88c3163 234 // Set the option value\r
beaaa3b7
OM
235 //pOptionData = (UINT8 *)&pSocket->bIncludeHeader;\r
236 //LengthInBytes = sizeof ( pSocket->bIncludeHeader );\r
a88c3163 237 }\r
238 break;\r
239 }\r
a88c3163 240 // Return the operation status\r
a88c3163 241 DBG_EXIT_STATUS ( Status );\r
242 return Status;\r
243}\r
244\r
245\r
246/**\r
247 Free a receive packet\r
248\r
249 This routine performs the network specific operations necessary\r
250 to free a receive packet.\r
251\r
252 This routine is called by ::EslSocketPortCloseTxDone to free a\r
253 receive packet.\r
254\r
255 @param [in] pPacket Address of an ::ESL_PACKET structure.\r
256 @param [in, out] pRxBytes Address of the count of RX bytes\r
257\r
258**/\r
259VOID\r
260EslIp4PacketFree (\r
261 IN ESL_PACKET * pPacket,\r
262 IN OUT size_t * pRxBytes\r
263 )\r
264{\r
265 EFI_IP4_RECEIVE_DATA * pRxData;\r
266 DBG_ENTER ( );\r
267\r
268 //\r
269 // Account for the receive bytes\r
270 //\r
271 pRxData = pPacket->Op.Ip4Rx.pRxData;\r
272 *pRxBytes -= pRxData->HeaderLength + pRxData->DataLength;\r
273\r
274 //\r
275 // Disconnect the buffer from the packet\r
276 //\r
277 pPacket->Op.Ip4Rx.pRxData = NULL;\r
278\r
279 //\r
280 // Return the buffer to the IP4 driver\r
281 //\r
282 gBS->SignalEvent ( pRxData->RecycleSignal );\r
283 DBG_EXIT ( );\r
284}\r
285\r
286\r
287/**\r
288 Initialize the network specific portions of an ::ESL_PORT structure.\r
289\r
290 This routine initializes the network specific portions of an\r
291 ::ESL_PORT structure for use by the socket.\r
292\r
293 This support routine is called by ::EslSocketPortAllocate\r
294 to connect the socket with the underlying network adapter\r
295 running the IPv4 protocol.\r
296\r
297 @param [in] pPort Address of an ESL_PORT structure\r
298 @param [in] DebugFlags Flags for debug messages\r
299\r
300 @retval EFI_SUCCESS - Socket successfully created\r
301\r
302 **/\r
303EFI_STATUS\r
304EslIp4PortAllocate (\r
305 IN ESL_PORT * pPort,\r
306 IN UINTN DebugFlags\r
307 )\r
308{\r
309 EFI_IP4_CONFIG_DATA * pConfig;\r
310 ESL_SOCKET * pSocket;\r
311 EFI_STATUS Status;\r
312\r
313 DBG_ENTER ( );\r
314\r
315 //\r
316 // Initialize the port\r
317 //\r
318 pSocket = pPort->pSocket;\r
319 pSocket->TxPacketOffset = OFFSET_OF ( ESL_PACKET, Op.Ip4Tx.TxData );\r
320 pSocket->TxTokenEventOffset = OFFSET_OF ( ESL_IO_MGMT, Token.Ip4Tx.Event );\r
321 pSocket->TxTokenOffset = OFFSET_OF ( EFI_IP4_COMPLETION_TOKEN, Packet.TxData );\r
322\r
323 //\r
324 // Save the cancel, receive and transmit addresses\r
325 //\r
326 pPort->pfnConfigure = (PFN_NET_CONFIGURE)pPort->pProtocol.IPv4->Configure;\r
327 pPort->pfnRxCancel = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Cancel;\r
3bdf9aae 328 pPort->pfnRxPoll = (PFN_NET_POLL)pPort->pProtocol.IPv4->Poll;\r
a88c3163 329 pPort->pfnRxStart = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Receive;\r
330 pPort->pfnTxStart = (PFN_NET_IO_START)pPort->pProtocol.IPv4->Transmit;\r
331\r
332 //\r
333 // Set the configuration flags\r
334 //\r
335 pConfig = &pPort->Context.Ip4.ModeData.ConfigData;\r
336 pConfig->AcceptIcmpErrors = FALSE;\r
337 pConfig->AcceptBroadcast = FALSE;\r
338 pConfig->AcceptPromiscuous = FALSE;\r
339 pConfig->TypeOfService = 0;\r
340 pConfig->TimeToLive = 255;\r
341 pConfig->DoNotFragment = FALSE;\r
342 pConfig->RawData = FALSE;\r
343 pConfig->ReceiveTimeout = 0;\r
344 pConfig->TransmitTimeout = 0;\r
345\r
346 //\r
347 // Set the default protocol\r
348 //\r
349 pConfig->DefaultProtocol = (UINT8)pSocket->Protocol;\r
350 pConfig->AcceptAnyProtocol = (BOOLEAN)( 0 == pConfig->DefaultProtocol );\r
351 Status = EFI_SUCCESS;\r
352\r
353 //\r
354 // Return the operation status\r
355 //\r
356 DBG_EXIT_STATUS ( Status );\r
357 return Status;\r
358}\r
359\r
360\r
361/**\r
362 Receive data from a network connection.\r
363\r
364 This routine attempts to return buffered data to the caller. The\r
365 data is removed from the urgent queue if the message flag MSG_OOB\r
366 is specified, otherwise data is removed from the normal queue.\r
367 See the \ref ReceiveEngine section.\r
368\r
369 This routine is called by ::EslSocketReceive to handle the network\r
370 specific receive operation to support SOCK_RAW sockets.\r
371\r
372 @param [in] pPort Address of an ::ESL_PORT structure.\r
373\r
374 @param [in] pPacket Address of an ::ESL_PACKET structure.\r
0e565888 375\r
a88c3163 376 @param [in] pbConsumePacket Address of a BOOLEAN indicating if the packet is to be consumed\r
0e565888 377\r
a88c3163 378 @param [in] BufferLength Length of the the buffer\r
0e565888 379\r
a88c3163 380 @param [in] pBuffer Address of a buffer to receive the data.\r
0e565888 381\r
a88c3163 382 @param [in] pDataLength Number of received data bytes in the buffer.\r
383\r
384 @param [out] pAddress Network address to receive the remote system address\r
385\r
386 @param [out] pSkipBytes Address to receive the number of bytes skipped\r
387\r
388 @return Returns the address of the next free byte in the buffer.\r
389\r
390 **/\r
391UINT8 *\r
392EslIp4Receive (\r
393 IN ESL_PORT * pPort,\r
394 IN ESL_PACKET * pPacket,\r
395 IN BOOLEAN * pbConsumePacket,\r
396 IN size_t BufferLength,\r
397 IN UINT8 * pBuffer,\r
398 OUT size_t * pDataLength,\r
399 OUT struct sockaddr * pAddress,\r
400 OUT size_t * pSkipBytes\r
401 )\r
402{\r
403 size_t DataBytes;\r
404 size_t HeaderBytes;\r
405 size_t LengthInBytes;\r
406 struct sockaddr_in * pRemoteAddress;\r
407 EFI_IP4_RECEIVE_DATA * pRxData;\r
408\r
409 DBG_ENTER ( );\r
410\r
411 //\r
412 // Return the remote system address if requested\r
413 //\r
414 pRxData = pPacket->Op.Ip4Rx.pRxData;\r
415 if ( NULL != pAddress ) {\r
416 //\r
417 // Build the remote address\r
418 //\r
419 DEBUG (( DEBUG_RX,\r
420 "Getting packet remote address: %d.%d.%d.%d\r\n",\r
421 pRxData->Header->SourceAddress.Addr[0],\r
422 pRxData->Header->SourceAddress.Addr[1],\r
423 pRxData->Header->SourceAddress.Addr[2],\r
424 pRxData->Header->SourceAddress.Addr[3]));\r
425 pRemoteAddress = (struct sockaddr_in *)pAddress;\r
426 CopyMem ( &pRemoteAddress->sin_addr,\r
427 &pRxData->Header->SourceAddress.Addr[0],\r
428 sizeof ( pRemoteAddress->sin_addr ));\r
429 }\r
430\r
431 //\r
432 // Copy the IP header\r
433 //\r
434 HeaderBytes = pRxData->HeaderLength;\r
435 if ( HeaderBytes > BufferLength ) {\r
436 HeaderBytes = BufferLength;\r
437 }\r
438 DEBUG (( DEBUG_RX,\r
439 "0x%08x --> 0x%08x: Copy header 0x%08x bytes\r\n",\r
440 pRxData->Header,\r
441 pBuffer,\r
442 HeaderBytes ));\r
443 CopyMem ( pBuffer, pRxData->Header, HeaderBytes );\r
444 pBuffer += HeaderBytes;\r
445 LengthInBytes = HeaderBytes;\r
446\r
447 //\r
448 // Copy the received data\r
449 //\r
450 if ( 0 < ( BufferLength - LengthInBytes )) {\r
451 pBuffer = EslSocketCopyFragmentedBuffer ( pRxData->FragmentCount,\r
452 &pRxData->FragmentTable[0],\r
453 BufferLength - LengthInBytes,\r
454 pBuffer,\r
455 &DataBytes );\r
456 LengthInBytes += DataBytes;\r
457 }\r
458\r
459 //\r
460 // Determine if the data is being read\r
461 //\r
462 if ( *pbConsumePacket ) {\r
463 //\r
464 // Display for the bytes consumed\r
465 //\r
466 DEBUG (( DEBUG_RX,\r
467 "0x%08x: Port account for 0x%08x bytes\r\n",\r
468 pPort,\r
469 LengthInBytes ));\r
470\r
471 //\r
472 // Account for any discarded data\r
473 //\r
474 *pSkipBytes = pRxData->HeaderLength + pRxData->DataLength - LengthInBytes;\r
475 }\r
476\r
477 //\r
478 // Return the data length and the buffer address\r
479 //\r
480 *pDataLength = LengthInBytes;\r
481 DBG_EXIT_HEX ( pBuffer );\r
482 return pBuffer;\r
483}\r
484\r
485\r
486/**\r
487 Get the remote socket address\r
488\r
489 This routine returns the address of the remote connection point\r
490 associated with the SOCK_RAW socket.\r
491\r
492 This routine is called by ::EslSocketGetPeerAddress to detemine\r
493 the IPv4 address associated with the network adapter.\r
494\r
495 @param [in] pPort Address of an ::ESL_PORT structure.\r
496\r
497 @param [out] pAddress Network address to receive the remote system address\r
498\r
499**/\r
500VOID\r
501EslIp4RemoteAddressGet (\r
502 IN ESL_PORT * pPort,\r
503 OUT struct sockaddr * pAddress\r
504 )\r
505{\r
506 struct sockaddr_in * pRemoteAddress;\r
507 ESL_IP4_CONTEXT * pIp4;\r
508\r
509 DBG_ENTER ( );\r
510\r
511 //\r
512 // Return the remote address\r
513 //\r
514 pIp4 = &pPort->Context.Ip4;\r
515 pRemoteAddress = (struct sockaddr_in *)pAddress;\r
516 pRemoteAddress->sin_family = AF_INET;\r
517 CopyMem ( &pRemoteAddress->sin_addr,\r
518 &pIp4->DestinationAddress.Addr[0],\r
519 sizeof ( pRemoteAddress->sin_addr ));\r
520\r
521 DBG_EXIT ( );\r
522}\r
523\r
524\r
525/**\r
526 Set the remote address\r
527\r
528 This routine sets the remote address in the port.\r
529\r
530 This routine is called by ::EslSocketConnect to specify the\r
531 remote network address.\r
532\r
533 @param [in] pPort Address of an ::ESL_PORT structure.\r
534\r
535 @param [in] pSockAddr Network address of the remote system.\r
536\r
537 @param [in] SockAddrLength Length in bytes of the network address.\r
538\r
539 @retval EFI_SUCCESS The operation was successful\r
540\r
541 **/\r
542EFI_STATUS\r
543EslIp4RemoteAddressSet (\r
544 IN ESL_PORT * pPort,\r
545 IN CONST struct sockaddr * pSockAddr,\r
546 IN socklen_t SockAddrLength\r
547 )\r
548{\r
549 ESL_IP4_CONTEXT * pIp4;\r
550 CONST struct sockaddr_in * pRemoteAddress;\r
551 EFI_STATUS Status;\r
552\r
553 DBG_ENTER ( );\r
554\r
555 //\r
556 // Set the remote address\r
557 //\r
558 pIp4 = &pPort->Context.Ip4;\r
559 pRemoteAddress = (struct sockaddr_in *)pSockAddr;\r
560 pIp4->DestinationAddress.Addr[0] = (UINT8)( pRemoteAddress->sin_addr.s_addr );\r
561 pIp4->DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );\r
562 pIp4->DestinationAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );\r
563 pIp4->DestinationAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );\r
f74dc4bb 564 pPort->pSocket->bAddressSet = TRUE;\r
a88c3163 565 Status = EFI_SUCCESS;\r
566\r
567 //\r
568 // Return the operation status\r
569 //\r
570 DBG_EXIT_STATUS ( Status );\r
571 return Status;\r
572}\r
573\r
574\r
575/**\r
576 Process the receive completion\r
577\r
578 This routine keeps the IPv4 driver's buffer and queues it in\r
579 in FIFO order to the data queue. The IP4 driver's buffer will\r
580 be returned by either ::EslIp4Receive or ::EslSocketPortCloseTxDone.\r
581 See the \ref ReceiveEngine section.\r
582\r
583 This routine is called by the IPv4 driver when data is\r
584 received.\r
585\r
586 @param [in] Event The receive completion event\r
587\r
588 @param [in] pIo The address of an ::ESL_IO_MGMT structure\r
589\r
590**/\r
591VOID\r
592EslIp4RxComplete (\r
593 IN EFI_EVENT Event,\r
594 IN ESL_IO_MGMT * pIo\r
595 )\r
596{\r
597 size_t LengthInBytes;\r
a88c3163 598 ESL_PACKET * pPacket;\r
599 EFI_IP4_RECEIVE_DATA * pRxData;\r
600 EFI_STATUS Status;\r
0e565888 601\r
a88c3163 602 DBG_ENTER ( );\r
0e565888 603\r
a88c3163 604 //\r
605 // Get the operation status.\r
606 //\r
a88c3163 607 Status = pIo->Token.Ip4Rx.Status;\r
608\r
609 //\r
610 // Get the packet length\r
611 //\r
612 pRxData = pIo->Token.Ip4Rx.Packet.RxData;\r
613 LengthInBytes = pRxData->HeaderLength + pRxData->DataLength;\r
614\r
0e565888 615 //{{\r
a88c3163 616 // +--------------------+ +----------------------+\r
617 // | ESL_IO_MGMT | | Data Buffer |\r
618 // | | | (Driver owned) |\r
619 // | +---------------+ +----------------------+\r
620 // | | Token | ^\r
621 // | | Rx Event | |\r
622 // | | | +----------------------+\r
623 // | | RxData --> | EFI_IP4_RECEIVE_DATA |\r
624 // +----+---------------+ | (Driver owned) |\r
625 // +----------------------+\r
626 // +--------------------+ ^\r
627 // | ESL_PACKET | .\r
628 // | | .\r
629 // | +---------------+ .\r
630 // | | pRxData --> NULL .......\r
631 // +----+---------------+\r
632 //\r
633 //\r
634 // Save the data in the packet\r
0e565888 635 //}}\r
a88c3163 636 pPacket = pIo->pPacket;\r
637 pPacket->Op.Ip4Rx.pRxData = pRxData;\r
638\r
639 //\r
640 // Complete this request\r
641 //\r
642 EslSocketRxComplete ( pIo, Status, LengthInBytes, FALSE );\r
643 DBG_EXIT ( );\r
644}\r
645\r
646\r
647/**\r
648 Determine if the socket is configured.\r
649\r
650 This routine uses the flag ESL_SOCKET::bConfigured to determine\r
651 if the network layer's configuration routine has been called.\r
652 This routine calls the ::EslSocketBind and configuration routines\r
653 if they were not already called. After the port is configured,\r
654 the \ref ReceiveEngine is started.\r
655\r
656 This routine is called by EslSocketIsConfigured to verify\r
657 that the socket is configured.\r
658\r
659 @param [in] pSocket Address of an ::ESL_SOCKET structure\r
0e565888 660\r
a88c3163 661 @retval EFI_SUCCESS - The port is connected\r
662 @retval EFI_NOT_STARTED - The port is not connected\r
663\r
664 **/\r
665 EFI_STATUS\r
666 EslIp4SocketIsConfigured (\r
667 IN ESL_SOCKET * pSocket\r
668 )\r
669{\r
670 UINTN Index;\r
671 ESL_PORT * pPort;\r
672 ESL_PORT * pNextPort;\r
673 ESL_IP4_CONTEXT * pIp4;\r
674 EFI_IP4_PROTOCOL * pIp4Protocol;\r
675 EFI_STATUS Status;\r
676 struct sockaddr_in LocalAddress;\r
677\r
678 DBG_ENTER ( );\r
679\r
680 //\r
681 // Assume success\r
682 //\r
683 Status = EFI_SUCCESS;\r
684\r
685 //\r
686 // Configure the port if necessary\r
687 //\r
688 if ( !pSocket->bConfigured ) {\r
689 //\r
690 // Fill in the port list if necessary\r
691 //\r
bb3aa953 692 pSocket->errno = ENETDOWN;\r
a88c3163 693 if ( NULL == pSocket->pPortList ) {\r
694 LocalAddress.sin_len = sizeof ( LocalAddress );\r
695 LocalAddress.sin_family = AF_INET;\r
696 LocalAddress.sin_addr.s_addr = 0;\r
697 LocalAddress.sin_port = 0;\r
698 Status = EslSocketBind ( &pSocket->SocketProtocol,\r
699 (struct sockaddr *)&LocalAddress,\r
700 LocalAddress.sin_len,\r
701 &pSocket->errno );\r
702 }\r
703\r
704 //\r
705 // Walk the port list\r
706 //\r
707 pPort = pSocket->pPortList;\r
708 while ( NULL != pPort ) {\r
709 //\r
710 // Update the raw setting\r
711 //\r
712 pIp4 = &pPort->Context.Ip4;\r
713 if ( pSocket->bIncludeHeader ) {\r
714 //\r
715 // IP header will be included with the data on transmit\r
716 //\r
717 pIp4->ModeData.ConfigData.RawData = TRUE;\r
718 }\r
719\r
720 //\r
721 // Attempt to configure the port\r
722 //\r
723 pNextPort = pPort->pLinkSocket;\r
724 pIp4Protocol = pPort->pProtocol.IPv4;\r
725 DEBUG (( DEBUG_TX,\r
726 "0x%08x: pPort Configuring for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",\r
727 pPort,\r
728 pIp4->ModeData.ConfigData.StationAddress.Addr[0],\r
729 pIp4->ModeData.ConfigData.StationAddress.Addr[1],\r
730 pIp4->ModeData.ConfigData.StationAddress.Addr[2],\r
731 pIp4->ModeData.ConfigData.StationAddress.Addr[3],\r
732 pIp4->DestinationAddress.Addr[0],\r
733 pIp4->DestinationAddress.Addr[1],\r
734 pIp4->DestinationAddress.Addr[2],\r
735 pIp4->DestinationAddress.Addr[3]));\r
736 Status = pIp4Protocol->Configure ( pIp4Protocol,\r
737 &pIp4->ModeData.ConfigData );\r
738 if ( !EFI_ERROR ( Status )) {\r
739 //\r
740 // Update the configuration data\r
741 //\r
742 Status = pIp4Protocol->GetModeData ( pIp4Protocol,\r
743 &pIp4->ModeData,\r
744 NULL,\r
745 NULL );\r
746 }\r
747 if ( EFI_ERROR ( Status )) {\r
bb3aa953 748 if ( !pSocket->bConfigured ) {\r
749 DEBUG (( DEBUG_LISTEN,\r
750 "ERROR - Failed to configure the Ip4 port, Status: %r\r\n",\r
751 Status ));\r
752 switch ( Status ) {\r
753 case EFI_ACCESS_DENIED:\r
754 pSocket->errno = EACCES;\r
755 break;\r
756\r
757 default:\r
758 case EFI_DEVICE_ERROR:\r
759 pSocket->errno = EIO;\r
760 break;\r
761\r
762 case EFI_INVALID_PARAMETER:\r
763 pSocket->errno = EADDRNOTAVAIL;\r
764 break;\r
765\r
766 case EFI_NO_MAPPING:\r
767 pSocket->errno = EAFNOSUPPORT;\r
768 break;\r
769\r
770 case EFI_OUT_OF_RESOURCES:\r
771 pSocket->errno = ENOBUFS;\r
772 break;\r
773\r
774 case EFI_UNSUPPORTED:\r
775 pSocket->errno = EOPNOTSUPP;\r
776 break;\r
777 }\r
a88c3163 778 }\r
779 }\r
780 else {\r
781 DEBUG (( DEBUG_TX,\r
782 "0x%08x: pPort Configured for %d.%d.%d.%d --> %d.%d.%d.%d\r\n",\r
783 pPort,\r
784 pIp4->ModeData.ConfigData.StationAddress.Addr[0],\r
785 pIp4->ModeData.ConfigData.StationAddress.Addr[1],\r
786 pIp4->ModeData.ConfigData.StationAddress.Addr[2],\r
787 pIp4->ModeData.ConfigData.StationAddress.Addr[3],\r
788 pIp4->DestinationAddress.Addr[0],\r
789 pIp4->DestinationAddress.Addr[1],\r
790 pIp4->DestinationAddress.Addr[2],\r
791 pIp4->DestinationAddress.Addr[3]));\r
792 DEBUG (( DEBUG_TX,\r
793 "Subnet Mask: %d.%d.%d.%d\r\n",\r
794 pIp4->ModeData.ConfigData.SubnetMask.Addr[0],\r
795 pIp4->ModeData.ConfigData.SubnetMask.Addr[1],\r
796 pIp4->ModeData.ConfigData.SubnetMask.Addr[2],\r
797 pIp4->ModeData.ConfigData.SubnetMask.Addr[3]));\r
798 DEBUG (( DEBUG_TX,\r
799 "Route Count: %d\r\n",\r
800 pIp4->ModeData.RouteCount ));\r
801 for ( Index = 0; pIp4->ModeData.RouteCount > Index; Index++ ) {\r
802 if ( 0 == Index ) {\r
803 DEBUG (( DEBUG_TX, "Route Table:\r\n" ));\r
804 }\r
805 DEBUG (( DEBUG_TX,\r
806 "%5d: %d.%d.%d.%d, %d.%d.%d.%d ==> %d.%d.%d.%d\r\n",\r
807 Index,\r
808 pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[0],\r
809 pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[1],\r
810 pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[2],\r
811 pIp4->ModeData.RouteTable[Index].SubnetAddress.Addr[3],\r
812 pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[0],\r
813 pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[1],\r
814 pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[2],\r
815 pIp4->ModeData.RouteTable[Index].SubnetMask.Addr[3],\r
816 pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[0],\r
817 pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[1],\r
818 pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[2],\r
819 pIp4->ModeData.RouteTable[Index].GatewayAddress.Addr[3]));\r
820 }\r
821 pPort->bConfigured = TRUE;\r
bb3aa953 822 pSocket->bConfigured = TRUE;\r
a88c3163 823\r
824 //\r
825 // Start the first read on the port\r
826 //\r
827 EslSocketRxStart ( pPort );\r
828\r
829 //\r
830 // The socket is connected\r
831 //\r
832 pSocket->State = SOCKET_STATE_CONNECTED;\r
bb3aa953 833 pSocket->errno = 0;\r
a88c3163 834 }\r
835\r
836 //\r
837 // Set the next port\r
838 //\r
839 pPort = pNextPort;\r
840 }\r
a88c3163 841 }\r
842\r
843 //\r
844 // Determine the socket configuration status\r
845 //\r
bb3aa953 846 Status = pSocket->bConfigured ? EFI_SUCCESS : EFI_NOT_STARTED;\r
0e565888 847\r
a88c3163 848 //\r
849 // Return the port connected state.\r
850 //\r
851 DBG_EXIT_STATUS ( Status );\r
852 return Status;\r
853}\r
854\r
855\r
856/**\r
857 Buffer data for transmission over a network connection.\r
858\r
859 This routine buffers data for the transmit engine in the normal\r
860 data queue. When the \ref TransmitEngine has resources, this\r
861 routine will start the transmission of the next buffer on the\r
862 network connection.\r
863\r
864 This routine is called by ::EslSocketTransmit to buffer\r
865 data for transmission. The data is copied into a local buffer\r
866 freeing the application buffer for reuse upon return. When\r
867 necessary, this routine starts the transmit engine that\r
868 performs the data transmission on the network connection. The\r
869 transmit engine transmits the data a packet at a time over the\r
870 network connection.\r
871\r
872 Transmission errors are returned during the next transmission or\r
873 during the close operation. Only buffering errors are returned\r
874 during the current transmission attempt.\r
875\r
876 @param [in] pSocket Address of an ::ESL_SOCKET structure\r
877\r
878 @param [in] Flags Message control flags\r
879\r
880 @param [in] BufferLength Length of the the buffer\r
881\r
882 @param [in] pBuffer Address of a buffer to receive the data.\r
883\r
884 @param [in] pDataLength Number of received data bytes in the buffer.\r
885\r
886 @param [in] pAddress Network address of the remote system address\r
887\r
888 @param [in] AddressLength Length of the remote network address structure\r
889\r
890 @retval EFI_SUCCESS - Socket data successfully buffered\r
891\r
892**/\r
893EFI_STATUS\r
894EslIp4TxBuffer (\r
895 IN ESL_SOCKET * pSocket,\r
896 IN int Flags,\r
897 IN size_t BufferLength,\r
898 IN CONST UINT8 * pBuffer,\r
899 OUT size_t * pDataLength,\r
900 IN const struct sockaddr * pAddress,\r
901 IN socklen_t AddressLength\r
902 )\r
903{\r
904 ESL_PACKET * pPacket;\r
905 ESL_PACKET * pPreviousPacket;\r
906 ESL_PORT * pPort;\r
907 const struct sockaddr_in * pRemoteAddress;\r
908 ESL_IP4_CONTEXT * pIp4;\r
909 size_t * pTxBytes;\r
910 ESL_IP4_TX_DATA * pTxData;\r
911 EFI_STATUS Status;\r
912 EFI_TPL TplPrevious;\r
913\r
914 DBG_ENTER ( );\r
915\r
916 //\r
917 // Assume failure\r
918 //\r
919 Status = EFI_UNSUPPORTED;\r
920 pSocket->errno = ENOTCONN;\r
921 *pDataLength = 0;\r
922\r
923 //\r
924 // Verify that the socket is connected\r
925 //\r
926 if ( SOCKET_STATE_CONNECTED == pSocket->State ) {\r
927 //\r
884ed923 928 // Verify that there is enough room to buffer another\r
929 // transmit operation\r
a88c3163 930 //\r
884ed923 931 pTxBytes = &pSocket->TxBytes;\r
932 if ( pSocket->MaxTxBuf > *pTxBytes ) {\r
a88c3163 933 //\r
884ed923 934 // Locate the port\r
a88c3163 935 //\r
884ed923 936 pPort = pSocket->pPortList;\r
937 while ( NULL != pPort ) {\r
938 //\r
939 // Determine the queue head\r
940 //\r
941 pIp4 = &pPort->Context.Ip4;\r
a88c3163 942\r
a88c3163 943 //\r
944 // Attempt to allocate the packet\r
945 //\r
946 Status = EslSocketPacketAllocate ( &pPacket,\r
947 sizeof ( pPacket->Op.Ip4Tx )\r
948 - sizeof ( pPacket->Op.Ip4Tx.Buffer )\r
949 + BufferLength,\r
950 0,\r
951 DEBUG_TX );\r
952 if ( !EFI_ERROR ( Status )) {\r
953 //\r
954 // Initialize the transmit operation\r
955 //\r
956 pTxData = &pPacket->Op.Ip4Tx;\r
957 pTxData->TxData.DestinationAddress.Addr[0] = pIp4->DestinationAddress.Addr[0];\r
958 pTxData->TxData.DestinationAddress.Addr[1] = pIp4->DestinationAddress.Addr[1];\r
959 pTxData->TxData.DestinationAddress.Addr[2] = pIp4->DestinationAddress.Addr[2];\r
960 pTxData->TxData.DestinationAddress.Addr[3] = pIp4->DestinationAddress.Addr[3];\r
961 pTxData->TxData.OverrideData = NULL;\r
962 pTxData->TxData.OptionsLength = 0;\r
963 pTxData->TxData.OptionsBuffer = NULL;\r
964 pTxData->TxData.TotalDataLength = (UINT32) BufferLength;\r
965 pTxData->TxData.FragmentCount = 1;\r
966 pTxData->TxData.FragmentTable[0].FragmentLength = (UINT32) BufferLength;\r
967 pTxData->TxData.FragmentTable[0].FragmentBuffer = &pPacket->Op.Ip4Tx.Buffer[0];\r
968\r
969 //\r
970 // Set the remote system address if necessary\r
971 //\r
972 if ( NULL != pAddress ) {\r
973 pRemoteAddress = (const struct sockaddr_in *)pAddress;\r
974 pTxData->Override.SourceAddress.Addr[0] = pIp4->ModeData.ConfigData.StationAddress.Addr[0];\r
975 pTxData->Override.SourceAddress.Addr[1] = pIp4->ModeData.ConfigData.StationAddress.Addr[1];\r
976 pTxData->Override.SourceAddress.Addr[2] = pIp4->ModeData.ConfigData.StationAddress.Addr[2];\r
977 pTxData->Override.SourceAddress.Addr[3] = pIp4->ModeData.ConfigData.StationAddress.Addr[3];\r
978 pTxData->TxData.DestinationAddress.Addr[0] = (UINT8)pRemoteAddress->sin_addr.s_addr;\r
979 pTxData->TxData.DestinationAddress.Addr[1] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 8 );\r
980 pTxData->TxData.DestinationAddress.Addr[2] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 16 );\r
981 pTxData->TxData.DestinationAddress.Addr[3] = (UINT8)( pRemoteAddress->sin_addr.s_addr >> 24 );\r
982 pTxData->Override.GatewayAddress.Addr[0] = 0;\r
983 pTxData->Override.GatewayAddress.Addr[1] = 0;\r
984 pTxData->Override.GatewayAddress.Addr[2] = 0;\r
985 pTxData->Override.GatewayAddress.Addr[3] = 0;\r
986 pTxData->Override.Protocol = (UINT8)pSocket->Protocol;\r
987 pTxData->Override.TypeOfService = 0;\r
988 pTxData->Override.TimeToLive = 255;\r
989 pTxData->Override.DoNotFragment = FALSE;\r
990\r
991 //\r
992 // Use the remote system address when sending this packet\r
993 //\r
994 pTxData->TxData.OverrideData = &pTxData->Override;\r
995 }\r
996\r
997 //\r
998 // Copy the data into the buffer\r
999 //\r
1000 CopyMem ( &pPacket->Op.Ip4Tx.Buffer[0],\r
1001 pBuffer,\r
1002 BufferLength );\r
1003\r
1004 //\r
1005 // Synchronize with the socket layer\r
1006 //\r
1007 RAISE_TPL ( TplPrevious, TPL_SOCKETS );\r
1008\r
1009 //\r
2dc09dd5 1010 // Display the request\r
a88c3163 1011 //\r
2dc09dd5
LL
1012 DEBUG (( DEBUG_TX,\r
1013 "Send %d bytes from 0x%08x, %d.%d.%d.%d --> %d.%d.%d.%d\r\n",\r
1014 BufferLength,\r
1015 pBuffer,\r
1016 pIp4->ModeData.ConfigData.StationAddress.Addr[0],\r
1017 pIp4->ModeData.ConfigData.StationAddress.Addr[1],\r
1018 pIp4->ModeData.ConfigData.StationAddress.Addr[2],\r
1019 pIp4->ModeData.ConfigData.StationAddress.Addr[3],\r
1020 pTxData->TxData.DestinationAddress.Addr[0],\r
1021 pTxData->TxData.DestinationAddress.Addr[1],\r
1022 pTxData->TxData.DestinationAddress.Addr[2],\r
1023 pTxData->TxData.DestinationAddress.Addr[3]));\r
a88c3163 1024\r
2dc09dd5
LL
1025 //\r
1026 // Queue the data for transmission\r
1027 //\r
1028 pPacket->pNext = NULL;\r
1029 pPreviousPacket = pSocket->pTxPacketListTail;\r
1030 if ( NULL == pPreviousPacket ) {\r
1031 pSocket->pTxPacketListHead = pPacket;\r
a88c3163 1032 }\r
1033 else {\r
2dc09dd5
LL
1034 pPreviousPacket->pNext = pPacket;\r
1035 }\r
1036 pSocket->pTxPacketListTail = pPacket;\r
1037 DEBUG (( DEBUG_TX,\r
1038 "0x%08x: Packet on transmit list\r\n",\r
1039 pPacket ));\r
1040\r
1041 //\r
1042 // Account for the buffered data\r
1043 //\r
1044 *pTxBytes += BufferLength;\r
1045 *pDataLength = BufferLength;\r
1046\r
1047 //\r
1048 // Start the transmit engine if it is idle\r
1049 //\r
1050 if ( NULL != pPort->pTxFree ) {\r
1051 EslSocketTxStart ( pPort,\r
1052 &pSocket->pTxPacketListHead,\r
1053 &pSocket->pTxPacketListTail,\r
1054 &pPort->pTxActive,\r
1055 &pPort->pTxFree );\r
a88c3163 1056\r
1057 //\r
2dc09dd5 1058 // Ignore any transmit error\r
a88c3163 1059 //\r
2dc09dd5
LL
1060 if ( EFI_ERROR ( pSocket->TxError )) {\r
1061 DEBUG (( DEBUG_TX,\r
1062 "0x%08x: Transmit error, Packet: 0x%08x, Status: %r\r\n",\r
1063 pPort,\r
1064 pPacket,\r
1065 pSocket->TxError ));\r
1066 }\r
1067 pSocket->TxError = EFI_SUCCESS;\r
a88c3163 1068 }\r
1069\r
1070 //\r
1071 // Release the socket layer synchronization\r
1072 //\r
1073 RESTORE_TPL ( TplPrevious );\r
1074 }\r
1075 else {\r
1076 //\r
1077 // Packet allocation failed\r
1078 //\r
1079 pSocket->errno = ENOMEM;\r
884ed923 1080 break;\r
a88c3163 1081 }\r
884ed923 1082\r
a88c3163 1083 //\r
884ed923 1084 // Set the next port\r
a88c3163 1085 //\r
884ed923 1086 pPort = pPort->pLinkSocket;\r
a88c3163 1087 }\r
1088 }\r
884ed923 1089 else {\r
1090 //\r
1091 // Not enough buffer space available\r
1092 //\r
1093 pSocket->errno = EAGAIN;\r
1094 Status = EFI_NOT_READY;\r
1095 }\r
a88c3163 1096 }\r
1097\r
1098 //\r
1099 // Return the operation status\r
1100 //\r
1101 DBG_EXIT_STATUS ( Status );\r
1102 return Status;\r
1103}\r
1104\r
1105\r
1106/**\r
1107 Process the transmit completion\r
1108\r
1109 This routine use ::EslSocketTxComplete to perform the transmit\r
1110 completion processing for data packets.\r
1111\r
1112 This routine is called by the IPv4 network layer when a data\r
1113 transmit request completes.\r
1114\r
1115 @param [in] Event The normal transmit completion event\r
1116\r
1117 @param [in] pIo The address of an ::ESL_IO_MGMT structure\r
1118\r
1119**/\r
1120VOID\r
1121EslIp4TxComplete (\r
1122 IN EFI_EVENT Event,\r
1123 IN ESL_IO_MGMT * pIo\r
1124 )\r
1125{\r
1126 UINT32 LengthInBytes;\r
1127 ESL_PORT * pPort;\r
1128 ESL_PACKET * pPacket;\r
1129 ESL_SOCKET * pSocket;\r
1130 EFI_STATUS Status;\r
0e565888 1131\r
a88c3163 1132 DBG_ENTER ( );\r
0e565888 1133\r
a88c3163 1134 //\r
1135 // Locate the active transmit packet\r
1136 //\r
1137 pPacket = pIo->pPacket;\r
1138 pPort = pIo->pPort;\r
1139 pSocket = pPort->pSocket;\r
1140\r
1141 //\r
1142 // Get the transmit length and status\r
1143 //\r
1144 LengthInBytes = pPacket->Op.Ip4Tx.TxData.TotalDataLength;\r
1145 pSocket->TxBytes -= LengthInBytes;\r
1146 Status = pIo->Token.Ip4Tx.Status;\r
1147\r
2dc09dd5
LL
1148 //\r
1149 // Ignore the transmit error\r
1150 //\r
1151 if ( EFI_ERROR ( Status )) {\r
1152 DEBUG (( DEBUG_TX,\r
1153 "0x%08x: Transmit completion error, Packet: 0x%08x, Status: %r\r\n",\r
1154 pPort,\r
1155 pPacket,\r
1156 Status ));\r
1157 Status = EFI_SUCCESS;\r
1158 }\r
1159\r
a88c3163 1160 //\r
1161 // Complete the transmit operation\r
1162 //\r
1163 EslSocketTxComplete ( pIo,\r
1164 LengthInBytes,\r
1165 Status,\r
1166 "Raw ",\r
1167 &pSocket->pTxPacketListHead,\r
1168 &pSocket->pTxPacketListTail,\r
1169 &pPort->pTxActive,\r
1170 &pPort->pTxFree );\r
1171 DBG_EXIT ( );\r
1172}\r
1173\r
1174\r
2dc09dd5
LL
1175/**\r
1176 Verify the adapter's IP address\r
1177\r
1178 This support routine is called by EslSocketBindTest.\r
1179\r
1180 @param [in] pPort Address of an ::ESL_PORT structure.\r
1181 @param [in] pConfigData Address of the configuration data\r
1182\r
1183 @retval EFI_SUCCESS - The IP address is valid\r
1184 @retval EFI_NOT_STARTED - The IP address is invalid\r
1185\r
1186 **/\r
1187EFI_STATUS\r
1188EslIp4VerifyLocalIpAddress (\r
1189 IN ESL_PORT * pPort,\r
1190 IN EFI_IP4_CONFIG_DATA * pConfigData\r
1191 )\r
1192{\r
1193 UINTN DataSize;\r
c581e503 1194 EFI_IP4_CONFIG2_INTERFACE_INFO * pIfInfo;\r
1195 EFI_IP4_CONFIG2_PROTOCOL * pIpConfig2Protocol;\r
2dc09dd5
LL
1196 ESL_SERVICE * pService;\r
1197 EFI_STATUS Status;\r
1198\r
1199 DBG_ENTER ( );\r
1200\r
1201 //\r
1202 // Use break instead of goto\r
1203 //\r
c581e503 1204 pIfInfo = NULL;\r
2dc09dd5
LL
1205 for ( ; ; ) {\r
1206 //\r
1207 // Determine if the IP address is specified\r
1208 //\r
1209 DEBUG (( DEBUG_BIND,\r
1210 "UseDefaultAddress: %s\r\n",\r
1211 pConfigData->UseDefaultAddress ? L"TRUE" : L"FALSE" ));\r
1212 DEBUG (( DEBUG_BIND,\r
1213 "Requested IP address: %d.%d.%d.%d\r\n",\r
1214 pConfigData->StationAddress.Addr [ 0 ],\r
1215 pConfigData->StationAddress.Addr [ 1 ],\r
1216 pConfigData->StationAddress.Addr [ 2 ],\r
1217 pConfigData->StationAddress.Addr [ 3 ]));\r
1218 if ( pConfigData->UseDefaultAddress\r
1219 || (( 0 == pConfigData->StationAddress.Addr [ 0 ])\r
1220 && ( 0 == pConfigData->StationAddress.Addr [ 1 ])\r
1221 && ( 0 == pConfigData->StationAddress.Addr [ 2 ])\r
1222 && ( 0 == pConfigData->StationAddress.Addr [ 3 ])))\r
1223 {\r
1224 Status = EFI_SUCCESS;\r
1225 break;\r
1226 }\r
1227\r
1228 //\r
1229 // Open the configuration protocol\r
1230 //\r
1231 pService = pPort->pService;\r
c581e503 1232 Status = gBS->OpenProtocol ( \r
1233 pService->Controller,\r
1234 &gEfiIp4Config2ProtocolGuid,\r
1235 (VOID **)&pIpConfig2Protocol,\r
1236 NULL,\r
1237 NULL,\r
1238 EFI_OPEN_PROTOCOL_GET_PROTOCOL \r
1239 );\r
2dc09dd5
LL
1240 if ( EFI_ERROR ( Status )) {\r
1241 DEBUG (( DEBUG_ERROR,\r
1242 "ERROR - IP Configuration Protocol not available, Status: %r\r\n",\r
1243 Status ));\r
1244 break;\r
1245 }\r
1246\r
1247 //\r
c581e503 1248 // Get the interface information size.\r
2dc09dd5
LL
1249 //\r
1250 DataSize = 0;\r
c581e503 1251 Status = pIpConfig2Protocol->GetData ( \r
1252 pIpConfig2Protocol,\r
1253 Ip4Config2DataTypeInterfaceInfo,\r
1254 &DataSize,\r
1255 NULL\r
1256 );\r
2dc09dd5
LL
1257 if ( EFI_BUFFER_TOO_SMALL != Status ) {\r
1258 DEBUG (( DEBUG_ERROR,\r
c581e503 1259 "ERROR - Failed to get the interface information size, Status: %r\r\n",\r
2dc09dd5
LL
1260 Status ));\r
1261 break;\r
1262 }\r
1263\r
1264 //\r
c581e503 1265 // Allocate the interface information buffer\r
2dc09dd5 1266 //\r
c581e503 1267 pIfInfo = AllocatePool ( DataSize );\r
1268 if ( NULL == pIfInfo ) {\r
2dc09dd5 1269 DEBUG (( DEBUG_ERROR,\r
c581e503 1270 "ERROR - Not enough memory to allocate the interface information buffer!\r\n" ));\r
2dc09dd5
LL
1271 Status = EFI_OUT_OF_RESOURCES;\r
1272 break;\r
1273 }\r
1274\r
1275 //\r
c581e503 1276 // Get the interface info.\r
2dc09dd5 1277 //\r
c581e503 1278 Status = pIpConfig2Protocol->GetData ( \r
1279 pIpConfig2Protocol,\r
1280 Ip4Config2DataTypeInterfaceInfo,\r
1281 &DataSize,\r
1282 pIfInfo\r
1283 );\r
2dc09dd5
LL
1284 if ( EFI_ERROR ( Status )) {\r
1285 DEBUG (( DEBUG_ERROR,\r
c581e503 1286 "ERROR - Failed to return the interface info, Status: %r\r\n",\r
2dc09dd5
LL
1287 Status ));\r
1288 break;\r
1289 }\r
1290\r
1291 //\r
1292 // Display the current configuration\r
1293 //\r
1294 DEBUG (( DEBUG_BIND,\r
1295 "Actual adapter IP address: %d.%d.%d.%d\r\n",\r
c581e503 1296 pIfInfo->StationAddress.Addr [ 0 ],\r
1297 pIfInfo->StationAddress.Addr [ 1 ],\r
1298 pIfInfo->StationAddress.Addr [ 2 ],\r
1299 pIfInfo->StationAddress.Addr [ 3 ]));\r
2dc09dd5
LL
1300\r
1301 //\r
1302 // Assume the port is not configured\r
1303 //\r
1304 Status = EFI_SUCCESS;\r
c581e503 1305 if (( pConfigData->StationAddress.Addr [ 0 ] == pIfInfo->StationAddress.Addr [ 0 ])\r
1306 && ( pConfigData->StationAddress.Addr [ 1 ] == pIfInfo->StationAddress.Addr [ 1 ])\r
1307 && ( pConfigData->StationAddress.Addr [ 2 ] == pIfInfo->StationAddress.Addr [ 2 ])\r
1308 && ( pConfigData->StationAddress.Addr [ 3 ] == pIfInfo->StationAddress.Addr [ 3 ])) {\r
2dc09dd5
LL
1309 break;\r
1310 }\r
1311\r
1312 //\r
1313 // The IP address did not match\r
1314 //\r
1315 Status = EFI_NOT_STARTED;\r
1316 break;\r
1317 }\r
1318\r
1319 //\r
1320 // Free the buffer if necessary\r
1321 //\r
c581e503 1322 if ( NULL != pIfInfo ) {\r
1323 FreePool ( pIfInfo );\r
2dc09dd5
LL
1324 }\r
1325\r
1326 //\r
1327 // Return the IP address status\r
1328 //\r
1329 DBG_EXIT_STATUS ( Status );\r
1330 return Status;\r
1331}\r
1332\r
1333\r
a88c3163 1334/**\r
1335 Interface between the socket layer and the network specific\r
1336 code that supports SOCK_RAW sockets over IPv4.\r
1337**/\r
1338CONST ESL_PROTOCOL_API cEslIp4Api = {\r
1339 "IPv4",\r
1340 IPPROTO_IP,\r
1341 OFFSET_OF ( ESL_PORT, Context.Ip4.ModeData.ConfigData ),\r
1342 OFFSET_OF ( ESL_LAYER, pIp4List ),\r
1343 OFFSET_OF ( struct sockaddr_in, sin_zero ),\r
1344 sizeof ( struct sockaddr_in ),\r
1345 AF_INET,\r
1346 sizeof (((ESL_PACKET *)0 )->Op.Ip4Rx ),\r
1347 sizeof (((ESL_PACKET *)0 )->Op.Ip4Rx ),\r
1348 OFFSET_OF ( ESL_IO_MGMT, Token.Ip4Rx.Packet.RxData ),\r
1349 FALSE,\r
1350 EADDRNOTAVAIL,\r
1351 NULL, // Accept\r
1352 NULL, // ConnectPoll\r
1353 NULL, // ConnectStart\r
1354 EslIp4SocketIsConfigured,\r
1355 EslIp4LocalAddressGet,\r
1356 EslIp4LocalAddressSet,\r
1357 NULL, // Listen\r
1358 EslIp4OptionGet,\r
1359 EslIp4OptionSet,\r
1360 EslIp4PacketFree,\r
1361 EslIp4PortAllocate,\r
1362 NULL, // PortClose\r
1363 NULL, // PortCloseOp\r
1364 TRUE,\r
1365 EslIp4Receive,\r
1366 EslIp4RemoteAddressGet,\r
1367 EslIp4RemoteAddressSet,\r
1368 EslIp4RxComplete,\r
1369 NULL, // RxStart\r
1370 EslIp4TxBuffer,\r
1371 EslIp4TxComplete,\r
2dc09dd5 1372 NULL, // TxOobComplete\r
a93b0f45 1373 (PFN_API_VERIFY_LOCAL_IP_ADDRESS)EslIp4VerifyLocalIpAddress\r
a88c3163 1374};\r