]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/Ip6Dxe/Ip6Common.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
d1050b9d
MK
104 IN BOOLEAN Router,\r
105 IN UINT8 Scope,\r
106 OUT EFI_IPv6_ADDRESS *Ip6Addr\r
a3bcde70
HT
107 )\r
108{\r
109 if (Ip6Addr == NULL) {\r
110 return EFI_INVALID_PARAMETER;\r
111 }\r
112\r
d1050b9d 113 if (!Router && (Scope == IP6_SITE_LOCAL_SCOPE)) {\r
a3bcde70
HT
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
d1050b9d 143 IN OUT IP6_SERVICE *IpSb\r
a3bcde70
HT
144 )\r
145{\r
d1050b9d
MK
146 UINT8 InterfaceId[8];\r
147 UINT8 Byte;\r
148 EFI_MAC_ADDRESS *MacAddr;\r
149 UINT32 AddrLen;\r
a3bcde70
HT
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
d1050b9d 158 if ((AddrLen != IP6_MAC_LEN) || (IpSb->InterfaceIdLen != IP6_IF_ID_LEN)) {\r
a3bcde70
HT
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
d1050b9d 174 Byte = (UINT8)(InterfaceId[0] & IP6_U_BIT);\r
a3bcde70
HT
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
d1050b9d 201 IN OUT IP6_SERVICE *IpSb\r
a3bcde70
HT
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
7de8045a 217 // Get the interface id if it is manually configured.\r
a3bcde70
HT
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
d1050b9d
MK
292 IN EFI_IPv6_ADDRESS *Ip6Addr,\r
293 OUT EFI_IPv6_ADDRESS *MulticastAddr\r
a3bcde70
HT
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
d1050b9d
MK
317 IN OUT IP6_INTERFACE *IpIf,\r
318 IN IP6_ADDRESS_INFO *AddrInfo\r
a3bcde70
HT
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
d1050b9d
MK
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
d1050b9d
MK
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
216f7970 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
d1050b9d 371 LIST_ENTRY *List;\r
216f7970 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
d1050b9d 376 List = &IpSb->Children;\r
216f7970 377 Context.ServiceBinding = &IpSb->ServiceBinding;\r
d1050b9d 378 Context.Address = Address;\r
216f7970 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
d1050b9d
MK
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
a3bcde70 424\r
d1050b9d 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
d1050b9d
MK
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 {\r
a3bcde70
HT
439 if (IpSb != NULL) {\r
440 NET_CHECK_SIGNATURE (IpSb, IP6_SERVICE_SIGNATURE);\r
441 Ip6CreateSNMulticastAddr (&AddrInfo->Address, &SnMCastAddr);\r
442 Ip6LeaveGroup (IpSb, &SnMCastAddr);\r
443\r
444 //\r
445 // Destroy any instance who is using the dying address as the source address.\r
446 //\r
447 Ip6DestroyInstanceByAddress (IpSb, &AddrInfo->Address);\r
448 }\r
449\r
450 RemoveEntryList (Entry);\r
451 FreePool (AddrInfo);\r
452 (*AddressCount)--;\r
453\r
454 Status = EFI_SUCCESS;\r
455 }\r
456 }\r
457\r
458 return Status;\r
459}\r
460\r
461/**\r
462 Check whether the incoming Ipv6 address is a solicited-node multicast address.\r
463\r
464 @param[in] Ip6 Ip6 address, in network order.\r
465\r
466 @retval TRUE Yes, solicited-node multicast address\r
467 @retval FALSE No\r
468\r
469**/\r
470BOOLEAN\r
471Ip6IsSNMulticastAddr (\r
d1050b9d 472 IN EFI_IPv6_ADDRESS *Ip6\r
a3bcde70
HT
473 )\r
474{\r
d1050b9d
MK
475 EFI_IPv6_ADDRESS Sn;\r
476 BOOLEAN Flag;\r
a3bcde70
HT
477\r
478 Ip6CreateSNMulticastAddr (Ip6, &Sn);\r
479 Flag = FALSE;\r
480\r
481 if (CompareMem (Sn.Addr, Ip6->Addr, 13) == 0) {\r
482 Flag = TRUE;\r
483 }\r
484\r
485 return Flag;\r
486}\r
487\r
488/**\r
489 Check whether the incoming IPv6 address is one of the maintained addresses in\r
490 the IP6 service binding instance.\r
491\r
492 @param[in] IpSb Points to a IP6 service binding instance.\r
493 @param[in] Address The IP6 address to be checked.\r
494 @param[out] Interface If not NULL, output the IP6 interface which\r
495 maintains the Address.\r
496 @param[out] AddressInfo If not NULL, output the IP6 address information\r
497 of the Address.\r
498\r
499 @retval TRUE Yes, it is one of the maintained address.\r
500 @retval FALSE No, it is not one of the maintained address.\r
501\r
502**/\r
503BOOLEAN\r
504Ip6IsOneOfSetAddress (\r
d1050b9d
MK
505 IN IP6_SERVICE *IpSb,\r
506 IN EFI_IPv6_ADDRESS *Address,\r
507 OUT IP6_INTERFACE **Interface OPTIONAL,\r
508 OUT IP6_ADDRESS_INFO **AddressInfo OPTIONAL\r
a3bcde70
HT
509 )\r
510{\r
d1050b9d
MK
511 LIST_ENTRY *Entry;\r
512 LIST_ENTRY *Entry2;\r
513 IP6_INTERFACE *IpIf;\r
514 IP6_ADDRESS_INFO *TmpAddressInfo;\r
a3bcde70
HT
515\r
516 //\r
517 // Check link-local address first\r
518 //\r
519 if (IpSb->LinkLocalOk && EFI_IP6_EQUAL (&IpSb->LinkLocalAddr, Address)) {\r
520 if (Interface != NULL) {\r
521 *Interface = IpSb->DefaultInterface;\r
522 }\r
523\r
524 if (AddressInfo != NULL) {\r
525 *AddressInfo = NULL;\r
526 }\r
527\r
528 return TRUE;\r
529 }\r
530\r
531 NET_LIST_FOR_EACH (Entry, &IpSb->Interfaces) {\r
532 IpIf = NET_LIST_USER_STRUCT_S (Entry, IP6_INTERFACE, Link, IP6_INTERFACE_SIGNATURE);\r
533\r
534 NET_LIST_FOR_EACH (Entry2, &IpIf->AddressList) {\r
535 TmpAddressInfo = NET_LIST_USER_STRUCT_S (Entry2, IP6_ADDRESS_INFO, Link, IP6_ADDR_INFO_SIGNATURE);\r
536\r
537 if (EFI_IP6_EQUAL (&TmpAddressInfo->Address, Address)) {\r
538 if (Interface != NULL) {\r
539 *Interface = IpIf;\r
540 }\r
541\r
542 if (AddressInfo != NULL) {\r
543 *AddressInfo = TmpAddressInfo;\r
544 }\r
545\r
546 return TRUE;\r
547 }\r
548 }\r
549 }\r
550\r
551 return FALSE;\r
552}\r
553\r
554/**\r
555 Check whether the incoming MAC address is valid.\r
556\r
557 @param[in] IpSb Points to a IP6 service binding instance.\r
558 @param[in] LinkAddress The MAC address.\r
559\r
560 @retval TRUE Yes, it is valid.\r
561 @retval FALSE No, it is not valid.\r
562\r
563**/\r
564BOOLEAN\r
565Ip6IsValidLinkAddress (\r
566 IN IP6_SERVICE *IpSb,\r
567 IN EFI_MAC_ADDRESS *LinkAddress\r
568 )\r
569{\r
d1050b9d 570 UINT32 Index;\r
a3bcde70
HT
571\r
572 //\r
573 // TODO: might be updated later to be more acceptable.\r
574 //\r
575 for (Index = IpSb->SnpMode.HwAddressSize; Index < sizeof (EFI_MAC_ADDRESS); Index++) {\r
576 if (LinkAddress->Addr[Index] != 0) {\r
577 return FALSE;\r
578 }\r
579 }\r
580\r
581 return TRUE;\r
582}\r
583\r
584/**\r
585 Copy the PrefixLength bits from Src to Dest.\r
586\r
587 @param[out] Dest A pointer to the buffer to copy to.\r
588 @param[in] Src A pointer to the buffer to copy from.\r
589 @param[in] PrefixLength The number of bits to copy.\r
590\r
591**/\r
592VOID\r
593Ip6CopyAddressByPrefix (\r
d1050b9d
MK
594 OUT EFI_IPv6_ADDRESS *Dest,\r
595 IN EFI_IPv6_ADDRESS *Src,\r
596 IN UINT8 PrefixLength\r
a3bcde70
HT
597 )\r
598{\r
d1050b9d
MK
599 UINT8 Byte;\r
600 UINT8 Bit;\r
601 UINT8 Mask;\r
a3bcde70
HT
602\r
603 ASSERT (Dest != NULL && Src != NULL);\r
c720da28 604 ASSERT (PrefixLength <= IP6_PREFIX_MAX);\r
a3bcde70 605\r
d1050b9d
MK
606 Byte = (UINT8)(PrefixLength / 8);\r
607 Bit = (UINT8)(PrefixLength % 8);\r
a3bcde70
HT
608\r
609 ZeroMem (Dest, sizeof (EFI_IPv6_ADDRESS));\r
610\r
611 CopyMem (Dest, Src, Byte);\r
612\r
613 if (Bit > 0) {\r
d1050b9d 614 Mask = (UINT8)(0xFF << (8 - Bit));\r
a3bcde70 615 ASSERT (Byte < 16);\r
d1050b9d 616 Dest->Addr[Byte] = (UINT8)(Src->Addr[Byte] & Mask);\r
a3bcde70
HT
617 }\r
618}\r
619\r
620/**\r
621 Get the MAC address for a multicast IP address. Call\r
622 Mnp's McastIpToMac to find the MAC address instead of\r
623 hard-coding the NIC to be Ethernet.\r
624\r
625 @param[in] Mnp The Mnp instance to get the MAC address.\r
626 @param[in] Multicast The multicast IP address to translate.\r
627 @param[out] Mac The buffer to hold the translated address.\r
628\r
629 @retval EFI_SUCCESS The multicast IP successfully\r
630 translated to a multicast MAC address.\r
631 @retval Other The address is not converted because an error occurred.\r
632\r
633**/\r
634EFI_STATUS\r
635Ip6GetMulticastMac (\r
d1050b9d
MK
636 IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,\r
637 IN EFI_IPv6_ADDRESS *Multicast,\r
638 OUT EFI_MAC_ADDRESS *Mac\r
a3bcde70
HT
639 )\r
640{\r
d1050b9d 641 EFI_IP_ADDRESS EfiIp;\r
a3bcde70
HT
642\r
643 IP6_COPY_ADDRESS (&EfiIp.v6, Multicast);\r
644\r
645 return Mnp->McastIpToMac (Mnp, TRUE, &EfiIp, Mac);\r
646}\r
647\r
a3bcde70
HT
648/**\r
649 Convert the multibyte field in IP header's byter order.\r
650 In spite of its name, it can also be used to convert from\r
651 host to network byte order.\r
652\r
653 @param[in, out] Head The IP head to convert.\r
654\r
655 @return Point to the converted IP head.\r
656\r
657**/\r
658EFI_IP6_HEADER *\r
659Ip6NtohHead (\r
d1050b9d 660 IN OUT EFI_IP6_HEADER *Head\r
a3bcde70
HT
661 )\r
662{\r
663 Head->FlowLabelL = NTOHS (Head->FlowLabelL);\r
664 Head->PayloadLength = NTOHS (Head->PayloadLength);\r
665\r
666 return Head;\r
667}\r