]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/Ip6Dxe/Ip6Common.c
BaseTools: Refactor hash tracking after checking for Sources section
[mirror_edk2.git] / NetworkPkg / Ip6Dxe / Ip6Common.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 The implementation of common functions shared by IP6 driver.\r
3\r
f75a7f56 4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
a3bcde70 5\r
ecf98fbc 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
a3bcde70
HT
7\r
8**/\r
9\r
10#include "Ip6Impl.h"\r
11\r
12/**\r
13 Build a array of EFI_IP6_ADDRESS_INFO to be returned to the caller. The number\r
14 of EFI_IP6_ADDRESS_INFO is also returned. If AddressList is NULL,\r
15 only the address count is returned.\r
16\r
17 @param[in] IpSb The IP6 service binding instance.\r
18 @param[out] AddressCount The number of returned addresses.\r
19 @param[out] AddressList The pointer to the array of EFI_IP6_ADDRESS_INFO.\r
20 This is an optional parameter.\r
21\r
22\r
23 @retval EFI_SUCCESS The address array successfully built.\r
24 @retval EFI_OUT_OF_RESOURCES Failed to allocate the memory for the address info.\r
25 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
26\r
27**/\r
28EFI_STATUS\r
29Ip6BuildEfiAddressList (\r
30 IN IP6_SERVICE *IpSb,\r
31 OUT UINT32 *AddressCount,\r
32 OUT EFI_IP6_ADDRESS_INFO **AddressList OPTIONAL\r
33 )\r
34{\r
35 UINT32 Count;\r
36 LIST_ENTRY *Entry;\r
37 EFI_IP6_ADDRESS_INFO *EfiAddrInfo;\r
38 IP6_ADDRESS_INFO *AddrInfo;\r
39\r
40 if (AddressCount == NULL) {\r
41 return EFI_INVALID_PARAMETER;\r
42 }\r
43\r
44 if (IpSb->LinkLocalOk) {\r
45 Count = 1 + IpSb->DefaultInterface->AddressCount;\r
46 } else {\r
47 Count = 0;\r
48 }\r
49\r
50 *AddressCount = Count;\r
51\r
52 if ((AddressList == NULL) || (Count == 0)) {\r
53 return EFI_SUCCESS;\r
54 }\r
55\r
56 if (*AddressList == NULL) {\r
57 *AddressList = AllocatePool (sizeof (EFI_IP6_ADDRESS_INFO) * Count);\r
58 if (*AddressList == NULL) {\r
59 return EFI_OUT_OF_RESOURCES;\r
60 }\r
61 }\r
62\r
63 EfiAddrInfo = *AddressList;\r
64\r
65 IP6_COPY_ADDRESS (&EfiAddrInfo->Address, &IpSb->LinkLocalAddr);\r
66 EfiAddrInfo->PrefixLength = IP6_LINK_LOCAL_PREFIX_LENGTH;\r
67\r
68 EfiAddrInfo++;\r
69 Count = 1;\r
70\r
71 NET_LIST_FOR_EACH (Entry, &IpSb->DefaultInterface->AddressList) {\r
72 AddrInfo = NET_LIST_USER_STRUCT_S (Entry, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);\r
73\r
74 IP6_COPY_ADDRESS (&EfiAddrInfo->Address, &AddrInfo->Address);\r
75 EfiAddrInfo->PrefixLength = AddrInfo->PrefixLength;\r
76\r
77 EfiAddrInfo++;\r
78 Count++;\r
79 }\r
80\r
81 ASSERT (Count == *AddressCount);\r
82\r
83 return EFI_SUCCESS;\r
84}\r
85\r
86/**\r
87 Generate the multicast addresses identify the group of all IPv6 nodes or IPv6\r
88 routers defined in RFC4291.\r
89\r
90 All Nodes Addresses: FF01::1, FF02::1.\r
91 All Router Addresses: FF01::2, FF02::2, FF05::2.\r
92\r
93 @param[in] Router If TRUE, generate all routers addresses,\r
94 else generate all node addresses.\r
95 @param[in] Scope interface-local(1), link-local(2), or site-local(5)\r
96 @param[out] Ip6Addr The generated multicast address.\r
97\r
98 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
99 @retval EFI_SUCCESS The address is generated.\r
100\r
101**/\r
102EFI_STATUS\r
103Ip6SetToAllNodeMulticast (\r
104 IN BOOLEAN Router,\r
105 IN UINT8 Scope,\r
106 OUT EFI_IPv6_ADDRESS *Ip6Addr\r
107 )\r
108{\r
109 if (Ip6Addr == NULL) {\r
110 return EFI_INVALID_PARAMETER;\r
111 }\r
112\r
113 if (!Router && Scope == IP6_SITE_LOCAL_SCOPE) {\r
114 return EFI_INVALID_PARAMETER;\r
115 }\r
116\r
117 ZeroMem (Ip6Addr, sizeof (EFI_IPv6_ADDRESS));\r
118 Ip6Addr->Addr[0] = 0xFF;\r
119 Ip6Addr->Addr[1] = Scope;\r
120\r
121 if (!Router) {\r
122 Ip6Addr->Addr[15] = 0x1;\r
123 } else {\r
124 Ip6Addr->Addr[15] = 0x2;\r
125 }\r
126\r
127 return EFI_SUCCESS;\r
128}\r
129\r
130/**\r
131 This function converts MAC address to 64 bits interface ID according to RFC4291\r
132 and returns the interface ID. Currently only 48-bit MAC address is supported by\r
133 this function.\r
134\r
135 @param[in, out] IpSb The IP6 service binding instance.\r
136\r
137 @retval NULL The operation fails.\r
138 @return Pointer to the generated interface ID.\r
139\r
140**/\r
141UINT8 *\r
142Ip6CreateInterfaceID (\r
143 IN OUT IP6_SERVICE *IpSb\r
144 )\r
145{\r
146 UINT8 InterfaceId[8];\r
147 UINT8 Byte;\r
148 EFI_MAC_ADDRESS *MacAddr;\r
149 UINT32 AddrLen;\r
150\r
151 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);\r
152\r
153 AddrLen = IpSb->SnpMode.HwAddressSize;\r
154\r
155 //\r
156 // Currently only IEEE 802 48-bit MACs are supported to create link local address.\r
157 //\r
158 if (AddrLen != IP6_MAC_LEN || IpSb->InterfaceIdLen != IP6_IF_ID_LEN) {\r
159 return NULL;\r
160 }\r
161\r
162 MacAddr = &IpSb->SnpMode.CurrentAddress;\r
163\r
164 //\r
165 // Convert MAC address to 64 bits interface ID according to Appendix A of RFC4291:\r
166 // 1. Insert 0xFFFE to the middle\r
167 // 2. Invert the universal/local bit - bit 6 in network order\r
168 //\r
169 CopyMem (InterfaceId, MacAddr, 3);\r
170 InterfaceId[3] = 0xFF;\r
171 InterfaceId[4] = 0xFE;\r
172 CopyMem (&InterfaceId[5], &MacAddr->Addr[3], 3);\r
173\r
174 Byte = (UINT8) (InterfaceId[0] & IP6_U_BIT);\r
175 if (Byte == IP6_U_BIT) {\r
176 InterfaceId[0] &= ~IP6_U_BIT;\r
177 } else {\r
178 InterfaceId[0] |= IP6_U_BIT;\r
179 }\r
180\r
181 //\r
182 // Return the interface ID.\r
183 //\r
184 return AllocateCopyPool (IpSb->InterfaceIdLen, InterfaceId);\r
185}\r
186\r
187/**\r
188 This function creates link-local address from interface identifier. The\r
189 interface identifier is normally created from MAC address. It might be manually\r
190 configured by administrator if the link-local address created from MAC address\r
191 is a duplicate address.\r
192\r
193 @param[in, out] IpSb The IP6 service binding instance.\r
194\r
195 @retval NULL If the operation fails.\r
196 @return The generated Link Local address, in network order.\r
197\r
198**/\r
199EFI_IPv6_ADDRESS *\r
200Ip6CreateLinkLocalAddr (\r
201 IN OUT IP6_SERVICE *IpSb\r
202 )\r
203{\r
204 EFI_IPv6_ADDRESS *Ip6Addr;\r
205 EFI_IP6_CONFIG_PROTOCOL *Ip6Config;\r
206 UINTN DataSize;\r
207 EFI_IP6_CONFIG_INTERFACE_ID InterfaceId;\r
208 EFI_STATUS Status;\r
209\r
210 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);\r
211\r
212 if (IpSb->InterfaceId != NULL) {\r
213 FreePool (IpSb->InterfaceId);\r
214 }\r
215\r
216 //\r
217 // Get the interface id if it is manully configured.\r
218 //\r
219 Ip6Config = &IpSb->Ip6ConfigInstance.Ip6Config;\r
220 DataSize = sizeof (EFI_IP6_CONFIG_INTERFACE_ID);\r
221 ZeroMem (&InterfaceId, DataSize);\r
222\r
223 Status = Ip6Config->GetData (\r
224 Ip6Config,\r
225 Ip6ConfigDataTypeAltInterfaceId,\r
226 &DataSize,\r
227 &InterfaceId\r
228 );\r
229 if (Status == EFI_NOT_FOUND) {\r
230 //\r
231 // Since the interface id is not configured, generate the interface id from\r
232 // MAC address.\r
233 //\r
234 IpSb->InterfaceId = Ip6CreateInterfaceID (IpSb);\r
235 if (IpSb->InterfaceId == NULL) {\r
236 return NULL;\r
237 }\r
238\r
239 CopyMem (&InterfaceId, IpSb->InterfaceId, IpSb->InterfaceIdLen);\r
240 //\r
241 // Record the interface id.\r
242 //\r
243 Status = Ip6Config->SetData (\r
244 Ip6Config,\r
245 Ip6ConfigDataTypeAltInterfaceId,\r
246 DataSize,\r
247 &InterfaceId\r
248 );\r
249 if (EFI_ERROR (Status)) {\r
250 FreePool (IpSb->InterfaceId);\r
251 IpSb->InterfaceId = NULL;\r
252 return NULL;\r
253 }\r
254 } else if (!EFI_ERROR (Status)) {\r
255 IpSb->InterfaceId = AllocateCopyPool (DataSize, &InterfaceId);\r
256 if (IpSb->InterfaceId == NULL) {\r
257 return NULL;\r
258 }\r
259 } else {\r
260 return NULL;\r
261 }\r
262\r
263 //\r
264 // Append FE80::/64 to the left of IPv6 address then return.\r
265 //\r
266 Ip6Addr = AllocateZeroPool (sizeof (EFI_IPv6_ADDRESS));\r
267 if (Ip6Addr == NULL) {\r
268 FreePool (IpSb->InterfaceId);\r
269 IpSb->InterfaceId = NULL;\r
270 return NULL;\r
271 }\r
272\r
273 CopyMem (&Ip6Addr->Addr[8], IpSb->InterfaceId, IpSb->InterfaceIdLen);\r
274 Ip6Addr->Addr[1] = 0x80;\r
275 Ip6Addr->Addr[0] = 0xFE;\r
276\r
277 return Ip6Addr;\r
278}\r
279\r
280/**\r
281 Compute the solicited-node multicast address for an unicast or anycast address,\r
282 by taking the low-order 24 bits of this address, and appending those bits to\r
283 the prefix FF02:0:0:0:0:1:FF00::/104.\r
284\r
285 @param[in] Ip6Addr The unicast or anycast address, in network order.\r
286 @param[out] MulticastAddr The generated solicited-node multicast address,\r
287 in network order.\r
288\r
289**/\r
290VOID\r
291Ip6CreateSNMulticastAddr (\r
292 IN EFI_IPv6_ADDRESS *Ip6Addr,\r
293 OUT EFI_IPv6_ADDRESS *MulticastAddr\r
294 )\r
295{\r
296 ASSERT (Ip6Addr != NULL && MulticastAddr != NULL);\r
297\r
298 ZeroMem (MulticastAddr, sizeof (EFI_IPv6_ADDRESS));\r
299\r
300 MulticastAddr->Addr[0] = 0xFF;\r
301 MulticastAddr->Addr[1] = 0x02;\r
302 MulticastAddr->Addr[11] = 0x1;\r
303 MulticastAddr->Addr[12] = 0xFF;\r
304\r
305 CopyMem (&MulticastAddr->Addr[13], &Ip6Addr->Addr[13], 3);\r
306}\r
307\r
308/**\r
309 Insert a node IP6_ADDRESS_INFO to an IP6 interface.\r
310\r
311 @param[in, out] IpIf Points to an IP6 interface.\r
312 @param[in] AddrInfo Points to IP6_ADDRESS_INFO\r
313\r
314**/\r
315VOID\r
316Ip6AddAddr (\r
317 IN OUT IP6_INTERFACE *IpIf,\r
318 IN IP6_ADDRESS_INFO *AddrInfo\r
319 )\r
320{\r
321 InsertHeadList (&IpIf->AddressList, &AddrInfo->Link);\r
322 IpIf->AddressCount++;\r
323}\r
324\r
216f7970 325/**\r
326 Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
f75a7f56 327\r
216f7970 328 @param[in] Entry The entry to be removed.\r
329 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
330\r
331 @retval EFI_SUCCESS The entry has been removed successfully.\r
332 @retval Others Fail to remove the entry.\r
333\r
334**/\r
335EFI_STATUS\r
1f7eb561 336EFIAPI\r
216f7970 337Ip6DestroyChildEntryByAddr (\r
338 IN LIST_ENTRY *Entry,\r
339 IN VOID *Context\r
1f7eb561 340 )\r
216f7970 341{\r
342 IP6_PROTOCOL *Instance;\r
343 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
344 EFI_IPv6_ADDRESS *Address;\r
f75a7f56 345\r
216f7970 346 Instance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);\r
347 ServiceBinding = ((IP6_DESTROY_CHILD_BY_ADDR_CALLBACK_CONTEXT*) Context)->ServiceBinding;\r
348 Address = ((IP6_DESTROY_CHILD_BY_ADDR_CALLBACK_CONTEXT*) Context)->Address;\r
349\r
350 if ((Instance->State == IP6_STATE_CONFIGED) && EFI_IP6_EQUAL (&Instance->ConfigData.StationAddress, Address)) {\r
351 return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
352 }\r
f75a7f56 353\r
216f7970 354 return EFI_SUCCESS;\r
355}\r
356\r
a3bcde70
HT
357/**\r
358 Destroy the IP instance if its StationAddress is removed. It is the help function\r
359 for Ip6RemoveAddr().\r
360\r
361 @param[in, out] IpSb Points to an IP6 service binding instance.\r
362 @param[in] Address The to be removed address\r
363\r
364**/\r
365VOID\r
366Ip6DestroyInstanceByAddress (\r
367 IN OUT IP6_SERVICE *IpSb,\r
368 IN EFI_IPv6_ADDRESS *Address\r
369 )\r
370{\r
216f7970 371 LIST_ENTRY *List;\r
372 IP6_DESTROY_CHILD_BY_ADDR_CALLBACK_CONTEXT Context;\r
a3bcde70
HT
373\r
374 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);\r
375\r
216f7970 376 List = &IpSb->Children;\r
377 Context.ServiceBinding = &IpSb->ServiceBinding;\r
378 Context.Address = Address;\r
379 NetDestroyLinkList (\r
380 List,\r
381 Ip6DestroyChildEntryByAddr,\r
382 &Context,\r
383 NULL\r
384 );\r
a3bcde70
HT
385}\r
386\r
387/**\r
388 Remove the IPv6 address from the address list node points to IP6_ADDRESS_INFO.\r
389\r
390 This function removes the matching IPv6 addresses from the address list and\r
391 adjusts the address count of the address list. If IpSb is not NULL, this function\r
392 calls Ip6LeaveGroup to see whether it should call Mnp->Groups() to remove the\r
393 its solicited-node multicast MAC address from the filter list and sends out\r
394 a Multicast Listener Done. If Prefix is NULL, all address in the address list\r
395 will be removed. If Prefix is not NULL, the address that matching the Prefix\r
396 with PrefixLength in the address list will be removed.\r
397\r
398 @param[in] IpSb NULL or points to IP6 service binding instance.\r
399 @param[in, out] AddressList Address list array.\r
400 @param[in, out] AddressCount The count of addresses in address list array.\r
401 @param[in] Prefix NULL or an IPv6 address prefix.\r
402 @param[in] PrefixLength The length of Prefix.\r
403\r
404 @retval EFI_SUCCESS The operation completed successfully.\r
405 @retval EFI_NOT_FOUND The address matching the Prefix with PrefixLength\r
406 cannot be found in the address list.\r
407 @retval EFI_INVALID_PARAMETER Any input parameter is invalid.\r
408\r
409**/\r
410EFI_STATUS\r
411Ip6RemoveAddr (\r
412 IN IP6_SERVICE *IpSb OPTIONAL,\r
413 IN OUT LIST_ENTRY *AddressList,\r
414 IN OUT UINT32 *AddressCount,\r
415 IN EFI_IPv6_ADDRESS *Prefix OPTIONAL,\r
416 IN UINT8 PrefixLength\r
417 )\r
418{\r
419 EFI_STATUS Status;\r
420 LIST_ENTRY *Entry;\r
421 LIST_ENTRY *Next;\r
422 IP6_ADDRESS_INFO *AddrInfo;\r
423 EFI_IPv6_ADDRESS SnMCastAddr;\r
424\r
c720da28 425 if (IsListEmpty (AddressList) || *AddressCount < 1 || PrefixLength > IP6_PREFIX_MAX) {\r
a3bcde70
HT
426 return EFI_INVALID_PARAMETER;\r
427 }\r
428\r
429 Status = EFI_NOT_FOUND;\r
430\r
431 NET_LIST_FOR_EACH_SAFE (Entry, Next, AddressList) {\r
432 AddrInfo = NET_LIST_USER_STRUCT_S (Entry, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);\r
433\r
434 if (Prefix == NULL ||\r
435 (PrefixLength == 128 && EFI_IP6_EQUAL (Prefix, &AddrInfo->Address)) ||\r
436 (PrefixLength == AddrInfo->PrefixLength && NetIp6IsNetEqual (Prefix, &AddrInfo->Address, PrefixLength))\r
437 ) {\r
438 if (IpSb != NULL) {\r
439 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);\r
440 Ip6CreateSNMulticastAddr (&AddrInfo->Address, &SnMCastAddr);\r
441 Ip6LeaveGroup (IpSb, &SnMCastAddr);\r
442\r
443 //\r
444 // Destroy any instance who is using the dying address as the source address.\r
445 //\r
446 Ip6DestroyInstanceByAddress (IpSb, &AddrInfo->Address);\r
447 }\r
448\r
449 RemoveEntryList (Entry);\r
450 FreePool (AddrInfo);\r
451 (*AddressCount)--;\r
452\r
453 Status = EFI_SUCCESS;\r
454 }\r
455 }\r
456\r
457 return Status;\r
458}\r
459\r
460/**\r
461 Check whether the incoming Ipv6 address is a solicited-node multicast address.\r
462\r
463 @param[in] Ip6 Ip6 address, in network order.\r
464\r
465 @retval TRUE Yes, solicited-node multicast address\r
466 @retval FALSE No\r
467\r
468**/\r
469BOOLEAN\r
470Ip6IsSNMulticastAddr (\r
471 IN EFI_IPv6_ADDRESS *Ip6\r
472 )\r
473{\r
474 EFI_IPv6_ADDRESS Sn;\r
475 BOOLEAN Flag;\r
476\r
477 Ip6CreateSNMulticastAddr (Ip6, &Sn);\r
478 Flag = FALSE;\r
479\r
480 if (CompareMem (Sn.Addr, Ip6->Addr, 13) == 0) {\r
481 Flag = TRUE;\r
482 }\r
483\r
484 return Flag;\r
485}\r
486\r
487/**\r
488 Check whether the incoming IPv6 address is one of the maintained addresses in\r
489 the IP6 service binding instance.\r
490\r
491 @param[in] IpSb Points to a IP6 service binding instance.\r
492 @param[in] Address The IP6 address to be checked.\r
493 @param[out] Interface If not NULL, output the IP6 interface which\r
494 maintains the Address.\r
495 @param[out] AddressInfo If not NULL, output the IP6 address information\r
496 of the Address.\r
497\r
498 @retval TRUE Yes, it is one of the maintained address.\r
499 @retval FALSE No, it is not one of the maintained address.\r
500\r
501**/\r
502BOOLEAN\r
503Ip6IsOneOfSetAddress (\r
504 IN IP6_SERVICE *IpSb,\r
505 IN EFI_IPv6_ADDRESS *Address,\r
506 OUT IP6_INTERFACE **Interface OPTIONAL,\r
507 OUT IP6_ADDRESS_INFO **AddressInfo OPTIONAL\r
508 )\r
509{\r
510 LIST_ENTRY *Entry;\r
511 LIST_ENTRY *Entry2;\r
512 IP6_INTERFACE *IpIf;\r
513 IP6_ADDRESS_INFO *TmpAddressInfo;\r
514\r
515 //\r
516 // Check link-local address first\r
517 //\r
518 if (IpSb->LinkLocalOk && EFI_IP6_EQUAL (&IpSb->LinkLocalAddr, Address)) {\r
519 if (Interface != NULL) {\r
520 *Interface = IpSb->DefaultInterface;\r
521 }\r
522\r
523 if (AddressInfo != NULL) {\r
524 *AddressInfo = NULL;\r
525 }\r
526\r
527 return TRUE;\r
528 }\r
529\r
530 NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {\r
531 IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);\r
532\r
533 NET_LIST_FOR_EACH (Entry2, &IpIf->AddressList) {\r
534 TmpAddressInfo = NET_LIST_USER_STRUCT_S (Entry2, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);\r
535\r
536 if (EFI_IP6_EQUAL (&TmpAddressInfo->Address, Address)) {\r
537 if (Interface != NULL) {\r
538 *Interface = IpIf;\r
539 }\r
540\r
541 if (AddressInfo != NULL) {\r
542 *AddressInfo = TmpAddressInfo;\r
543 }\r
544\r
545 return TRUE;\r
546 }\r
547 }\r
548 }\r
549\r
550 return FALSE;\r
551}\r
552\r
553/**\r
554 Check whether the incoming MAC address is valid.\r
555\r
556 @param[in] IpSb Points to a IP6 service binding instance.\r
557 @param[in] LinkAddress The MAC address.\r
558\r
559 @retval TRUE Yes, it is valid.\r
560 @retval FALSE No, it is not valid.\r
561\r
562**/\r
563BOOLEAN\r
564Ip6IsValidLinkAddress (\r
565 IN IP6_SERVICE *IpSb,\r
566 IN EFI_MAC_ADDRESS *LinkAddress\r
567 )\r
568{\r
569 UINT32 Index;\r
570\r
571 //\r
572 // TODO: might be updated later to be more acceptable.\r
573 //\r
574 for (Index = IpSb->SnpMode.HwAddressSize; Index < sizeof (EFI_MAC_ADDRESS); Index++) {\r
575 if (LinkAddress->Addr[Index] != 0) {\r
576 return FALSE;\r
577 }\r
578 }\r
579\r
580 return TRUE;\r
581}\r
582\r
583/**\r
584 Copy the PrefixLength bits from Src to Dest.\r
585\r
586 @param[out] Dest A pointer to the buffer to copy to.\r
587 @param[in] Src A pointer to the buffer to copy from.\r
588 @param[in] PrefixLength The number of bits to copy.\r
589\r
590**/\r
591VOID\r
592Ip6CopyAddressByPrefix (\r
593 OUT EFI_IPv6_ADDRESS *Dest,\r
594 IN EFI_IPv6_ADDRESS *Src,\r
595 IN UINT8 PrefixLength\r
596 )\r
597{\r
598 UINT8 Byte;\r
599 UINT8 Bit;\r
600 UINT8 Mask;\r
601\r
602 ASSERT (Dest != NULL && Src != NULL);\r
c720da28 603 ASSERT (PrefixLength <= IP6_PREFIX_MAX);\r
a3bcde70
HT
604\r
605 Byte = (UINT8) (PrefixLength / 8);\r
606 Bit = (UINT8) (PrefixLength % 8);\r
607\r
608 ZeroMem (Dest, sizeof (EFI_IPv6_ADDRESS));\r
609\r
610 CopyMem (Dest, Src, Byte);\r
611\r
612 if (Bit > 0) {\r
613 Mask = (UINT8) (0xFF << (8 - Bit));\r
614 ASSERT (Byte < 16);\r
615 Dest->Addr[Byte] = (UINT8) (Src->Addr[Byte] & Mask);\r
616 }\r
617}\r
618\r
619/**\r
620 Get the MAC address for a multicast IP address. Call\r
621 Mnp's McastIpToMac to find the MAC address instead of\r
622 hard-coding the NIC to be Ethernet.\r
623\r
624 @param[in] Mnp The Mnp instance to get the MAC address.\r
625 @param[in] Multicast The multicast IP address to translate.\r
626 @param[out] Mac The buffer to hold the translated address.\r
627\r
628 @retval EFI_SUCCESS The multicast IP successfully\r
629 translated to a multicast MAC address.\r
630 @retval Other The address is not converted because an error occurred.\r
631\r
632**/\r
633EFI_STATUS\r
634Ip6GetMulticastMac (\r
635 IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,\r
636 IN EFI_IPv6_ADDRESS *Multicast,\r
637 OUT EFI_MAC_ADDRESS *Mac\r
638 )\r
639{\r
640 EFI_IP_ADDRESS EfiIp;\r
641\r
642 IP6_COPY_ADDRESS (&EfiIp.v6, Multicast);\r
643\r
644 return Mnp->McastIpToMac (Mnp, TRUE, &EfiIp, Mac);\r
645}\r
646\r
a3bcde70
HT
647/**\r
648 Convert the multibyte field in IP header's byter order.\r
649 In spite of its name, it can also be used to convert from\r
650 host to network byte order.\r
651\r
652 @param[in, out] Head The IP head to convert.\r
653\r
654 @return Point to the converted IP head.\r
655\r
656**/\r
657EFI_IP6_HEADER *\r
658Ip6NtohHead (\r
659 IN OUT EFI_IP6_HEADER *Head\r
660 )\r
661{\r
662 Head->FlowLabelL = NTOHS (Head->FlowLabelL);\r
663 Head->PayloadLength = NTOHS (Head->PayloadLength);\r
664\r
665 return Head;\r
666}\r
667\r