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