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