]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Common.c
Fix a conformance issue in gBS->CreateEvent() & gBS->CreateEventEx():
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Common.c
CommitLineData
772db4bb 1/** @file\r
2\r
3Copyright (c) 2005 - 2006, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12\r
13Module Name:\r
14\r
15 Ip4Common.c\r
16\r
17Abstract:\r
18\r
19\r
20**/\r
21\r
22#include "Ip4Impl.h"\r
23\r
24\r
25/**\r
26 Return the cast type (Unicast/Boradcast) specific to a\r
27 interface. All the addresses are host byte ordered.\r
28\r
29 @param IpAddr The IP address to classify in host byte order\r
30 @param IpIf The interface that IpAddr received from\r
31\r
32 @return The cast type of this IP address specific to the interface.\r
33 @retval IP4_LOCAL_HOST The IpAddr equals to the interface's address\r
34 @retval IP4_SUBNET_BROADCAST The IpAddr is a directed subnet boradcast to the\r
35 interface\r
36 @retval IP4_NET_BROADCAST The IpAddr is a network broadcast to the interface\r
37\r
38**/\r
39INTN\r
40Ip4GetNetCast (\r
41 IN IP4_ADDR IpAddr,\r
42 IN IP4_INTERFACE *IpIf\r
43 )\r
44{\r
45 if (IpAddr == IpIf->Ip) {\r
46 return IP4_LOCAL_HOST;\r
47\r
48 } else if (IpAddr == IpIf->SubnetBrdcast) {\r
49 return IP4_SUBNET_BROADCAST;\r
50\r
51 } else if (IpAddr == IpIf->NetBrdcast) {\r
52 return IP4_NET_BROADCAST;\r
53\r
54 }\r
55\r
56 return 0;\r
57}\r
58\r
59\r
60/**\r
61 Find the cast type of the packet related to the local host.\r
62 This isn't the same as link layer cast type. For example, DHCP\r
63 server may send local broadcast to the local unicast MAC.\r
64\r
65 @param IpSb The IP4 service binding instance that received the\r
66 packet\r
67 @param Dst The destination address in the packet (host byte\r
68 order)\r
69 @param Src The source address in the packet (host byte order)\r
70\r
71 @return The cast type for the Dst, it will return on the first non-promiscuous\r
72 @return cast type to a configured interface. If the packet doesn't match any of\r
73 @return the interface, multicast address and local broadcast address are checked.\r
74\r
75**/\r
76INTN\r
77Ip4GetHostCast (\r
78 IN IP4_SERVICE *IpSb,\r
79 IN IP4_ADDR Dst,\r
80 IN IP4_ADDR Src\r
81 )\r
82{\r
83 NET_LIST_ENTRY *Entry;\r
84 IP4_INTERFACE *IpIf;\r
85 INTN Type;\r
86 INTN Class;\r
87\r
88 Type = 0;\r
89\r
90 if (IpSb->MnpConfigData.EnablePromiscuousReceive) {\r
91 Type = IP4_PROMISCUOUS;\r
92 }\r
93\r
94 //\r
95 // Go through the interface list of the IP service, most likely.\r
96 //\r
97 NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {\r
98 IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);\r
99\r
100 //\r
101 // Skip the unconfigured interface and invalid source address:\r
102 // source address can't be broadcast.\r
103 //\r
104 if (!IpIf->Configured || IP4_IS_BROADCAST (Ip4GetNetCast (Src, IpIf))) {\r
105 continue;\r
106 }\r
107\r
108 if ((Class = Ip4GetNetCast (Dst, IpIf)) > Type) {\r
109 return Class;\r
110 }\r
111 }\r
112\r
113 //\r
114 // If it is local broadcast address. The source address must\r
115 // be a unicast address on one of the direct connected network.\r
116 // If it is a multicast address, accept it only if we are in\r
117 // the group.\r
118 //\r
119 if (Dst == IP4_ALLONE_ADDRESS) {\r
120 IpIf = Ip4FindNet (IpSb, Src);\r
121\r
122 if (IpIf && !IP4_IS_BROADCAST (Ip4GetNetCast (Src, IpIf))) {\r
123 return IP4_LOCAL_BROADCAST;\r
124 }\r
125\r
126 } else if (IP4_IS_MULTICAST (Dst) && Ip4FindGroup (&IpSb->IgmpCtrl, Dst)) {\r
127 return IP4_MULTICAST;\r
128 }\r
129\r
130 return Type;\r
131}\r
132\r
133\r
134/**\r
135 Find an interface whose configured IP address is Ip\r
136\r
137 @param IpSb The IP4 service binding instance\r
138 @param Ip The Ip address (host byte order) to find\r
139\r
140 @return The IP4_INTERFACE point if found, otherwise NULL\r
141\r
142**/\r
143IP4_INTERFACE *\r
144Ip4FindInterface (\r
145 IN IP4_SERVICE *IpSb,\r
146 IN IP4_ADDR Ip\r
147 )\r
148{\r
149 NET_LIST_ENTRY *Entry;\r
150 IP4_INTERFACE *IpIf;\r
151\r
152 NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {\r
153 IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);\r
154\r
155 if (IpIf->Configured && (IpIf->Ip == Ip)) {\r
156 return IpIf;\r
157 }\r
158 }\r
159\r
160 return NULL;\r
161}\r
162\r
163\r
164/**\r
165 Find an interface that Ip is on that connected network.\r
166\r
167 @param IpSb The IP4 service binding instance\r
168 @param Ip The Ip address (host byte order) to find\r
169\r
170 @return The IP4_INTERFACE point if found, otherwise NULL\r
171\r
172**/\r
173IP4_INTERFACE *\r
174Ip4FindNet (\r
175 IN IP4_SERVICE *IpSb,\r
176 IN IP4_ADDR Ip\r
177 )\r
178{\r
179 NET_LIST_ENTRY *Entry;\r
180 IP4_INTERFACE *IpIf;\r
181\r
182 NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {\r
183 IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);\r
184\r
185 if (IpIf->Configured && IP4_NET_EQUAL (Ip, IpIf->Ip, IpIf->SubnetMask)) {\r
186 return IpIf;\r
187 }\r
188 }\r
189\r
190 return NULL;\r
191}\r
192\r
193\r
194/**\r
195 Find an interface of the service with the same Ip/Netmask pair.\r
196\r
197 @param IpSb Ip4 service binding instance\r
198 @param Ip The Ip adress to find (host byte order)\r
199 @param Netmask The network to find (host byte order)\r
200\r
201 @return The IP4_INTERFACE point if found, otherwise NULL\r
202\r
203**/\r
204IP4_INTERFACE *\r
205Ip4FindStationAddress (\r
206 IN IP4_SERVICE *IpSb,\r
207 IN IP4_ADDR Ip,\r
208 IN IP4_ADDR Netmask\r
209 )\r
210{\r
211 NET_LIST_ENTRY *Entry;\r
212 IP4_INTERFACE *IpIf;\r
213\r
214 NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {\r
215 IpIf = NET_LIST_USER_STRUCT (Entry, IP4_INTERFACE, Link);\r
216\r
217 if (IpIf->Configured && (IpIf->Ip == Ip) && (IpIf->SubnetMask == Netmask)) {\r
218 return IpIf;\r
219 }\r
220 }\r
221\r
222 return NULL;\r
223}\r
224\r
225\r
226/**\r
227 Get the MAC address for a multicast IP address. Call\r
228 Mnp's McastIpToMac to find the MAC address in stead of\r
229 hard code the NIC to be Ethernet.\r
230\r
231 @param Mnp The Mnp instance to get the MAC address.\r
232 @param Multicast The multicast IP address to translate.\r
233 @param Mac The buffer to hold the translated address.\r
234\r
235 @return Returns EFI_SUCCESS if the multicast IP is successfully\r
236 @return translated to a multicast MAC address. Otherwise some error.\r
237\r
238**/\r
239EFI_STATUS\r
240Ip4GetMulticastMac (\r
241 IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,\r
242 IN IP4_ADDR Multicast,\r
243 OUT EFI_MAC_ADDRESS *Mac\r
244 )\r
245{\r
246 EFI_IP_ADDRESS EfiIp;\r
247\r
248 EFI_IP4 (EfiIp.v4) = HTONL (Multicast);\r
249 return Mnp->McastIpToMac (Mnp, FALSE, &EfiIp, Mac);\r
250}\r
251\r
252\r
253/**\r
254 Convert the multibyte field in IP header's byter order.\r
255 In spite of its name, it can also be used to convert from\r
256 host to network byte order.\r
257\r
258 @param Head The IP head to convert\r
259\r
260 @return Point to the converted IP head\r
261\r
262**/\r
263IP4_HEAD *\r
264Ip4NtohHead (\r
265 IN IP4_HEAD *Head\r
266 )\r
267{\r
268 Head->TotalLen = NTOHS (Head->TotalLen);\r
269 Head->Id = NTOHS (Head->Id);\r
270 Head->Fragment = NTOHS (Head->Fragment);\r
271 Head->Src = NTOHL (Head->Src);\r
272 Head->Dst = NTOHL (Head->Dst);\r
273\r
274 return Head;\r
275}\r
276\r
277\r
278/**\r
279 Set the Ip4 variable data.\r
280\r
281 @param IpSb Ip4 service binding instance\r
282\r
283 @retval EFI_OUT_OF_RESOURCES There are not enough resources to set the variable.\r
284 @retval other Set variable failed.\r
285\r
286**/\r
287EFI_STATUS\r
288Ip4SetVariableData (\r
289 IN IP4_SERVICE *IpSb\r
290 )\r
291{\r
292 UINT32 NumConfiguredInstance;\r
293 NET_LIST_ENTRY *Entry;\r
294 UINTN VariableDataSize;\r
295 EFI_IP4_VARIABLE_DATA *Ip4VariableData;\r
296 EFI_IP4_ADDRESS_PAIR *Ip4AddressPair;\r
297 IP4_PROTOCOL *IpInstance;\r
298 CHAR16 *NewMacString;\r
299 EFI_STATUS Status;\r
300\r
301 NumConfiguredInstance = 0;\r
302\r
303 //\r
304 // Go through the children list to count the configured children.\r
305 //\r
306 NET_LIST_FOR_EACH (Entry, &IpSb->Children) {\r
307 IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, Link, IP4_PROTOCOL_SIGNATURE);\r
308\r
309 if (IpInstance->State == IP4_STATE_CONFIGED) {\r
310 NumConfiguredInstance++;\r
311 }\r
312 }\r
313\r
314 //\r
315 // Calculate the size of the Ip4VariableData. As there may be no IP child,\r
316 // we should add extra buffer for the address paris only if the number of configured\r
317 // children is more than 1.\r
318 //\r
319 VariableDataSize = sizeof (EFI_IP4_VARIABLE_DATA);\r
320\r
321 if (NumConfiguredInstance > 1) {\r
322 VariableDataSize += sizeof (EFI_IP4_ADDRESS_PAIR) * (NumConfiguredInstance - 1);\r
323 }\r
324\r
325 Ip4VariableData = NetAllocatePool (VariableDataSize);\r
326 if (Ip4VariableData == NULL) {\r
327 return EFI_OUT_OF_RESOURCES;\r
328 }\r
329\r
330 Ip4VariableData->DriverHandle = IpSb->Image;\r
331 Ip4VariableData->AddressCount = NumConfiguredInstance;\r
332\r
333 Ip4AddressPair = &Ip4VariableData->AddressPairs[0];\r
334\r
335 //\r
336 // Go through the children list to fill the configured children's address pairs.\r
337 //\r
338 NET_LIST_FOR_EACH (Entry, &IpSb->Children) {\r
339 IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, Link, IP4_PROTOCOL_SIGNATURE);\r
340\r
341 if (IpInstance->State == IP4_STATE_CONFIGED) {\r
342 Ip4AddressPair->InstanceHandle = IpInstance->Handle;\r
343 EFI_IP4 (Ip4AddressPair->Ip4Address) = NTOHL (IpInstance->Interface->Ip);\r
344 EFI_IP4 (Ip4AddressPair->SubnetMask) = NTOHL (IpInstance->Interface->SubnetMask);\r
345\r
346 Ip4AddressPair++;\r
347 }\r
348 }\r
349\r
350 //\r
351 // Get the mac string.\r
352 //\r
353 Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &NewMacString);\r
354 if (EFI_ERROR (Status)) {\r
355 goto ON_ERROR;\r
356 }\r
357\r
358 if (IpSb->MacString != NULL) {\r
359 //\r
360 // The variable is set already, we're going to update it.\r
361 //\r
362 if (StrCmp (IpSb->MacString, NewMacString) != 0) {\r
363 //\r
364 // The mac address is changed, delete the previous variable first.\r
365 //\r
366 gRT->SetVariable (\r
367 IpSb->MacString,\r
368 &gEfiIp4ServiceBindingProtocolGuid,\r
369 EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
370 0,\r
371 NULL\r
372 );\r
373 }\r
374\r
375 NetFreePool (IpSb->MacString);\r
376 }\r
377\r
378 IpSb->MacString = NewMacString;\r
379\r
380 Status = gRT->SetVariable (\r
381 IpSb->MacString,\r
382 &gEfiIp4ServiceBindingProtocolGuid,\r
383 EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
384 VariableDataSize,\r
385 (VOID *) Ip4VariableData\r
386 );\r
387\r
388ON_ERROR:\r
389\r
390 NetFreePool (Ip4VariableData);\r
391\r
392 return Status;\r
393}\r
394\r
395\r
396/**\r
397 Clear the variable and free the resource.\r
398\r
399 @param IpSb Ip4 service binding instance\r
400\r
401 @return None.\r
402\r
403**/\r
404VOID\r
405Ip4ClearVariableData (\r
406 IN IP4_SERVICE *IpSb\r
407 )\r
408{\r
409 ASSERT (IpSb->MacString != NULL);\r
410\r
411 gRT->SetVariable (\r
412 IpSb->MacString,\r
413 &gEfiIp4ServiceBindingProtocolGuid,\r
414 EFI_VARIABLE_BOOTSERVICE_ACCESS,\r
415 0,\r
416 NULL\r
417 );\r
418\r
419 NetFreePool (IpSb->MacString);\r
420 IpSb->MacString = NULL;\r
421}\r