8a67d61d |
1 | /** @file\r |
2 | \r |
3 | Copyright (c) 2006 - 2007, Intel Corporation\r |
4 | All rights reserved. This program and the accompanying materials\r |
5 | are licensed and made available under the terms and conditions of the BSD License\r |
6 | which accompanies this distribution. The full text of the license may be found at\r |
7 | http://opensource.org/licenses/bsd-license.php\r |
8 | \r |
9 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r |
10 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r |
11 | \r |
12 | Module Name:\r |
13 | \r |
14 | Udp4Main.c\r |
15 | \r |
16 | Abstract:\r |
17 | \r |
18 | \r |
19 | **/\r |
20 | \r |
21 | #include "Udp4Impl.h"\r |
22 | \r |
23 | #include <Protocol/Ip4.h>\r |
24 | \r |
25 | EFI_UDP4_PROTOCOL mUdp4Protocol = {\r |
26 | Udp4GetModeData,\r |
27 | Udp4Configure,\r |
28 | Udp4Groups,\r |
29 | Udp4Routes,\r |
30 | Udp4Transmit,\r |
31 | Udp4Receive,\r |
32 | Udp4Cancel,\r |
33 | Udp4Poll\r |
34 | };\r |
35 | \r |
36 | \r |
37 | /**\r |
38 | This function copies the current operational settings of this EFI UDPv4 Protocol\r |
39 | instance into user-supplied buffers. This function is used optionally to retrieve\r |
40 | the operational mode data of underlying networks or drivers.\r |
41 | \r |
42 | @param This Pointer to the EFI_UDP4_PROTOCOL instance.\r |
43 | @param Udp4ConfigData Pointer to the buffer to receive the current\r |
44 | configuration data.\r |
45 | @param Ip4ModeData Pointer to the EFI IPv4 Protocol mode data\r |
46 | structure.\r |
47 | @param MnpConfigData Pointer to the managed network configuration data\r |
48 | structure.\r |
49 | @param SnpModeData Pointer to the simple network mode data structure.\r |
50 | \r |
51 | @retval EFI_SUCCESS The mode data was read.\r |
52 | @retval EFI_NOT_STARTED When Udp4ConfigData is queried, no configuration\r |
53 | data is available because this instance has not\r |
54 | been started.\r |
55 | @retval EFI_INVALID_PARAMETER This is NULL.\r |
56 | \r |
57 | **/\r |
58 | EFI_STATUS\r |
59 | EFIAPI\r |
60 | Udp4GetModeData (\r |
61 | IN EFI_UDP4_PROTOCOL *This,\r |
62 | OUT EFI_UDP4_CONFIG_DATA *Udp4ConfigData OPTIONAL,\r |
63 | OUT EFI_IP4_MODE_DATA *Ip4ModeData OPTIONAL,\r |
64 | OUT EFI_MANAGED_NETWORK_CONFIG_DATA *MnpConfigData OPTIONAL,\r |
65 | OUT EFI_SIMPLE_NETWORK_MODE *SnpModeData OPTIONAL\r |
66 | )\r |
67 | {\r |
68 | UDP4_INSTANCE_DATA *Instance;\r |
69 | EFI_IP4_PROTOCOL *Ip;\r |
70 | EFI_TPL OldTpl;\r |
71 | EFI_STATUS Status;\r |
72 | \r |
73 | if (This == NULL) {\r |
74 | return EFI_INVALID_PARAMETER;\r |
75 | }\r |
76 | \r |
77 | Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);\r |
78 | \r |
79 | if (!Instance->Configured && (Udp4ConfigData != NULL)) {\r |
80 | return EFI_NOT_STARTED;\r |
81 | }\r |
82 | \r |
83 | OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r |
84 | \r |
85 | if (Udp4ConfigData != NULL) {\r |
86 | //\r |
87 | // Set the Udp4ConfigData.\r |
88 | //\r |
687a2e5f |
89 | CopyMem (Udp4ConfigData, &Instance->ConfigData, sizeof (*Udp4ConfigData));\r |
8a67d61d |
90 | }\r |
91 | \r |
92 | Ip = Instance->IpInfo->Ip;\r |
93 | \r |
94 | //\r |
95 | // Get the underlying Ip4ModeData, MnpConfigData and SnpModeData.\r |
96 | //\r |
97 | Status = Ip->GetModeData (Ip, Ip4ModeData, MnpConfigData, SnpModeData);\r |
98 | \r |
99 | NET_RESTORE_TPL (OldTpl);\r |
100 | \r |
101 | return Status;\r |
102 | }\r |
103 | \r |
104 | \r |
105 | /**\r |
106 | This function is used to do the following:\r |
107 | Initialize and start this instance of the EFI UDPv4 Protocol.\r |
108 | Change the filtering rules and operational parameters.\r |
109 | Reset this instance of the EFI UDPv4 Protocol.\r |
110 | \r |
111 | @param This Pointer to the EFI_UDP4_PROTOCOL instance.\r |
112 | @param UdpConfigData Pointer to the buffer to receive the current mode\r |
113 | data.\r |
114 | \r |
115 | @retval EFI_SUCCESS The configuration settings were set, changed, or\r |
116 | reset successfully.\r |
117 | @retval EFI_NO_MAPPING When using a default address, configuration (DHCP,\r |
118 | BOOTP, RARP, etc.) is not finished yet.\r |
119 | @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE: This is\r |
120 | NULL. UdpConfigData.StationAddress is not a valid\r |
121 | unicast IPv4 address. UdpConfigData.SubnetMask is\r |
122 | not a valid IPv4 address mask.\r |
123 | UdpConfigData.RemoteAddress is not a valid unicast\r |
124 | IPv4 address if it is not zero.\r |
125 | @retval EFI_ALREADY_STARTED The EFI UDPv4 Protocol instance is already\r |
126 | started/configured and must be stopped/reset\r |
127 | before it can be reconfigured. Only TypeOfService,\r |
128 | TimeToLive, DoNotFragment, ReceiveTimeout, and\r |
129 | TransmitTimeout can be reconfigured without\r |
130 | stopping the current instance of the EFI UDPv4\r |
131 | Protocol.\r |
132 | @retval EFI_ACCESS_DENIED UdpConfigData.AllowDuplicatePort is FALSE and\r |
133 | UdpConfigData.StationPort is already used by other\r |
134 | instance.\r |
135 | @retval EFI_OUT_OF_RESOURCES The EFI UDPv4 Protocol driver cannot allocate\r |
136 | memory for this EFI UDPv4 Protocol instance.\r |
137 | @retval EFI_DEVICE_ERROR An unexpected network or system error occurred and\r |
138 | this instance was not opened.\r |
139 | \r |
140 | **/\r |
141 | EFI_STATUS\r |
142 | EFIAPI\r |
143 | Udp4Configure (\r |
144 | IN EFI_UDP4_PROTOCOL *This,\r |
145 | IN EFI_UDP4_CONFIG_DATA *UdpConfigData OPTIONAL\r |
146 | )\r |
147 | {\r |
148 | EFI_STATUS Status;\r |
149 | UDP4_INSTANCE_DATA *Instance;\r |
150 | UDP4_SERVICE_DATA *Udp4Service;\r |
151 | EFI_TPL OldTpl;\r |
152 | IP4_ADDR StationAddress;\r |
153 | IP4_ADDR SubnetMask;\r |
154 | IP4_ADDR RemoteAddress;\r |
155 | EFI_IP4_CONFIG_DATA Ip4ConfigData;\r |
772db4bb |
156 | IP4_ADDR LocalAddr;\r |
157 | IP4_ADDR RemoteAddr;\r |
8a67d61d |
158 | \r |
159 | if (This == NULL) {\r |
160 | return EFI_INVALID_PARAMETER;\r |
161 | }\r |
162 | \r |
163 | Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);\r |
164 | \r |
165 | if (!Instance->Configured && (UdpConfigData == NULL)) {\r |
166 | return EFI_SUCCESS;\r |
167 | }\r |
168 | \r |
169 | Udp4Service = Instance->Udp4Service;\r |
170 | Status = EFI_SUCCESS;\r |
171 | \r |
172 | OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r |
173 | \r |
174 | if (UdpConfigData != NULL) {\r |
175 | \r |
772db4bb |
176 | NetCopyMem (&StationAddress, &UdpConfigData->StationAddress, sizeof (IP4_ADDR));\r |
177 | NetCopyMem (&SubnetMask, &UdpConfigData->SubnetMask, sizeof (IP4_ADDR));\r |
178 | NetCopyMem (&RemoteAddress, &UdpConfigData->RemoteAddress, sizeof (IP4_ADDR));\r |
179 | \r |
180 | StationAddress = NTOHL (StationAddress);\r |
181 | SubnetMask = NTOHL (SubnetMask);\r |
182 | RemoteAddress = NTOHL (RemoteAddress);\r |
183 | \r |
8a67d61d |
184 | \r |
185 | if (!UdpConfigData->UseDefaultAddress &&\r |
186 | (!IP4_IS_VALID_NETMASK (SubnetMask) ||\r |
187 | !((StationAddress == 0) || Ip4IsUnicast (StationAddress, SubnetMask)) ||\r |
188 | !((RemoteAddress == 0) || Ip4IsUnicast (RemoteAddress, 0)))) {\r |
189 | //\r |
190 | // Don't use default address, and subnet mask is invalid or StationAddress is not\r |
191 | // a valid unicast IPv4 address or RemoteAddress is not a valid unicast IPv4 address\r |
192 | // if it is not 0.\r |
193 | //\r |
194 | Status = EFI_INVALID_PARAMETER;\r |
195 | goto ON_EXIT;\r |
196 | }\r |
197 | \r |
198 | if (Instance->Configured) {\r |
199 | //\r |
200 | // The instance is already configured, try to do the re-configuration.\r |
201 | //\r |
202 | if (!Udp4IsReconfigurable (&Instance->ConfigData, UdpConfigData)) {\r |
203 | //\r |
204 | // If the new configuration data wants to change some unreconfigurable\r |
205 | // settings, return EFI_ALREADY_STARTED.\r |
206 | //\r |
207 | Status = EFI_ALREADY_STARTED;\r |
208 | goto ON_EXIT;\r |
209 | }\r |
210 | \r |
211 | //\r |
212 | // Save the reconfigurable parameters.\r |
213 | //\r |
214 | Instance->ConfigData.TypeOfService = UdpConfigData->TypeOfService;\r |
215 | Instance->ConfigData.TimeToLive = UdpConfigData->TimeToLive;\r |
216 | Instance->ConfigData.DoNotFragment = UdpConfigData->DoNotFragment;\r |
217 | Instance->ConfigData.ReceiveTimeout = UdpConfigData->ReceiveTimeout;\r |
218 | Instance->ConfigData.TransmitTimeout = UdpConfigData->TransmitTimeout;\r |
219 | } else {\r |
220 | //\r |
221 | // Construct the Ip configuration data from the UdpConfigData.\r |
222 | //\r |
223 | Udp4BuildIp4ConfigData (UdpConfigData, &Ip4ConfigData);\r |
224 | \r |
225 | //\r |
226 | // Configure the Ip instance wrapped in the IpInfo.\r |
227 | //\r |
228 | Status = IpIoConfigIp (Instance->IpInfo, &Ip4ConfigData);\r |
229 | if (EFI_ERROR (Status)) {\r |
230 | if (Status == EFI_NO_MAPPING) {\r |
231 | Instance->IsNoMapping = TRUE;\r |
232 | }\r |
233 | \r |
234 | goto ON_EXIT;\r |
235 | }\r |
236 | \r |
237 | Instance->IsNoMapping = FALSE;\r |
238 | \r |
239 | //\r |
240 | // Save the configuration data.\r |
241 | //\r |
687a2e5f |
242 | CopyMem (&Instance->ConfigData, UdpConfigData, sizeof (Instance->ConfigData));\r |
8a67d61d |
243 | Instance->ConfigData.StationAddress = Ip4ConfigData.StationAddress;\r |
244 | Instance->ConfigData.SubnetMask = Ip4ConfigData.SubnetMask;\r |
245 | \r |
246 | //\r |
247 | // Try to allocate the required port resource.\r |
248 | //\r |
249 | Status = Udp4Bind (&Udp4Service->ChildrenList, &Instance->ConfigData);\r |
250 | if (EFI_ERROR (Status)) {\r |
251 | //\r |
252 | // Reset the ip instance if bind fails.\r |
253 | //\r |
254 | IpIoConfigIp (Instance->IpInfo, NULL);\r |
255 | goto ON_EXIT;\r |
256 | }\r |
257 | \r |
258 | //\r |
259 | // Pre calculate the checksum for the pseudo head, ignore the UDP length first.\r |
260 | //\r |
772db4bb |
261 | NetCopyMem (&LocalAddr, &Instance->ConfigData.StationAddress, sizeof (IP4_ADDR));\r |
262 | NetCopyMem (&RemoteAddr, &Instance->ConfigData.RemoteAddress, sizeof (IP4_ADDR));\r |
8a67d61d |
263 | Instance->HeadSum = NetPseudoHeadChecksum (\r |
772db4bb |
264 | LocalAddr,\r |
265 | RemoteAddr,\r |
8a67d61d |
266 | EFI_IP_PROTO_UDP,\r |
267 | 0\r |
268 | );\r |
269 | \r |
270 | Instance->Configured = TRUE;\r |
271 | }\r |
272 | } else {\r |
273 | //\r |
274 | // UdpConfigData is NULL, reset the instance.\r |
275 | //\r |
276 | Instance->Configured = FALSE;\r |
277 | Instance->IsNoMapping = FALSE;\r |
278 | \r |
279 | //\r |
280 | // Reset the Ip instance wrapped in the IpInfo.\r |
281 | //\r |
282 | IpIoConfigIp (Instance->IpInfo, NULL);\r |
283 | \r |
284 | //\r |
285 | // Cancel all the user tokens.\r |
286 | //\r |
287 | Udp4InstanceCancelToken (Instance, NULL);\r |
288 | \r |
289 | //\r |
290 | // Remove the buffered RxData for this instance.\r |
291 | //\r |
292 | Udp4FlushRxData (&Instance->RcvdDgramQue);\r |
293 | }\r |
294 | \r |
295 | Udp4SetVariableData (Instance->Udp4Service);\r |
296 | \r |
297 | ON_EXIT:\r |
298 | \r |
299 | NET_RESTORE_TPL (OldTpl);\r |
300 | \r |
301 | return Status;\r |
302 | }\r |
303 | \r |
304 | \r |
305 | /**\r |
306 | This function is used to enable and disable the multicast group filtering.\r |
307 | \r |
308 | @param This Pointer to the EFI_UDP4_PROTOCOL instance.\r |
309 | @param JoinFlag Set to TRUE to join a multicast group. Set to\r |
310 | FALSE to leave one or all multicast groups.\r |
311 | @param MulticastAddress Pointer to multicast group address to join or\r |
312 | leave.\r |
313 | \r |
314 | @retval EFI_SUCCESS The operation completed successfully.\r |
315 | @retval EFI_NOT_STARTED The EFI UDPv4 Protocol instance has not been\r |
316 | started.\r |
317 | @retval EFI_NO_MAPPING When using a default address, configuration (DHCP,\r |
318 | BOOTP, RARP, etc.) is not finished yet.\r |
319 | @retval EFI_OUT_OF_RESOURCES Could not allocate resources to join the group.\r |
320 | @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r |
321 | This is NULL. JoinFlag is TRUE and\r |
322 | MulticastAddress is NULL. JoinFlag is TRUE and\r |
323 | *MulticastAddress is not a valid multicast\r |
324 | address.\r |
325 | @retval EFI_ALREADY_STARTED The group address is already in the group table\r |
326 | (when JoinFlag is TRUE).\r |
327 | @retval EFI_NOT_FOUND The group address is not in the group table (when\r |
328 | JoinFlag is FALSE).\r |
329 | @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r |
330 | \r |
331 | **/\r |
332 | EFI_STATUS\r |
333 | EFIAPI\r |
334 | Udp4Groups (\r |
335 | IN EFI_UDP4_PROTOCOL *This,\r |
336 | IN BOOLEAN JoinFlag,\r |
337 | IN EFI_IPv4_ADDRESS *MulticastAddress OPTIONAL\r |
338 | )\r |
339 | {\r |
340 | EFI_STATUS Status;\r |
341 | UDP4_INSTANCE_DATA *Instance;\r |
342 | EFI_IP4_PROTOCOL *Ip;\r |
343 | EFI_TPL OldTpl;\r |
772db4bb |
344 | IP4_ADDR McastIp;\r |
8a67d61d |
345 | \r |
772db4bb |
346 | if ((This == NULL) || (JoinFlag && (MulticastAddress == NULL))) {\r |
8a67d61d |
347 | return EFI_INVALID_PARAMETER;\r |
348 | }\r |
349 | \r |
772db4bb |
350 | McastIp = 0;\r |
351 | if (JoinFlag) {\r |
352 | NetCopyMem (&McastIp, MulticastAddress, sizeof (IP4_ADDR));\r |
353 | \r |
687a2e5f |
354 | if (!IP4_IS_MULTICAST (NTOHL (McastIp))) {\r |
772db4bb |
355 | return EFI_INVALID_PARAMETER;\r |
356 | }\r |
357 | }\r |
358 | \r |
8a67d61d |
359 | Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);\r |
360 | \r |
361 | if (Instance->IsNoMapping) {\r |
362 | return EFI_NO_MAPPING;\r |
363 | }\r |
364 | \r |
365 | if (!Instance->Configured) {\r |
366 | return EFI_NOT_STARTED;\r |
367 | }\r |
368 | \r |
369 | Ip = Instance->IpInfo->Ip;\r |
370 | \r |
371 | OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r |
372 | \r |
373 | //\r |
374 | // Invoke the Ip instance the Udp4 instance consumes to do the group operation.\r |
375 | //\r |
376 | Status = Ip->Groups (Ip, JoinFlag, MulticastAddress);\r |
377 | \r |
378 | if (EFI_ERROR (Status)) {\r |
379 | goto ON_EXIT;\r |
380 | }\r |
381 | \r |
382 | //\r |
383 | // Keep a local copy of the configured multicast IPs because IpIo receives\r |
384 | // datagrams from the 0 station address IP instance and then UDP delivers to\r |
385 | // the matched instance. This copy of multicast IPs is used to avoid receive\r |
386 | // the mutlicast datagrams destinated to multicast IPs the other instances configured.\r |
387 | //\r |
388 | if (JoinFlag) {\r |
389 | \r |
772db4bb |
390 | NetMapInsertTail (&Instance->McastIps, (VOID *) (UINTN) McastIp, NULL);\r |
8a67d61d |
391 | } else {\r |
392 | \r |
393 | NetMapIterate (&Instance->McastIps, Udp4LeaveGroup, MulticastAddress);\r |
394 | }\r |
395 | \r |
396 | ON_EXIT:\r |
397 | \r |
398 | NET_RESTORE_TPL (OldTpl);\r |
399 | \r |
400 | return Status;\r |
401 | }\r |
402 | \r |
403 | \r |
404 | /**\r |
405 | This function adds a route to or deletes a route from the routing table.\r |
406 | \r |
407 | @param This Pointer to the EFI_UDP4_PROTOCOL instance.\r |
408 | @param DeleteRoute Set to TRUE to delete this route from the routing\r |
409 | table. Set to FALSE to add this route to the\r |
410 | routing table.\r |
411 | @param SubnetAddress The destination network address that needs to be\r |
412 | routed.\r |
413 | @param SubnetMask The subnet mask of SubnetAddress.\r |
414 | @param GatewayAddress The gateway IP address for this route.\r |
415 | \r |
416 | @retval EFI_SUCCESS The operation completed successfully.\r |
417 | @retval EFI_NOT_STARTED The EFI UDPv4 Protocol instance has not been\r |
418 | started.\r |
419 | @retval EFI_NO_MAPPING When using a default address, configuration (DHCP,\r |
420 | BOOTP, RARP, etc.) is not finished yet.\r |
421 | @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r |
422 | This is NULL. SubnetAddress is NULL. SubnetMask is\r |
423 | NULL. GatewayAddress is NULL. SubnetAddress is not\r |
424 | a valid subnet address. SubnetMask is not a valid\r |
425 | subnet mask. GatewayAddress is not a valid unicast\r |
426 | IP address.\r |
427 | @retval EFI_OUT_OF_RESOURCES Could not add the entry to the routing table.\r |
428 | @retval EFI_NOT_FOUND This route is not in the routing table.\r |
429 | @retval EFI_ACCESS_DENIED The route is already defined in the routing table.\r |
430 | \r |
431 | **/\r |
432 | EFI_STATUS\r |
433 | EFIAPI\r |
434 | Udp4Routes (\r |
435 | IN EFI_UDP4_PROTOCOL *This,\r |
436 | IN BOOLEAN DeleteRoute,\r |
437 | IN EFI_IPv4_ADDRESS *SubnetAddress,\r |
438 | IN EFI_IPv4_ADDRESS *SubnetMask,\r |
439 | IN EFI_IPv4_ADDRESS *GatewayAddress\r |
440 | )\r |
441 | {\r |
442 | UDP4_INSTANCE_DATA *Instance;\r |
443 | EFI_IP4_PROTOCOL *Ip;\r |
444 | \r |
445 | if (This == NULL) {\r |
446 | return EFI_INVALID_PARAMETER;\r |
447 | }\r |
448 | \r |
449 | Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);\r |
450 | \r |
451 | if (Instance->IsNoMapping) {\r |
452 | return EFI_NO_MAPPING;\r |
453 | }\r |
454 | \r |
455 | if (!Instance->Configured) {\r |
456 | return EFI_NOT_STARTED;\r |
457 | }\r |
458 | \r |
459 | Ip = Instance->IpInfo->Ip;\r |
460 | \r |
461 | //\r |
462 | // Invoke the Ip instance the Udp4 instance consumes to do the actual operation.\r |
463 | //\r |
464 | return Ip->Routes (Ip, DeleteRoute, SubnetAddress, SubnetMask, GatewayAddress);\r |
465 | }\r |
466 | \r |
467 | \r |
468 | /**\r |
469 | This function places a sending request to this instance of the EFI UDPv4 Protocol,\r |
470 | alongside the transmit data that was filled by the user.\r |
471 | \r |
472 | @param This Pointer to the EFI_UDP4_PROTOCOL instance.\r |
473 | @param Token Pointer to the completion token that will be\r |
474 | placed into the transmit queue.\r |
475 | \r |
476 | @retval EFI_SUCCESS The data has been queued for transmission.\r |
477 | @retval EFI_NOT_STARTED This EFI UDPv4 Protocol instance has not been\r |
478 | started.\r |
479 | @retval EFI_NO_MAPPING When using a default address, configuration (DHCP,\r |
480 | BOOTP, RARP, etc.) is not finished yet.\r |
481 | @retval EFI_INVALID_PARAMETER One or more of the following are TRUE: This is\r |
482 | NULL. Token is NULL. Token.Event is NULL.\r |
483 | Token.Packet.TxData is NULL.\r |
484 | Token.Packet.TxData.FragmentCount is zero.\r |
485 | Token.Packet.TxData.DataLength is not equal to the\r |
486 | sum of fragment lengths. One or more of the\r |
487 | Token.Packet.TxData.FragmentTable[].\r |
488 | FragmentLength fields is zero. One or more of the\r |
489 | Token.Packet.TxData.FragmentTable[].\r |
490 | FragmentBuffer fields is NULL.\r |
491 | Token.Packet.TxData. GatewayAddress is not a\r |
492 | unicast IPv4 address if it is not NULL. One or\r |
493 | more IPv4 addresses in Token.Packet.TxData.\r |
494 | UdpSessionData are not valid unicast IPv4\r |
495 | addresses if the UdpSessionData is not NULL.\r |
496 | @retval EFI_ACCESS_DENIED The transmit completion token with the same\r |
497 | Token.Event is already in the transmit queue.\r |
498 | @retval EFI_NOT_READY The completion token could not be queued because\r |
499 | the transmit queue is full.\r |
500 | @retval EFI_OUT_OF_RESOURCES Could not queue the transmit data.\r |
501 | @retval EFI_NOT_FOUND There is no route to the destination network or\r |
502 | address.\r |
503 | @retval EFI_BAD_BUFFER_SIZE The data length is greater than the maximum UDP\r |
504 | packet size. Or the length of the IP header + UDP\r |
505 | header + data length is greater than MTU if\r |
506 | DoNotFragment is TRUE.\r |
507 | \r |
508 | **/\r |
509 | EFI_STATUS\r |
510 | EFIAPI\r |
511 | Udp4Transmit (\r |
512 | IN EFI_UDP4_PROTOCOL *This,\r |
513 | IN EFI_UDP4_COMPLETION_TOKEN *Token\r |
514 | )\r |
515 | {\r |
516 | EFI_STATUS Status;\r |
517 | UDP4_INSTANCE_DATA *Instance;\r |
518 | EFI_TPL OldTpl;\r |
519 | NET_BUF *Packet;\r |
520 | EFI_UDP4_HEADER *Udp4Header;\r |
521 | EFI_UDP4_CONFIG_DATA *ConfigData;\r |
772db4bb |
522 | IP4_ADDR Source;\r |
8a67d61d |
523 | IP4_ADDR Destination;\r |
524 | EFI_UDP4_TRANSMIT_DATA *TxData;\r |
525 | EFI_UDP4_SESSION_DATA *UdpSessionData;\r |
526 | UDP4_SERVICE_DATA *Udp4Service;\r |
527 | IP_IO_OVERRIDE Override;\r |
528 | UINT16 HeadSum;\r |
529 | \r |
530 | if ((This == NULL) || (Token == NULL)) {\r |
531 | return EFI_INVALID_PARAMETER;\r |
532 | }\r |
533 | \r |
534 | Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);\r |
535 | \r |
536 | if (Instance->IsNoMapping) {\r |
537 | return EFI_NO_MAPPING;\r |
538 | }\r |
539 | \r |
540 | if (!Instance->Configured) {\r |
541 | return EFI_NOT_STARTED;\r |
542 | }\r |
543 | \r |
544 | OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r |
545 | \r |
546 | //\r |
547 | // Validate the Token, if the token is invalid return the error code.\r |
548 | //\r |
549 | Status = Udp4ValidateTxToken (Instance, Token);\r |
550 | if (EFI_ERROR (Status)) {\r |
551 | goto ON_EXIT;\r |
552 | }\r |
553 | \r |
554 | if (EFI_ERROR (NetMapIterate (&Instance->TxTokens, Udp4TokenExist, Token)) ||\r |
555 | EFI_ERROR (NetMapIterate (&Instance->RxTokens, Udp4TokenExist, Token))) {\r |
556 | //\r |
557 | // Try to find a duplicate token in the two token maps, if found, return\r |
558 | // EFI_ACCESS_DENIED.\r |
559 | //\r |
560 | Status = EFI_ACCESS_DENIED;\r |
561 | goto ON_EXIT;\r |
562 | }\r |
563 | \r |
564 | TxData = Token->Packet.TxData;\r |
565 | \r |
566 | //\r |
567 | // Create a net buffer to hold the user buffer and the udp header.\r |
568 | //\r |
569 | Packet = NetbufFromExt (\r |
570 | (NET_FRAGMENT *)TxData->FragmentTable,\r |
571 | TxData->FragmentCount,\r |
572 | UDP4_HEADER_SIZE,\r |
573 | 0,\r |
574 | Udp4NetVectorExtFree,\r |
575 | NULL\r |
576 | );\r |
577 | if (Packet == NULL) {\r |
578 | Status = EFI_OUT_OF_RESOURCES;\r |
579 | goto ON_EXIT;\r |
580 | }\r |
581 | \r |
582 | //\r |
583 | // Store the IpIo in ProtoData.\r |
584 | //\r |
585 | Udp4Service = Instance->Udp4Service;\r |
586 | *((UINTN *) &Packet->ProtoData[0]) = (UINTN) (Udp4Service->IpIo);\r |
587 | \r |
588 | Udp4Header = (EFI_UDP4_HEADER *) NetbufAllocSpace (Packet, UDP4_HEADER_SIZE, TRUE);\r |
589 | ConfigData = &Instance->ConfigData;\r |
590 | \r |
591 | //\r |
592 | // Fill the udp header.\r |
593 | //\r |
594 | Udp4Header->SrcPort = HTONS (ConfigData->StationPort);\r |
595 | Udp4Header->DstPort = HTONS (ConfigData->RemotePort);\r |
596 | Udp4Header->Length = HTONS (Packet->TotalSize);\r |
597 | Udp4Header->Checksum = 0;\r |
598 | \r |
599 | UdpSessionData = TxData->UdpSessionData;\r |
600 | Override.SourceAddress = ConfigData->StationAddress;\r |
601 | \r |
602 | if (UdpSessionData != NULL) {\r |
603 | //\r |
604 | // Set the SourceAddress, SrcPort and Destination according to the specified\r |
605 | // UdpSessionData.\r |
606 | //\r |
84b5c78e |
607 | if (!EFI_IP4_EQUAL (&UdpSessionData->SourceAddress, &mZeroIp4Addr)) {\r |
772db4bb |
608 | NetCopyMem (&Override.SourceAddress, &UdpSessionData->SourceAddress, sizeof (EFI_IPv4_ADDRESS));\r |
8a67d61d |
609 | }\r |
610 | \r |
611 | if (UdpSessionData->SourcePort != 0) {\r |
612 | Udp4Header->SrcPort = HTONS (UdpSessionData->SourcePort);\r |
613 | }\r |
614 | \r |
8a67d61d |
615 | if (UdpSessionData->DestinationPort != 0) {\r |
616 | Udp4Header->DstPort = HTONS (UdpSessionData->DestinationPort);\r |
617 | }\r |
618 | \r |
772db4bb |
619 | NetCopyMem (&Source, &Override.SourceAddress, sizeof (IP4_ADDR));\r |
620 | NetCopyMem (&Destination, &UdpSessionData->DestinationAddress, sizeof (IP4_ADDR));\r |
621 | \r |
8a67d61d |
622 | //\r |
623 | // calculate the pseudo head checksum using the overridden parameters.\r |
624 | //\r |
625 | HeadSum = NetPseudoHeadChecksum (\r |
772db4bb |
626 | Source,\r |
8a67d61d |
627 | Destination,\r |
628 | EFI_IP_PROTO_UDP,\r |
629 | 0\r |
630 | );\r |
631 | } else {\r |
632 | //\r |
633 | // UdpSessionData is NULL, use the address and port information previously configured.\r |
634 | //\r |
772db4bb |
635 | NetCopyMem (&Destination, &ConfigData->RemoteAddress, sizeof (IP4_ADDR));\r |
636 | \r |
637 | HeadSum = Instance->HeadSum;\r |
8a67d61d |
638 | }\r |
639 | \r |
640 | //\r |
641 | // calculate the checksum.\r |
642 | //\r |
643 | Udp4Header->Checksum = Udp4Checksum (Packet, HeadSum);\r |
644 | if (Udp4Header->Checksum == 0) {\r |
645 | //\r |
646 | // If the calculated checksum is 0, fill the Checksum field with all ones.\r |
647 | //\r |
648 | Udp4Header->Checksum = 0xffff;\r |
649 | }\r |
650 | \r |
651 | //\r |
652 | // Fill the IpIo Override data.\r |
653 | //\r |
772db4bb |
654 | if (TxData->GatewayAddress != NULL) {\r |
655 | NetCopyMem (&Override.GatewayAddress, TxData->GatewayAddress, sizeof (EFI_IPv4_ADDRESS));\r |
656 | } else {\r |
657 | NetZeroMem (&Override.GatewayAddress, sizeof (EFI_IPv4_ADDRESS));\r |
658 | }\r |
659 | \r |
8a67d61d |
660 | Override.Protocol = EFI_IP_PROTO_UDP;\r |
661 | Override.TypeOfService = ConfigData->TypeOfService;\r |
662 | Override.TimeToLive = ConfigData->TimeToLive;\r |
663 | Override.DoNotFragment = ConfigData->DoNotFragment;\r |
664 | \r |
665 | //\r |
666 | // Save the token into the TxToken map.\r |
667 | //\r |
668 | Status = NetMapInsertTail (&Instance->TxTokens, Token, Packet);\r |
669 | if (EFI_ERROR (Status)) {\r |
670 | goto FREE_PACKET;\r |
671 | }\r |
672 | \r |
673 | //\r |
674 | // Send out this datagram through IpIo.\r |
675 | //\r |
676 | Status = IpIoSend (\r |
677 | Udp4Service->IpIo,\r |
678 | Packet,\r |
679 | Instance->IpInfo,\r |
680 | Instance,\r |
681 | Token,\r |
682 | Destination,\r |
683 | &Override\r |
684 | );\r |
685 | if (EFI_ERROR (Status)) {\r |
686 | //\r |
687 | // Remove this token from the TxTokens.\r |
688 | //\r |
689 | Udp4RemoveToken (&Instance->TxTokens, Token);\r |
690 | }\r |
691 | \r |
692 | FREE_PACKET:\r |
693 | \r |
694 | NetbufFree (Packet);\r |
695 | \r |
696 | ON_EXIT:\r |
697 | \r |
698 | NET_RESTORE_TPL (OldTpl);\r |
699 | \r |
700 | return Status;\r |
701 | }\r |
702 | \r |
703 | \r |
704 | /**\r |
705 | This function places a completion token into the receive packet queue. This function\r |
706 | is always asynchronous.\r |
707 | \r |
708 | @param This Pointer to the EFI_UDP4_PROTOCOL instance.\r |
709 | @param Token Pointer to a token that is associated with the\r |
710 | receive data descriptor.\r |
711 | \r |
712 | @retval EFI_SUCCESS The receive completion token is cached.\r |
713 | @retval EFI_NOT_STARTED This EFI UDPv4 Protocol instance has not been\r |
714 | started.\r |
715 | @retval EFI_NO_MAPPING When using a default address, configuration (DHCP,\r |
716 | BOOTP, RARP, etc.) is not finished yet.\r |
717 | @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:\r |
718 | This is NULL. Token is NULL. Token.Event is NULL.\r |
719 | @retval EFI_OUT_OF_RESOURCES The receive completion token could not be queued\r |
720 | due to a lack of system resources (usually\r |
721 | memory).\r |
722 | @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r |
723 | The EFI UDPv4 Protocol instance has been reset to\r |
724 | startup defaults.\r |
725 | @retval EFI_ACCESS_DENIED A receive completion token with the same\r |
726 | Token.Event is already in the receive queue.\r |
727 | @retval EFI_NOT_READY The receive request could not be queued because\r |
728 | the receive queue is full.\r |
729 | \r |
730 | **/\r |
731 | EFI_STATUS\r |
732 | EFIAPI\r |
733 | Udp4Receive (\r |
734 | IN EFI_UDP4_PROTOCOL *This,\r |
735 | IN EFI_UDP4_COMPLETION_TOKEN *Token\r |
736 | )\r |
737 | {\r |
738 | EFI_STATUS Status;\r |
739 | UDP4_INSTANCE_DATA *Instance;\r |
740 | EFI_TPL OldTpl;\r |
741 | \r |
742 | if ((This == NULL) || (Token == NULL) || (Token->Event == NULL)) {\r |
743 | return EFI_INVALID_PARAMETER;\r |
744 | }\r |
745 | \r |
746 | Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);\r |
747 | \r |
748 | if (Instance->IsNoMapping) {\r |
749 | return EFI_NO_MAPPING;\r |
750 | }\r |
751 | \r |
752 | if (!Instance->Configured) {\r |
753 | return EFI_NOT_STARTED;\r |
754 | }\r |
755 | \r |
756 | OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r |
757 | \r |
758 | if (EFI_ERROR (NetMapIterate (&Instance->RxTokens, Udp4TokenExist, Token))||\r |
759 | EFI_ERROR (NetMapIterate (&Instance->TxTokens, Udp4TokenExist, Token))) {\r |
760 | //\r |
761 | // Return EFI_ACCESS_DENIED if the specified token is already in the TxTokens or\r |
762 | // RxTokens map.\r |
763 | //\r |
764 | Status = EFI_ACCESS_DENIED;\r |
765 | goto ON_EXIT;\r |
766 | }\r |
767 | \r |
768 | Token->Packet.RxData = NULL;\r |
769 | \r |
770 | //\r |
771 | // Save the token into the RxTokens map.\r |
772 | //\r |
773 | Status = NetMapInsertTail (&Instance->RxTokens, Token, NULL);\r |
774 | if (EFI_ERROR (Status)) {\r |
775 | return EFI_NOT_READY;\r |
776 | }\r |
777 | \r |
778 | //\r |
779 | // If there is an icmp error, report it.\r |
780 | //\r |
781 | Udp4ReportIcmpError (Instance);\r |
782 | \r |
783 | //\r |
784 | // Try to delivered the received datagrams.\r |
785 | //\r |
786 | Udp4InstanceDeliverDgram (Instance);\r |
787 | \r |
788 | ON_EXIT:\r |
789 | \r |
790 | NET_RESTORE_TPL (OldTpl);\r |
791 | \r |
792 | return Status;\r |
793 | }\r |
794 | \r |
795 | \r |
796 | /**\r |
797 | This function is used to abort a pending transmit or receive request.\r |
798 | \r |
799 | @param This Pointer to the EFI_UDP4_PROTOCOL instance.\r |
800 | @param Token Pointer to a token that has been issued by\r |
801 | EFI_UDP4_PROTOCOL.Transmit() or\r |
802 | EFI_UDP4_PROTOCOL.Receive().\r |
803 | \r |
804 | @retval EFI_SUCCESS The asynchronous I/O request is aborted and\r |
805 | Token.Event is signaled. When Token is NULL, all\r |
806 | pending requests are aborted and their events are\r |
807 | signaled.\r |
808 | @retval EFI_INVALID_PARAMETER This is NULL.\r |
809 | @retval EFI_NOT_STARTED This instance has not been started.\r |
810 | @retval EFI_NO_MAPPING When using the default address, configuration\r |
811 | (DHCP, BOOTP, RARP, etc.) is not finished yet.\r |
812 | @retval EFI_NOT_FOUND When Token is not NULL, the asynchronous I/O\r |
813 | request is not found in the transmit or receive\r |
814 | queue. It is either completed or not issued by\r |
815 | Transmit() or Receive().\r |
816 | \r |
817 | **/\r |
818 | EFI_STATUS\r |
819 | EFIAPI\r |
820 | Udp4Cancel (\r |
821 | IN EFI_UDP4_PROTOCOL *This,\r |
822 | IN EFI_UDP4_COMPLETION_TOKEN *Token OPTIONAL\r |
823 | )\r |
824 | {\r |
825 | EFI_STATUS Status;\r |
826 | UDP4_INSTANCE_DATA *Instance;\r |
827 | EFI_TPL OldTpl;\r |
828 | \r |
829 | if (This == NULL) {\r |
830 | return EFI_INVALID_PARAMETER;\r |
831 | }\r |
832 | \r |
833 | Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);\r |
834 | \r |
835 | if (Instance->IsNoMapping) {\r |
836 | return EFI_NO_MAPPING;\r |
837 | }\r |
838 | \r |
839 | if (!Instance->Configured) {\r |
840 | return EFI_NOT_STARTED;\r |
841 | }\r |
842 | \r |
843 | OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r |
844 | \r |
845 | //\r |
846 | // Cancle the tokens specified by Token for this instance.\r |
847 | //\r |
848 | Status = Udp4InstanceCancelToken (Instance, Token);\r |
849 | \r |
850 | NET_RESTORE_TPL (OldTpl);\r |
851 | \r |
852 | return Status;\r |
853 | }\r |
854 | \r |
855 | \r |
856 | /**\r |
857 | This function can be used by network drivers and applications to increase the rate that\r |
858 | data packets are moved between the communications device and the transmit/receive queues.\r |
859 | Argumens:\r |
860 | This - Pointer to the EFI_UDP4_PROTOCOL instance.\r |
861 | \r |
862 | @retval EFI_SUCCESS Incoming or outgoing data was processed.\r |
863 | @retval EFI_INVALID_PARAMETER This is NULL.\r |
864 | @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.\r |
865 | @retval EFI_TIMEOUT Data was dropped out of the transmit and/or\r |
866 | receive queue.\r |
867 | \r |
868 | **/\r |
869 | EFI_STATUS\r |
870 | EFIAPI\r |
871 | Udp4Poll (\r |
872 | IN EFI_UDP4_PROTOCOL *This\r |
873 | )\r |
874 | {\r |
875 | UDP4_INSTANCE_DATA *Instance;\r |
876 | EFI_IP4_PROTOCOL *Ip;\r |
877 | \r |
878 | if (This == NULL) {\r |
879 | return EFI_INVALID_PARAMETER;\r |
880 | }\r |
881 | \r |
882 | Instance = UDP4_INSTANCE_DATA_FROM_THIS (This);\r |
883 | Ip = Instance->IpInfo->Ip;\r |
884 | \r |
885 | //\r |
886 | // Invode the Ip instance consumed by the udp instance to do the poll operation.\r |
887 | //\r |
888 | return Ip->Poll (Ip);\r |
889 | }\r |