2 The implementation of EFI IPv6 Configuration Protocol.
4 Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
5 Copyright (c) Microsoft Corporation.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
13 LIST_ENTRY mIp6ConfigInstanceList
= {&mIp6ConfigInstanceList
, &mIp6ConfigInstanceList
};
16 The event process routine when the DHCPv6 service binding protocol is installed
19 @param[in] Event Not used.
20 @param[in] Context Pointer to the IP6 config instance data.
25 Ip6ConfigOnDhcp6SbInstalled (
31 Update the current policy to NewPolicy. During the transition
32 period, the default router list, on-link prefix list, autonomous prefix list
33 and address list in all interfaces will be released.
35 @param[in] IpSb The IP6 service binding instance.
36 @param[in] NewPolicy The new policy to be updated to.
40 Ip6ConfigOnPolicyChanged (
42 IN EFI_IP6_CONFIG_POLICY NewPolicy
49 IP6_DAD_ENTRY
*DadEntry
;
50 IP6_DELAY_JOIN_LIST
*DelayNode
;
51 IP6_ADDRESS_INFO
*AddrInfo
;
52 IP6_PROTOCOL
*Instance
;
58 // Currently there are only two policies: Manual and Automatic. Regardless of
59 // what transition is going on, i.e., Manual -> Automatic and Automatic ->
60 // Manual, we have to free default router list, on-link prefix list, autonomous
61 // prefix list, address list in all the interfaces and destroy any IPv6 child
62 // instance whose local IP is neither 0 nor the link-local address.
64 Ip6CleanDefaultRouterList (IpSb
);
65 Ip6CleanPrefixListTable (IpSb
, &IpSb
->OnlinkPrefix
);
66 Ip6CleanPrefixListTable (IpSb
, &IpSb
->AutonomousPrefix
);
69 // It's tricky... If the LinkLocal address is O.K., add back the link-local
70 // prefix to the on-link prefix table.
72 if (IpSb
->LinkLocalOk
) {
73 Ip6CreatePrefixListEntry (
76 (UINT32
) IP6_INFINIT_LIFETIME
,
77 (UINT32
) IP6_INFINIT_LIFETIME
,
78 IP6_LINK_LOCAL_PREFIX_LENGTH
,
83 if (!IsListEmpty (&IpSb
->DefaultInterface
->AddressList
) && IpSb
->DefaultInterface
->AddressCount
> 0) {
85 // If any IPv6 children (Instance) in configured state and use global unicast address, it will be
86 // destroyed in Ip6RemoveAddr() function later. Then, the upper layer driver's Stop() function will be
87 // called, which may break the upper layer network stacks. So, the driver should take the responsibility
88 // for the recovery by using ConnectController() after Ip6RemoveAddr().
89 // Here, just check whether need to recover the upper layer network stacks later.
91 NET_LIST_FOR_EACH (Entry
, &IpSb
->DefaultInterface
->AddressList
) {
92 AddrInfo
= NET_LIST_USER_STRUCT_S (Entry
, IP6_ADDRESS_INFO
, Link
, IP6_ADDR_INFO_SIGNATURE
);
93 if (!IsListEmpty (&IpSb
->Children
)) {
94 NET_LIST_FOR_EACH (Entry2
, &IpSb
->Children
) {
95 Instance
= NET_LIST_USER_STRUCT_S (Entry2
, IP6_PROTOCOL
, Link
, IP6_PROTOCOL_SIGNATURE
);
96 if ((Instance
->State
== IP6_STATE_CONFIGED
) && EFI_IP6_EQUAL (&Instance
->ConfigData
.StationAddress
, &AddrInfo
->Address
)) {
105 // All IPv6 children that use global unicast address as its source address
106 // should be destroyed now. The survivers are those use the link-local address
107 // or the unspecified address as the source address.
108 // TODO: Conduct a check here.
111 &IpSb
->DefaultInterface
->AddressList
,
112 &IpSb
->DefaultInterface
->AddressCount
,
117 if (IpSb
->Controller
!= NULL
&& Recovery
) {
119 // ConnectController() to recover the upper layer network stacks.
121 gBS
->ConnectController (IpSb
->Controller
, NULL
, NULL
, TRUE
);
126 NET_LIST_FOR_EACH (Entry
, &IpSb
->Interfaces
) {
128 // remove all pending delay node and DAD entries for the global addresses.
130 IpIf
= NET_LIST_USER_STRUCT_S (Entry
, IP6_INTERFACE
, Link
, IP6_INTERFACE_SIGNATURE
);
132 NET_LIST_FOR_EACH_SAFE (Entry2
, Next
, &IpIf
->DelayJoinList
) {
133 DelayNode
= NET_LIST_USER_STRUCT (Entry2
, IP6_DELAY_JOIN_LIST
, Link
);
134 if (!NetIp6IsLinkLocalAddr (&DelayNode
->AddressInfo
->Address
)) {
135 RemoveEntryList (&DelayNode
->Link
);
136 FreePool (DelayNode
);
140 NET_LIST_FOR_EACH_SAFE (Entry2
, Next
, &IpIf
->DupAddrDetectList
) {
141 DadEntry
= NET_LIST_USER_STRUCT_S (Entry2
, IP6_DAD_ENTRY
, Link
, IP6_DAD_ENTRY_SIGNATURE
);
143 if (!NetIp6IsLinkLocalAddr (&DadEntry
->AddressInfo
->Address
)) {
145 // Fail this DAD entry if the address is not link-local.
147 Ip6OnDADFinished (FALSE
, IpIf
, DadEntry
);
152 if (NewPolicy
== Ip6ConfigPolicyAutomatic
) {
154 // Set parameters to trigger router solicitation sending in timer handler.
156 IpSb
->RouterAdvertiseReceived
= FALSE
;
157 IpSb
->SolicitTimer
= IP6_MAX_RTR_SOLICITATIONS
;
161 IpSb
->Ticks
= (UINT32
) IP6_GET_TICKS (IP6_ONE_SECOND_IN_MS
);
166 The work function to trigger the DHCPv6 process to perform a stateful autoconfiguration.
168 @param[in] Instance Pointer to the IP6 config instance data.
169 @param[in] OtherInfoOnly If FALSE, get stateful address and other information
170 via DHCPv6. Otherwise, only get the other information.
172 @retval EFI_SUCCESS The operation finished successfully.
173 @retval EFI_UNSUPPORTED The DHCP6 driver is not available.
177 Ip6ConfigStartStatefulAutoConfig (
178 IN IP6_CONFIG_INSTANCE
*Instance
,
179 IN BOOLEAN OtherInfoOnly
184 EFI_DHCP6_CONFIG_DATA Dhcp6CfgData
;
185 EFI_DHCP6_PROTOCOL
*Dhcp6
;
186 EFI_DHCP6_PACKET_OPTION
*OptList
[1];
188 EFI_DHCP6_PACKET_OPTION
*Oro
;
189 EFI_DHCP6_RETRANSMISSION InfoReqReXmit
;
192 // A host must not invoke stateful address configuration if it is already
193 // participating in the statuful protocol as a result of an earlier advertisement.
195 if (Instance
->Dhcp6Handle
!= NULL
) {
199 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
201 Instance
->OtherInfoOnly
= OtherInfoOnly
;
203 Status
= NetLibCreateServiceChild (
206 &gEfiDhcp6ServiceBindingProtocolGuid
,
207 &Instance
->Dhcp6Handle
210 if (Status
== EFI_UNSUPPORTED
) {
212 // No DHCPv6 Service Binding protocol, register a notify.
214 if (Instance
->Dhcp6SbNotifyEvent
== NULL
) {
215 Instance
->Dhcp6SbNotifyEvent
= EfiCreateProtocolNotifyEvent (
216 &gEfiDhcp6ServiceBindingProtocolGuid
,
218 Ip6ConfigOnDhcp6SbInstalled
,
220 &Instance
->Registration
225 if (EFI_ERROR (Status
)) {
229 if (Instance
->Dhcp6SbNotifyEvent
!= NULL
) {
230 gBS
->CloseEvent (Instance
->Dhcp6SbNotifyEvent
);
233 Status
= gBS
->OpenProtocol (
234 Instance
->Dhcp6Handle
,
235 &gEfiDhcp6ProtocolGuid
,
236 (VOID
**) &Instance
->Dhcp6
,
239 EFI_OPEN_PROTOCOL_BY_DRIVER
241 ASSERT_EFI_ERROR (Status
);
243 Dhcp6
= Instance
->Dhcp6
;
244 Dhcp6
->Configure (Dhcp6
, NULL
);
247 // Set the exta options to send. Here we only want the option request option
250 Oro
= (EFI_DHCP6_PACKET_OPTION
*) OptBuf
;
251 Oro
->OpCode
= HTONS (DHCP6_OPT_ORO
);
252 Oro
->OpLen
= HTONS (2);
253 *((UINT16
*) &Oro
->Data
[0]) = HTONS (DHCP6_OPT_DNS_SERVERS
);
256 Status
= EFI_SUCCESS
;
258 if (!OtherInfoOnly
) {
260 // Get stateful address and other information via DHCPv6.
262 Dhcp6CfgData
.Dhcp6Callback
= NULL
;
263 Dhcp6CfgData
.CallbackContext
= NULL
;
264 Dhcp6CfgData
.OptionCount
= 1;
265 Dhcp6CfgData
.OptionList
= &OptList
[0];
266 Dhcp6CfgData
.IaDescriptor
.Type
= EFI_DHCP6_IA_TYPE_NA
;
267 Dhcp6CfgData
.IaDescriptor
.IaId
= Instance
->IaId
;
268 Dhcp6CfgData
.IaInfoEvent
= Instance
->Dhcp6Event
;
269 Dhcp6CfgData
.ReconfigureAccept
= FALSE
;
270 Dhcp6CfgData
.RapidCommit
= FALSE
;
271 Dhcp6CfgData
.SolicitRetransmission
= NULL
;
273 Status
= Dhcp6
->Configure (Dhcp6
, &Dhcp6CfgData
);
275 if (!EFI_ERROR (Status
)) {
277 if (IpSb
->LinkLocalOk
) {
278 Status
= Dhcp6
->Start (Dhcp6
);
280 IpSb
->Dhcp6NeedStart
= TRUE
;
286 // Only get other information via DHCPv6, this doesn't require a config
289 InfoReqReXmit
.Irt
= 4;
290 InfoReqReXmit
.Mrc
= 64;
291 InfoReqReXmit
.Mrt
= 60;
292 InfoReqReXmit
.Mrd
= 0;
294 if (IpSb
->LinkLocalOk
) {
295 Status
= Dhcp6
->InfoRequest (
302 Instance
->Dhcp6Event
,
303 Ip6ConfigOnDhcp6Reply
,
307 IpSb
->Dhcp6NeedInfoRequest
= TRUE
;
316 Signal the registered event. It is the callback routine for NetMapIterate.
318 @param[in] Map Points to the list of registered event.
319 @param[in] Item The registered event.
320 @param[in] Arg Not used.
325 Ip6ConfigSignalEvent (
327 IN NET_MAP_ITEM
*Item
,
331 gBS
->SignalEvent ((EFI_EVENT
) Item
->Key
);
337 Read the configuration data from variable storage according to the VarName and
338 gEfiIp6ConfigProtocolGuid. It checks the integrity of variable data. If the
339 data is corrupted, it clears the variable data to ZERO. Otherwise, it outputs the
340 configuration data to IP6_CONFIG_INSTANCE.
342 @param[in] VarName The pointer to the variable name
343 @param[in, out] Instance The pointer to the IP6 config instance data.
345 @retval EFI_NOT_FOUND The variable can not be found or already corrupted.
346 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
347 @retval EFI_SUCCESS The configuration data was retrieved successfully.
351 Ip6ConfigReadConfigData (
353 IN OUT IP6_CONFIG_INSTANCE
*Instance
358 IP6_CONFIG_VARIABLE
*Variable
;
359 IP6_CONFIG_DATA_ITEM
*DataItem
;
361 IP6_CONFIG_DATA_RECORD DataRecord
;
365 // Try to read the configuration variable.
368 Status
= gRT
->GetVariable (
370 &gEfiIp6ConfigProtocolGuid
,
376 if (Status
== EFI_BUFFER_TOO_SMALL
) {
378 // Allocate buffer and read the config variable.
380 Variable
= AllocatePool (VarSize
);
381 if (Variable
== NULL
) {
382 return EFI_OUT_OF_RESOURCES
;
385 Status
= gRT
->GetVariable (
387 &gEfiIp6ConfigProtocolGuid
,
392 if (EFI_ERROR (Status
) || (UINT16
) (~NetblockChecksum ((UINT8
*) Variable
, (UINT32
) VarSize
)) != 0) {
394 // GetVariable error or the variable is corrupted.
400 // Get the IAID we use.
402 Instance
->IaId
= Variable
->IaId
;
404 for (Index
= 0; Index
< Variable
->DataRecordCount
; Index
++) {
406 CopyMem (&DataRecord
, &Variable
->DataRecord
[Index
], sizeof (DataRecord
));
408 DataItem
= &Instance
->DataItem
[DataRecord
.DataType
];
409 if (DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
) &&
410 (DataItem
->DataSize
!= DataRecord
.DataSize
)
413 // Perhaps a corrupted data record...
418 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
420 // This data item has variable length data.
421 // Check that the length is contained within the variable before allocating.
423 if (DataRecord
.DataSize
> VarSize
- DataRecord
.Offset
) {
427 DataItem
->Data
.Ptr
= AllocatePool (DataRecord
.DataSize
);
428 if (DataItem
->Data
.Ptr
== NULL
) {
430 // no memory resource
436 Data
= (CHAR8
*) Variable
+ DataRecord
.Offset
;
437 CopyMem (DataItem
->Data
.Ptr
, Data
, DataRecord
.DataSize
);
439 DataItem
->DataSize
= DataRecord
.DataSize
;
440 DataItem
->Status
= EFI_SUCCESS
;
451 // Fall back to the default value.
453 if (Variable
!= NULL
) {
458 // Remove the problematic variable and return EFI_NOT_FOUND, a new
459 // variable will be set again.
463 &gEfiIp6ConfigProtocolGuid
,
464 IP6_CONFIG_VARIABLE_ATTRIBUTE
,
469 return EFI_NOT_FOUND
;
473 Write the configuration data from IP6_CONFIG_INSTANCE to variable storage.
475 @param[in] VarName The pointer to the variable name.
476 @param[in] Instance The pointer to the IP6 configuration instance data.
478 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
479 @retval EFI_SUCCESS The configuration data is written successfully.
483 Ip6ConfigWriteConfigData (
485 IN IP6_CONFIG_INSTANCE
*Instance
490 IP6_CONFIG_DATA_ITEM
*DataItem
;
491 IP6_CONFIG_VARIABLE
*Variable
;
492 IP6_CONFIG_DATA_RECORD
*DataRecord
;
496 VarSize
= sizeof (IP6_CONFIG_VARIABLE
) - sizeof (IP6_CONFIG_DATA_RECORD
);
498 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
500 DataItem
= &Instance
->DataItem
[Index
];
501 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
503 VarSize
+= sizeof (IP6_CONFIG_DATA_RECORD
) + DataItem
->DataSize
;
507 Variable
= AllocatePool (VarSize
);
508 if (Variable
== NULL
) {
509 return EFI_OUT_OF_RESOURCES
;
512 Variable
->IaId
= Instance
->IaId
;
513 Heap
= (CHAR8
*) Variable
+ VarSize
;
514 Variable
->DataRecordCount
= 0;
516 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
518 DataItem
= &Instance
->DataItem
[Index
];
519 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
521 Heap
-= DataItem
->DataSize
;
522 CopyMem (Heap
, DataItem
->Data
.Ptr
, DataItem
->DataSize
);
524 DataRecord
= &Variable
->DataRecord
[Variable
->DataRecordCount
];
525 DataRecord
->DataType
= (EFI_IP6_CONFIG_DATA_TYPE
) Index
;
526 DataRecord
->DataSize
= (UINT32
) DataItem
->DataSize
;
527 DataRecord
->Offset
= (UINT16
) (Heap
- (CHAR8
*) Variable
);
529 Variable
->DataRecordCount
++;
533 Variable
->Checksum
= 0;
534 Variable
->Checksum
= (UINT16
) ~NetblockChecksum ((UINT8
*) Variable
, (UINT32
) VarSize
);
536 Status
= gRT
->SetVariable (
538 &gEfiIp6ConfigProtocolGuid
,
539 IP6_CONFIG_VARIABLE_ATTRIBUTE
,
550 The work function for EfiIp6ConfigGetData() to get the interface information
551 of the communication device this IP6Config instance manages.
553 @param[in] Instance Pointer to the IP6 config instance data.
554 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in
555 bytes, the size of buffer required to store the specified
557 @param[in] Data The data buffer in which the configuration data is returned.
558 Ignored if DataSize is ZERO.
560 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified
561 configuration data, and the required size is
562 returned in DataSize.
563 @retval EFI_SUCCESS The specified configuration data was obtained.
568 IN IP6_CONFIG_INSTANCE
*Instance
,
569 IN OUT UINTN
*DataSize
,
570 IN VOID
*Data OPTIONAL
575 IP6_CONFIG_DATA_ITEM
*Item
;
576 EFI_IP6_CONFIG_INTERFACE_INFO
*IfInfo
;
580 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
581 Length
= sizeof (EFI_IP6_CONFIG_INTERFACE_INFO
);
584 // Calculate the required length, add the buffer size for AddressInfo and
587 Ip6BuildEfiAddressList (IpSb
, &AddressCount
, NULL
);
588 Ip6BuildEfiRouteTable (IpSb
->RouteTable
, &RouteCount
, NULL
);
590 Length
+= AddressCount
* sizeof (EFI_IP6_ADDRESS_INFO
) + RouteCount
* sizeof (EFI_IP6_ROUTE_TABLE
);
592 if (*DataSize
< Length
) {
594 return EFI_BUFFER_TOO_SMALL
;
598 // Copy the fixed size part of the interface info.
600 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeInterfaceInfo
];
601 IfInfo
= (EFI_IP6_CONFIG_INTERFACE_INFO
*) Data
;
602 CopyMem (IfInfo
, Item
->Data
.Ptr
, sizeof (EFI_IP6_CONFIG_INTERFACE_INFO
));
607 IfInfo
->AddressInfo
= (EFI_IP6_ADDRESS_INFO
*) (IfInfo
+ 1);
608 Ip6BuildEfiAddressList (IpSb
, &IfInfo
->AddressInfoCount
, &IfInfo
->AddressInfo
);
613 IfInfo
->RouteTable
= (EFI_IP6_ROUTE_TABLE
*) (IfInfo
->AddressInfo
+ IfInfo
->AddressInfoCount
);
614 Ip6BuildEfiRouteTable (IpSb
->RouteTable
, &IfInfo
->RouteCount
, &IfInfo
->RouteTable
);
616 if (IfInfo
->AddressInfoCount
== 0) {
617 IfInfo
->AddressInfo
= NULL
;
620 if (IfInfo
->RouteCount
== 0) {
621 IfInfo
->RouteTable
= NULL
;
628 The work function for EfiIp6ConfigSetData() to set the alternative interface ID
629 for the communication device managed by this IP6Config instance, if the link local
630 IPv6 addresses generated from the interface ID based on the default source the
631 EFI IPv6 Protocol uses is a duplicate address.
633 @param[in] Instance Pointer to the IP6 configuration instance data.
634 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
635 @param[in] Data The data buffer to set.
637 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type,
639 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
640 network stack was set.
644 Ip6ConfigSetAltIfId (
645 IN IP6_CONFIG_INSTANCE
*Instance
,
650 EFI_IP6_CONFIG_INTERFACE_ID
*OldIfId
;
651 EFI_IP6_CONFIG_INTERFACE_ID
*NewIfId
;
652 IP6_CONFIG_DATA_ITEM
*DataItem
;
654 if (DataSize
!= sizeof (EFI_IP6_CONFIG_INTERFACE_ID
)) {
655 return EFI_BAD_BUFFER_SIZE
;
658 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeAltInterfaceId
];
659 OldIfId
= DataItem
->Data
.AltIfId
;
660 NewIfId
= (EFI_IP6_CONFIG_INTERFACE_ID
*) Data
;
662 CopyMem (OldIfId
, NewIfId
, DataSize
);
663 DataItem
->Status
= EFI_SUCCESS
;
669 The work function for EfiIp6ConfigSetData() to set the general configuration
670 policy for the EFI IPv6 network stack that is running on the communication device
671 managed by this IP6Config instance. The policy will affect other configuration settings.
673 @param[in] Instance Pointer to the IP6 config instance data.
674 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
675 @param[in] Data The data buffer to set.
677 @retval EFI_INVALID_PARAMETER The to be set policy is invalid.
678 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
679 @retval EFI_ABORTED The new policy equals the current policy.
680 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
681 network stack was set.
686 IN IP6_CONFIG_INSTANCE
*Instance
,
691 EFI_IP6_CONFIG_POLICY NewPolicy
;
692 IP6_CONFIG_DATA_ITEM
*DataItem
;
695 if (DataSize
!= sizeof (EFI_IP6_CONFIG_POLICY
)) {
696 return EFI_BAD_BUFFER_SIZE
;
699 NewPolicy
= *((EFI_IP6_CONFIG_POLICY
*) Data
);
701 if (NewPolicy
> Ip6ConfigPolicyAutomatic
) {
702 return EFI_INVALID_PARAMETER
;
705 if (NewPolicy
== Instance
->Policy
) {
710 // Clean the ManualAddress, Gateway and DnsServers, shrink the variable
711 // data size, and fire up all the related events.
713 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
714 if (DataItem
->Data
.Ptr
!= NULL
) {
715 FreePool (DataItem
->Data
.Ptr
);
717 DataItem
->Data
.Ptr
= NULL
;
718 DataItem
->DataSize
= 0;
719 DataItem
->Status
= EFI_NOT_FOUND
;
720 NetMapIterate (&DataItem
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
722 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeGateway
];
723 if (DataItem
->Data
.Ptr
!= NULL
) {
724 FreePool (DataItem
->Data
.Ptr
);
726 DataItem
->Data
.Ptr
= NULL
;
727 DataItem
->DataSize
= 0;
728 DataItem
->Status
= EFI_NOT_FOUND
;
729 NetMapIterate (&DataItem
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
731 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
732 DataItem
->Data
.Ptr
= NULL
;
733 DataItem
->DataSize
= 0;
734 DataItem
->Status
= EFI_NOT_FOUND
;
735 NetMapIterate (&DataItem
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
737 if (NewPolicy
== Ip6ConfigPolicyManual
) {
739 // The policy is changed from automatic to manual. Stop the DHCPv6 process
740 // and destroy the DHCPv6 child.
742 if (Instance
->Dhcp6Handle
!= NULL
) {
743 Ip6ConfigDestroyDhcp6 (Instance
);
747 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
748 Ip6ConfigOnPolicyChanged (IpSb
, NewPolicy
);
750 Instance
->Policy
= NewPolicy
;
757 The work function for EfiIp6ConfigSetData() to set the number of consecutive
758 Neighbor Solicitation messages sent while performing Duplicate Address Detection
759 on a tentative address. A value of ZERO indicates that Duplicate Address Detection
760 will not be performed on a tentative address.
762 @param[in] Instance The Instance Pointer to the IP6 config instance data.
763 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
764 @param[in] Data The data buffer to set.
766 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
767 @retval EFI_ABORTED The new transmit count equals the current configuration.
768 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
769 network stack was set.
773 Ip6ConfigSetDadXmits (
774 IN IP6_CONFIG_INSTANCE
*Instance
,
779 EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS
*OldDadXmits
;
781 if (DataSize
!= sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS
)) {
782 return EFI_BAD_BUFFER_SIZE
;
785 OldDadXmits
= Instance
->DataItem
[Ip6ConfigDataTypeDupAddrDetectTransmits
].Data
.DadXmits
;
787 if ((*(UINT32
*) Data
) == OldDadXmits
->DupAddrDetectTransmits
) {
792 OldDadXmits
->DupAddrDetectTransmits
= *((UINT32
*) Data
);
798 The callback function for Ip6SetAddr. The prototype is defined
799 as IP6_DAD_CALLBACK. It is called after Duplicate Address Detection is performed
800 for the manual address set by Ip6ConfigSetManualAddress.
802 @param[in] IsDadPassed If TRUE, Duplicate Address Detection passed.
803 @param[in] TargetAddress The tentative IPv6 address to be checked.
804 @param[in] Context Pointer to the IP6 configuration instance data.
808 Ip6ManualAddrDadCallback (
809 IN BOOLEAN IsDadPassed
,
810 IN EFI_IPv6_ADDRESS
*TargetAddress
,
814 IP6_CONFIG_INSTANCE
*Instance
;
816 IP6_CONFIG_DATA_ITEM
*Item
;
817 EFI_IP6_CONFIG_MANUAL_ADDRESS
*ManualAddr
;
818 EFI_IP6_CONFIG_MANUAL_ADDRESS
*PassedAddr
;
823 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
824 NET_CHECK_SIGNATURE (Instance
, IP6_CONFIG_INSTANCE_SIGNATURE
);
825 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
828 if (Item
->DataSize
== 0) {
832 for (Index
= 0; Index
< Item
->DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
); Index
++) {
834 // Find the original tag used to place into the NET_MAP.
836 ManualAddr
= Item
->Data
.ManualAddress
+ Index
;
837 if (EFI_IP6_EQUAL (TargetAddress
, &ManualAddr
->Address
)) {
842 ASSERT (Index
!= Item
->DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
));
845 NetMapInsertTail (&Instance
->DadPassedMap
, ManualAddr
, NULL
);
847 NetMapInsertTail (&Instance
->DadFailedMap
, ManualAddr
, NULL
);
850 DadPassCount
= NetMapGetCount (&Instance
->DadPassedMap
);
851 DadFailCount
= NetMapGetCount (&Instance
->DadFailedMap
);
853 if ((DadPassCount
+ DadFailCount
) == (Item
->DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
))) {
855 // All addresses have finished the configuration process.
857 if (DadFailCount
!= 0) {
859 // There is at least one duplicate address.
861 FreePool (Item
->Data
.Ptr
);
863 Item
->DataSize
= DadPassCount
* sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
);
864 if (Item
->DataSize
== 0) {
866 // All failed, bad luck.
868 Item
->Data
.Ptr
= NULL
;
869 Item
->Status
= EFI_NOT_FOUND
;
872 // Part of addresses are detected to be duplicates, so update the
873 // data with those passed.
875 PassedAddr
= (EFI_IP6_CONFIG_MANUAL_ADDRESS
*) AllocatePool (Item
->DataSize
);
876 ASSERT (PassedAddr
!= NULL
);
878 Item
->Data
.Ptr
= PassedAddr
;
879 Item
->Status
= EFI_SUCCESS
;
881 while (!NetMapIsEmpty (&Instance
->DadPassedMap
)) {
882 ManualAddr
= (EFI_IP6_CONFIG_MANUAL_ADDRESS
*) NetMapRemoveHead (&Instance
->DadPassedMap
, NULL
);
883 CopyMem (PassedAddr
, ManualAddr
, sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
));
888 ASSERT ((UINTN
) PassedAddr
- (UINTN
) Item
->Data
.Ptr
== Item
->DataSize
);
892 // All addresses are valid.
894 Item
->Status
= EFI_SUCCESS
;
898 // Remove the tags we put in the NET_MAPs.
900 while (!NetMapIsEmpty (&Instance
->DadFailedMap
)) {
901 NetMapRemoveHead (&Instance
->DadFailedMap
, NULL
);
904 while (!NetMapIsEmpty (&Instance
->DadPassedMap
)) {
905 NetMapRemoveHead (&Instance
->DadPassedMap
, NULL
);
909 // Signal the waiting events.
911 NetMapIterate (&Item
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
912 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
913 Ip6ConfigWriteConfigData (IpSb
->MacString
, Instance
);
918 The work function for EfiIp6ConfigSetData() to set the station addresses manually
919 for the EFI IPv6 network stack. It is only configurable when the policy is
920 Ip6ConfigPolicyManual.
922 @param[in] Instance Pointer to the IP6 configuration instance data.
923 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
924 @param[in] Data The data buffer to set.
926 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
927 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
928 under the current policy.
929 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
930 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
931 @retval EFI_NOT_READY An asynchronous process is invoked to set the specified
932 configuration data, and the process is not finished.
933 @retval EFI_ABORTED The manual addresses to be set equal current
935 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
936 network stack was set.
940 Ip6ConfigSetManualAddress (
941 IN IP6_CONFIG_INSTANCE
*Instance
,
946 EFI_IP6_CONFIG_MANUAL_ADDRESS
*NewAddress
;
947 EFI_IP6_CONFIG_MANUAL_ADDRESS
*TmpAddress
;
948 IP6_CONFIG_DATA_ITEM
*DataItem
;
949 UINTN NewAddressCount
;
953 IP6_ADDRESS_INFO
*CurrentAddrInfo
;
954 IP6_ADDRESS_INFO
*Copy
;
955 LIST_ENTRY CurrentSourceList
;
956 UINT32 CurrentSourceCount
;
960 IP6_PREFIX_LIST_ENTRY
*PrefixEntry
;
964 IP6_DAD_ENTRY
*DadEntry
;
965 IP6_DELAY_JOIN_LIST
*DelayNode
;
969 CurrentAddrInfo
= NULL
;
978 Status
= EFI_SUCCESS
;
980 ASSERT (Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
].Status
!= EFI_NOT_READY
);
982 if ((DataSize
!= 0) && ((DataSize
% sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
)) != 0)) {
983 return EFI_BAD_BUFFER_SIZE
;
986 if (Instance
->Policy
!= Ip6ConfigPolicyManual
) {
987 return EFI_WRITE_PROTECTED
;
990 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
992 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
994 if (Data
!= NULL
&& DataSize
!= 0) {
995 NewAddressCount
= DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
);
996 NewAddress
= (EFI_IP6_CONFIG_MANUAL_ADDRESS
*) Data
;
998 for (Index1
= 0; Index1
< NewAddressCount
; Index1
++, NewAddress
++) {
1000 if (NetIp6IsLinkLocalAddr (&NewAddress
->Address
) ||
1001 !NetIp6IsValidUnicast (&NewAddress
->Address
) ||
1002 (NewAddress
->PrefixLength
> 128)
1005 // make sure the IPv6 address is unicast and not link-local address &&
1006 // the prefix length is valid.
1008 return EFI_INVALID_PARAMETER
;
1011 TmpAddress
= NewAddress
+ 1;
1012 for (Index2
= Index1
+ 1; Index2
< NewAddressCount
; Index2
++, TmpAddress
++) {
1014 // Any two addresses in the array can't be equal.
1016 if (EFI_IP6_EQUAL (&TmpAddress
->Address
, &NewAddress
->Address
)) {
1018 return EFI_INVALID_PARAMETER
;
1024 // Build the current source address list.
1026 InitializeListHead (&CurrentSourceList
);
1027 CurrentSourceCount
= 0;
1029 NET_LIST_FOR_EACH (Entry
, &IpSb
->Interfaces
) {
1030 IpIf
= NET_LIST_USER_STRUCT_S (Entry
, IP6_INTERFACE
, Link
, IP6_INTERFACE_SIGNATURE
);
1032 NET_LIST_FOR_EACH (Entry2
, &IpIf
->AddressList
) {
1033 CurrentAddrInfo
= NET_LIST_USER_STRUCT_S (Entry2
, IP6_ADDRESS_INFO
, Link
, IP6_ADDR_INFO_SIGNATURE
);
1035 Copy
= AllocateCopyPool (sizeof (IP6_ADDRESS_INFO
), CurrentAddrInfo
);
1040 InsertTailList (&CurrentSourceList
, &Copy
->Link
);
1041 CurrentSourceCount
++;
1046 // Update the value... a long journey starts
1048 NewAddress
= AllocateCopyPool (DataSize
, Data
);
1049 if (NewAddress
== NULL
) {
1050 Ip6RemoveAddr (NULL
, &CurrentSourceList
, &CurrentSourceCount
, NULL
, 0);
1052 return EFI_OUT_OF_RESOURCES
;
1056 // Store the new data, and init the DataItem status to EFI_NOT_READY because
1057 // we may have an asynchronous configuration process.
1059 if (DataItem
->Data
.Ptr
!= NULL
) {
1060 FreePool (DataItem
->Data
.Ptr
);
1062 DataItem
->Data
.Ptr
= NewAddress
;
1063 DataItem
->DataSize
= DataSize
;
1064 DataItem
->Status
= EFI_NOT_READY
;
1067 // Trigger DAD, it's an asynchronous process.
1071 for (Index1
= 0; Index1
< NewAddressCount
; Index1
++, NewAddress
++) {
1072 if (Ip6IsOneOfSetAddress (IpSb
, &NewAddress
->Address
, NULL
, &CurrentAddrInfo
)) {
1073 ASSERT (CurrentAddrInfo
!= NULL
);
1075 // Remove this already existing source address from the CurrentSourceList
1081 &CurrentSourceCount
,
1082 &CurrentAddrInfo
->Address
,
1087 // If the new address's prefix length is not specified, just use the previous configured
1088 // prefix length for this address.
1090 if (NewAddress
->PrefixLength
== 0) {
1091 NewAddress
->PrefixLength
= CurrentAddrInfo
->PrefixLength
;
1095 // This manual address is already in use, see whether prefix length is changed.
1097 if (NewAddress
->PrefixLength
!= CurrentAddrInfo
->PrefixLength
) {
1099 // Remove the on-link prefix table, the route entry will be removed
1102 PrefixEntry
= Ip6FindPrefixListEntry (
1105 CurrentAddrInfo
->PrefixLength
,
1106 &CurrentAddrInfo
->Address
1108 if (PrefixEntry
!= NULL
) {
1109 Ip6DestroyPrefixListEntry (IpSb
, PrefixEntry
, TRUE
, FALSE
);
1113 // Save the prefix length.
1115 CurrentAddrInfo
->PrefixLength
= NewAddress
->PrefixLength
;
1120 // create a new on-link prefix entry.
1122 PrefixEntry
= Ip6FindPrefixListEntry (
1125 NewAddress
->PrefixLength
,
1126 &NewAddress
->Address
1128 if (PrefixEntry
== NULL
) {
1129 Ip6CreatePrefixListEntry (
1132 (UINT32
) IP6_INFINIT_LIFETIME
,
1133 (UINT32
) IP6_INFINIT_LIFETIME
,
1134 NewAddress
->PrefixLength
,
1135 &NewAddress
->Address
1139 CurrentAddrInfo
->IsAnycast
= NewAddress
->IsAnycast
;
1141 // Artificially mark this address passed DAD be'coz it is already in use.
1143 Ip6ManualAddrDadCallback (TRUE
, &NewAddress
->Address
, Instance
);
1151 // Set the new address, this will trigger DAD and activate the address if
1155 IpSb
->DefaultInterface
,
1156 &NewAddress
->Address
,
1157 NewAddress
->IsAnycast
,
1158 NewAddress
->PrefixLength
,
1159 (UINT32
) IP6_INFINIT_LIFETIME
,
1160 (UINT32
) IP6_INFINIT_LIFETIME
,
1161 Ip6ManualAddrDadCallback
,
1168 // Check the CurrentSourceList, it now contains those addresses currently in
1169 // use and will be removed.
1171 IpIf
= IpSb
->DefaultInterface
;
1173 while (!IsListEmpty (&CurrentSourceList
)) {
1176 CurrentAddrInfo
= NET_LIST_HEAD (&CurrentSourceList
, IP6_ADDRESS_INFO
, Link
);
1179 // This local address is going to be removed, the IP instances that are
1180 // currently using it will be destroyed.
1185 &IpIf
->AddressCount
,
1186 &CurrentAddrInfo
->Address
,
1191 // Remove the on-link prefix table, the route entry will be removed
1194 PrefixEntry
= Ip6FindPrefixListEntry (
1197 CurrentAddrInfo
->PrefixLength
,
1198 &CurrentAddrInfo
->Address
1200 if (PrefixEntry
!= NULL
) {
1201 Ip6DestroyPrefixListEntry (IpSb
, PrefixEntry
, TRUE
, FALSE
);
1204 RemoveEntryList (&CurrentAddrInfo
->Link
);
1205 FreePool (CurrentAddrInfo
);
1209 if (DataItem
->Status
== EFI_NOT_READY
) {
1211 // If DAD is disabled on this interface, the configuration process is
1212 // actually synchronous, and the data item's status will be changed to
1213 // the final status before we reach here, just check it.
1215 Status
= EFI_NOT_READY
;
1217 Status
= EFI_SUCCESS
;
1221 // No update is taken, reset the status to success and return EFI_ABORTED.
1223 DataItem
->Status
= EFI_SUCCESS
;
1224 Status
= EFI_ABORTED
;
1228 // DataSize is 0 and Data is NULL, clean up the manual address.
1230 if (DataItem
->Data
.Ptr
!= NULL
) {
1231 FreePool (DataItem
->Data
.Ptr
);
1233 DataItem
->Data
.Ptr
= NULL
;
1234 DataItem
->DataSize
= 0;
1235 DataItem
->Status
= EFI_NOT_FOUND
;
1237 Ip6CleanDefaultRouterList (IpSb
);
1238 Ip6CleanPrefixListTable (IpSb
, &IpSb
->OnlinkPrefix
);
1239 Ip6CleanPrefixListTable (IpSb
, &IpSb
->AutonomousPrefix
);
1240 Ip6CleanAssembleTable (&IpSb
->Assemble
);
1242 if (IpSb
->LinkLocalOk
) {
1243 Ip6CreatePrefixListEntry (
1246 (UINT32
) IP6_INFINIT_LIFETIME
,
1247 (UINT32
) IP6_INFINIT_LIFETIME
,
1248 IP6_LINK_LOCAL_PREFIX_LENGTH
,
1249 &IpSb
->LinkLocalAddr
1255 &IpSb
->DefaultInterface
->AddressList
,
1256 &IpSb
->DefaultInterface
->AddressCount
,
1261 NET_LIST_FOR_EACH (Entry
, &IpSb
->Interfaces
) {
1263 // Remove all pending delay node and DAD entries for the global addresses.
1265 IpIf
= NET_LIST_USER_STRUCT_S (Entry
, IP6_INTERFACE
, Link
, IP6_INTERFACE_SIGNATURE
);
1267 NET_LIST_FOR_EACH_SAFE (Entry2
, Next
, &IpIf
->DelayJoinList
) {
1268 DelayNode
= NET_LIST_USER_STRUCT (Entry2
, IP6_DELAY_JOIN_LIST
, Link
);
1269 if (!NetIp6IsLinkLocalAddr (&DelayNode
->AddressInfo
->Address
)) {
1270 RemoveEntryList (&DelayNode
->Link
);
1271 FreePool (DelayNode
);
1275 NET_LIST_FOR_EACH_SAFE (Entry2
, Next
, &IpIf
->DupAddrDetectList
) {
1276 DadEntry
= NET_LIST_USER_STRUCT_S (Entry2
, IP6_DAD_ENTRY
, Link
, IP6_DAD_ENTRY_SIGNATURE
);
1278 if (!NetIp6IsLinkLocalAddr (&DadEntry
->AddressInfo
->Address
)) {
1280 // Fail this DAD entry if the address is not link-local.
1282 Ip6OnDADFinished (FALSE
, IpIf
, DadEntry
);
1292 The work function for EfiIp6ConfigSetData() to set the gateway addresses manually
1293 for the EFI IPv6 network stack that is running on the communication device that
1294 this EFI IPv6 Configuration Protocol manages. It is not configurable when the policy is
1295 Ip6ConfigPolicyAutomatic. The gateway addresses must be unicast IPv6 addresses.
1297 @param[in] Instance The pointer to the IP6 config instance data.
1298 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1299 @param[in] Data The data buffer to set. This points to an array of
1300 EFI_IPv6_ADDRESS instances.
1302 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1303 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1304 under the current policy.
1305 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1306 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to complete the operation.
1307 @retval EFI_ABORTED The manual gateway addresses to be set equal the
1308 current configuration.
1309 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1310 network stack was set.
1314 Ip6ConfigSetGateway (
1315 IN IP6_CONFIG_INSTANCE
*Instance
,
1322 EFI_IPv6_ADDRESS
*OldGateway
;
1323 EFI_IPv6_ADDRESS
*NewGateway
;
1324 UINTN OldGatewayCount
;
1325 UINTN NewGatewayCount
;
1326 IP6_CONFIG_DATA_ITEM
*Item
;
1330 IP6_DEFAULT_ROUTER
*DefaultRouter
;
1336 DefaultRouter
= NULL
;
1341 if ((DataSize
!= 0) && (DataSize
% sizeof (EFI_IPv6_ADDRESS
) != 0)) {
1342 return EFI_BAD_BUFFER_SIZE
;
1345 if (Instance
->Policy
!= Ip6ConfigPolicyManual
) {
1346 return EFI_WRITE_PROTECTED
;
1349 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
1350 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeGateway
];
1351 OldGateway
= Item
->Data
.Gateway
;
1352 OldGatewayCount
= Item
->DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1354 for (Index1
= 0; Index1
< OldGatewayCount
; Index1
++) {
1356 // Remove this default router.
1358 DefaultRouter
= Ip6FindDefaultRouter (IpSb
, OldGateway
+ Index1
);
1359 if (DefaultRouter
!= NULL
) {
1360 Ip6DestroyDefaultRouter (IpSb
, DefaultRouter
);
1365 if (Data
!= NULL
&& DataSize
!= 0) {
1366 NewGateway
= (EFI_IPv6_ADDRESS
*) Data
;
1367 NewGatewayCount
= DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1368 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1370 if (!NetIp6IsValidUnicast (NewGateway
+ Index1
)) {
1372 return EFI_INVALID_PARAMETER
;
1375 for (Index2
= Index1
+ 1; Index2
< NewGatewayCount
; Index2
++) {
1376 if (EFI_IP6_EQUAL (NewGateway
+ Index1
, NewGateway
+ Index2
)) {
1377 return EFI_INVALID_PARAMETER
;
1382 if (NewGatewayCount
!= OldGatewayCount
) {
1383 Tmp
= AllocatePool (DataSize
);
1385 return EFI_OUT_OF_RESOURCES
;
1391 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1393 DefaultRouter
= Ip6FindDefaultRouter (IpSb
, NewGateway
+ Index1
);
1394 if (DefaultRouter
== NULL
) {
1395 Ip6CreateDefaultRouter (IpSb
, NewGateway
+ Index1
, IP6_INF_ROUTER_LIFETIME
);
1400 if (!OneRemoved
&& !OneAdded
) {
1401 Item
->Status
= EFI_SUCCESS
;
1406 if (Item
->Data
.Ptr
!= NULL
) {
1407 FreePool (Item
->Data
.Ptr
);
1409 Item
->Data
.Ptr
= Tmp
;
1412 CopyMem (Item
->Data
.Ptr
, Data
, DataSize
);
1413 Item
->DataSize
= DataSize
;
1414 Item
->Status
= EFI_SUCCESS
;
1419 // DataSize is 0 and Data is NULL, clean up the Gateway address.
1421 if (Item
->Data
.Ptr
!= NULL
) {
1422 FreePool (Item
->Data
.Ptr
);
1424 Item
->Data
.Ptr
= NULL
;
1426 Item
->Status
= EFI_NOT_FOUND
;
1433 The work function for EfiIp6ConfigSetData() to set the DNS server list for the
1434 EFI IPv6 network stack running on the communication device that this EFI IPv6
1435 Configuration Protocol manages. It is not configurable when the policy is
1436 Ip6ConfigPolicyAutomatic. The DNS server addresses must be unicast IPv6 addresses.
1438 @param[in] Instance The pointer to the IP6 config instance data.
1439 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1440 @param[in] Data The data buffer to set, points to an array of
1441 EFI_IPv6_ADDRESS instances.
1443 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1444 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1445 under the current policy.
1446 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1447 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
1448 @retval EFI_ABORTED The DNS server addresses to be set equal the current
1450 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1451 network stack was set.
1455 Ip6ConfigSetDnsServer (
1456 IN IP6_CONFIG_INSTANCE
*Instance
,
1463 EFI_IPv6_ADDRESS
*OldDns
;
1464 EFI_IPv6_ADDRESS
*NewDns
;
1467 IP6_CONFIG_DATA_ITEM
*Item
;
1476 if ((DataSize
!= 0) && (DataSize
% sizeof (EFI_IPv6_ADDRESS
) != 0)) {
1477 return EFI_BAD_BUFFER_SIZE
;
1480 if (Instance
->Policy
!= Ip6ConfigPolicyManual
) {
1481 return EFI_WRITE_PROTECTED
;
1484 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
1486 if (Data
!= NULL
&& DataSize
!= 0) {
1487 NewDns
= (EFI_IPv6_ADDRESS
*) Data
;
1488 OldDns
= Item
->Data
.DnsServers
;
1489 NewDnsCount
= DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1490 OldDnsCount
= Item
->DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1493 if (NewDnsCount
!= OldDnsCount
) {
1494 Tmp
= AllocatePool (DataSize
);
1496 return EFI_OUT_OF_RESOURCES
;
1502 for (NewIndex
= 0; NewIndex
< NewDnsCount
; NewIndex
++) {
1504 if (!NetIp6IsValidUnicast (NewDns
+ NewIndex
)) {
1506 // The dns server address must be unicast.
1511 return EFI_INVALID_PARAMETER
;
1516 // If any address in the new setting is not in the old settings, skip the
1517 // comparision below.
1522 for (OldIndex
= 0; OldIndex
< OldDnsCount
; OldIndex
++) {
1523 if (EFI_IP6_EQUAL (NewDns
+ NewIndex
, OldDns
+ OldIndex
)) {
1525 // If found break out.
1531 if (OldIndex
== OldDnsCount
) {
1536 if (!OneAdded
&& (DataSize
== Item
->DataSize
)) {
1538 // No new item is added and the size is the same.
1540 Item
->Status
= EFI_SUCCESS
;
1544 if (Item
->Data
.Ptr
!= NULL
) {
1545 FreePool (Item
->Data
.Ptr
);
1547 Item
->Data
.Ptr
= Tmp
;
1550 CopyMem (Item
->Data
.Ptr
, Data
, DataSize
);
1551 Item
->DataSize
= DataSize
;
1552 Item
->Status
= EFI_SUCCESS
;
1556 // DataSize is 0 and Data is NULL, clean up the DnsServer address.
1558 if (Item
->Data
.Ptr
!= NULL
) {
1559 FreePool (Item
->Data
.Ptr
);
1561 Item
->Data
.Ptr
= NULL
;
1563 Item
->Status
= EFI_NOT_FOUND
;
1570 Generate the operational state of the interface this IP6 config instance manages
1571 and output in EFI_IP6_CONFIG_INTERFACE_INFO.
1573 @param[in] IpSb The pointer to the IP6 service binding instance.
1574 @param[out] IfInfo The pointer to the IP6 configuration interface information structure.
1578 Ip6ConfigInitIfInfo (
1579 IN IP6_SERVICE
*IpSb
,
1580 OUT EFI_IP6_CONFIG_INTERFACE_INFO
*IfInfo
1585 sizeof (IfInfo
->Name
),
1587 IpSb
->Ip6ConfigInstance
.IfIndex
1590 IfInfo
->IfType
= IpSb
->SnpMode
.IfType
;
1591 IfInfo
->HwAddressSize
= IpSb
->SnpMode
.HwAddressSize
;
1592 CopyMem (&IfInfo
->HwAddress
, &IpSb
->SnpMode
.CurrentAddress
, IfInfo
->HwAddressSize
);
1596 Parse DHCPv6 reply packet to get the DNS server list.
1597 It is the work function for Ip6ConfigOnDhcp6Reply and Ip6ConfigOnDhcp6Event.
1599 @param[in] Dhcp6 The pointer to the EFI_DHCP6_PROTOCOL instance.
1600 @param[in, out] Instance The pointer to the IP6 configuration instance data.
1601 @param[in] Reply The pointer to the DHCPv6 reply packet.
1603 @retval EFI_SUCCESS The DNS server address was retrieved from the reply packet.
1604 @retval EFI_NOT_READY The reply packet does not contain the DNS server option, or
1605 the DNS server address is not valid.
1609 Ip6ConfigParseDhcpReply (
1610 IN EFI_DHCP6_PROTOCOL
*Dhcp6
,
1611 IN OUT IP6_CONFIG_INSTANCE
*Instance
,
1612 IN EFI_DHCP6_PACKET
*Reply
1617 EFI_DHCP6_PACKET_OPTION
**OptList
;
1622 EFI_IPv6_ADDRESS
*DnsServer
;
1623 IP6_CONFIG_DATA_ITEM
*Item
;
1626 // A DHCPv6 reply packet is received as the response to our InfoRequest
1630 Status
= Dhcp6
->Parse (Dhcp6
, Reply
, &OptCount
, NULL
);
1631 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1632 return EFI_NOT_READY
;
1635 OptList
= AllocatePool (OptCount
* sizeof (EFI_DHCP6_PACKET_OPTION
*));
1636 if (OptList
== NULL
) {
1637 return EFI_NOT_READY
;
1640 Status
= Dhcp6
->Parse (Dhcp6
, Reply
, &OptCount
, OptList
);
1641 if (EFI_ERROR (Status
)) {
1642 Status
= EFI_NOT_READY
;
1646 Status
= EFI_SUCCESS
;
1648 for (Index
= 0; Index
< OptCount
; Index
++) {
1650 // Go through all the options to check the ones we are interested in.
1651 // The OpCode and Length are in network byte-order and may not be naturally
1654 CopyMem (&OpCode
, &OptList
[Index
]->OpCode
, sizeof (OpCode
));
1655 OpCode
= NTOHS (OpCode
);
1657 if (OpCode
== DHCP6_OPT_DNS_SERVERS
) {
1658 CopyMem (&Length
, &OptList
[Index
]->OpLen
, sizeof (Length
));
1659 Length
= NTOHS (Length
);
1661 if ((Length
== 0) || ((Length
% sizeof (EFI_IPv6_ADDRESS
)) != 0)) {
1663 // The length should be a multiple of 16 bytes.
1665 Status
= EFI_NOT_READY
;
1670 // Validate the DnsServers: whether they are unicast addresses.
1672 DnsServer
= (EFI_IPv6_ADDRESS
*) OptList
[Index
]->Data
;
1673 for (Index2
= 0; Index2
< Length
/ sizeof (EFI_IPv6_ADDRESS
); Index2
++) {
1674 if (!NetIp6IsValidUnicast (DnsServer
)) {
1675 Status
= EFI_NOT_READY
;
1682 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
1684 if (Item
->DataSize
!= Length
) {
1685 if (Item
->Data
.Ptr
!= NULL
) {
1686 FreePool (Item
->Data
.Ptr
);
1689 Item
->Data
.Ptr
= AllocatePool (Length
);
1690 ASSERT (Item
->Data
.Ptr
!= NULL
);
1693 CopyMem (Item
->Data
.Ptr
, OptList
[Index
]->Data
, Length
);
1694 Item
->DataSize
= Length
;
1695 Item
->Status
= EFI_SUCCESS
;
1698 // Signal the waiting events.
1700 NetMapIterate (&Item
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
1713 The callback function for Ip6SetAddr. The prototype is defined
1714 as IP6_DAD_CALLBACK. It is called after Duplicate Address Detection is performed
1715 on the tentative address by DHCPv6 in Ip6ConfigOnDhcp6Event().
1717 @param[in] IsDadPassed If TRUE, Duplicate Address Detection passes.
1718 @param[in] TargetAddress The tentative IPv6 address to be checked.
1719 @param[in] Context Pointer to the IP6 configuration instance data.
1723 Ip6ConfigSetStatefulAddrCallback (
1724 IN BOOLEAN IsDadPassed
,
1725 IN EFI_IPv6_ADDRESS
*TargetAddress
,
1729 IP6_CONFIG_INSTANCE
*Instance
;
1731 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
1732 NET_CHECK_SIGNATURE (Instance
, IP6_CONFIG_INSTANCE_SIGNATURE
);
1735 // We should record the addresses that fail the DAD, and DECLINE them.
1739 // Decrease the count, no interests in those passed DAD.
1741 if (Instance
->FailedIaAddressCount
> 0 ) {
1742 Instance
->FailedIaAddressCount
--;
1748 IP6_COPY_ADDRESS (Instance
->DeclineAddress
+ Instance
->DeclineAddressCount
, TargetAddress
);
1749 Instance
->DeclineAddressCount
++;
1752 if (Instance
->FailedIaAddressCount
== Instance
->DeclineAddressCount
) {
1754 // The checking on all addresses are finished.
1756 if (Instance
->DeclineAddressCount
!= 0) {
1758 // Decline those duplicates.
1760 if (Instance
->Dhcp6
!= NULL
) {
1761 Instance
->Dhcp6
->Decline (
1763 Instance
->DeclineAddressCount
,
1764 Instance
->DeclineAddress
1769 if (Instance
->DeclineAddress
!= NULL
) {
1770 FreePool (Instance
->DeclineAddress
);
1772 Instance
->DeclineAddress
= NULL
;
1773 Instance
->DeclineAddressCount
= 0;
1778 The event handle routine when DHCPv6 process is finished or is updated.
1780 @param[in] Event Not used.
1781 @param[in] Context The pointer to the IP6 configuration instance data.
1786 Ip6ConfigOnDhcp6Event (
1791 IP6_CONFIG_INSTANCE
*Instance
;
1792 EFI_DHCP6_PROTOCOL
*Dhcp6
;
1794 EFI_DHCP6_MODE_DATA Dhcp6ModeData
;
1796 EFI_DHCP6_IA_ADDRESS
*IaAddr
;
1799 IP6_ADDRESS_INFO
*AddrInfo
;
1800 IP6_INTERFACE
*IpIf
;
1802 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
1804 if ((Instance
->Policy
!= Ip6ConfigPolicyAutomatic
) || Instance
->OtherInfoOnly
) {
1806 // IPv6 is not operating in the automatic policy now or
1807 // the DHCPv6 information request message exchange is aborted.
1813 // The stateful address autoconfiguration is done or updated.
1815 Dhcp6
= Instance
->Dhcp6
;
1817 Status
= Dhcp6
->GetModeData (Dhcp6
, &Dhcp6ModeData
, NULL
);
1818 if (EFI_ERROR (Status
)) {
1822 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
1823 IpIf
= IpSb
->DefaultInterface
;
1824 Ia
= Dhcp6ModeData
.Ia
;
1825 IaAddr
= Ia
->IaAddress
;
1827 if (Instance
->DeclineAddress
!= NULL
) {
1828 FreePool (Instance
->DeclineAddress
);
1831 Instance
->DeclineAddress
= (EFI_IPv6_ADDRESS
*) AllocatePool (Ia
->IaAddressCount
* sizeof (EFI_IPv6_ADDRESS
));
1832 if (Instance
->DeclineAddress
== NULL
) {
1836 Instance
->FailedIaAddressCount
= Ia
->IaAddressCount
;
1837 Instance
->DeclineAddressCount
= 0;
1839 for (Index
= 0; Index
< Ia
->IaAddressCount
; Index
++, IaAddr
++) {
1840 if (Ia
->IaAddress
[Index
].ValidLifetime
!= 0 && Ia
->State
== Dhcp6Bound
) {
1842 // Set this address, either it's a new address or with updated lifetimes.
1843 // An appropriate prefix length will be set.
1850 IaAddr
->ValidLifetime
,
1851 IaAddr
->PreferredLifetime
,
1852 Ip6ConfigSetStatefulAddrCallback
,
1857 // discard this address, artificially decrease the count as if this address
1860 if (Ip6IsOneOfSetAddress (IpSb
, &IaAddr
->IpAddress
, NULL
, &AddrInfo
)) {
1861 ASSERT (AddrInfo
!= NULL
);
1865 &IpIf
->AddressCount
,
1867 AddrInfo
->PrefixLength
1871 if (Instance
->FailedIaAddressCount
> 0) {
1872 Instance
->FailedIaAddressCount
--;
1878 // Parse the Reply packet to get the options we need.
1880 if (Dhcp6ModeData
.Ia
->ReplyPacket
!= NULL
) {
1881 Ip6ConfigParseDhcpReply (Dhcp6
, Instance
, Dhcp6ModeData
.Ia
->ReplyPacket
);
1886 FreePool (Dhcp6ModeData
.ClientId
);
1887 FreePool (Dhcp6ModeData
.Ia
);
1891 The event process routine when the DHCPv6 server is answered with a reply packet
1892 for an information request.
1894 @param[in] This Points to the EFI_DHCP6_PROTOCOL.
1895 @param[in] Context The pointer to the IP6 configuration instance data.
1896 @param[in] Packet The DHCPv6 reply packet.
1898 @retval EFI_SUCCESS The DNS server address was retrieved from the reply packet.
1899 @retval EFI_NOT_READY The reply packet does not contain the DNS server option, or
1900 the DNS server address is not valid.
1905 Ip6ConfigOnDhcp6Reply (
1906 IN EFI_DHCP6_PROTOCOL
*This
,
1908 IN EFI_DHCP6_PACKET
*Packet
1911 return Ip6ConfigParseDhcpReply (This
, (IP6_CONFIG_INSTANCE
*) Context
, Packet
);
1915 The event process routine when the DHCPv6 service binding protocol is installed
1918 @param[in] Event Not used.
1919 @param[in] Context The pointer to the IP6 config instance data.
1924 Ip6ConfigOnDhcp6SbInstalled (
1929 IP6_CONFIG_INSTANCE
*Instance
;
1931 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
1933 if ((Instance
->Dhcp6Handle
!= NULL
) || (Instance
->Policy
!= Ip6ConfigPolicyAutomatic
)) {
1935 // The DHCP6 child is already created or the policy is no longer AUTOMATIC.
1940 Ip6ConfigStartStatefulAutoConfig (Instance
, Instance
->OtherInfoOnly
);
1944 Set the configuration for the EFI IPv6 network stack running on the communication
1945 device this EFI IPv6 Configuration Protocol instance manages.
1947 This function is used to set the configuration data of type DataType for the EFI
1948 IPv6 network stack that is running on the communication device that this EFI IPv6
1949 Configuration Protocol instance manages.
1951 DataSize is used to calculate the count of structure instances in the Data for
1952 a DataType in which multiple structure instances are allowed.
1954 This function is always non-blocking. When setting some type of configuration data,
1955 an asynchronous process is invoked to check the correctness of the data, such as
1956 performing Duplicate Address Detection on the manually set local IPv6 addresses.
1957 EFI_NOT_READY is returned immediately to indicate that such an asynchronous process
1958 is invoked, and the process is not finished yet. The caller wanting to get the result
1959 of the asynchronous process is required to call RegisterDataNotify() to register an
1960 event on the specified configuration data. Once the event is signaled, the caller
1961 can call GetData() to obtain the configuration data and know the result.
1962 For other types of configuration data that do not require an asynchronous configuration
1963 process, the result of the operation is immediately returned.
1965 @param[in] This The pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
1966 @param[in] DataType The type of data to set.
1967 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1968 @param[in] Data The data buffer to set. The type of the data buffer is
1969 associated with the DataType.
1971 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1972 network stack was set successfully.
1973 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
1975 - One or more fields in Data and DataSizedo not match the
1976 requirement of the data type indicated by DataType.
1977 @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified
1978 configuration data cannot be set under the current policy.
1979 @retval EFI_ACCESS_DENIED Another set operation on the specified configuration
1980 data is already in process.
1981 @retval EFI_NOT_READY An asynchronous process was invoked to set the specified
1982 configuration data, and the process is not finished yet.
1983 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type
1984 indicated by DataType.
1985 @retval EFI_UNSUPPORTED This DataType is not supported.
1986 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1987 @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
1992 EfiIp6ConfigSetData (
1993 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
1994 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
2001 IP6_CONFIG_INSTANCE
*Instance
;
2004 if ((This
== NULL
) || (Data
== NULL
&& DataSize
!= 0) || (Data
!= NULL
&& DataSize
== 0)) {
2005 return EFI_INVALID_PARAMETER
;
2008 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
2009 return EFI_UNSUPPORTED
;
2012 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
2013 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
2014 NET_CHECK_SIGNATURE (IpSb
, IP6_SERVICE_SIGNATURE
);
2016 if (IpSb
->LinkLocalDadFail
) {
2017 return EFI_DEVICE_ERROR
;
2020 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2022 Status
= Instance
->DataItem
[DataType
].Status
;
2023 if (Status
!= EFI_NOT_READY
) {
2025 if (Instance
->DataItem
[DataType
].SetData
== NULL
) {
2027 // This type of data is readonly.
2029 Status
= EFI_WRITE_PROTECTED
;
2032 Status
= Instance
->DataItem
[DataType
].SetData (Instance
, DataSize
, Data
);
2033 if (!EFI_ERROR (Status
)) {
2035 // Fire up the events registered with this type of data.
2037 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip6ConfigSignalEvent
, NULL
);
2038 Ip6ConfigWriteConfigData (IpSb
->MacString
, Instance
);
2039 } else if (Status
== EFI_ABORTED
) {
2041 // The SetData is aborted because the data to set is the same with
2042 // the one maintained.
2044 Status
= EFI_SUCCESS
;
2045 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip6ConfigSignalEvent
, NULL
);
2050 // Another asynchronous process is on the way.
2052 Status
= EFI_ACCESS_DENIED
;
2055 gBS
->RestoreTPL (OldTpl
);
2061 Get the configuration data for the EFI IPv6 network stack running on the communication
2062 device that this EFI IPv6 Configuration Protocol instance manages.
2064 This function returns the configuration data of type DataType for the EFI IPv6 network
2065 stack running on the communication device that this EFI IPv6 Configuration Protocol instance
2068 The caller is responsible for allocating the buffer used to return the specified
2069 configuration data. The required size will be returned to the caller if the size of
2070 the buffer is too small.
2072 EFI_NOT_READY is returned if the specified configuration data is not ready due to an
2073 asynchronous configuration process already in progress. The caller can call RegisterDataNotify()
2074 to register an event on the specified configuration data. Once the asynchronous configuration
2075 process is finished, the event will be signaled, and a subsequent GetData() call will return
2076 the specified configuration data.
2078 @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
2079 @param[in] DataType The type of data to get.
2080 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in bytes, the
2081 size of buffer required to store the specified configuration data.
2082 @param[in] Data The data buffer in which the configuration data is returned. The
2083 type of the data buffer is associated with the DataType.
2084 This is an optional parameter that may be NULL.
2086 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
2087 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
2090 - Data is NULL if *DataSize is not zero.
2091 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data,
2092 and the required size is returned in DataSize.
2093 @retval EFI_NOT_READY The specified configuration data is not ready due to an
2094 asynchronous configuration process already in progress.
2095 @retval EFI_NOT_FOUND The specified configuration data is not found.
2100 EfiIp6ConfigGetData (
2101 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
2102 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
2103 IN OUT UINTN
*DataSize
,
2104 IN VOID
*Data OPTIONAL
2109 IP6_CONFIG_INSTANCE
*Instance
;
2110 IP6_CONFIG_DATA_ITEM
*DataItem
;
2112 if ((This
== NULL
) || (DataSize
== NULL
) || ((*DataSize
!= 0) && (Data
== NULL
))) {
2113 return EFI_INVALID_PARAMETER
;
2116 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
2117 return EFI_NOT_FOUND
;
2120 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2122 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
2123 DataItem
= &Instance
->DataItem
[DataType
];
2125 Status
= Instance
->DataItem
[DataType
].Status
;
2126 if (!EFI_ERROR (Status
)) {
2128 if (DataItem
->GetData
!= NULL
) {
2130 Status
= DataItem
->GetData (Instance
, DataSize
, Data
);
2131 } else if (*DataSize
< Instance
->DataItem
[DataType
].DataSize
) {
2133 // Update the buffer length.
2135 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
2136 Status
= EFI_BUFFER_TOO_SMALL
;
2139 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
2140 CopyMem (Data
, Instance
->DataItem
[DataType
].Data
.Ptr
, *DataSize
);
2144 gBS
->RestoreTPL (OldTpl
);
2150 Register an event that is signaled whenever a configuration process on the specified
2151 configuration data is done.
2153 This function registers an event that is to be signaled whenever a configuration
2154 process on the specified configuration data is performed. An event can be registered
2155 for a different DataType simultaneously. The caller is responsible for determining
2156 which type of configuration data causes the signaling of the event in such an event.
2158 @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
2159 @param[in] DataType The type of data to unregister the event for.
2160 @param[in] Event The event to register.
2162 @retval EFI_SUCCESS The notification event for the specified configuration data is
2164 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
2165 @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not
2167 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
2168 @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
2173 EfiIp6ConfigRegisterDataNotify (
2174 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
2175 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
2181 IP6_CONFIG_INSTANCE
*Instance
;
2185 if ((This
== NULL
) || (Event
== NULL
)) {
2186 return EFI_INVALID_PARAMETER
;
2189 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
2190 return EFI_UNSUPPORTED
;
2193 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2195 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
2196 EventMap
= &Instance
->DataItem
[DataType
].EventMap
;
2199 // Check whether this event is already registered for this DataType.
2201 Item
= NetMapFindKey (EventMap
, Event
);
2204 Status
= NetMapInsertTail (EventMap
, Event
, NULL
);
2206 if (EFI_ERROR (Status
)) {
2208 Status
= EFI_OUT_OF_RESOURCES
;
2213 Status
= EFI_ACCESS_DENIED
;
2216 gBS
->RestoreTPL (OldTpl
);
2222 Remove a previously registered event for the specified configuration data.
2224 @param This The pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
2225 @param DataType The type of data to remove from the previously
2227 @param Event The event to be unregistered.
2229 @retval EFI_SUCCESS The event registered for the specified
2230 configuration data was removed.
2231 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
2232 @retval EFI_NOT_FOUND The Event has not been registered for the
2238 EfiIp6ConfigUnregisterDataNotify (
2239 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
2240 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
2246 IP6_CONFIG_INSTANCE
*Instance
;
2249 if ((This
== NULL
) || (Event
== NULL
)) {
2250 return EFI_INVALID_PARAMETER
;
2253 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
2254 return EFI_NOT_FOUND
;
2257 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2259 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
2261 Item
= NetMapFindKey (&Instance
->DataItem
[DataType
].EventMap
, Event
);
2264 NetMapRemoveItem (&Instance
->DataItem
[DataType
].EventMap
, Item
, NULL
);
2265 Status
= EFI_SUCCESS
;
2268 Status
= EFI_NOT_FOUND
;
2271 gBS
->RestoreTPL (OldTpl
);
2277 Initialize an IP6_CONFIG_INSTANCE.
2279 @param[out] Instance The buffer of IP6_CONFIG_INSTANCE to be initialized.
2281 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
2282 @retval EFI_SUCCESS The IP6_CONFIG_INSTANCE initialized successfully.
2286 Ip6ConfigInitInstance (
2287 OUT IP6_CONFIG_INSTANCE
*Instance
2291 IP6_CONFIG_INSTANCE
*TmpInstance
;
2296 IP6_CONFIG_DATA_ITEM
*DataItem
;
2298 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
2300 Instance
->Signature
= IP6_CONFIG_INSTANCE_SIGNATURE
;
2303 // Determine the index of this interface.
2306 NET_LIST_FOR_EACH (Entry
, &mIp6ConfigInstanceList
) {
2307 TmpInstance
= NET_LIST_USER_STRUCT_S (Entry
, IP6_CONFIG_INSTANCE
, Link
, IP6_CONFIG_INSTANCE_SIGNATURE
);
2309 if (TmpInstance
->IfIndex
> IfIndex
) {
2311 // There is a sequence hole because some interface is down.
2319 Instance
->IfIndex
= IfIndex
;
2320 NetListInsertBefore (Entry
, &Instance
->Link
);
2322 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
2324 // Initialize the event map for each data item.
2326 NetMapInit (&Instance
->DataItem
[Index
].EventMap
);
2330 // Initialize the NET_MAPs used for DAD on manually configured source addresses.
2332 NetMapInit (&Instance
->DadFailedMap
);
2333 NetMapInit (&Instance
->DadPassedMap
);
2336 // Initialize each data type: associate storage and set data size for the
2337 // fixed size data types, hook the SetData function, set the data attribute.
2339 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeInterfaceInfo
];
2340 DataItem
->GetData
= Ip6ConfigGetIfInfo
;
2341 DataItem
->Data
.Ptr
= &Instance
->InterfaceInfo
;
2342 DataItem
->DataSize
= sizeof (Instance
->InterfaceInfo
);
2343 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
| DATA_ATTRIB_VOLATILE
);
2344 Ip6ConfigInitIfInfo (IpSb
, &Instance
->InterfaceInfo
);
2346 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeAltInterfaceId
];
2347 DataItem
->SetData
= Ip6ConfigSetAltIfId
;
2348 DataItem
->Data
.Ptr
= &Instance
->AltIfId
;
2349 DataItem
->DataSize
= sizeof (Instance
->AltIfId
);
2350 DataItem
->Status
= EFI_NOT_FOUND
;
2351 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2353 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypePolicy
];
2354 DataItem
->SetData
= Ip6ConfigSetPolicy
;
2355 DataItem
->Data
.Ptr
= &Instance
->Policy
;
2356 DataItem
->DataSize
= sizeof (Instance
->Policy
);
2357 Instance
->Policy
= Ip6ConfigPolicyManual
;
2358 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2360 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeDupAddrDetectTransmits
];
2361 DataItem
->SetData
= Ip6ConfigSetDadXmits
;
2362 DataItem
->Data
.Ptr
= &Instance
->DadXmits
;
2363 DataItem
->DataSize
= sizeof (Instance
->DadXmits
);
2364 Instance
->DadXmits
.DupAddrDetectTransmits
= IP6_CONFIG_DEFAULT_DAD_XMITS
;
2365 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2367 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
2368 DataItem
->SetData
= Ip6ConfigSetManualAddress
;
2369 DataItem
->Status
= EFI_NOT_FOUND
;
2371 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeGateway
];
2372 DataItem
->SetData
= Ip6ConfigSetGateway
;
2373 DataItem
->Status
= EFI_NOT_FOUND
;
2375 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
2376 DataItem
->SetData
= Ip6ConfigSetDnsServer
;
2377 DataItem
->Status
= EFI_NOT_FOUND
;
2380 // Create the event used for DHCP.
2382 Status
= gBS
->CreateEvent (
2385 Ip6ConfigOnDhcp6Event
,
2387 &Instance
->Dhcp6Event
2389 ASSERT_EFI_ERROR (Status
);
2391 Instance
->Configured
= TRUE
;
2394 // Try to read the config data from NV variable.
2396 Status
= Ip6ConfigReadConfigData (IpSb
->MacString
, Instance
);
2397 if (Status
== EFI_NOT_FOUND
) {
2399 // The NV variable is not set, so generate a random IAID, and write down the
2400 // fresh new configuration as the NV variable now.
2402 Instance
->IaId
= NET_RANDOM (NetRandomInitSeed ());
2404 for (Index
= 0; Index
< IpSb
->SnpMode
.HwAddressSize
; Index
++) {
2405 Instance
->IaId
|= (IpSb
->SnpMode
.CurrentAddress
.Addr
[Index
] << ((Index
<< 3) & 31));
2408 Ip6ConfigWriteConfigData (IpSb
->MacString
, Instance
);
2409 } else if (EFI_ERROR (Status
)) {
2413 Instance
->Ip6Config
.SetData
= EfiIp6ConfigSetData
;
2414 Instance
->Ip6Config
.GetData
= EfiIp6ConfigGetData
;
2415 Instance
->Ip6Config
.RegisterDataNotify
= EfiIp6ConfigRegisterDataNotify
;
2416 Instance
->Ip6Config
.UnregisterDataNotify
= EfiIp6ConfigUnregisterDataNotify
;
2420 // Publish the IP6 configuration form
2422 return Ip6ConfigFormInit (Instance
);
2426 Release an IP6_CONFIG_INSTANCE.
2428 @param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
2432 Ip6ConfigCleanInstance (
2433 IN OUT IP6_CONFIG_INSTANCE
*Instance
2437 IP6_CONFIG_DATA_ITEM
*DataItem
;
2439 if (Instance
->DeclineAddress
!= NULL
) {
2440 FreePool (Instance
->DeclineAddress
);
2443 if (!Instance
->Configured
) {
2447 if (Instance
->Dhcp6Handle
!= NULL
) {
2449 Ip6ConfigDestroyDhcp6 (Instance
);
2455 if (Instance
->Dhcp6Event
!= NULL
) {
2456 gBS
->CloseEvent (Instance
->Dhcp6Event
);
2459 NetMapClean (&Instance
->DadPassedMap
);
2460 NetMapClean (&Instance
->DadFailedMap
);
2462 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
2464 DataItem
= &Instance
->DataItem
[Index
];
2466 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
2467 if (DataItem
->Data
.Ptr
!= NULL
) {
2468 FreePool (DataItem
->Data
.Ptr
);
2470 DataItem
->Data
.Ptr
= NULL
;
2471 DataItem
->DataSize
= 0;
2474 NetMapClean (&Instance
->DataItem
[Index
].EventMap
);
2477 Ip6ConfigFormUnload (Instance
);
2479 RemoveEntryList (&Instance
->Link
);
2483 Destroy the Dhcp6 child in IP6_CONFIG_INSTANCE and release the resources.
2485 @param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
2487 @retval EFI_SUCCESS The child was successfully destroyed.
2488 @retval Others Failed to destroy the child.
2492 Ip6ConfigDestroyDhcp6 (
2493 IN OUT IP6_CONFIG_INSTANCE
*Instance
2498 EFI_DHCP6_PROTOCOL
*Dhcp6
;
2500 Dhcp6
= Instance
->Dhcp6
;
2501 ASSERT (Dhcp6
!= NULL
);
2503 Dhcp6
->Stop (Dhcp6
);
2504 Dhcp6
->Configure (Dhcp6
, NULL
);
2505 Instance
->Dhcp6
= NULL
;
2507 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
2510 // Close DHCPv6 protocol and destroy the child.
2512 Status
= gBS
->CloseProtocol (
2513 Instance
->Dhcp6Handle
,
2514 &gEfiDhcp6ProtocolGuid
,
2518 if (EFI_ERROR (Status
)) {
2522 Status
= NetLibDestroyServiceChild (
2525 &gEfiDhcp6ServiceBindingProtocolGuid
,
2526 Instance
->Dhcp6Handle
2529 Instance
->Dhcp6Handle
= NULL
;