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