2 The implementation of EFI IPv6 Configuration Protocol.
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 LIST_ENTRY mIp6ConfigInstanceList
= {&mIp6ConfigInstanceList
, &mIp6ConfigInstanceList
};
15 The event process routine when the DHCPv6 service binding protocol is installed
18 @param[in] Event Not used.
19 @param[in] Context Pointer to the IP6 config instance data.
24 Ip6ConfigOnDhcp6SbInstalled (
30 Update the current policy to NewPolicy. During the transition
31 period, the default router list, on-link prefix list, autonomous prefix list
32 and address list in all interfaces will be released.
34 @param[in] IpSb The IP6 service binding instance.
35 @param[in] NewPolicy The new policy to be updated to.
39 Ip6ConfigOnPolicyChanged (
41 IN EFI_IP6_CONFIG_POLICY NewPolicy
48 IP6_DAD_ENTRY
*DadEntry
;
49 IP6_DELAY_JOIN_LIST
*DelayNode
;
50 IP6_ADDRESS_INFO
*AddrInfo
;
51 IP6_PROTOCOL
*Instance
;
57 // Currently there are only two policies: Manual and Automatic. Regardless of
58 // what transition is going on, i.e., Manual -> Automatic and Automatic ->
59 // Manual, we have to free default router list, on-link prefix list, autonomous
60 // prefix list, address list in all the interfaces and destroy any IPv6 child
61 // instance whose local IP is neither 0 nor the link-local address.
63 Ip6CleanDefaultRouterList (IpSb
);
64 Ip6CleanPrefixListTable (IpSb
, &IpSb
->OnlinkPrefix
);
65 Ip6CleanPrefixListTable (IpSb
, &IpSb
->AutonomousPrefix
);
68 // It's tricky... If the LinkLocal address is O.K., add back the link-local
69 // prefix to the on-link prefix table.
71 if (IpSb
->LinkLocalOk
) {
72 Ip6CreatePrefixListEntry (
75 (UINT32
) IP6_INFINIT_LIFETIME
,
76 (UINT32
) IP6_INFINIT_LIFETIME
,
77 IP6_LINK_LOCAL_PREFIX_LENGTH
,
82 if (!IsListEmpty (&IpSb
->DefaultInterface
->AddressList
) && IpSb
->DefaultInterface
->AddressCount
> 0) {
84 // If any IPv6 children (Instance) in configured state and use global unicast address, it will be
85 // destroyed in Ip6RemoveAddr() function later. Then, the upper layer driver's Stop() function will be
86 // called, which may break the upper layer network stacks. So, the driver should take the responsibility
87 // for the recovery by using ConnectController() after Ip6RemoveAddr().
88 // Here, just check whether need to recover the upper layer network stacks later.
90 NET_LIST_FOR_EACH (Entry
, &IpSb
->DefaultInterface
->AddressList
) {
91 AddrInfo
= NET_LIST_USER_STRUCT_S (Entry
, IP6_ADDRESS_INFO
, Link
, IP6_ADDR_INFO_SIGNATURE
);
92 if (!IsListEmpty (&IpSb
->Children
)) {
93 NET_LIST_FOR_EACH (Entry2
, &IpSb
->Children
) {
94 Instance
= NET_LIST_USER_STRUCT_S (Entry2
, IP6_PROTOCOL
, Link
, IP6_PROTOCOL_SIGNATURE
);
95 if ((Instance
->State
== IP6_STATE_CONFIGED
) && EFI_IP6_EQUAL (&Instance
->ConfigData
.StationAddress
, &AddrInfo
->Address
)) {
104 // All IPv6 children that use global unicast address as it's source address
105 // should be destroyed now. The survivers are those use the link-local address
106 // or the unspecified address as the source address.
107 // TODO: Conduct a check here.
110 &IpSb
->DefaultInterface
->AddressList
,
111 &IpSb
->DefaultInterface
->AddressCount
,
116 if (IpSb
->Controller
!= NULL
&& Recovery
) {
118 // ConnectController() to recover the upper layer network stacks.
120 gBS
->ConnectController (IpSb
->Controller
, NULL
, NULL
, TRUE
);
125 NET_LIST_FOR_EACH (Entry
, &IpSb
->Interfaces
) {
127 // remove all pending delay node and DAD entries for the global addresses.
129 IpIf
= NET_LIST_USER_STRUCT_S (Entry
, IP6_INTERFACE
, Link
, IP6_INTERFACE_SIGNATURE
);
131 NET_LIST_FOR_EACH_SAFE (Entry2
, Next
, &IpIf
->DelayJoinList
) {
132 DelayNode
= NET_LIST_USER_STRUCT (Entry2
, IP6_DELAY_JOIN_LIST
, Link
);
133 if (!NetIp6IsLinkLocalAddr (&DelayNode
->AddressInfo
->Address
)) {
134 RemoveEntryList (&DelayNode
->Link
);
135 FreePool (DelayNode
);
139 NET_LIST_FOR_EACH_SAFE (Entry2
, Next
, &IpIf
->DupAddrDetectList
) {
140 DadEntry
= NET_LIST_USER_STRUCT_S (Entry2
, IP6_DAD_ENTRY
, Link
, IP6_DAD_ENTRY_SIGNATURE
);
142 if (!NetIp6IsLinkLocalAddr (&DadEntry
->AddressInfo
->Address
)) {
144 // Fail this DAD entry if the address is not link-local.
146 Ip6OnDADFinished (FALSE
, IpIf
, DadEntry
);
151 if (NewPolicy
== Ip6ConfigPolicyAutomatic
) {
153 // Set parameters to trigger router solicitation sending in timer handler.
155 IpSb
->RouterAdvertiseReceived
= FALSE
;
156 IpSb
->SolicitTimer
= IP6_MAX_RTR_SOLICITATIONS
;
160 IpSb
->Ticks
= (UINT32
) IP6_GET_TICKS (IP6_ONE_SECOND_IN_MS
);
165 The work function to trigger the DHCPv6 process to perform a stateful autoconfiguration.
167 @param[in] Instance Pointer to the IP6 config instance data.
168 @param[in] OtherInfoOnly If FALSE, get stateful address and other information
169 via DHCPv6. Otherwise, only get the other information.
171 @retval EFI_SUCCESS The operation finished successfully.
172 @retval EFI_UNSUPPORTED The DHCP6 driver is not available.
176 Ip6ConfigStartStatefulAutoConfig (
177 IN IP6_CONFIG_INSTANCE
*Instance
,
178 IN BOOLEAN OtherInfoOnly
183 EFI_DHCP6_CONFIG_DATA Dhcp6CfgData
;
184 EFI_DHCP6_PROTOCOL
*Dhcp6
;
185 EFI_DHCP6_PACKET_OPTION
*OptList
[1];
187 EFI_DHCP6_PACKET_OPTION
*Oro
;
188 EFI_DHCP6_RETRANSMISSION InfoReqReXmit
;
191 // A host must not invoke stateful address configuration if it is already
192 // participating in the statuful protocol as a result of an earlier advertisement.
194 if (Instance
->Dhcp6Handle
!= NULL
) {
198 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
200 Instance
->OtherInfoOnly
= OtherInfoOnly
;
202 Status
= NetLibCreateServiceChild (
205 &gEfiDhcp6ServiceBindingProtocolGuid
,
206 &Instance
->Dhcp6Handle
209 if (Status
== EFI_UNSUPPORTED
) {
211 // No DHCPv6 Service Binding protocol, register a notify.
213 if (Instance
->Dhcp6SbNotifyEvent
== NULL
) {
214 Instance
->Dhcp6SbNotifyEvent
= EfiCreateProtocolNotifyEvent (
215 &gEfiDhcp6ServiceBindingProtocolGuid
,
217 Ip6ConfigOnDhcp6SbInstalled
,
219 &Instance
->Registration
224 if (EFI_ERROR (Status
)) {
228 if (Instance
->Dhcp6SbNotifyEvent
!= NULL
) {
229 gBS
->CloseEvent (Instance
->Dhcp6SbNotifyEvent
);
232 Status
= gBS
->OpenProtocol (
233 Instance
->Dhcp6Handle
,
234 &gEfiDhcp6ProtocolGuid
,
235 (VOID
**) &Instance
->Dhcp6
,
238 EFI_OPEN_PROTOCOL_BY_DRIVER
240 ASSERT_EFI_ERROR (Status
);
242 Dhcp6
= Instance
->Dhcp6
;
243 Dhcp6
->Configure (Dhcp6
, NULL
);
246 // Set the exta options to send. Here we only want the option request option
249 Oro
= (EFI_DHCP6_PACKET_OPTION
*) OptBuf
;
250 Oro
->OpCode
= HTONS (DHCP6_OPT_ORO
);
251 Oro
->OpLen
= HTONS (2);
252 *((UINT16
*) &Oro
->Data
[0]) = HTONS (DHCP6_OPT_DNS_SERVERS
);
255 Status
= EFI_SUCCESS
;
257 if (!OtherInfoOnly
) {
259 // Get stateful address and other information via DHCPv6.
261 Dhcp6CfgData
.Dhcp6Callback
= NULL
;
262 Dhcp6CfgData
.CallbackContext
= NULL
;
263 Dhcp6CfgData
.OptionCount
= 1;
264 Dhcp6CfgData
.OptionList
= &OptList
[0];
265 Dhcp6CfgData
.IaDescriptor
.Type
= EFI_DHCP6_IA_TYPE_NA
;
266 Dhcp6CfgData
.IaDescriptor
.IaId
= Instance
->IaId
;
267 Dhcp6CfgData
.IaInfoEvent
= Instance
->Dhcp6Event
;
268 Dhcp6CfgData
.ReconfigureAccept
= FALSE
;
269 Dhcp6CfgData
.RapidCommit
= FALSE
;
270 Dhcp6CfgData
.SolicitRetransmission
= NULL
;
272 Status
= Dhcp6
->Configure (Dhcp6
, &Dhcp6CfgData
);
274 if (!EFI_ERROR (Status
)) {
276 if (IpSb
->LinkLocalOk
) {
277 Status
= Dhcp6
->Start (Dhcp6
);
279 IpSb
->Dhcp6NeedStart
= TRUE
;
285 // Only get other information via DHCPv6, this doesn't require a config
288 InfoReqReXmit
.Irt
= 4;
289 InfoReqReXmit
.Mrc
= 64;
290 InfoReqReXmit
.Mrt
= 60;
291 InfoReqReXmit
.Mrd
= 0;
293 if (IpSb
->LinkLocalOk
) {
294 Status
= Dhcp6
->InfoRequest (
301 Instance
->Dhcp6Event
,
302 Ip6ConfigOnDhcp6Reply
,
306 IpSb
->Dhcp6NeedInfoRequest
= TRUE
;
315 Signal the registered event. It is the callback routine for NetMapIterate.
317 @param[in] Map Points to the list of registered event.
318 @param[in] Item The registered event.
319 @param[in] Arg Not used.
324 Ip6ConfigSignalEvent (
326 IN NET_MAP_ITEM
*Item
,
330 gBS
->SignalEvent ((EFI_EVENT
) Item
->Key
);
336 Read the configuration data from variable storage according to the VarName and
337 gEfiIp6ConfigProtocolGuid. It checks the integrity of variable data. If the
338 data is corrupted, it clears the variable data to ZERO. Othewise, it outputs the
339 configuration data to IP6_CONFIG_INSTANCE.
341 @param[in] VarName The pointer to the variable name
342 @param[in, out] Instance The pointer to the IP6 config instance data.
344 @retval EFI_NOT_FOUND The variable can not be found or already corrupted.
345 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
346 @retval EFI_SUCCESS The configuration data was retrieved successfully.
350 Ip6ConfigReadConfigData (
352 IN OUT IP6_CONFIG_INSTANCE
*Instance
357 IP6_CONFIG_VARIABLE
*Variable
;
358 IP6_CONFIG_DATA_ITEM
*DataItem
;
360 IP6_CONFIG_DATA_RECORD DataRecord
;
364 // Try to read the configuration variable.
367 Status
= gRT
->GetVariable (
369 &gEfiIp6ConfigProtocolGuid
,
375 if (Status
== EFI_BUFFER_TOO_SMALL
) {
377 // Allocate buffer and read the config variable.
379 Variable
= AllocatePool (VarSize
);
380 if (Variable
== NULL
) {
381 return EFI_OUT_OF_RESOURCES
;
384 Status
= gRT
->GetVariable (
386 &gEfiIp6ConfigProtocolGuid
,
391 if (EFI_ERROR (Status
) || (UINT16
) (~NetblockChecksum ((UINT8
*) Variable
, (UINT32
) VarSize
)) != 0) {
393 // GetVariable still error or the variable is corrupted.
394 // Fall back to the default value.
399 // Remove the problematic variable and return EFI_NOT_FOUND, a new
400 // variable will be set again.
404 &gEfiIp6ConfigProtocolGuid
,
405 IP6_CONFIG_VARIABLE_ATTRIBUTE
,
410 return EFI_NOT_FOUND
;
414 // Get the IAID we use.
416 Instance
->IaId
= Variable
->IaId
;
418 for (Index
= 0; Index
< Variable
->DataRecordCount
; Index
++) {
420 CopyMem (&DataRecord
, &Variable
->DataRecord
[Index
], sizeof (DataRecord
));
422 DataItem
= &Instance
->DataItem
[DataRecord
.DataType
];
423 if (DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
) &&
424 (DataItem
->DataSize
!= DataRecord
.DataSize
)
427 // Perhaps a corrupted data record...
432 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
434 // This data item has variable length data.
436 DataItem
->Data
.Ptr
= AllocatePool (DataRecord
.DataSize
);
437 if (DataItem
->Data
.Ptr
== NULL
) {
439 // no memory resource
445 Data
= (CHAR8
*) Variable
+ DataRecord
.Offset
;
446 CopyMem (DataItem
->Data
.Ptr
, Data
, DataRecord
.DataSize
);
448 DataItem
->DataSize
= DataRecord
.DataSize
;
449 DataItem
->Status
= EFI_SUCCESS
;
460 Write the configuration data from IP6_CONFIG_INSTANCE to variable storage.
462 @param[in] VarName The pointer to the variable name.
463 @param[in] Instance The pointer to the IP6 configuration instance data.
465 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
466 @retval EFI_SUCCESS The configuration data is written successfully.
470 Ip6ConfigWriteConfigData (
472 IN IP6_CONFIG_INSTANCE
*Instance
477 IP6_CONFIG_DATA_ITEM
*DataItem
;
478 IP6_CONFIG_VARIABLE
*Variable
;
479 IP6_CONFIG_DATA_RECORD
*DataRecord
;
483 VarSize
= sizeof (IP6_CONFIG_VARIABLE
) - sizeof (IP6_CONFIG_DATA_RECORD
);
485 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
487 DataItem
= &Instance
->DataItem
[Index
];
488 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
490 VarSize
+= sizeof (IP6_CONFIG_DATA_RECORD
) + DataItem
->DataSize
;
494 Variable
= AllocatePool (VarSize
);
495 if (Variable
== NULL
) {
496 return EFI_OUT_OF_RESOURCES
;
499 Variable
->IaId
= Instance
->IaId
;
500 Heap
= (CHAR8
*) Variable
+ VarSize
;
501 Variable
->DataRecordCount
= 0;
503 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
505 DataItem
= &Instance
->DataItem
[Index
];
506 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
508 Heap
-= DataItem
->DataSize
;
509 CopyMem (Heap
, DataItem
->Data
.Ptr
, DataItem
->DataSize
);
511 DataRecord
= &Variable
->DataRecord
[Variable
->DataRecordCount
];
512 DataRecord
->DataType
= (EFI_IP6_CONFIG_DATA_TYPE
) Index
;
513 DataRecord
->DataSize
= (UINT32
) DataItem
->DataSize
;
514 DataRecord
->Offset
= (UINT16
) (Heap
- (CHAR8
*) Variable
);
516 Variable
->DataRecordCount
++;
520 Variable
->Checksum
= 0;
521 Variable
->Checksum
= (UINT16
) ~NetblockChecksum ((UINT8
*) Variable
, (UINT32
) VarSize
);
523 Status
= gRT
->SetVariable (
525 &gEfiIp6ConfigProtocolGuid
,
526 IP6_CONFIG_VARIABLE_ATTRIBUTE
,
537 The work function for EfiIp6ConfigGetData() to get the interface information
538 of the communication device this IP6Config instance manages.
540 @param[in] Instance Pointer to the IP6 config instance data.
541 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in
542 bytes, the size of buffer required to store the specified
544 @param[in] Data The data buffer in which the configuration data is returned.
545 Ignored if DataSize is ZERO.
547 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified
548 configuration data, and the required size is
549 returned in DataSize.
550 @retval EFI_SUCCESS The specified configuration data was obtained.
555 IN IP6_CONFIG_INSTANCE
*Instance
,
556 IN OUT UINTN
*DataSize
,
557 IN VOID
*Data OPTIONAL
562 IP6_CONFIG_DATA_ITEM
*Item
;
563 EFI_IP6_CONFIG_INTERFACE_INFO
*IfInfo
;
567 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
568 Length
= sizeof (EFI_IP6_CONFIG_INTERFACE_INFO
);
571 // Calculate the required length, add the buffer size for AddressInfo and
574 Ip6BuildEfiAddressList (IpSb
, &AddressCount
, NULL
);
575 Ip6BuildEfiRouteTable (IpSb
->RouteTable
, &RouteCount
, NULL
);
577 Length
+= AddressCount
* sizeof (EFI_IP6_ADDRESS_INFO
) + RouteCount
* sizeof (EFI_IP6_ROUTE_TABLE
);
579 if (*DataSize
< Length
) {
581 return EFI_BUFFER_TOO_SMALL
;
585 // Copy the fixed size part of the interface info.
587 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeInterfaceInfo
];
588 IfInfo
= (EFI_IP6_CONFIG_INTERFACE_INFO
*) Data
;
589 CopyMem (IfInfo
, Item
->Data
.Ptr
, sizeof (EFI_IP6_CONFIG_INTERFACE_INFO
));
594 IfInfo
->AddressInfo
= (EFI_IP6_ADDRESS_INFO
*) (IfInfo
+ 1);
595 Ip6BuildEfiAddressList (IpSb
, &IfInfo
->AddressInfoCount
, &IfInfo
->AddressInfo
);
600 IfInfo
->RouteTable
= (EFI_IP6_ROUTE_TABLE
*) (IfInfo
->AddressInfo
+ IfInfo
->AddressInfoCount
);
601 Ip6BuildEfiRouteTable (IpSb
->RouteTable
, &IfInfo
->RouteCount
, &IfInfo
->RouteTable
);
603 if (IfInfo
->AddressInfoCount
== 0) {
604 IfInfo
->AddressInfo
= NULL
;
607 if (IfInfo
->RouteCount
== 0) {
608 IfInfo
->RouteTable
= NULL
;
615 The work function for EfiIp6ConfigSetData() to set the alternative inteface ID
616 for the communication device managed by this IP6Config instance, if the link local
617 IPv6 addresses generated from the interface ID based on the default source the
618 EFI IPv6 Protocol uses is a duplicate address.
620 @param[in] Instance Pointer to the IP6 configuration instance data.
621 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
622 @param[in] Data The data buffer to set.
624 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type,
626 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
627 network stack was set.
631 Ip6ConfigSetAltIfId (
632 IN IP6_CONFIG_INSTANCE
*Instance
,
637 EFI_IP6_CONFIG_INTERFACE_ID
*OldIfId
;
638 EFI_IP6_CONFIG_INTERFACE_ID
*NewIfId
;
639 IP6_CONFIG_DATA_ITEM
*DataItem
;
641 if (DataSize
!= sizeof (EFI_IP6_CONFIG_INTERFACE_ID
)) {
642 return EFI_BAD_BUFFER_SIZE
;
645 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeAltInterfaceId
];
646 OldIfId
= DataItem
->Data
.AltIfId
;
647 NewIfId
= (EFI_IP6_CONFIG_INTERFACE_ID
*) Data
;
649 CopyMem (OldIfId
, NewIfId
, DataSize
);
650 DataItem
->Status
= EFI_SUCCESS
;
656 The work function for EfiIp6ConfigSetData() to set the general configuration
657 policy for the EFI IPv6 network stack that is running on the communication device
658 managed by this IP6Config instance. The policy will affect other configuration settings.
660 @param[in] Instance Pointer to the IP6 config instance data.
661 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
662 @param[in] Data The data buffer to set.
664 @retval EFI_INVALID_PARAMETER The to be set policy is invalid.
665 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
666 @retval EFI_ABORTED The new policy equals the current policy.
667 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
668 network stack was set.
673 IN IP6_CONFIG_INSTANCE
*Instance
,
678 EFI_IP6_CONFIG_POLICY NewPolicy
;
679 IP6_CONFIG_DATA_ITEM
*DataItem
;
682 if (DataSize
!= sizeof (EFI_IP6_CONFIG_POLICY
)) {
683 return EFI_BAD_BUFFER_SIZE
;
686 NewPolicy
= *((EFI_IP6_CONFIG_POLICY
*) Data
);
688 if (NewPolicy
> Ip6ConfigPolicyAutomatic
) {
689 return EFI_INVALID_PARAMETER
;
692 if (NewPolicy
== Instance
->Policy
) {
697 // Clean the ManualAddress, Gateway and DnsServers, shrink the variable
698 // data size, and fire up all the related events.
700 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
701 if (DataItem
->Data
.Ptr
!= NULL
) {
702 FreePool (DataItem
->Data
.Ptr
);
704 DataItem
->Data
.Ptr
= NULL
;
705 DataItem
->DataSize
= 0;
706 DataItem
->Status
= EFI_NOT_FOUND
;
707 NetMapIterate (&DataItem
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
709 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeGateway
];
710 if (DataItem
->Data
.Ptr
!= NULL
) {
711 FreePool (DataItem
->Data
.Ptr
);
713 DataItem
->Data
.Ptr
= NULL
;
714 DataItem
->DataSize
= 0;
715 DataItem
->Status
= EFI_NOT_FOUND
;
716 NetMapIterate (&DataItem
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
718 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
719 DataItem
->Data
.Ptr
= NULL
;
720 DataItem
->DataSize
= 0;
721 DataItem
->Status
= EFI_NOT_FOUND
;
722 NetMapIterate (&DataItem
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
724 if (NewPolicy
== Ip6ConfigPolicyManual
) {
726 // The policy is changed from automatic to manual. Stop the DHCPv6 process
727 // and destroy the DHCPv6 child.
729 if (Instance
->Dhcp6Handle
!= NULL
) {
730 Ip6ConfigDestroyDhcp6 (Instance
);
734 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
735 Ip6ConfigOnPolicyChanged (IpSb
, NewPolicy
);
737 Instance
->Policy
= NewPolicy
;
744 The work function for EfiIp6ConfigSetData() to set the number of consecutive
745 Neighbor Solicitation messages sent while performing Duplicate Address Detection
746 on a tentative address. A value of ZERO indicates that Duplicate Address Detection
747 will not be performed on a tentative address.
749 @param[in] Instance The Instance Pointer to the IP6 config instance data.
750 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
751 @param[in] Data The data buffer to set.
753 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
754 @retval EFI_ABORTED The new transmit count equals the current configuration.
755 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
756 network stack was set.
760 Ip6ConfigSetDadXmits (
761 IN IP6_CONFIG_INSTANCE
*Instance
,
766 EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS
*OldDadXmits
;
768 if (DataSize
!= sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS
)) {
769 return EFI_BAD_BUFFER_SIZE
;
772 OldDadXmits
= Instance
->DataItem
[Ip6ConfigDataTypeDupAddrDetectTransmits
].Data
.DadXmits
;
774 if ((*(UINT32
*) Data
) == OldDadXmits
->DupAddrDetectTransmits
) {
779 OldDadXmits
->DupAddrDetectTransmits
= *((UINT32
*) Data
);
785 The callback function for Ip6SetAddr. The prototype is defined
786 as IP6_DAD_CALLBACK. It is called after Duplicate Address Detection is performed
787 for the manual address set by Ip6ConfigSetManualAddress.
789 @param[in] IsDadPassed If TRUE, Duplicate Address Detection passed.
790 @param[in] TargetAddress The tentative IPv6 address to be checked.
791 @param[in] Context Pointer to the IP6 configuration instance data.
795 Ip6ManualAddrDadCallback (
796 IN BOOLEAN IsDadPassed
,
797 IN EFI_IPv6_ADDRESS
*TargetAddress
,
801 IP6_CONFIG_INSTANCE
*Instance
;
803 IP6_CONFIG_DATA_ITEM
*Item
;
804 EFI_IP6_CONFIG_MANUAL_ADDRESS
*ManualAddr
;
805 EFI_IP6_CONFIG_MANUAL_ADDRESS
*PassedAddr
;
810 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
811 NET_CHECK_SIGNATURE (Instance
, IP6_CONFIG_INSTANCE_SIGNATURE
);
812 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
815 if (Item
->DataSize
== 0) {
819 for (Index
= 0; Index
< Item
->DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
); Index
++) {
821 // Find the original tag used to place into the NET_MAP.
823 ManualAddr
= Item
->Data
.ManualAddress
+ Index
;
824 if (EFI_IP6_EQUAL (TargetAddress
, &ManualAddr
->Address
)) {
829 ASSERT (Index
!= Item
->DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
));
832 NetMapInsertTail (&Instance
->DadPassedMap
, ManualAddr
, NULL
);
834 NetMapInsertTail (&Instance
->DadFailedMap
, ManualAddr
, NULL
);
837 DadPassCount
= NetMapGetCount (&Instance
->DadPassedMap
);
838 DadFailCount
= NetMapGetCount (&Instance
->DadFailedMap
);
840 if ((DadPassCount
+ DadFailCount
) == (Item
->DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
))) {
842 // All addresses have finished the configuration process.
844 if (DadFailCount
!= 0) {
846 // There is at least one duplicate address.
848 FreePool (Item
->Data
.Ptr
);
850 Item
->DataSize
= DadPassCount
* sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
);
851 if (Item
->DataSize
== 0) {
853 // All failed, bad luck.
855 Item
->Data
.Ptr
= NULL
;
856 Item
->Status
= EFI_NOT_FOUND
;
859 // Part of addresses are detected to be duplicates, so update the
860 // data with those passed.
862 PassedAddr
= (EFI_IP6_CONFIG_MANUAL_ADDRESS
*) AllocatePool (Item
->DataSize
);
863 ASSERT (PassedAddr
!= NULL
);
865 Item
->Data
.Ptr
= PassedAddr
;
866 Item
->Status
= EFI_SUCCESS
;
868 while (!NetMapIsEmpty (&Instance
->DadPassedMap
)) {
869 ManualAddr
= (EFI_IP6_CONFIG_MANUAL_ADDRESS
*) NetMapRemoveHead (&Instance
->DadPassedMap
, NULL
);
870 CopyMem (PassedAddr
, ManualAddr
, sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
));
875 ASSERT ((UINTN
) PassedAddr
- (UINTN
) Item
->Data
.Ptr
== Item
->DataSize
);
879 // All addresses are valid.
881 Item
->Status
= EFI_SUCCESS
;
885 // Remove the tags we put in the NET_MAPs.
887 while (!NetMapIsEmpty (&Instance
->DadFailedMap
)) {
888 NetMapRemoveHead (&Instance
->DadFailedMap
, NULL
);
891 while (!NetMapIsEmpty (&Instance
->DadPassedMap
)) {
892 NetMapRemoveHead (&Instance
->DadPassedMap
, NULL
);
896 // Signal the waiting events.
898 NetMapIterate (&Item
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
899 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
900 Ip6ConfigWriteConfigData (IpSb
->MacString
, Instance
);
905 The work function for EfiIp6ConfigSetData() to set the station addresses manually
906 for the EFI IPv6 network stack. It is only configurable when the policy is
907 Ip6ConfigPolicyManual.
909 @param[in] Instance Pointer to the IP6 configuration instance data.
910 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
911 @param[in] Data The data buffer to set.
913 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
914 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
915 under the current policy.
916 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
917 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
918 @retval EFI_NOT_READY An asynchrous process is invoked to set the specified
919 configuration data, and the process is not finished.
920 @retval EFI_ABORTED The manual addresses to be set equal current
922 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
923 network stack was set.
927 Ip6ConfigSetManualAddress (
928 IN IP6_CONFIG_INSTANCE
*Instance
,
933 EFI_IP6_CONFIG_MANUAL_ADDRESS
*NewAddress
;
934 EFI_IP6_CONFIG_MANUAL_ADDRESS
*TmpAddress
;
935 IP6_CONFIG_DATA_ITEM
*DataItem
;
936 UINTN NewAddressCount
;
940 IP6_ADDRESS_INFO
*CurrentAddrInfo
;
941 IP6_ADDRESS_INFO
*Copy
;
942 LIST_ENTRY CurrentSourceList
;
943 UINT32 CurrentSourceCount
;
947 IP6_PREFIX_LIST_ENTRY
*PrefixEntry
;
951 IP6_DAD_ENTRY
*DadEntry
;
952 IP6_DELAY_JOIN_LIST
*DelayNode
;
956 CurrentAddrInfo
= NULL
;
965 Status
= EFI_SUCCESS
;
967 ASSERT (Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
].Status
!= EFI_NOT_READY
);
969 if ((DataSize
!= 0) && ((DataSize
% sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
)) != 0)) {
970 return EFI_BAD_BUFFER_SIZE
;
973 if (Instance
->Policy
!= Ip6ConfigPolicyManual
) {
974 return EFI_WRITE_PROTECTED
;
977 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
979 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
981 if (Data
!= NULL
&& DataSize
!= 0) {
982 NewAddressCount
= DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
);
983 NewAddress
= (EFI_IP6_CONFIG_MANUAL_ADDRESS
*) Data
;
985 for (Index1
= 0; Index1
< NewAddressCount
; Index1
++, NewAddress
++) {
987 if (NetIp6IsLinkLocalAddr (&NewAddress
->Address
) ||
988 !NetIp6IsValidUnicast (&NewAddress
->Address
) ||
989 (NewAddress
->PrefixLength
> 128)
992 // make sure the IPv6 address is unicast and not link-local address &&
993 // the prefix length is valid.
995 return EFI_INVALID_PARAMETER
;
998 TmpAddress
= NewAddress
+ 1;
999 for (Index2
= Index1
+ 1; Index2
< NewAddressCount
; Index2
++, TmpAddress
++) {
1001 // Any two addresses in the array can't be equal.
1003 if (EFI_IP6_EQUAL (&TmpAddress
->Address
, &NewAddress
->Address
)) {
1005 return EFI_INVALID_PARAMETER
;
1011 // Build the current source address list.
1013 InitializeListHead (&CurrentSourceList
);
1014 CurrentSourceCount
= 0;
1016 NET_LIST_FOR_EACH (Entry
, &IpSb
->Interfaces
) {
1017 IpIf
= NET_LIST_USER_STRUCT_S (Entry
, IP6_INTERFACE
, Link
, IP6_INTERFACE_SIGNATURE
);
1019 NET_LIST_FOR_EACH (Entry2
, &IpIf
->AddressList
) {
1020 CurrentAddrInfo
= NET_LIST_USER_STRUCT_S (Entry2
, IP6_ADDRESS_INFO
, Link
, IP6_ADDR_INFO_SIGNATURE
);
1022 Copy
= AllocateCopyPool (sizeof (IP6_ADDRESS_INFO
), CurrentAddrInfo
);
1027 InsertTailList (&CurrentSourceList
, &Copy
->Link
);
1028 CurrentSourceCount
++;
1033 // Update the value... a long journey starts
1035 NewAddress
= AllocateCopyPool (DataSize
, Data
);
1036 if (NewAddress
== NULL
) {
1037 Ip6RemoveAddr (NULL
, &CurrentSourceList
, &CurrentSourceCount
, NULL
, 0);
1039 return EFI_OUT_OF_RESOURCES
;
1043 // Store the new data, and init the DataItem status to EFI_NOT_READY because
1044 // we may have an asynchronous configuration process.
1046 if (DataItem
->Data
.Ptr
!= NULL
) {
1047 FreePool (DataItem
->Data
.Ptr
);
1049 DataItem
->Data
.Ptr
= NewAddress
;
1050 DataItem
->DataSize
= DataSize
;
1051 DataItem
->Status
= EFI_NOT_READY
;
1054 // Trigger DAD, it's an asynchronous process.
1058 for (Index1
= 0; Index1
< NewAddressCount
; Index1
++, NewAddress
++) {
1059 if (Ip6IsOneOfSetAddress (IpSb
, &NewAddress
->Address
, NULL
, &CurrentAddrInfo
)) {
1060 ASSERT (CurrentAddrInfo
!= NULL
);
1062 // Remove this already existing source address from the CurrentSourceList
1068 &CurrentSourceCount
,
1069 &CurrentAddrInfo
->Address
,
1074 // If the new address's prefix length is not specified, just use the previous configured
1075 // prefix length for this address.
1077 if (NewAddress
->PrefixLength
== 0) {
1078 NewAddress
->PrefixLength
= CurrentAddrInfo
->PrefixLength
;
1082 // This manual address is already in use, see whether prefix length is changed.
1084 if (NewAddress
->PrefixLength
!= CurrentAddrInfo
->PrefixLength
) {
1086 // Remove the on-link prefix table, the route entry will be removed
1089 PrefixEntry
= Ip6FindPrefixListEntry (
1092 CurrentAddrInfo
->PrefixLength
,
1093 &CurrentAddrInfo
->Address
1095 if (PrefixEntry
!= NULL
) {
1096 Ip6DestroyPrefixListEntry (IpSb
, PrefixEntry
, TRUE
, FALSE
);
1100 // Save the prefix length.
1102 CurrentAddrInfo
->PrefixLength
= NewAddress
->PrefixLength
;
1107 // create a new on-link prefix entry.
1109 PrefixEntry
= Ip6FindPrefixListEntry (
1112 NewAddress
->PrefixLength
,
1113 &NewAddress
->Address
1115 if (PrefixEntry
== NULL
) {
1116 Ip6CreatePrefixListEntry (
1119 (UINT32
) IP6_INFINIT_LIFETIME
,
1120 (UINT32
) IP6_INFINIT_LIFETIME
,
1121 NewAddress
->PrefixLength
,
1122 &NewAddress
->Address
1126 CurrentAddrInfo
->IsAnycast
= NewAddress
->IsAnycast
;
1128 // Artificially mark this address passed DAD be'coz it is already in use.
1130 Ip6ManualAddrDadCallback (TRUE
, &NewAddress
->Address
, Instance
);
1138 // Set the new address, this will trigger DAD and activate the address if
1142 IpSb
->DefaultInterface
,
1143 &NewAddress
->Address
,
1144 NewAddress
->IsAnycast
,
1145 NewAddress
->PrefixLength
,
1146 (UINT32
) IP6_INFINIT_LIFETIME
,
1147 (UINT32
) IP6_INFINIT_LIFETIME
,
1148 Ip6ManualAddrDadCallback
,
1155 // Check the CurrentSourceList, it now contains those addresses currently in
1156 // use and will be removed.
1158 IpIf
= IpSb
->DefaultInterface
;
1160 while (!IsListEmpty (&CurrentSourceList
)) {
1163 CurrentAddrInfo
= NET_LIST_HEAD (&CurrentSourceList
, IP6_ADDRESS_INFO
, Link
);
1166 // This local address is going to be removed, the IP instances that are
1167 // currently using it will be destroyed.
1172 &IpIf
->AddressCount
,
1173 &CurrentAddrInfo
->Address
,
1178 // Remove the on-link prefix table, the route entry will be removed
1181 PrefixEntry
= Ip6FindPrefixListEntry (
1184 CurrentAddrInfo
->PrefixLength
,
1185 &CurrentAddrInfo
->Address
1187 if (PrefixEntry
!= NULL
) {
1188 Ip6DestroyPrefixListEntry (IpSb
, PrefixEntry
, TRUE
, FALSE
);
1191 RemoveEntryList (&CurrentAddrInfo
->Link
);
1192 FreePool (CurrentAddrInfo
);
1196 if (DataItem
->Status
== EFI_NOT_READY
) {
1198 // If DAD is disabled on this interface, the configuration process is
1199 // actually synchronous, and the data item's status will be changed to
1200 // the final status before we reach here, just check it.
1202 Status
= EFI_NOT_READY
;
1204 Status
= EFI_SUCCESS
;
1208 // No update is taken, reset the status to success and return EFI_ABORTED.
1210 DataItem
->Status
= EFI_SUCCESS
;
1211 Status
= EFI_ABORTED
;
1215 // DataSize is 0 and Data is NULL, clean up the manual address.
1217 if (DataItem
->Data
.Ptr
!= NULL
) {
1218 FreePool (DataItem
->Data
.Ptr
);
1220 DataItem
->Data
.Ptr
= NULL
;
1221 DataItem
->DataSize
= 0;
1222 DataItem
->Status
= EFI_NOT_FOUND
;
1224 Ip6CleanDefaultRouterList (IpSb
);
1225 Ip6CleanPrefixListTable (IpSb
, &IpSb
->OnlinkPrefix
);
1226 Ip6CleanPrefixListTable (IpSb
, &IpSb
->AutonomousPrefix
);
1227 Ip6CleanAssembleTable (&IpSb
->Assemble
);
1229 if (IpSb
->LinkLocalOk
) {
1230 Ip6CreatePrefixListEntry (
1233 (UINT32
) IP6_INFINIT_LIFETIME
,
1234 (UINT32
) IP6_INFINIT_LIFETIME
,
1235 IP6_LINK_LOCAL_PREFIX_LENGTH
,
1236 &IpSb
->LinkLocalAddr
1242 &IpSb
->DefaultInterface
->AddressList
,
1243 &IpSb
->DefaultInterface
->AddressCount
,
1248 NET_LIST_FOR_EACH (Entry
, &IpSb
->Interfaces
) {
1250 // Remove all pending delay node and DAD entries for the global addresses.
1252 IpIf
= NET_LIST_USER_STRUCT_S (Entry
, IP6_INTERFACE
, Link
, IP6_INTERFACE_SIGNATURE
);
1254 NET_LIST_FOR_EACH_SAFE (Entry2
, Next
, &IpIf
->DelayJoinList
) {
1255 DelayNode
= NET_LIST_USER_STRUCT (Entry2
, IP6_DELAY_JOIN_LIST
, Link
);
1256 if (!NetIp6IsLinkLocalAddr (&DelayNode
->AddressInfo
->Address
)) {
1257 RemoveEntryList (&DelayNode
->Link
);
1258 FreePool (DelayNode
);
1262 NET_LIST_FOR_EACH_SAFE (Entry2
, Next
, &IpIf
->DupAddrDetectList
) {
1263 DadEntry
= NET_LIST_USER_STRUCT_S (Entry2
, IP6_DAD_ENTRY
, Link
, IP6_DAD_ENTRY_SIGNATURE
);
1265 if (!NetIp6IsLinkLocalAddr (&DadEntry
->AddressInfo
->Address
)) {
1267 // Fail this DAD entry if the address is not link-local.
1269 Ip6OnDADFinished (FALSE
, IpIf
, DadEntry
);
1279 The work function for EfiIp6ConfigSetData() to set the gateway addresses manually
1280 for the EFI IPv6 network stack that is running on the communication device that
1281 this EFI IPv6 Configuration Protocol manages. It is not configurable when the policy is
1282 Ip6ConfigPolicyAutomatic. The gateway addresses must be unicast IPv6 addresses.
1284 @param[in] Instance The pointer to the IP6 config instance data.
1285 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1286 @param[in] Data The data buffer to set. This points to an array of
1287 EFI_IPv6_ADDRESS instances.
1289 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1290 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1291 under the current policy.
1292 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1293 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to complete the operation.
1294 @retval EFI_ABORTED The manual gateway addresses to be set equal the
1295 current configuration.
1296 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1297 network stack was set.
1301 Ip6ConfigSetGateway (
1302 IN IP6_CONFIG_INSTANCE
*Instance
,
1309 EFI_IPv6_ADDRESS
*OldGateway
;
1310 EFI_IPv6_ADDRESS
*NewGateway
;
1311 UINTN OldGatewayCount
;
1312 UINTN NewGatewayCount
;
1313 IP6_CONFIG_DATA_ITEM
*Item
;
1317 IP6_DEFAULT_ROUTER
*DefaultRouter
;
1323 DefaultRouter
= NULL
;
1328 if ((DataSize
!= 0) && (DataSize
% sizeof (EFI_IPv6_ADDRESS
) != 0)) {
1329 return EFI_BAD_BUFFER_SIZE
;
1332 if (Instance
->Policy
!= Ip6ConfigPolicyManual
) {
1333 return EFI_WRITE_PROTECTED
;
1336 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
1337 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeGateway
];
1338 OldGateway
= Item
->Data
.Gateway
;
1339 OldGatewayCount
= Item
->DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1341 for (Index1
= 0; Index1
< OldGatewayCount
; Index1
++) {
1343 // Remove this default router.
1345 DefaultRouter
= Ip6FindDefaultRouter (IpSb
, OldGateway
+ Index1
);
1346 if (DefaultRouter
!= NULL
) {
1347 Ip6DestroyDefaultRouter (IpSb
, DefaultRouter
);
1352 if (Data
!= NULL
&& DataSize
!= 0) {
1353 NewGateway
= (EFI_IPv6_ADDRESS
*) Data
;
1354 NewGatewayCount
= DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1355 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1357 if (!NetIp6IsValidUnicast (NewGateway
+ Index1
)) {
1359 return EFI_INVALID_PARAMETER
;
1362 for (Index2
= Index1
+ 1; Index2
< NewGatewayCount
; Index2
++) {
1363 if (EFI_IP6_EQUAL (NewGateway
+ Index1
, NewGateway
+ Index2
)) {
1364 return EFI_INVALID_PARAMETER
;
1369 if (NewGatewayCount
!= OldGatewayCount
) {
1370 Tmp
= AllocatePool (DataSize
);
1372 return EFI_OUT_OF_RESOURCES
;
1378 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1380 DefaultRouter
= Ip6FindDefaultRouter (IpSb
, NewGateway
+ Index1
);
1381 if (DefaultRouter
== NULL
) {
1382 Ip6CreateDefaultRouter (IpSb
, NewGateway
+ Index1
, IP6_INF_ROUTER_LIFETIME
);
1387 if (!OneRemoved
&& !OneAdded
) {
1388 Item
->Status
= EFI_SUCCESS
;
1393 if (Item
->Data
.Ptr
!= NULL
) {
1394 FreePool (Item
->Data
.Ptr
);
1396 Item
->Data
.Ptr
= Tmp
;
1399 CopyMem (Item
->Data
.Ptr
, Data
, DataSize
);
1400 Item
->DataSize
= DataSize
;
1401 Item
->Status
= EFI_SUCCESS
;
1406 // DataSize is 0 and Data is NULL, clean up the Gateway address.
1408 if (Item
->Data
.Ptr
!= NULL
) {
1409 FreePool (Item
->Data
.Ptr
);
1411 Item
->Data
.Ptr
= NULL
;
1413 Item
->Status
= EFI_NOT_FOUND
;
1420 The work function for EfiIp6ConfigSetData() to set the DNS server list for the
1421 EFI IPv6 network stack running on the communication device that this EFI IPv6
1422 Configuration Protocol manages. It is not configurable when the policy is
1423 Ip6ConfigPolicyAutomatic. The DNS server addresses must be unicast IPv6 addresses.
1425 @param[in] Instance The pointer to the IP6 config instance data.
1426 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1427 @param[in] Data The data buffer to set, points to an array of
1428 EFI_IPv6_ADDRESS instances.
1430 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1431 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1432 under the current policy.
1433 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1434 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
1435 @retval EFI_ABORTED The DNS server addresses to be set equal the current
1437 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1438 network stack was set.
1442 Ip6ConfigSetDnsServer (
1443 IN IP6_CONFIG_INSTANCE
*Instance
,
1450 EFI_IPv6_ADDRESS
*OldDns
;
1451 EFI_IPv6_ADDRESS
*NewDns
;
1454 IP6_CONFIG_DATA_ITEM
*Item
;
1463 if ((DataSize
!= 0) && (DataSize
% sizeof (EFI_IPv6_ADDRESS
) != 0)) {
1464 return EFI_BAD_BUFFER_SIZE
;
1467 if (Instance
->Policy
!= Ip6ConfigPolicyManual
) {
1468 return EFI_WRITE_PROTECTED
;
1471 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
1473 if (Data
!= NULL
&& DataSize
!= 0) {
1474 NewDns
= (EFI_IPv6_ADDRESS
*) Data
;
1475 OldDns
= Item
->Data
.DnsServers
;
1476 NewDnsCount
= DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1477 OldDnsCount
= Item
->DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1480 if (NewDnsCount
!= OldDnsCount
) {
1481 Tmp
= AllocatePool (DataSize
);
1483 return EFI_OUT_OF_RESOURCES
;
1489 for (NewIndex
= 0; NewIndex
< NewDnsCount
; NewIndex
++) {
1491 if (!NetIp6IsValidUnicast (NewDns
+ NewIndex
)) {
1493 // The dns server address must be unicast.
1498 return EFI_INVALID_PARAMETER
;
1503 // If any address in the new setting is not in the old settings, skip the
1504 // comparision below.
1509 for (OldIndex
= 0; OldIndex
< OldDnsCount
; OldIndex
++) {
1510 if (EFI_IP6_EQUAL (NewDns
+ NewIndex
, OldDns
+ OldIndex
)) {
1512 // If found break out.
1518 if (OldIndex
== OldDnsCount
) {
1523 if (!OneAdded
&& (DataSize
== Item
->DataSize
)) {
1525 // No new item is added and the size is the same.
1527 Item
->Status
= EFI_SUCCESS
;
1531 if (Item
->Data
.Ptr
!= NULL
) {
1532 FreePool (Item
->Data
.Ptr
);
1534 Item
->Data
.Ptr
= Tmp
;
1537 CopyMem (Item
->Data
.Ptr
, Data
, DataSize
);
1538 Item
->DataSize
= DataSize
;
1539 Item
->Status
= EFI_SUCCESS
;
1543 // DataSize is 0 and Data is NULL, clean up the DnsServer address.
1545 if (Item
->Data
.Ptr
!= NULL
) {
1546 FreePool (Item
->Data
.Ptr
);
1548 Item
->Data
.Ptr
= NULL
;
1550 Item
->Status
= EFI_NOT_FOUND
;
1557 Generate the operational state of the interface this IP6 config instance manages
1558 and output in EFI_IP6_CONFIG_INTERFACE_INFO.
1560 @param[in] IpSb The pointer to the IP6 service binding instance.
1561 @param[out] IfInfo The pointer to the IP6 configuration interface information structure.
1565 Ip6ConfigInitIfInfo (
1566 IN IP6_SERVICE
*IpSb
,
1567 OUT EFI_IP6_CONFIG_INTERFACE_INFO
*IfInfo
1572 sizeof (IfInfo
->Name
),
1574 IpSb
->Ip6ConfigInstance
.IfIndex
1577 IfInfo
->IfType
= IpSb
->SnpMode
.IfType
;
1578 IfInfo
->HwAddressSize
= IpSb
->SnpMode
.HwAddressSize
;
1579 CopyMem (&IfInfo
->HwAddress
, &IpSb
->SnpMode
.CurrentAddress
, IfInfo
->HwAddressSize
);
1583 Parse DHCPv6 reply packet to get the DNS server list.
1584 It is the work function for Ip6ConfigOnDhcp6Reply and Ip6ConfigOnDhcp6Event.
1586 @param[in] Dhcp6 The pointer to the EFI_DHCP6_PROTOCOL instance.
1587 @param[in, out] Instance The pointer to the IP6 configuration instance data.
1588 @param[in] Reply The pointer to the DHCPv6 reply packet.
1590 @retval EFI_SUCCESS The DNS server address was retrieved from the reply packet.
1591 @retval EFI_NOT_READY The reply packet does not contain the DNS server option, or
1592 the DNS server address is not valid.
1596 Ip6ConfigParseDhcpReply (
1597 IN EFI_DHCP6_PROTOCOL
*Dhcp6
,
1598 IN OUT IP6_CONFIG_INSTANCE
*Instance
,
1599 IN EFI_DHCP6_PACKET
*Reply
1604 EFI_DHCP6_PACKET_OPTION
**OptList
;
1609 EFI_IPv6_ADDRESS
*DnsServer
;
1610 IP6_CONFIG_DATA_ITEM
*Item
;
1613 // A DHCPv6 reply packet is received as the response to our InfoRequest
1617 Status
= Dhcp6
->Parse (Dhcp6
, Reply
, &OptCount
, NULL
);
1618 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1619 return EFI_NOT_READY
;
1622 OptList
= AllocatePool (OptCount
* sizeof (EFI_DHCP6_PACKET_OPTION
*));
1623 if (OptList
== NULL
) {
1624 return EFI_NOT_READY
;
1627 Status
= Dhcp6
->Parse (Dhcp6
, Reply
, &OptCount
, OptList
);
1628 if (EFI_ERROR (Status
)) {
1629 Status
= EFI_NOT_READY
;
1633 Status
= EFI_SUCCESS
;
1635 for (Index
= 0; Index
< OptCount
; Index
++) {
1637 // Go through all the options to check the ones we are interested in.
1638 // The OpCode and Length are in network byte-order and may not be naturally
1641 CopyMem (&OpCode
, &OptList
[Index
]->OpCode
, sizeof (OpCode
));
1642 OpCode
= NTOHS (OpCode
);
1644 if (OpCode
== DHCP6_OPT_DNS_SERVERS
) {
1645 CopyMem (&Length
, &OptList
[Index
]->OpLen
, sizeof (Length
));
1646 Length
= NTOHS (Length
);
1648 if ((Length
== 0) || ((Length
% sizeof (EFI_IPv6_ADDRESS
)) != 0)) {
1650 // The length should be a multiple of 16 bytes.
1652 Status
= EFI_NOT_READY
;
1657 // Validate the DnsServers: whether they are unicast addresses.
1659 DnsServer
= (EFI_IPv6_ADDRESS
*) OptList
[Index
]->Data
;
1660 for (Index2
= 0; Index2
< Length
/ sizeof (EFI_IPv6_ADDRESS
); Index2
++) {
1661 if (!NetIp6IsValidUnicast (DnsServer
)) {
1662 Status
= EFI_NOT_READY
;
1669 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
1671 if (Item
->DataSize
!= Length
) {
1672 if (Item
->Data
.Ptr
!= NULL
) {
1673 FreePool (Item
->Data
.Ptr
);
1676 Item
->Data
.Ptr
= AllocatePool (Length
);
1677 ASSERT (Item
->Data
.Ptr
!= NULL
);
1680 CopyMem (Item
->Data
.Ptr
, OptList
[Index
]->Data
, Length
);
1681 Item
->DataSize
= Length
;
1682 Item
->Status
= EFI_SUCCESS
;
1685 // Signal the waiting events.
1687 NetMapIterate (&Item
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
1700 The callback function for Ip6SetAddr. The prototype is defined
1701 as IP6_DAD_CALLBACK. It is called after Duplicate Address Detection is performed
1702 on the tentative address by DHCPv6 in Ip6ConfigOnDhcp6Event().
1704 @param[in] IsDadPassed If TRUE, Duplicate Address Detection passes.
1705 @param[in] TargetAddress The tentative IPv6 address to be checked.
1706 @param[in] Context Pointer to the IP6 configuration instance data.
1710 Ip6ConfigSetStatefulAddrCallback (
1711 IN BOOLEAN IsDadPassed
,
1712 IN EFI_IPv6_ADDRESS
*TargetAddress
,
1716 IP6_CONFIG_INSTANCE
*Instance
;
1718 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
1719 NET_CHECK_SIGNATURE (Instance
, IP6_CONFIG_INSTANCE_SIGNATURE
);
1722 // We should record the addresses that fail the DAD, and DECLINE them.
1726 // Decrease the count, no interests in those passed DAD.
1728 if (Instance
->FailedIaAddressCount
> 0 ) {
1729 Instance
->FailedIaAddressCount
--;
1735 IP6_COPY_ADDRESS (Instance
->DeclineAddress
+ Instance
->DeclineAddressCount
, TargetAddress
);
1736 Instance
->DeclineAddressCount
++;
1739 if (Instance
->FailedIaAddressCount
== Instance
->DeclineAddressCount
) {
1741 // The checking on all addresses are finished.
1743 if (Instance
->DeclineAddressCount
!= 0) {
1745 // Decline those duplicates.
1747 if (Instance
->Dhcp6
!= NULL
) {
1748 Instance
->Dhcp6
->Decline (
1750 Instance
->DeclineAddressCount
,
1751 Instance
->DeclineAddress
1756 if (Instance
->DeclineAddress
!= NULL
) {
1757 FreePool (Instance
->DeclineAddress
);
1759 Instance
->DeclineAddress
= NULL
;
1760 Instance
->DeclineAddressCount
= 0;
1765 The event handle routine when DHCPv6 process is finished or is updated.
1767 @param[in] Event Not used.
1768 @param[in] Context The pointer to the IP6 configuration instance data.
1773 Ip6ConfigOnDhcp6Event (
1778 IP6_CONFIG_INSTANCE
*Instance
;
1779 EFI_DHCP6_PROTOCOL
*Dhcp6
;
1781 EFI_DHCP6_MODE_DATA Dhcp6ModeData
;
1783 EFI_DHCP6_IA_ADDRESS
*IaAddr
;
1786 IP6_ADDRESS_INFO
*AddrInfo
;
1787 IP6_INTERFACE
*IpIf
;
1789 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
1791 if ((Instance
->Policy
!= Ip6ConfigPolicyAutomatic
) || Instance
->OtherInfoOnly
) {
1793 // IPv6 is not operating in the automatic policy now or
1794 // the DHCPv6 information request message exchange is aborted.
1800 // The stateful address autoconfiguration is done or updated.
1802 Dhcp6
= Instance
->Dhcp6
;
1804 Status
= Dhcp6
->GetModeData (Dhcp6
, &Dhcp6ModeData
, NULL
);
1805 if (EFI_ERROR (Status
)) {
1809 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
1810 IpIf
= IpSb
->DefaultInterface
;
1811 Ia
= Dhcp6ModeData
.Ia
;
1812 IaAddr
= Ia
->IaAddress
;
1814 if (Instance
->DeclineAddress
!= NULL
) {
1815 FreePool (Instance
->DeclineAddress
);
1818 Instance
->DeclineAddress
= (EFI_IPv6_ADDRESS
*) AllocatePool (Ia
->IaAddressCount
* sizeof (EFI_IPv6_ADDRESS
));
1819 if (Instance
->DeclineAddress
== NULL
) {
1823 Instance
->FailedIaAddressCount
= Ia
->IaAddressCount
;
1824 Instance
->DeclineAddressCount
= 0;
1826 for (Index
= 0; Index
< Ia
->IaAddressCount
; Index
++, IaAddr
++) {
1827 if (Ia
->IaAddress
[Index
].ValidLifetime
!= 0 && Ia
->State
== Dhcp6Bound
) {
1829 // Set this address, either it's a new address or with updated lifetimes.
1830 // An appropriate prefix length will be set.
1837 IaAddr
->ValidLifetime
,
1838 IaAddr
->PreferredLifetime
,
1839 Ip6ConfigSetStatefulAddrCallback
,
1844 // discard this address, artificially decrease the count as if this address
1847 if (Ip6IsOneOfSetAddress (IpSb
, &IaAddr
->IpAddress
, NULL
, &AddrInfo
)) {
1848 ASSERT (AddrInfo
!= NULL
);
1852 &IpIf
->AddressCount
,
1854 AddrInfo
->PrefixLength
1858 if (Instance
->FailedIaAddressCount
> 0) {
1859 Instance
->FailedIaAddressCount
--;
1865 // Parse the Reply packet to get the options we need.
1867 if (Dhcp6ModeData
.Ia
->ReplyPacket
!= NULL
) {
1868 Ip6ConfigParseDhcpReply (Dhcp6
, Instance
, Dhcp6ModeData
.Ia
->ReplyPacket
);
1873 FreePool (Dhcp6ModeData
.ClientId
);
1874 FreePool (Dhcp6ModeData
.Ia
);
1878 The event process routine when the DHCPv6 server is answered with a reply packet
1879 for an information request.
1881 @param[in] This Points to the EFI_DHCP6_PROTOCOL.
1882 @param[in] Context The pointer to the IP6 configuration instance data.
1883 @param[in] Packet The DHCPv6 reply packet.
1885 @retval EFI_SUCCESS The DNS server address was retrieved from the reply packet.
1886 @retval EFI_NOT_READY The reply packet does not contain the DNS server option, or
1887 the DNS server address is not valid.
1892 Ip6ConfigOnDhcp6Reply (
1893 IN EFI_DHCP6_PROTOCOL
*This
,
1895 IN EFI_DHCP6_PACKET
*Packet
1898 return Ip6ConfigParseDhcpReply (This
, (IP6_CONFIG_INSTANCE
*) Context
, Packet
);
1902 The event process routine when the DHCPv6 service binding protocol is installed
1905 @param[in] Event Not used.
1906 @param[in] Context The pointer to the IP6 config instance data.
1911 Ip6ConfigOnDhcp6SbInstalled (
1916 IP6_CONFIG_INSTANCE
*Instance
;
1918 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
1920 if ((Instance
->Dhcp6Handle
!= NULL
) || (Instance
->Policy
!= Ip6ConfigPolicyAutomatic
)) {
1922 // The DHCP6 child is already created or the policy is no longer AUTOMATIC.
1927 Ip6ConfigStartStatefulAutoConfig (Instance
, Instance
->OtherInfoOnly
);
1931 Set the configuration for the EFI IPv6 network stack running on the communication
1932 device this EFI IPv6 Configuration Protocol instance manages.
1934 This function is used to set the configuration data of type DataType for the EFI
1935 IPv6 network stack that is running on the communication device that this EFI IPv6
1936 Configuration Protocol instance manages.
1938 DataSize is used to calculate the count of structure instances in the Data for
1939 a DataType in which multiple structure instances are allowed.
1941 This function is always non-blocking. When setting some type of configuration data,
1942 an asynchronous process is invoked to check the correctness of the data, such as
1943 performing Duplicate Address Detection on the manually set local IPv6 addresses.
1944 EFI_NOT_READY is returned immediately to indicate that such an asynchronous process
1945 is invoked, and the process is not finished yet. The caller wanting to get the result
1946 of the asynchronous process is required to call RegisterDataNotify() to register an
1947 event on the specified configuration data. Once the event is signaled, the caller
1948 can call GetData() to obtain the configuration data and know the result.
1949 For other types of configuration data that do not require an asynchronous configuration
1950 process, the result of the operation is immediately returned.
1952 @param[in] This The pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
1953 @param[in] DataType The type of data to set.
1954 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1955 @param[in] Data The data buffer to set. The type of the data buffer is
1956 associated with the DataType.
1958 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1959 network stack was set successfully.
1960 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
1962 - One or more fields in Data and DataSizedo not match the
1963 requirement of the data type indicated by DataType.
1964 @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified
1965 configuration data cannot be set under the current policy.
1966 @retval EFI_ACCESS_DENIED Another set operation on the specified configuration
1967 data is already in process.
1968 @retval EFI_NOT_READY An asynchronous process was invoked to set the specified
1969 configuration data, and the process is not finished yet.
1970 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type
1971 indicated by DataType.
1972 @retval EFI_UNSUPPORTED This DataType is not supported.
1973 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1974 @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
1979 EfiIp6ConfigSetData (
1980 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
1981 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
1988 IP6_CONFIG_INSTANCE
*Instance
;
1991 if ((This
== NULL
) || (Data
== NULL
&& DataSize
!= 0) || (Data
!= NULL
&& DataSize
== 0)) {
1992 return EFI_INVALID_PARAMETER
;
1995 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
1996 return EFI_UNSUPPORTED
;
1999 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
2000 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
2001 NET_CHECK_SIGNATURE (IpSb
, IP6_SERVICE_SIGNATURE
);
2003 if (IpSb
->LinkLocalDadFail
) {
2004 return EFI_DEVICE_ERROR
;
2007 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2009 Status
= Instance
->DataItem
[DataType
].Status
;
2010 if (Status
!= EFI_NOT_READY
) {
2012 if (Instance
->DataItem
[DataType
].SetData
== NULL
) {
2014 // This type of data is readonly.
2016 Status
= EFI_WRITE_PROTECTED
;
2019 Status
= Instance
->DataItem
[DataType
].SetData (Instance
, DataSize
, Data
);
2020 if (!EFI_ERROR (Status
)) {
2022 // Fire up the events registered with this type of data.
2024 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip6ConfigSignalEvent
, NULL
);
2025 Ip6ConfigWriteConfigData (IpSb
->MacString
, Instance
);
2026 } else if (Status
== EFI_ABORTED
) {
2028 // The SetData is aborted because the data to set is the same with
2029 // the one maintained.
2031 Status
= EFI_SUCCESS
;
2032 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip6ConfigSignalEvent
, NULL
);
2037 // Another asynchornous process is on the way.
2039 Status
= EFI_ACCESS_DENIED
;
2042 gBS
->RestoreTPL (OldTpl
);
2048 Get the configuration data for the EFI IPv6 network stack running on the communication
2049 device that this EFI IPv6 Configuration Protocol instance manages.
2051 This function returns the configuration data of type DataType for the EFI IPv6 network
2052 stack running on the communication device that this EFI IPv6 Configuration Protocol instance
2055 The caller is responsible for allocating the buffer used to return the specified
2056 configuration data. The required size will be returned to the caller if the size of
2057 the buffer is too small.
2059 EFI_NOT_READY is returned if the specified configuration data is not ready due to an
2060 asynchronous configuration process already in progress. The caller can call RegisterDataNotify()
2061 to register an event on the specified configuration data. Once the asynchronous configuration
2062 process is finished, the event will be signaled, and a subsequent GetData() call will return
2063 the specified configuration data.
2065 @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
2066 @param[in] DataType The type of data to get.
2067 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in bytes, the
2068 size of buffer required to store the specified configuration data.
2069 @param[in] Data The data buffer in which the configuration data is returned. The
2070 type of the data buffer is associated with the DataType.
2071 This is an optional parameter that may be NULL.
2073 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
2074 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
2077 - Data is NULL if *DataSize is not zero.
2078 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data,
2079 and the required size is returned in DataSize.
2080 @retval EFI_NOT_READY The specified configuration data is not ready due to an
2081 asynchronous configuration process already in progress.
2082 @retval EFI_NOT_FOUND The specified configuration data is not found.
2087 EfiIp6ConfigGetData (
2088 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
2089 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
2090 IN OUT UINTN
*DataSize
,
2091 IN VOID
*Data OPTIONAL
2096 IP6_CONFIG_INSTANCE
*Instance
;
2097 IP6_CONFIG_DATA_ITEM
*DataItem
;
2099 if ((This
== NULL
) || (DataSize
== NULL
) || ((*DataSize
!= 0) && (Data
== NULL
))) {
2100 return EFI_INVALID_PARAMETER
;
2103 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
2104 return EFI_NOT_FOUND
;
2107 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2109 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
2110 DataItem
= &Instance
->DataItem
[DataType
];
2112 Status
= Instance
->DataItem
[DataType
].Status
;
2113 if (!EFI_ERROR (Status
)) {
2115 if (DataItem
->GetData
!= NULL
) {
2117 Status
= DataItem
->GetData (Instance
, DataSize
, Data
);
2118 } else if (*DataSize
< Instance
->DataItem
[DataType
].DataSize
) {
2120 // Update the buffer length.
2122 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
2123 Status
= EFI_BUFFER_TOO_SMALL
;
2126 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
2127 CopyMem (Data
, Instance
->DataItem
[DataType
].Data
.Ptr
, *DataSize
);
2131 gBS
->RestoreTPL (OldTpl
);
2137 Register an event that is signaled whenever a configuration process on the specified
2138 configuration data is done.
2140 This function registers an event that is to be signaled whenever a configuration
2141 process on the specified configuration data is performed. An event can be registered
2142 for a different DataType simultaneously. The caller is responsible for determining
2143 which type of configuration data causes the signaling of the event in such an event.
2145 @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
2146 @param[in] DataType The type of data to unregister the event for.
2147 @param[in] Event The event to register.
2149 @retval EFI_SUCCESS The notification event for the specified configuration data is
2151 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
2152 @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not
2154 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
2155 @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
2160 EfiIp6ConfigRegisterDataNotify (
2161 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
2162 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
2168 IP6_CONFIG_INSTANCE
*Instance
;
2172 if ((This
== NULL
) || (Event
== NULL
)) {
2173 return EFI_INVALID_PARAMETER
;
2176 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
2177 return EFI_UNSUPPORTED
;
2180 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2182 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
2183 EventMap
= &Instance
->DataItem
[DataType
].EventMap
;
2186 // Check whether this event is already registered for this DataType.
2188 Item
= NetMapFindKey (EventMap
, Event
);
2191 Status
= NetMapInsertTail (EventMap
, Event
, NULL
);
2193 if (EFI_ERROR (Status
)) {
2195 Status
= EFI_OUT_OF_RESOURCES
;
2200 Status
= EFI_ACCESS_DENIED
;
2203 gBS
->RestoreTPL (OldTpl
);
2209 Remove a previously registered event for the specified configuration data.
2211 @param This The pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
2212 @param DataType The type of data to remove from the previously
2214 @param Event The event to be unregistered.
2216 @retval EFI_SUCCESS The event registered for the specified
2217 configuration data was removed.
2218 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
2219 @retval EFI_NOT_FOUND The Event has not been registered for the
2225 EfiIp6ConfigUnregisterDataNotify (
2226 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
2227 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
2233 IP6_CONFIG_INSTANCE
*Instance
;
2236 if ((This
== NULL
) || (Event
== NULL
)) {
2237 return EFI_INVALID_PARAMETER
;
2240 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
2241 return EFI_NOT_FOUND
;
2244 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2246 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
2248 Item
= NetMapFindKey (&Instance
->DataItem
[DataType
].EventMap
, Event
);
2251 NetMapRemoveItem (&Instance
->DataItem
[DataType
].EventMap
, Item
, NULL
);
2252 Status
= EFI_SUCCESS
;
2255 Status
= EFI_NOT_FOUND
;
2258 gBS
->RestoreTPL (OldTpl
);
2264 Initialize an IP6_CONFIG_INSTANCE.
2266 @param[out] Instance The buffer of IP6_CONFIG_INSTANCE to be initialized.
2268 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
2269 @retval EFI_SUCCESS The IP6_CONFIG_INSTANCE initialized successfully.
2273 Ip6ConfigInitInstance (
2274 OUT IP6_CONFIG_INSTANCE
*Instance
2278 IP6_CONFIG_INSTANCE
*TmpInstance
;
2283 IP6_CONFIG_DATA_ITEM
*DataItem
;
2285 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
2287 Instance
->Signature
= IP6_CONFIG_INSTANCE_SIGNATURE
;
2290 // Determine the index of this interface.
2293 NET_LIST_FOR_EACH (Entry
, &mIp6ConfigInstanceList
) {
2294 TmpInstance
= NET_LIST_USER_STRUCT_S (Entry
, IP6_CONFIG_INSTANCE
, Link
, IP6_CONFIG_INSTANCE_SIGNATURE
);
2296 if (TmpInstance
->IfIndex
> IfIndex
) {
2298 // There is a sequence hole because some interface is down.
2306 Instance
->IfIndex
= IfIndex
;
2307 NetListInsertBefore (Entry
, &Instance
->Link
);
2309 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
2311 // Initialize the event map for each data item.
2313 NetMapInit (&Instance
->DataItem
[Index
].EventMap
);
2317 // Initialize the NET_MAPs used for DAD on manually configured source addresses.
2319 NetMapInit (&Instance
->DadFailedMap
);
2320 NetMapInit (&Instance
->DadPassedMap
);
2323 // Initialize each data type: associate storage and set data size for the
2324 // fixed size data types, hook the SetData function, set the data attribute.
2326 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeInterfaceInfo
];
2327 DataItem
->GetData
= Ip6ConfigGetIfInfo
;
2328 DataItem
->Data
.Ptr
= &Instance
->InterfaceInfo
;
2329 DataItem
->DataSize
= sizeof (Instance
->InterfaceInfo
);
2330 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
| DATA_ATTRIB_VOLATILE
);
2331 Ip6ConfigInitIfInfo (IpSb
, &Instance
->InterfaceInfo
);
2333 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeAltInterfaceId
];
2334 DataItem
->SetData
= Ip6ConfigSetAltIfId
;
2335 DataItem
->Data
.Ptr
= &Instance
->AltIfId
;
2336 DataItem
->DataSize
= sizeof (Instance
->AltIfId
);
2337 DataItem
->Status
= EFI_NOT_FOUND
;
2338 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2340 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypePolicy
];
2341 DataItem
->SetData
= Ip6ConfigSetPolicy
;
2342 DataItem
->Data
.Ptr
= &Instance
->Policy
;
2343 DataItem
->DataSize
= sizeof (Instance
->Policy
);
2344 Instance
->Policy
= Ip6ConfigPolicyManual
;
2345 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2347 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeDupAddrDetectTransmits
];
2348 DataItem
->SetData
= Ip6ConfigSetDadXmits
;
2349 DataItem
->Data
.Ptr
= &Instance
->DadXmits
;
2350 DataItem
->DataSize
= sizeof (Instance
->DadXmits
);
2351 Instance
->DadXmits
.DupAddrDetectTransmits
= IP6_CONFIG_DEFAULT_DAD_XMITS
;
2352 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2354 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
2355 DataItem
->SetData
= Ip6ConfigSetManualAddress
;
2356 DataItem
->Status
= EFI_NOT_FOUND
;
2358 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeGateway
];
2359 DataItem
->SetData
= Ip6ConfigSetGateway
;
2360 DataItem
->Status
= EFI_NOT_FOUND
;
2362 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
2363 DataItem
->SetData
= Ip6ConfigSetDnsServer
;
2364 DataItem
->Status
= EFI_NOT_FOUND
;
2367 // Create the event used for DHCP.
2369 Status
= gBS
->CreateEvent (
2372 Ip6ConfigOnDhcp6Event
,
2374 &Instance
->Dhcp6Event
2376 ASSERT_EFI_ERROR (Status
);
2378 Instance
->Configured
= TRUE
;
2381 // Try to read the config data from NV variable.
2383 Status
= Ip6ConfigReadConfigData (IpSb
->MacString
, Instance
);
2384 if (Status
== EFI_NOT_FOUND
) {
2386 // The NV variable is not set, so generate a random IAID, and write down the
2387 // fresh new configuration as the NV variable now.
2389 Instance
->IaId
= NET_RANDOM (NetRandomInitSeed ());
2391 for (Index
= 0; Index
< IpSb
->SnpMode
.HwAddressSize
; Index
++) {
2392 Instance
->IaId
|= (IpSb
->SnpMode
.CurrentAddress
.Addr
[Index
] << ((Index
<< 3) & 31));
2395 Ip6ConfigWriteConfigData (IpSb
->MacString
, Instance
);
2396 } else if (EFI_ERROR (Status
)) {
2400 Instance
->Ip6Config
.SetData
= EfiIp6ConfigSetData
;
2401 Instance
->Ip6Config
.GetData
= EfiIp6ConfigGetData
;
2402 Instance
->Ip6Config
.RegisterDataNotify
= EfiIp6ConfigRegisterDataNotify
;
2403 Instance
->Ip6Config
.UnregisterDataNotify
= EfiIp6ConfigUnregisterDataNotify
;
2407 // Publish the IP6 configuration form
2409 return Ip6ConfigFormInit (Instance
);
2413 Release an IP6_CONFIG_INSTANCE.
2415 @param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
2419 Ip6ConfigCleanInstance (
2420 IN OUT IP6_CONFIG_INSTANCE
*Instance
2424 IP6_CONFIG_DATA_ITEM
*DataItem
;
2426 if (Instance
->DeclineAddress
!= NULL
) {
2427 FreePool (Instance
->DeclineAddress
);
2430 if (!Instance
->Configured
) {
2434 if (Instance
->Dhcp6Handle
!= NULL
) {
2436 Ip6ConfigDestroyDhcp6 (Instance
);
2442 if (Instance
->Dhcp6Event
!= NULL
) {
2443 gBS
->CloseEvent (Instance
->Dhcp6Event
);
2446 NetMapClean (&Instance
->DadPassedMap
);
2447 NetMapClean (&Instance
->DadFailedMap
);
2449 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
2451 DataItem
= &Instance
->DataItem
[Index
];
2453 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
2454 if (DataItem
->Data
.Ptr
!= NULL
) {
2455 FreePool (DataItem
->Data
.Ptr
);
2457 DataItem
->Data
.Ptr
= NULL
;
2458 DataItem
->DataSize
= 0;
2461 NetMapClean (&Instance
->DataItem
[Index
].EventMap
);
2464 Ip6ConfigFormUnload (Instance
);
2466 RemoveEntryList (&Instance
->Link
);
2470 Destroy the Dhcp6 child in IP6_CONFIG_INSTANCE and release the resources.
2472 @param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
2474 @retval EFI_SUCCESS The child was successfully destroyed.
2475 @retval Others Failed to destroy the child.
2479 Ip6ConfigDestroyDhcp6 (
2480 IN OUT IP6_CONFIG_INSTANCE
*Instance
2485 EFI_DHCP6_PROTOCOL
*Dhcp6
;
2487 Dhcp6
= Instance
->Dhcp6
;
2488 ASSERT (Dhcp6
!= NULL
);
2490 Dhcp6
->Stop (Dhcp6
);
2491 Dhcp6
->Configure (Dhcp6
, NULL
);
2492 Instance
->Dhcp6
= NULL
;
2494 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
2497 // Close DHCPv6 protocol and destroy the child.
2499 Status
= gBS
->CloseProtocol (
2500 Instance
->Dhcp6Handle
,
2501 &gEfiDhcp6ProtocolGuid
,
2505 if (EFI_ERROR (Status
)) {
2509 Status
= NetLibDestroyServiceChild (
2512 &gEfiDhcp6ServiceBindingProtocolGuid
,
2513 Instance
->Dhcp6Handle
2516 Instance
->Dhcp6Handle
= NULL
;