2 The implementation of EFI IPv6 Configuration Protocol.
4 Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php.
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 LIST_ENTRY mIp6ConfigInstanceList
= {&mIp6ConfigInstanceList
, &mIp6ConfigInstanceList
};
21 The event process routine when the DHCPv6 service binding protocol is installed
24 @param[in] Event Not used.
25 @param[in] Context Pointer to the IP6 config instance data.
30 Ip6ConfigOnDhcp6SbInstalled (
36 Update the current policy to NewPolicy. During the transition
37 period, the default router list, on-link prefix list, autonomous prefix list
38 and address list in all interfaces will be released.
40 @param[in] IpSb The IP6 service binding instance.
41 @param[in] NewPolicy The new policy to be updated to.
45 Ip6ConfigOnPolicyChanged (
47 IN EFI_IP6_CONFIG_POLICY NewPolicy
54 IP6_DAD_ENTRY
*DadEntry
;
55 IP6_DELAY_JOIN_LIST
*DelayNode
;
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
,
84 // All IPv6 children that use global unicast address as it's source address
85 // should be destryoed now. The survivers are those use the link-local address
86 // or the unspecified address as the source address.
87 // TODO: Conduct a check here.
90 &IpSb
->DefaultInterface
->AddressList
,
91 &IpSb
->DefaultInterface
->AddressCount
,
96 NET_LIST_FOR_EACH (Entry
, &IpSb
->Interfaces
) {
98 // remove all pending delay node and DAD entries for the global addresses.
100 IpIf
= NET_LIST_USER_STRUCT_S (Entry
, IP6_INTERFACE
, Link
, IP6_INTERFACE_SIGNATURE
);
102 NET_LIST_FOR_EACH_SAFE (Entry2
, Next
, &IpIf
->DelayJoinList
) {
103 DelayNode
= NET_LIST_USER_STRUCT (Entry2
, IP6_DELAY_JOIN_LIST
, Link
);
104 if (!NetIp6IsLinkLocalAddr (&DelayNode
->AddressInfo
->Address
)) {
105 RemoveEntryList (&DelayNode
->Link
);
106 FreePool (DelayNode
);
110 NET_LIST_FOR_EACH_SAFE (Entry2
, Next
, &IpIf
->DupAddrDetectList
) {
111 DadEntry
= NET_LIST_USER_STRUCT_S (Entry2
, IP6_DAD_ENTRY
, Link
, IP6_DAD_ENTRY_SIGNATURE
);
113 if (!NetIp6IsLinkLocalAddr (&DadEntry
->AddressInfo
->Address
)) {
115 // Fail this DAD entry if the address is not link-local.
117 Ip6OnDADFinished (FALSE
, IpIf
, DadEntry
);
122 if (NewPolicy
== Ip6ConfigPolicyAutomatic
) {
124 // Set parameters to trigger router solicitation sending in timer handler.
126 IpSb
->RouterAdvertiseReceived
= FALSE
;
127 IpSb
->SolicitTimer
= IP6_MAX_RTR_SOLICITATIONS
;
131 IpSb
->Ticks
= (UINT32
) IP6_GET_TICKS (IP6_ONE_SECOND_IN_MS
);
137 The work function to trigger the DHCPv6 process to perform a stateful autoconfiguration.
139 @param[in] Instance Pointer to the IP6 config instance data.
140 @param[in] OtherInfoOnly If FALSE, get stateful address and other information
141 via DHCPv6. Otherwise, only get the other information.
143 @retval EFI_SUCCESS The operation finished successfully.
144 @retval EFI_UNSUPPORTED The DHCP6 driver is not available.
148 Ip6ConfigStartStatefulAutoConfig (
149 IN IP6_CONFIG_INSTANCE
*Instance
,
150 IN BOOLEAN OtherInfoOnly
155 EFI_DHCP6_CONFIG_DATA Dhcp6CfgData
;
156 EFI_DHCP6_PROTOCOL
*Dhcp6
;
157 EFI_DHCP6_PACKET_OPTION
*OptList
[1];
159 EFI_DHCP6_PACKET_OPTION
*Oro
;
160 EFI_DHCP6_RETRANSMISSION InfoReqReXmit
;
163 // A host must not invoke stateful address configuration if it is already
164 // participating in the statuful protocol as a result of an earlier advertisement.
166 if (Instance
->Dhcp6Handle
!= NULL
) {
170 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
172 Instance
->OtherInfoOnly
= OtherInfoOnly
;
174 Status
= NetLibCreateServiceChild (
177 &gEfiDhcp6ServiceBindingProtocolGuid
,
178 &Instance
->Dhcp6Handle
181 if (Status
== EFI_UNSUPPORTED
) {
183 // No DHCPv6 Service Binding protocol, register a notify.
185 if (Instance
->Dhcp6SbNotifyEvent
== NULL
) {
186 Instance
->Dhcp6SbNotifyEvent
= EfiCreateProtocolNotifyEvent (
187 &gEfiDhcp6ServiceBindingProtocolGuid
,
189 Ip6ConfigOnDhcp6SbInstalled
,
191 &Instance
->Registration
196 if (EFI_ERROR (Status
)) {
200 if (Instance
->Dhcp6SbNotifyEvent
!= NULL
) {
201 gBS
->CloseEvent (Instance
->Dhcp6SbNotifyEvent
);
204 Status
= gBS
->OpenProtocol (
205 Instance
->Dhcp6Handle
,
206 &gEfiDhcp6ProtocolGuid
,
207 (VOID
**) &Instance
->Dhcp6
,
210 EFI_OPEN_PROTOCOL_BY_DRIVER
212 ASSERT_EFI_ERROR (Status
);
214 Dhcp6
= Instance
->Dhcp6
;
215 Dhcp6
->Configure (Dhcp6
, NULL
);
218 // Set the exta options to send. Here we only want the option request option
221 Oro
= (EFI_DHCP6_PACKET_OPTION
*) OptBuf
;
222 Oro
->OpCode
= HTONS (DHCP6_OPT_ORO
);
223 Oro
->OpLen
= HTONS (2);
224 *((UINT16
*) &Oro
->Data
[0]) = HTONS (DHCP6_OPT_DNS_SERVERS
);
227 Status
= EFI_SUCCESS
;
229 if (!OtherInfoOnly
) {
231 // Get stateful address and other information via DHCPv6.
233 Dhcp6CfgData
.Dhcp6Callback
= NULL
;
234 Dhcp6CfgData
.CallbackContext
= NULL
;
235 Dhcp6CfgData
.OptionCount
= 1;
236 Dhcp6CfgData
.OptionList
= &OptList
[0];
237 Dhcp6CfgData
.IaDescriptor
.Type
= EFI_DHCP6_IA_TYPE_NA
;
238 Dhcp6CfgData
.IaDescriptor
.IaId
= Instance
->IaId
;
239 Dhcp6CfgData
.IaInfoEvent
= Instance
->Dhcp6Event
;
240 Dhcp6CfgData
.ReconfigureAccept
= FALSE
;
241 Dhcp6CfgData
.RapidCommit
= FALSE
;
242 Dhcp6CfgData
.SolicitRetransmission
= NULL
;
244 Status
= Dhcp6
->Configure (Dhcp6
, &Dhcp6CfgData
);
246 if (!EFI_ERROR (Status
)) {
248 if (IpSb
->LinkLocalOk
) {
249 Status
= Dhcp6
->Start (Dhcp6
);
251 IpSb
->Dhcp6NeedStart
= TRUE
;
257 // Only get other information via DHCPv6, this doesn't require a config
260 InfoReqReXmit
.Irt
= 4;
261 InfoReqReXmit
.Mrc
= 64;
262 InfoReqReXmit
.Mrt
= 60;
263 InfoReqReXmit
.Mrd
= 0;
265 if (IpSb
->LinkLocalOk
) {
266 Status
= Dhcp6
->InfoRequest (
273 Instance
->Dhcp6Event
,
274 Ip6ConfigOnDhcp6Reply
,
278 IpSb
->Dhcp6NeedInfoRequest
= TRUE
;
287 Signal the registered event. It is the callback routine for NetMapIterate.
289 @param[in] Map Points to the list of registered event.
290 @param[in] Item The registered event.
291 @param[in] Arg Not used.
296 Ip6ConfigSignalEvent (
298 IN NET_MAP_ITEM
*Item
,
302 gBS
->SignalEvent ((EFI_EVENT
) Item
->Key
);
308 Read the configuration data from variable storage according to the VarName and
309 gEfiIp6ConfigProtocolGuid. It checks the integrity of variable data. If the
310 data is corrupted, it clears the variable data to ZERO. Othewise, it outputs the
311 configuration data to IP6_CONFIG_INSTANCE.
313 @param[in] VarName The pointer to the variable name
314 @param[in, out] Instance The pointer to the IP6 config instance data.
316 @retval EFI_NOT_FOUND The variable can not be found or already corrupted.
317 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
318 @retval EFI_SUCCESS The configuration data was retrieved successfully.
322 Ip6ConfigReadConfigData (
324 IN OUT IP6_CONFIG_INSTANCE
*Instance
329 IP6_CONFIG_VARIABLE
*Variable
;
330 IP6_CONFIG_DATA_ITEM
*DataItem
;
332 IP6_CONFIG_DATA_RECORD DataRecord
;
336 // Try to read the configuration variable.
339 Status
= gRT
->GetVariable (
341 &gEfiIp6ConfigProtocolGuid
,
347 if (Status
== EFI_BUFFER_TOO_SMALL
) {
349 // Allocate buffer and read the config variable.
351 Variable
= AllocatePool (VarSize
);
352 if (Variable
== NULL
) {
353 return EFI_OUT_OF_RESOURCES
;
356 Status
= gRT
->GetVariable (
358 &gEfiIp6ConfigProtocolGuid
,
363 if (EFI_ERROR (Status
) || (UINT16
) (~NetblockChecksum ((UINT8
*) Variable
, (UINT32
) VarSize
)) != 0) {
365 // GetVariable still error or the variable is corrupted.
366 // Fall back to the default value.
371 // Remove the problematic variable and return EFI_NOT_FOUND, a new
372 // variable will be set again.
376 &gEfiIp6ConfigProtocolGuid
,
377 IP6_CONFIG_VARIABLE_ATTRIBUTE
,
382 return EFI_NOT_FOUND
;
386 // Get the IAID we use.
388 Instance
->IaId
= Variable
->IaId
;
390 for (Index
= 0; Index
< Variable
->DataRecordCount
; Index
++) {
392 CopyMem (&DataRecord
, &Variable
->DataRecord
[Index
], sizeof (DataRecord
));
394 DataItem
= &Instance
->DataItem
[DataRecord
.DataType
];
395 if (DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
) &&
396 (DataItem
->DataSize
!= DataRecord
.DataSize
)
399 // Perhaps a corrupted data record...
404 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
406 // This data item has variable length data.
408 DataItem
->Data
.Ptr
= AllocatePool (DataRecord
.DataSize
);
409 if (DataItem
->Data
.Ptr
== NULL
) {
411 // no memory resource
417 Data
= (CHAR8
*) Variable
+ DataRecord
.Offset
;
418 CopyMem (DataItem
->Data
.Ptr
, Data
, DataRecord
.DataSize
);
420 DataItem
->DataSize
= DataRecord
.DataSize
;
421 DataItem
->Status
= EFI_SUCCESS
;
432 Write the configuration data from IP6_CONFIG_INSTANCE to variable storage.
434 @param[in] VarName The pointer to the variable name.
435 @param[in] Instance The pointer to the IP6 configuration instance data.
437 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
438 @retval EFI_SUCCESS The configuration data is written successfully.
442 Ip6ConfigWriteConfigData (
444 IN IP6_CONFIG_INSTANCE
*Instance
449 IP6_CONFIG_DATA_ITEM
*DataItem
;
450 IP6_CONFIG_VARIABLE
*Variable
;
451 IP6_CONFIG_DATA_RECORD
*DataRecord
;
455 VarSize
= sizeof (IP6_CONFIG_VARIABLE
) - sizeof (IP6_CONFIG_DATA_RECORD
);
457 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
459 DataItem
= &Instance
->DataItem
[Index
];
460 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
462 VarSize
+= sizeof (IP6_CONFIG_DATA_RECORD
) + DataItem
->DataSize
;
466 Variable
= AllocatePool (VarSize
);
467 if (Variable
== NULL
) {
468 return EFI_OUT_OF_RESOURCES
;
471 Variable
->IaId
= Instance
->IaId
;
472 Heap
= (CHAR8
*) Variable
+ VarSize
;
473 Variable
->DataRecordCount
= 0;
475 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
477 DataItem
= &Instance
->DataItem
[Index
];
478 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
480 Heap
-= DataItem
->DataSize
;
481 CopyMem (Heap
, DataItem
->Data
.Ptr
, DataItem
->DataSize
);
483 DataRecord
= &Variable
->DataRecord
[Variable
->DataRecordCount
];
484 DataRecord
->DataType
= (EFI_IP6_CONFIG_DATA_TYPE
) Index
;
485 DataRecord
->DataSize
= (UINT32
) DataItem
->DataSize
;
486 DataRecord
->Offset
= (UINT16
) (Heap
- (CHAR8
*) Variable
);
488 Variable
->DataRecordCount
++;
492 Variable
->Checksum
= 0;
493 Variable
->Checksum
= (UINT16
) ~NetblockChecksum ((UINT8
*) Variable
, (UINT32
) VarSize
);
495 Status
= gRT
->SetVariable (
497 &gEfiIp6ConfigProtocolGuid
,
498 IP6_CONFIG_VARIABLE_ATTRIBUTE
,
509 The work function for EfiIp6ConfigGetData() to get the interface information
510 of the communication device this IP6Config instance manages.
512 @param[in] Instance Pointer to the IP6 config instance data.
513 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in
514 bytes, the size of buffer required to store the specified
516 @param[in] Data The data buffer in which the configuration data is returned.
517 Ignored if DataSize is ZERO.
519 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified
520 configuration data, and the required size is
521 returned in DataSize.
522 @retval EFI_SUCCESS The specified configuration data was obtained.
527 IN IP6_CONFIG_INSTANCE
*Instance
,
528 IN OUT UINTN
*DataSize
,
529 IN VOID
*Data OPTIONAL
534 IP6_CONFIG_DATA_ITEM
*Item
;
535 EFI_IP6_CONFIG_INTERFACE_INFO
*IfInfo
;
539 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
540 Length
= sizeof (EFI_IP6_CONFIG_INTERFACE_INFO
);
543 // Calculate the required length, add the buffer size for AddressInfo and
546 Ip6BuildEfiAddressList (IpSb
, &AddressCount
, NULL
);
547 Ip6BuildEfiRouteTable (IpSb
->RouteTable
, &RouteCount
, NULL
);
549 Length
+= AddressCount
* sizeof (EFI_IP6_ADDRESS_INFO
) + RouteCount
* sizeof (EFI_IP6_ROUTE_TABLE
);
551 if (*DataSize
< Length
) {
553 return EFI_BUFFER_TOO_SMALL
;
557 // Copy the fixed size part of the interface info.
559 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeInterfaceInfo
];
560 IfInfo
= (EFI_IP6_CONFIG_INTERFACE_INFO
*) Data
;
561 CopyMem (IfInfo
, Item
->Data
.Ptr
, sizeof (EFI_IP6_CONFIG_INTERFACE_INFO
));
566 IfInfo
->AddressInfo
= (EFI_IP6_ADDRESS_INFO
*) (IfInfo
+ 1);
567 Ip6BuildEfiAddressList (IpSb
, &IfInfo
->AddressInfoCount
, &IfInfo
->AddressInfo
);
572 IfInfo
->RouteTable
= (EFI_IP6_ROUTE_TABLE
*) (IfInfo
->AddressInfo
+ IfInfo
->AddressInfoCount
);
573 Ip6BuildEfiRouteTable (IpSb
->RouteTable
, &IfInfo
->RouteCount
, &IfInfo
->RouteTable
);
575 if (IfInfo
->AddressInfoCount
== 0) {
576 IfInfo
->AddressInfo
= NULL
;
579 if (IfInfo
->RouteCount
== 0) {
580 IfInfo
->RouteTable
= NULL
;
587 The work function for EfiIp6ConfigSetData() to set the alternative inteface ID
588 for the communication device managed by this IP6Config instance, if the link local
589 IPv6 addresses generated from the interface ID based on the default source the
590 EFI IPv6 Protocol uses is a duplicate address.
592 @param[in] Instance Pointer to the IP6 configuration instance data.
593 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
594 @param[in] Data The data buffer to set.
596 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type,
598 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
599 network stack was set.
603 Ip6ConfigSetAltIfId (
604 IN IP6_CONFIG_INSTANCE
*Instance
,
609 EFI_IP6_CONFIG_INTERFACE_ID
*OldIfId
;
610 EFI_IP6_CONFIG_INTERFACE_ID
*NewIfId
;
611 IP6_CONFIG_DATA_ITEM
*DataItem
;
613 if (DataSize
!= sizeof (EFI_IP6_CONFIG_INTERFACE_ID
)) {
614 return EFI_BAD_BUFFER_SIZE
;
617 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeAltInterfaceId
];
618 OldIfId
= DataItem
->Data
.AltIfId
;
619 NewIfId
= (EFI_IP6_CONFIG_INTERFACE_ID
*) Data
;
621 CopyMem (OldIfId
, NewIfId
, DataSize
);
622 DataItem
->Status
= EFI_SUCCESS
;
628 The work function for EfiIp6ConfigSetData() to set the general configuration
629 policy for the EFI IPv6 network stack that is running on the communication device
630 managed by this IP6Config instance. The policy will affect other configuration settings.
632 @param[in] Instance Pointer to the IP6 config instance data.
633 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
634 @param[in] Data The data buffer to set.
636 @retval EFI_INVALID_PARAMETER The to be set policy is invalid.
637 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
638 @retval EFI_ABORTED The new policy equals the current policy.
639 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
640 network stack was set.
645 IN IP6_CONFIG_INSTANCE
*Instance
,
650 EFI_IP6_CONFIG_POLICY NewPolicy
;
651 IP6_CONFIG_DATA_ITEM
*DataItem
;
654 if (DataSize
!= sizeof (EFI_IP6_CONFIG_POLICY
)) {
655 return EFI_BAD_BUFFER_SIZE
;
658 NewPolicy
= *((EFI_IP6_CONFIG_POLICY
*) Data
);
660 if (NewPolicy
> Ip6ConfigPolicyAutomatic
) {
661 return EFI_INVALID_PARAMETER
;
664 if (NewPolicy
== Instance
->Policy
) {
669 // Clean the ManualAddress, Gateway and DnsServers, shrink the variable
670 // data size, and fire up all the related events.
672 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
673 if (DataItem
->Data
.Ptr
!= NULL
) {
674 FreePool (DataItem
->Data
.Ptr
);
676 DataItem
->Data
.Ptr
= NULL
;
677 DataItem
->DataSize
= 0;
678 DataItem
->Status
= EFI_NOT_FOUND
;
679 NetMapIterate (&DataItem
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
681 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeGateway
];
682 if (DataItem
->Data
.Ptr
!= NULL
) {
683 FreePool (DataItem
->Data
.Ptr
);
685 DataItem
->Data
.Ptr
= NULL
;
686 DataItem
->DataSize
= 0;
687 DataItem
->Status
= EFI_NOT_FOUND
;
688 NetMapIterate (&DataItem
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
690 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
691 DataItem
->Data
.Ptr
= NULL
;
692 DataItem
->DataSize
= 0;
693 DataItem
->Status
= EFI_NOT_FOUND
;
694 NetMapIterate (&DataItem
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
696 if (NewPolicy
== Ip6ConfigPolicyManual
) {
698 // The policy is changed from automatic to manual. Stop the DHCPv6 process
699 // and destroy the DHCPv6 child.
701 if (Instance
->Dhcp6Handle
!= NULL
) {
702 Ip6ConfigDestroyDhcp6 (Instance
);
706 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
707 Ip6ConfigOnPolicyChanged (IpSb
, NewPolicy
);
709 Instance
->Policy
= NewPolicy
;
716 The work function for EfiIp6ConfigSetData() to set the number of consecutive
717 Neighbor Solicitation messages sent while performing Duplicate Address Detection
718 on a tentative address. A value of ZERO indicates that Duplicate Address Detection
719 will not be performed on a tentative address.
721 @param[in] Instance The Instance Pointer to the IP6 config instance data.
722 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
723 @param[in] Data The data buffer to set.
725 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
726 @retval EFI_ABORTED The new transmit count equals the current configuration.
727 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
728 network stack was set.
732 Ip6ConfigSetDadXmits (
733 IN IP6_CONFIG_INSTANCE
*Instance
,
738 EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS
*OldDadXmits
;
740 if (DataSize
!= sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS
)) {
741 return EFI_BAD_BUFFER_SIZE
;
744 OldDadXmits
= Instance
->DataItem
[Ip6ConfigDataTypeDupAddrDetectTransmits
].Data
.DadXmits
;
746 if ((*(UINT32
*) Data
) == OldDadXmits
->DupAddrDetectTransmits
) {
751 OldDadXmits
->DupAddrDetectTransmits
= *((UINT32
*) Data
);
757 The callback function for Ip6SetAddr. The prototype is defined
758 as IP6_DAD_CALLBACK. It is called after Duplicate Address Detection is performed
759 for the manual address set by Ip6ConfigSetMaunualAddress.
761 @param[in] IsDadPassed If TRUE, Duplicate Address Detection passed.
762 @param[in] TargetAddress The tentative IPv6 address to be checked.
763 @param[in] Context Pointer to the IP6 configuration instance data.
767 Ip6ManualAddrDadCallback (
768 IN BOOLEAN IsDadPassed
,
769 IN EFI_IPv6_ADDRESS
*TargetAddress
,
773 IP6_CONFIG_INSTANCE
*Instance
;
775 IP6_CONFIG_DATA_ITEM
*Item
;
776 EFI_IP6_CONFIG_MANUAL_ADDRESS
*ManualAddr
;
777 EFI_IP6_CONFIG_MANUAL_ADDRESS
*PassedAddr
;
782 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
783 NET_CHECK_SIGNATURE (Instance
, IP6_CONFIG_INSTANCE_SIGNATURE
);
784 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
787 for (Index
= 0; Index
< Item
->DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
); Index
++) {
789 // Find the original tag used to place into the NET_MAP.
791 ManualAddr
= Item
->Data
.ManualAddress
+ Index
;
792 if (EFI_IP6_EQUAL (TargetAddress
, &ManualAddr
->Address
)) {
797 ASSERT (Index
!= Item
->DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
));
800 NetMapInsertTail (&Instance
->DadPassedMap
, ManualAddr
, NULL
);
802 NetMapInsertTail (&Instance
->DadFailedMap
, ManualAddr
, NULL
);
805 DadPassCount
= NetMapGetCount (&Instance
->DadPassedMap
);
806 DadFailCount
= NetMapGetCount (&Instance
->DadFailedMap
);
808 if ((DadPassCount
+ DadFailCount
) == (Item
->DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
))) {
810 // All addresses have finished the configuration process.
812 if (DadFailCount
!= 0) {
814 // There is at least one duplicate address.
816 FreePool (Item
->Data
.Ptr
);
818 Item
->DataSize
= DadPassCount
* sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
);
819 if (Item
->DataSize
== 0) {
821 // All failed, bad luck.
823 Item
->Data
.Ptr
= NULL
;
824 Item
->Status
= EFI_NOT_FOUND
;
827 // Part of addresses are detected to be duplicates, so update the
828 // data with those passed.
830 PassedAddr
= (EFI_IP6_CONFIG_MANUAL_ADDRESS
*) AllocatePool (Item
->DataSize
);
831 ASSERT (PassedAddr
!= NULL
);
833 Item
->Data
.Ptr
= PassedAddr
;
834 Item
->Status
= EFI_SUCCESS
;
836 while (!NetMapIsEmpty (&Instance
->DadPassedMap
)) {
837 ManualAddr
= (EFI_IP6_CONFIG_MANUAL_ADDRESS
*) NetMapRemoveHead (&Instance
->DadPassedMap
, NULL
);
838 CopyMem (PassedAddr
, ManualAddr
, sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
));
843 ASSERT ((UINTN
) PassedAddr
- (UINTN
) Item
->Data
.Ptr
== Item
->DataSize
);
847 // All addresses are valid.
849 Item
->Status
= EFI_SUCCESS
;
853 // Remove the tags we put in the NET_MAPs.
855 while (!NetMapIsEmpty (&Instance
->DadFailedMap
)) {
856 NetMapRemoveHead (&Instance
->DadFailedMap
, NULL
);
859 while (!NetMapIsEmpty (&Instance
->DadPassedMap
)) {
860 NetMapRemoveHead (&Instance
->DadPassedMap
, NULL
);
864 // Signal the waiting events.
866 NetMapIterate (&Item
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
867 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
868 Ip6ConfigWriteConfigData (IpSb
->MacString
, Instance
);
873 The work function for EfiIp6ConfigSetData() to set the station addresses manually
874 for the EFI IPv6 network stack. It is only configurable when the policy is
875 Ip6ConfigPolicyManual.
877 @param[in] Instance Pointer to the IP6 configuration instance data.
878 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
879 @param[in] Data The data buffer to set.
881 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
882 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
883 under the current policy.
884 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
885 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
886 @retval EFI_NOT_READY An asynchrous process is invoked to set the specified
887 configuration data, and the process is not finished.
888 @retval EFI_ABORTED The manual addresses to be set equal current
890 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
891 network stack was set.
895 Ip6ConfigSetMaunualAddress (
896 IN IP6_CONFIG_INSTANCE
*Instance
,
901 EFI_IP6_CONFIG_MANUAL_ADDRESS
*NewAddress
;
902 EFI_IP6_CONFIG_MANUAL_ADDRESS
*TmpAddress
;
903 IP6_CONFIG_DATA_ITEM
*DataItem
;
904 UINTN NewAddressCount
;
908 IP6_ADDRESS_INFO
*CurrentAddrInfo
;
909 IP6_ADDRESS_INFO
*Copy
;
910 LIST_ENTRY CurrentSourceList
;
911 UINT32 CurrentSourceCount
;
915 IP6_PREFIX_LIST_ENTRY
*PrefixEntry
;
919 ASSERT (Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
].Status
!= EFI_NOT_READY
);
921 if (((DataSize
% sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
)) != 0) || (DataSize
== 0)) {
922 return EFI_BAD_BUFFER_SIZE
;
925 if (Instance
->Policy
!= Ip6ConfigPolicyManual
) {
926 return EFI_WRITE_PROTECTED
;
929 NewAddressCount
= DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
);
930 NewAddress
= (EFI_IP6_CONFIG_MANUAL_ADDRESS
*) Data
;
932 for (Index1
= 0; Index1
< NewAddressCount
; Index1
++, NewAddress
++) {
934 if (NetIp6IsLinkLocalAddr (&NewAddress
->Address
) ||
935 !NetIp6IsValidUnicast (&NewAddress
->Address
) ||
936 (NewAddress
->PrefixLength
> 128)
939 // make sure the IPv6 address is unicast and not link-local address &&
940 // the prefix length is valid.
942 return EFI_INVALID_PARAMETER
;
945 TmpAddress
= NewAddress
+ 1;
946 for (Index2
= Index1
+ 1; Index2
< NewAddressCount
; Index2
++, TmpAddress
++) {
948 // Any two addresses in the array can't be equal.
950 if (EFI_IP6_EQUAL (&TmpAddress
->Address
, &NewAddress
->Address
)) {
952 return EFI_INVALID_PARAMETER
;
957 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
960 // Build the current source address list.
962 InitializeListHead (&CurrentSourceList
);
963 CurrentSourceCount
= 0;
965 NET_LIST_FOR_EACH (Entry
, &IpSb
->Interfaces
) {
966 IpIf
= NET_LIST_USER_STRUCT_S (Entry
, IP6_INTERFACE
, Link
, IP6_INTERFACE_SIGNATURE
);
968 NET_LIST_FOR_EACH (Entry2
, &IpIf
->AddressList
) {
969 CurrentAddrInfo
= NET_LIST_USER_STRUCT_S (Entry2
, IP6_ADDRESS_INFO
, Link
, IP6_ADDR_INFO_SIGNATURE
);
971 Copy
= AllocateCopyPool (sizeof (IP6_ADDRESS_INFO
), CurrentAddrInfo
);
976 InsertTailList (&CurrentSourceList
, &Copy
->Link
);
977 CurrentSourceCount
++;
982 // Update the value... a long journey starts
984 NewAddress
= AllocateCopyPool (DataSize
, Data
);
985 if (NewAddress
== NULL
) {
986 Ip6RemoveAddr (NULL
, &CurrentSourceList
, &CurrentSourceCount
, NULL
, 0);
988 return EFI_OUT_OF_RESOURCES
;
992 // Store the new data, and init the DataItem status to EFI_NOT_READY because
993 // we may have an asynchronous configuration process.
995 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
996 if (DataItem
->Data
.Ptr
!= NULL
) {
997 FreePool (DataItem
->Data
.Ptr
);
999 DataItem
->Data
.Ptr
= NewAddress
;
1000 DataItem
->DataSize
= DataSize
;
1001 DataItem
->Status
= EFI_NOT_READY
;
1004 // Trigger DAD, it's an asynchronous process.
1008 for (Index1
= 0; Index1
< NewAddressCount
; Index1
++, NewAddress
++) {
1009 if (Ip6IsOneOfSetAddress (IpSb
, &NewAddress
->Address
, NULL
, &CurrentAddrInfo
)) {
1010 ASSERT (CurrentAddrInfo
!= NULL
);
1012 // Remove this already existing source address from the CurrentSourceList
1018 &CurrentSourceCount
,
1019 &CurrentAddrInfo
->Address
,
1024 // If the new address's prefix length is not specified, just use the previous configured
1025 // prefix length for this address.
1027 if (NewAddress
->PrefixLength
== 0) {
1028 NewAddress
->PrefixLength
= CurrentAddrInfo
->PrefixLength
;
1032 // This manual address is already in use, see whether prefix length is changed.
1034 if (NewAddress
->PrefixLength
!= CurrentAddrInfo
->PrefixLength
) {
1036 // Remove the on-link prefix table, the route entry will be removed
1039 PrefixEntry
= Ip6FindPrefixListEntry (
1042 CurrentAddrInfo
->PrefixLength
,
1043 &CurrentAddrInfo
->Address
1045 if (PrefixEntry
!= NULL
) {
1046 Ip6DestroyPrefixListEntry (IpSb
, PrefixEntry
, TRUE
, FALSE
);
1050 // Save the prefix length.
1052 CurrentAddrInfo
->PrefixLength
= NewAddress
->PrefixLength
;
1057 // create a new on-link prefix entry.
1059 PrefixEntry
= Ip6FindPrefixListEntry (
1062 NewAddress
->PrefixLength
,
1063 &NewAddress
->Address
1065 if (PrefixEntry
== NULL
) {
1066 Ip6CreatePrefixListEntry (
1069 (UINT32
) IP6_INFINIT_LIFETIME
,
1070 (UINT32
) IP6_INFINIT_LIFETIME
,
1071 NewAddress
->PrefixLength
,
1072 &NewAddress
->Address
1076 CurrentAddrInfo
->IsAnycast
= NewAddress
->IsAnycast
;
1078 // Artificially mark this address passed DAD be'coz it is already in use.
1080 Ip6ManualAddrDadCallback (TRUE
, &NewAddress
->Address
, Instance
);
1088 // Set the new address, this will trigger DAD and activate the address if
1092 IpSb
->DefaultInterface
,
1093 &NewAddress
->Address
,
1094 NewAddress
->IsAnycast
,
1095 NewAddress
->PrefixLength
,
1096 (UINT32
) IP6_INFINIT_LIFETIME
,
1097 (UINT32
) IP6_INFINIT_LIFETIME
,
1098 Ip6ManualAddrDadCallback
,
1105 // Check the CurrentSourceList, it now contains those addresses currently in
1106 // use and will be removed.
1108 IpIf
= IpSb
->DefaultInterface
;
1110 while (!IsListEmpty (&CurrentSourceList
)) {
1113 CurrentAddrInfo
= NET_LIST_HEAD (&CurrentSourceList
, IP6_ADDRESS_INFO
, Link
);
1116 // This local address is going to be removed, the IP instances that are
1117 // currently using it will be destroyed.
1122 &IpIf
->AddressCount
,
1123 &CurrentAddrInfo
->Address
,
1128 // Remove the on-link prefix table, the route entry will be removed
1131 PrefixEntry
= Ip6FindPrefixListEntry (
1134 CurrentAddrInfo
->PrefixLength
,
1135 &CurrentAddrInfo
->Address
1137 if (PrefixEntry
!= NULL
) {
1138 Ip6DestroyPrefixListEntry (IpSb
, PrefixEntry
, TRUE
, FALSE
);
1141 RemoveEntryList (&CurrentAddrInfo
->Link
);
1142 FreePool (CurrentAddrInfo
);
1146 if (DataItem
->Status
== EFI_NOT_READY
) {
1148 // If DAD is disabled on this interface, the configuration process is
1149 // actually synchronous, and the data item's status will be changed to
1150 // the final status before we reach here, just check it.
1152 Status
= EFI_NOT_READY
;
1154 Status
= EFI_SUCCESS
;
1158 // No update is taken, reset the status to success and return EFI_ABORTED.
1160 DataItem
->Status
= EFI_SUCCESS
;
1161 Status
= EFI_ABORTED
;
1168 The work function for EfiIp6ConfigSetData() to set the gateway addresses manually
1169 for the EFI IPv6 network stack that is running on the communication device that
1170 this EFI IPv6 Configuration Protocol manages. It is not configurable when the policy is
1171 Ip6ConfigPolicyAutomatic. The gateway addresses must be unicast IPv6 addresses.
1173 @param[in] Instance The pointer to the IP6 config instance data.
1174 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1175 @param[in] Data The data buffer to set. This points to an array of
1176 EFI_IPv6_ADDRESS instances.
1178 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1179 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1180 under the current policy.
1181 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1182 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to complete the operation.
1183 @retval EFI_ABORTED The manual gateway addresses to be set equal the
1184 current configuration.
1185 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1186 network stack was set.
1190 Ip6ConfigSetGateway (
1191 IN IP6_CONFIG_INSTANCE
*Instance
,
1198 EFI_IPv6_ADDRESS
*OldGateway
;
1199 EFI_IPv6_ADDRESS
*NewGateway
;
1200 UINTN OldGatewayCount
;
1201 UINTN NewGatewayCount
;
1202 IP6_CONFIG_DATA_ITEM
*Item
;
1206 IP6_DEFAULT_ROUTER
*DefaultRouter
;
1209 if ((DataSize
% sizeof (EFI_IPv6_ADDRESS
) != 0) || (DataSize
== 0)) {
1210 return EFI_BAD_BUFFER_SIZE
;
1213 if (Instance
->Policy
!= Ip6ConfigPolicyManual
) {
1214 return EFI_WRITE_PROTECTED
;
1217 NewGateway
= (EFI_IPv6_ADDRESS
*) Data
;
1218 NewGatewayCount
= DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1219 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1221 if (!NetIp6IsValidUnicast (NewGateway
+ Index1
)) {
1223 return EFI_INVALID_PARAMETER
;
1226 for (Index2
= Index1
+ 1; Index2
< NewGatewayCount
; Index2
++) {
1227 if (EFI_IP6_EQUAL (NewGateway
+ Index1
, NewGateway
+ Index2
)) {
1228 return EFI_INVALID_PARAMETER
;
1233 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
1234 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeGateway
];
1235 OldGateway
= Item
->Data
.Gateway
;
1236 OldGatewayCount
= Item
->DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1240 if (NewGatewayCount
!= OldGatewayCount
) {
1241 Tmp
= AllocatePool (DataSize
);
1243 return EFI_OUT_OF_RESOURCES
;
1249 for (Index1
= 0; Index1
< OldGatewayCount
; Index1
++) {
1251 // Find the gateways that are no long in the new setting and remove them.
1253 for (Index2
= 0; Index2
< NewGatewayCount
; Index2
++) {
1254 if (EFI_IP6_EQUAL (OldGateway
+ Index1
, NewGateway
+ Index2
)) {
1260 if (Index2
== NewGatewayCount
) {
1262 // Remove this default router.
1264 DefaultRouter
= Ip6FindDefaultRouter (IpSb
, OldGateway
+ Index1
);
1265 if (DefaultRouter
!= NULL
) {
1266 Ip6DestroyDefaultRouter (IpSb
, DefaultRouter
);
1271 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1273 DefaultRouter
= Ip6FindDefaultRouter (IpSb
, NewGateway
+ Index1
);
1274 if (DefaultRouter
== NULL
) {
1275 Ip6CreateDefaultRouter (IpSb
, NewGateway
+ Index1
, IP6_INF_ROUTER_LIFETIME
);
1280 if (!OneRemoved
&& !OneAdded
) {
1281 Item
->Status
= EFI_SUCCESS
;
1286 if (Item
->Data
.Ptr
!= NULL
) {
1287 FreePool (Item
->Data
.Ptr
);
1289 Item
->Data
.Ptr
= Tmp
;
1292 CopyMem (Item
->Data
.Ptr
, Data
, DataSize
);
1293 Item
->DataSize
= DataSize
;
1294 Item
->Status
= EFI_SUCCESS
;
1300 The work function for EfiIp6ConfigSetData() to set the DNS server list for the
1301 EFI IPv6 network stack running on the communication device that this EFI IPv6
1302 Configuration Protocol manages. It is not configurable when the policy is
1303 Ip6ConfigPolicyAutomatic. The DNS server addresses must be unicast IPv6 addresses.
1305 @param[in] Instance The pointer to the IP6 config instance data.
1306 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1307 @param[in] Data The data buffer to set, points to an array of
1308 EFI_IPv6_ADDRESS instances.
1310 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1311 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1312 under the current policy.
1313 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1314 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
1315 @retval EFI_ABORTED The DNS server addresses to be set equal the current
1317 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1318 network stack was set.
1322 Ip6ConfigSetDnsServer (
1323 IN IP6_CONFIG_INSTANCE
*Instance
,
1331 EFI_IPv6_ADDRESS
*OldDns
;
1332 EFI_IPv6_ADDRESS
*NewDns
;
1335 IP6_CONFIG_DATA_ITEM
*Item
;
1339 if ((DataSize
% sizeof (EFI_IPv6_ADDRESS
) != 0) || (DataSize
== 0)) {
1340 return EFI_BAD_BUFFER_SIZE
;
1343 if (Instance
->Policy
!= Ip6ConfigPolicyManual
) {
1344 return EFI_WRITE_PROTECTED
;
1347 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
1348 NewDns
= (EFI_IPv6_ADDRESS
*) Data
;
1349 OldDns
= Item
->Data
.DnsServers
;
1350 NewDnsCount
= DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1351 OldDnsCount
= Item
->DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1354 if (NewDnsCount
!= OldDnsCount
) {
1355 Tmp
= AllocatePool (DataSize
);
1357 return EFI_OUT_OF_RESOURCES
;
1363 for (NewIndex
= 0; NewIndex
< NewDnsCount
; NewIndex
++) {
1365 if (!NetIp6IsValidUnicast (NewDns
+ NewIndex
)) {
1367 // The dns server address must be unicast.
1372 return EFI_INVALID_PARAMETER
;
1375 for (Index1
= NewIndex
+ 1; Index1
< NewDnsCount
; Index1
++) {
1376 if (EFI_IP6_EQUAL (NewDns
+ NewIndex
, NewDns
+ Index1
)) {
1380 return EFI_INVALID_PARAMETER
;
1386 // If any address in the new setting is not in the old settings, skip the
1387 // comparision below.
1392 for (OldIndex
= 0; OldIndex
< OldDnsCount
; OldIndex
++) {
1393 if (EFI_IP6_EQUAL (NewDns
+ NewIndex
, OldDns
+ OldIndex
)) {
1395 // If found break out.
1401 if (OldIndex
== OldDnsCount
) {
1406 if (!OneAdded
&& (DataSize
== Item
->DataSize
)) {
1408 // No new item is added and the size is the same.
1410 Item
->Status
= EFI_SUCCESS
;
1414 if (Item
->Data
.Ptr
!= NULL
) {
1415 FreePool (Item
->Data
.Ptr
);
1417 Item
->Data
.Ptr
= Tmp
;
1420 CopyMem (Item
->Data
.Ptr
, Data
, DataSize
);
1421 Item
->DataSize
= DataSize
;
1422 Item
->Status
= EFI_SUCCESS
;
1428 Generate the operational state of the interface this IP6 config instance manages
1429 and output in EFI_IP6_CONFIG_INTERFACE_INFO.
1431 @param[in] IpSb The pointer to the IP6 service binding instance.
1432 @param[out] IfInfo The pointer to the IP6 configuration interface information structure.
1436 Ip6ConfigInitIfInfo (
1437 IN IP6_SERVICE
*IpSb
,
1438 OUT EFI_IP6_CONFIG_INTERFACE_INFO
*IfInfo
1443 sizeof (IfInfo
->Name
),
1445 IpSb
->Ip6ConfigInstance
.IfIndex
1448 IfInfo
->IfType
= IpSb
->SnpMode
.IfType
;
1449 IfInfo
->HwAddressSize
= IpSb
->SnpMode
.HwAddressSize
;
1450 CopyMem (&IfInfo
->HwAddress
, &IpSb
->SnpMode
.CurrentAddress
, IfInfo
->HwAddressSize
);
1454 Parse DHCPv6 reply packet to get the DNS server list.
1455 It is the work function for Ip6ConfigOnDhcp6Reply and Ip6ConfigOnDhcp6Event.
1457 @param[in] Dhcp6 The pointer to the EFI_DHCP6_PROTOCOL instance.
1458 @param[in, out] Instance The pointer to the IP6 configuration instance data.
1459 @param[in] Reply The pointer to the DHCPv6 reply packet.
1461 @retval EFI_SUCCESS The DNS server address was retrieved from the reply packet.
1462 @retval EFI_NOT_READY The reply packet does not contain the DNS server option, or
1463 the DNS server address is not valid.
1467 Ip6ConfigParseDhcpReply (
1468 IN EFI_DHCP6_PROTOCOL
*Dhcp6
,
1469 IN OUT IP6_CONFIG_INSTANCE
*Instance
,
1470 IN EFI_DHCP6_PACKET
*Reply
1475 EFI_DHCP6_PACKET_OPTION
**OptList
;
1480 EFI_IPv6_ADDRESS
*DnsServer
;
1481 IP6_CONFIG_DATA_ITEM
*Item
;
1484 // A DHCPv6 reply packet is received as the response to our InfoRequest
1488 Status
= Dhcp6
->Parse (Dhcp6
, Reply
, &OptCount
, NULL
);
1489 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1490 return EFI_NOT_READY
;
1493 OptList
= AllocatePool (OptCount
* sizeof (EFI_DHCP6_PACKET_OPTION
*));
1494 if (OptList
== NULL
) {
1495 return EFI_NOT_READY
;
1498 Status
= Dhcp6
->Parse (Dhcp6
, Reply
, &OptCount
, OptList
);
1499 if (EFI_ERROR (Status
)) {
1500 Status
= EFI_NOT_READY
;
1504 Status
= EFI_SUCCESS
;
1506 for (Index
= 0; Index
< OptCount
; Index
++) {
1508 // Go through all the options to check the ones we are interested in.
1509 // The OpCode and Length are in network byte-order and may not be naturally
1512 CopyMem (&OpCode
, &OptList
[Index
]->OpCode
, sizeof (OpCode
));
1513 OpCode
= NTOHS (OpCode
);
1515 if (OpCode
== DHCP6_OPT_DNS_SERVERS
) {
1516 CopyMem (&Length
, &OptList
[Index
]->OpLen
, sizeof (Length
));
1517 Length
= NTOHS (Length
);
1519 if ((Length
== 0) || ((Length
% sizeof (EFI_IPv6_ADDRESS
)) != 0)) {
1521 // The length should be a multiple of 16 bytes.
1523 Status
= EFI_NOT_READY
;
1528 // Validate the DnsServers: whether they are unicast addresses.
1530 DnsServer
= (EFI_IPv6_ADDRESS
*) OptList
[Index
]->Data
;
1531 for (Index2
= 0; Index2
< Length
/ sizeof (EFI_IPv6_ADDRESS
); Index2
++) {
1532 if (!NetIp6IsValidUnicast (DnsServer
)) {
1533 Status
= EFI_NOT_READY
;
1540 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
1542 if (Item
->DataSize
!= Length
) {
1543 if (Item
->Data
.Ptr
!= NULL
) {
1544 FreePool (Item
->Data
.Ptr
);
1547 Item
->Data
.Ptr
= AllocatePool (Length
);
1548 ASSERT (Item
->Data
.Ptr
!= NULL
);
1551 CopyMem (Item
->Data
.Ptr
, OptList
[Index
]->Data
, Length
);
1552 Item
->DataSize
= Length
;
1553 Item
->Status
= EFI_SUCCESS
;
1556 // Signal the waiting events.
1558 NetMapIterate (&Item
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
1571 The callback function for Ip6SetAddr. The prototype is defined
1572 as IP6_DAD_CALLBACK. It is called after Duplicate Address Detection is performed
1573 on the tentative address by DHCPv6 in Ip6ConfigOnDhcp6Event().
1575 @param[in] IsDadPassed If TRUE, Duplicate Address Detection passes.
1576 @param[in] TargetAddress The tentative IPv6 address to be checked.
1577 @param[in] Context Pointer to the IP6 configuration instance data.
1581 Ip6ConfigSetStatefulAddrCallback (
1582 IN BOOLEAN IsDadPassed
,
1583 IN EFI_IPv6_ADDRESS
*TargetAddress
,
1587 IP6_CONFIG_INSTANCE
*Instance
;
1589 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
1590 NET_CHECK_SIGNATURE (Instance
, IP6_CONFIG_INSTANCE_SIGNATURE
);
1593 // We should record the addresses that fail the DAD, and DECLINE them.
1597 // Decrease the count, no interests in those passed DAD.
1599 if (Instance
->FailedIaAddressCount
> 0 ) {
1600 Instance
->FailedIaAddressCount
--;
1606 IP6_COPY_ADDRESS (Instance
->DeclineAddress
+ Instance
->DeclineAddressCount
, TargetAddress
);
1607 Instance
->DeclineAddressCount
++;
1610 if (Instance
->FailedIaAddressCount
== Instance
->DeclineAddressCount
) {
1612 // The checking on all addresses are finished.
1614 if (Instance
->DeclineAddressCount
!= 0) {
1616 // Decline those duplicates.
1618 if (Instance
->Dhcp6
!= NULL
) {
1619 Instance
->Dhcp6
->Decline (
1621 Instance
->DeclineAddressCount
,
1622 Instance
->DeclineAddress
1627 if (Instance
->DeclineAddress
!= NULL
) {
1628 FreePool (Instance
->DeclineAddress
);
1630 Instance
->DeclineAddress
= NULL
;
1631 Instance
->DeclineAddressCount
= 0;
1636 The event handle routine when DHCPv6 process is finished or is updated.
1638 @param[in] Event Not used.
1639 @param[in] Context The pointer to the IP6 configuration instance data.
1644 Ip6ConfigOnDhcp6Event (
1649 IP6_CONFIG_INSTANCE
*Instance
;
1650 EFI_DHCP6_PROTOCOL
*Dhcp6
;
1652 EFI_DHCP6_MODE_DATA Dhcp6ModeData
;
1654 EFI_DHCP6_IA_ADDRESS
*IaAddr
;
1657 IP6_ADDRESS_INFO
*AddrInfo
;
1658 IP6_INTERFACE
*IpIf
;
1660 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
1662 if ((Instance
->Policy
!= Ip6ConfigPolicyAutomatic
) || Instance
->OtherInfoOnly
) {
1664 // IPv6 is not operating in the automatic policy now or
1665 // the DHCPv6 information request message exchange is aborted.
1671 // The stateful address autoconfiguration is done or updated.
1673 Dhcp6
= Instance
->Dhcp6
;
1675 Status
= Dhcp6
->GetModeData (Dhcp6
, &Dhcp6ModeData
, NULL
);
1676 if (EFI_ERROR (Status
)) {
1680 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
1681 IpIf
= IpSb
->DefaultInterface
;
1682 Ia
= Dhcp6ModeData
.Ia
;
1683 IaAddr
= Ia
->IaAddress
;
1685 if (Instance
->DeclineAddress
!= NULL
) {
1686 FreePool (Instance
->DeclineAddress
);
1689 Instance
->DeclineAddress
= (EFI_IPv6_ADDRESS
*) AllocatePool (Ia
->IaAddressCount
* sizeof (EFI_IPv6_ADDRESS
));
1690 if (Instance
->DeclineAddress
== NULL
) {
1694 Instance
->FailedIaAddressCount
= Ia
->IaAddressCount
;
1695 Instance
->DeclineAddressCount
= 0;
1697 for (Index
= 0; Index
< Ia
->IaAddressCount
; Index
++, IaAddr
++) {
1698 if (Ia
->IaAddress
[Index
].ValidLifetime
!= 0 && Ia
->State
== Dhcp6Bound
) {
1700 // Set this address, either it's a new address or with updated lifetimes.
1701 // An appropriate prefix length will be set.
1708 IaAddr
->ValidLifetime
,
1709 IaAddr
->PreferredLifetime
,
1710 Ip6ConfigSetStatefulAddrCallback
,
1715 // discard this address, artificially decrease the count as if this address
1718 if (Ip6IsOneOfSetAddress (IpSb
, &IaAddr
->IpAddress
, NULL
, &AddrInfo
)) {
1719 ASSERT (AddrInfo
!= NULL
);
1723 &IpIf
->AddressCount
,
1725 AddrInfo
->PrefixLength
1729 if (Instance
->FailedIaAddressCount
> 0) {
1730 Instance
->FailedIaAddressCount
--;
1736 // Parse the Reply packet to get the options we need.
1738 if (Dhcp6ModeData
.Ia
->ReplyPacket
!= NULL
) {
1739 Ip6ConfigParseDhcpReply (Dhcp6
, Instance
, Dhcp6ModeData
.Ia
->ReplyPacket
);
1744 FreePool (Dhcp6ModeData
.ClientId
);
1745 FreePool (Dhcp6ModeData
.Ia
);
1749 The event process routine when the DHCPv6 server is answered with a reply packet
1750 for an information request.
1752 @param[in] This Points to the EFI_DHCP6_PROTOCOL.
1753 @param[in] Context The pointer to the IP6 configuration instance data.
1754 @param[in] Packet The DHCPv6 reply packet.
1756 @retval EFI_SUCCESS The DNS server address was retrieved from the reply packet.
1757 @retval EFI_NOT_READY The reply packet does not contain the DNS server option, or
1758 the DNS server address is not valid.
1763 Ip6ConfigOnDhcp6Reply (
1764 IN EFI_DHCP6_PROTOCOL
*This
,
1766 IN EFI_DHCP6_PACKET
*Packet
1769 return Ip6ConfigParseDhcpReply (This
, (IP6_CONFIG_INSTANCE
*) Context
, Packet
);
1773 The event process routine when the DHCPv6 service binding protocol is installed
1776 @param[in] Event Not used.
1777 @param[in] Context The pointer to the IP6 config instance data.
1782 Ip6ConfigOnDhcp6SbInstalled (
1787 IP6_CONFIG_INSTANCE
*Instance
;
1789 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
1791 if ((Instance
->Dhcp6Handle
!= NULL
) || (Instance
->Policy
!= Ip6ConfigPolicyAutomatic
)) {
1793 // The DHCP6 child is already created or the policy is no longer AUTOMATIC.
1798 Ip6ConfigStartStatefulAutoConfig (Instance
, Instance
->OtherInfoOnly
);
1802 Set the configuration for the EFI IPv6 network stack running on the communication
1803 device this EFI IPv6 Configuration Protocol instance manages.
1805 This function is used to set the configuration data of type DataType for the EFI
1806 IPv6 network stack that is running on the communication device that this EFI IPv6
1807 Configuration Protocol instance manages.
1809 DataSize is used to calculate the count of structure instances in the Data for
1810 a DataType in which multiple structure instances are allowed.
1812 This function is always non-blocking. When setting some type of configuration data,
1813 an asynchronous process is invoked to check the correctness of the data, such as
1814 performing Duplicate Address Detection on the manually set local IPv6 addresses.
1815 EFI_NOT_READY is returned immediately to indicate that such an asynchronous process
1816 is invoked, and the process is not finished yet. The caller wanting to get the result
1817 of the asynchronous process is required to call RegisterDataNotify() to register an
1818 event on the specified configuration data. Once the event is signaled, the caller
1819 can call GetData() to obtain the configuration data and know the result.
1820 For other types of configuration data that do not require an asynchronous configuration
1821 process, the result of the operation is immediately returned.
1823 @param[in] This The pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
1824 @param[in] DataType The type of data to set.
1825 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1826 @param[in] Data The data buffer to set. The type of the data buffer is
1827 associated with the DataType.
1829 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1830 network stack was set successfully.
1831 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
1834 - One or more fields in Data do not match the requirement of the
1835 data type indicated by DataType.
1836 @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified
1837 configuration data cannot be set under the current policy.
1838 @retval EFI_ACCESS_DENIED Another set operation on the specified configuration
1839 data is already in process.
1840 @retval EFI_NOT_READY An asynchronous process was invoked to set the specified
1841 configuration data, and the process is not finished yet.
1842 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type
1843 indicated by DataType.
1844 @retval EFI_UNSUPPORTED This DataType is not supported.
1845 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1846 @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
1851 EfiIp6ConfigSetData (
1852 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
1853 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
1860 IP6_CONFIG_INSTANCE
*Instance
;
1863 if ((This
== NULL
) || (Data
== NULL
)) {
1864 return EFI_INVALID_PARAMETER
;
1867 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
1868 return EFI_UNSUPPORTED
;
1871 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
1872 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
1873 NET_CHECK_SIGNATURE (IpSb
, IP6_SERVICE_SIGNATURE
);
1875 if (IpSb
->LinkLocalDadFail
) {
1876 return EFI_DEVICE_ERROR
;
1879 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1881 Status
= Instance
->DataItem
[DataType
].Status
;
1882 if (Status
!= EFI_NOT_READY
) {
1884 if (Instance
->DataItem
[DataType
].SetData
== NULL
) {
1886 // This type of data is readonly.
1888 Status
= EFI_WRITE_PROTECTED
;
1891 Status
= Instance
->DataItem
[DataType
].SetData (Instance
, DataSize
, Data
);
1892 if (!EFI_ERROR (Status
)) {
1894 // Fire up the events registered with this type of data.
1896 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip6ConfigSignalEvent
, NULL
);
1897 Ip6ConfigWriteConfigData (IpSb
->MacString
, Instance
);
1898 } else if (Status
== EFI_ABORTED
) {
1900 // The SetData is aborted because the data to set is the same with
1901 // the one maintained.
1903 Status
= EFI_SUCCESS
;
1904 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip6ConfigSignalEvent
, NULL
);
1909 // Another asynchornous process is on the way.
1911 Status
= EFI_ACCESS_DENIED
;
1914 gBS
->RestoreTPL (OldTpl
);
1920 Get the configuration data for the EFI IPv6 network stack running on the communication
1921 device that this EFI IPv6 Configuration Protocol instance manages.
1923 This function returns the configuration data of type DataType for the EFI IPv6 network
1924 stack running on the communication device that this EFI IPv6 Configuration Protocol instance
1927 The caller is responsible for allocating the buffer used to return the specified
1928 configuration data. The required size will be returned to the caller if the size of
1929 the buffer is too small.
1931 EFI_NOT_READY is returned if the specified configuration data is not ready due to an
1932 asynchronous configuration process already in progress. The caller can call RegisterDataNotify()
1933 to register an event on the specified configuration data. Once the asynchronous configuration
1934 process is finished, the event will be signaled, and a subsequent GetData() call will return
1935 the specified configuration data.
1937 @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
1938 @param[in] DataType The type of data to get.
1939 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in bytes, the
1940 size of buffer required to store the specified configuration data.
1941 @param[in] Data The data buffer in which the configuration data is returned. The
1942 type of the data buffer is associated with the DataType.
1943 This is an optional parameter that may be NULL.
1945 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
1946 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
1949 - Data is NULL if *DataSize is not zero.
1950 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data,
1951 and the required size is returned in DataSize.
1952 @retval EFI_NOT_READY The specified configuration data is not ready due to an
1953 asynchronous configuration process already in progress.
1954 @retval EFI_NOT_FOUND The specified configuration data is not found.
1959 EfiIp6ConfigGetData (
1960 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
1961 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
1962 IN OUT UINTN
*DataSize
,
1963 IN VOID
*Data OPTIONAL
1968 IP6_CONFIG_INSTANCE
*Instance
;
1969 IP6_CONFIG_DATA_ITEM
*DataItem
;
1971 if ((This
== NULL
) || (DataSize
== NULL
) || ((*DataSize
!= 0) && (Data
== NULL
))) {
1972 return EFI_INVALID_PARAMETER
;
1975 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
1976 return EFI_NOT_FOUND
;
1979 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1981 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
1982 DataItem
= &Instance
->DataItem
[DataType
];
1984 Status
= Instance
->DataItem
[DataType
].Status
;
1985 if (!EFI_ERROR (Status
)) {
1987 if (DataItem
->GetData
!= NULL
) {
1989 Status
= DataItem
->GetData (Instance
, DataSize
, Data
);
1990 } else if (*DataSize
< Instance
->DataItem
[DataType
].DataSize
) {
1992 // Update the buffer length.
1994 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
1995 Status
= EFI_BUFFER_TOO_SMALL
;
1998 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
1999 CopyMem (Data
, Instance
->DataItem
[DataType
].Data
.Ptr
, *DataSize
);
2003 gBS
->RestoreTPL (OldTpl
);
2009 Register an event that is signaled whenever a configuration process on the specified
2010 configuration data is done.
2012 This function registers an event that is to be signaled whenever a configuration
2013 process on the specified configuration data is performed. An event can be registered
2014 for a different DataType simultaneously. The caller is responsible for determining
2015 which type of configuration data causes the signaling of the event in such an event.
2017 @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
2018 @param[in] DataType The type of data to unregister the event for.
2019 @param[in] Event The event to register.
2021 @retval EFI_SUCCESS The notification event for the specified configuration data is
2023 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
2024 @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not
2026 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
2027 @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
2032 EfiIp6ConfigRegisterDataNotify (
2033 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
2034 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
2040 IP6_CONFIG_INSTANCE
*Instance
;
2044 if ((This
== NULL
) || (Event
== NULL
)) {
2045 return EFI_INVALID_PARAMETER
;
2048 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
2049 return EFI_UNSUPPORTED
;
2052 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2054 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
2055 EventMap
= &Instance
->DataItem
[DataType
].EventMap
;
2058 // Check whether this event is already registered for this DataType.
2060 Item
= NetMapFindKey (EventMap
, Event
);
2063 Status
= NetMapInsertTail (EventMap
, Event
, NULL
);
2065 if (EFI_ERROR (Status
)) {
2067 Status
= EFI_OUT_OF_RESOURCES
;
2072 Status
= EFI_ACCESS_DENIED
;
2075 gBS
->RestoreTPL (OldTpl
);
2081 Remove a previously registered event for the specified configuration data.
2083 @param This The pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
2084 @param DataType The type of data to remove from the previously
2086 @param Event The event to be unregistered.
2088 @retval EFI_SUCCESS The event registered for the specified
2089 configuration data was removed.
2090 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
2091 @retval EFI_NOT_FOUND The Event has not been registered for the
2097 EfiIp6ConfigUnregisterDataNotify (
2098 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
2099 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
2105 IP6_CONFIG_INSTANCE
*Instance
;
2108 if ((This
== NULL
) || (Event
== NULL
)) {
2109 return EFI_INVALID_PARAMETER
;
2112 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
2113 return EFI_NOT_FOUND
;
2116 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2118 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
2120 Item
= NetMapFindKey (&Instance
->DataItem
[DataType
].EventMap
, Event
);
2123 NetMapRemoveItem (&Instance
->DataItem
[DataType
].EventMap
, Item
, NULL
);
2124 Status
= EFI_SUCCESS
;
2127 Status
= EFI_NOT_FOUND
;
2130 gBS
->RestoreTPL (OldTpl
);
2136 Initialize an IP6_CONFIG_INSTANCE.
2138 @param[out] Instance The buffer of IP6_CONFIG_INSTANCE to be initialized.
2140 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
2141 @retval EFI_SUCCESS The IP6_CONFIG_INSTANCE initialized successfully.
2145 Ip6ConfigInitInstance (
2146 OUT IP6_CONFIG_INSTANCE
*Instance
2150 IP6_CONFIG_INSTANCE
*TmpInstance
;
2155 IP6_CONFIG_DATA_ITEM
*DataItem
;
2157 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
2159 Instance
->Signature
= IP6_CONFIG_INSTANCE_SIGNATURE
;
2162 // Determine the index of this interface.
2165 NET_LIST_FOR_EACH (Entry
, &mIp6ConfigInstanceList
) {
2166 TmpInstance
= NET_LIST_USER_STRUCT_S (Entry
, IP6_CONFIG_INSTANCE
, Link
, IP6_CONFIG_INSTANCE_SIGNATURE
);
2168 if (TmpInstance
->IfIndex
> IfIndex
) {
2170 // There is a sequence hole because some interface is down.
2178 Instance
->IfIndex
= IfIndex
;
2179 NetListInsertBefore (Entry
, &Instance
->Link
);
2181 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
2183 // Initialize the event map for each data item.
2185 NetMapInit (&Instance
->DataItem
[Index
].EventMap
);
2189 // Initialize the NET_MAPs used for DAD on manually configured source addresses.
2191 NetMapInit (&Instance
->DadFailedMap
);
2192 NetMapInit (&Instance
->DadPassedMap
);
2195 // Initialize each data type: associate storage and set data size for the
2196 // fixed size data types, hook the SetData function, set the data attribute.
2198 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeInterfaceInfo
];
2199 DataItem
->GetData
= Ip6ConfigGetIfInfo
;
2200 DataItem
->Data
.Ptr
= &Instance
->InterfaceInfo
;
2201 DataItem
->DataSize
= sizeof (Instance
->InterfaceInfo
);
2202 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
| DATA_ATTRIB_VOLATILE
);
2203 Ip6ConfigInitIfInfo (IpSb
, &Instance
->InterfaceInfo
);
2205 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeAltInterfaceId
];
2206 DataItem
->SetData
= Ip6ConfigSetAltIfId
;
2207 DataItem
->Data
.Ptr
= &Instance
->AltIfId
;
2208 DataItem
->DataSize
= sizeof (Instance
->AltIfId
);
2209 DataItem
->Status
= EFI_NOT_FOUND
;
2210 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2212 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypePolicy
];
2213 DataItem
->SetData
= Ip6ConfigSetPolicy
;
2214 DataItem
->Data
.Ptr
= &Instance
->Policy
;
2215 DataItem
->DataSize
= sizeof (Instance
->Policy
);
2216 Instance
->Policy
= Ip6ConfigPolicyManual
;
2217 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2219 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeDupAddrDetectTransmits
];
2220 DataItem
->SetData
= Ip6ConfigSetDadXmits
;
2221 DataItem
->Data
.Ptr
= &Instance
->DadXmits
;
2222 DataItem
->DataSize
= sizeof (Instance
->DadXmits
);
2223 Instance
->DadXmits
.DupAddrDetectTransmits
= IP6_CONFIG_DEFAULT_DAD_XMITS
;
2224 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2226 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
2227 DataItem
->SetData
= Ip6ConfigSetMaunualAddress
;
2228 DataItem
->Status
= EFI_NOT_FOUND
;
2230 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeGateway
];
2231 DataItem
->SetData
= Ip6ConfigSetGateway
;
2232 DataItem
->Status
= EFI_NOT_FOUND
;
2234 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
2235 DataItem
->SetData
= Ip6ConfigSetDnsServer
;
2236 DataItem
->Status
= EFI_NOT_FOUND
;
2239 // Create the event used for DHCP.
2241 Status
= gBS
->CreateEvent (
2244 Ip6ConfigOnDhcp6Event
,
2246 &Instance
->Dhcp6Event
2248 ASSERT_EFI_ERROR (Status
);
2250 Instance
->Configured
= TRUE
;
2253 // Try to read the config data from NV variable.
2255 Status
= Ip6ConfigReadConfigData (IpSb
->MacString
, Instance
);
2256 if (Status
== EFI_NOT_FOUND
) {
2258 // The NV variable is not set, so generate a random IAID, and write down the
2259 // fresh new configuration as the NV variable now.
2261 Instance
->IaId
= NET_RANDOM (NetRandomInitSeed ());
2263 for (Index
= 0; Index
< IpSb
->SnpMode
.HwAddressSize
; Index
++) {
2264 Instance
->IaId
|= (IpSb
->SnpMode
.CurrentAddress
.Addr
[Index
] << ((Index
<< 3) & 31));
2267 Ip6ConfigWriteConfigData (IpSb
->MacString
, Instance
);
2268 } else if (EFI_ERROR (Status
)) {
2272 Instance
->Ip6Config
.SetData
= EfiIp6ConfigSetData
;
2273 Instance
->Ip6Config
.GetData
= EfiIp6ConfigGetData
;
2274 Instance
->Ip6Config
.RegisterDataNotify
= EfiIp6ConfigRegisterDataNotify
;
2275 Instance
->Ip6Config
.UnregisterDataNotify
= EfiIp6ConfigUnregisterDataNotify
;
2279 // Publish the IP6 configuration form
2281 return Ip6ConfigFormInit (Instance
);
2285 Release an IP6_CONFIG_INSTANCE.
2287 @param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
2291 Ip6ConfigCleanInstance (
2292 IN OUT IP6_CONFIG_INSTANCE
*Instance
2296 IP6_CONFIG_DATA_ITEM
*DataItem
;
2298 if (Instance
->DeclineAddress
!= NULL
) {
2299 FreePool (Instance
->DeclineAddress
);
2302 if (!Instance
->Configured
) {
2306 if (Instance
->Dhcp6Handle
!= NULL
) {
2308 Ip6ConfigDestroyDhcp6 (Instance
);
2314 if (Instance
->Dhcp6Event
!= NULL
) {
2315 gBS
->CloseEvent (Instance
->Dhcp6Event
);
2318 NetMapClean (&Instance
->DadPassedMap
);
2319 NetMapClean (&Instance
->DadFailedMap
);
2321 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
2323 DataItem
= &Instance
->DataItem
[Index
];
2325 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
2326 if (DataItem
->Data
.Ptr
!= NULL
) {
2327 FreePool (DataItem
->Data
.Ptr
);
2329 DataItem
->Data
.Ptr
= NULL
;
2330 DataItem
->DataSize
= 0;
2333 NetMapClean (&Instance
->DataItem
[Index
].EventMap
);
2336 Ip6ConfigFormUnload (Instance
);
2338 RemoveEntryList (&Instance
->Link
);
2342 Destroy the Dhcp6 child in IP6_CONFIG_INSTANCE and release the resources.
2344 @param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
2346 @retval EFI_SUCCESS The child was successfully destroyed.
2347 @retval Others Failed to destroy the child.
2351 Ip6ConfigDestroyDhcp6 (
2352 IN OUT IP6_CONFIG_INSTANCE
*Instance
2357 EFI_DHCP6_PROTOCOL
*Dhcp6
;
2359 Dhcp6
= Instance
->Dhcp6
;
2360 ASSERT (Dhcp6
!= NULL
);
2362 Dhcp6
->Stop (Dhcp6
);
2363 Dhcp6
->Configure (Dhcp6
, NULL
);
2364 Instance
->Dhcp6
= NULL
;
2366 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
2369 // Close DHCPv6 protocol and destroy the child.
2371 Status
= gBS
->CloseProtocol (
2372 Instance
->Dhcp6Handle
,
2373 &gEfiDhcp6ProtocolGuid
,
2377 if (EFI_ERROR (Status
)) {
2381 Status
= NetLibDestroyServiceChild (
2384 &gEfiDhcp6ServiceBindingProtocolGuid
,
2385 Instance
->Dhcp6Handle
2388 Instance
->Dhcp6Handle
= NULL
;