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