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