2 The implementation of EFI IPv6 Configuration Protocol.
4 Copyright (c) 2009 - 2011, 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
;
57 // Currently there are only two policies: Manual and Automatic. Regardless of
58 // what transition is going on, i.e., Manual -> Automatic and Automatic ->
59 // Manual, we have to free default router list, on-link prefix list, autonomous
60 // prefix list, address list in all the interfaces and destroy any IPv6 child
61 // instance whose local IP is neither 0 nor the link-local address.
63 Ip6CleanDefaultRouterList (IpSb
);
64 Ip6CleanPrefixListTable (IpSb
, &IpSb
->OnlinkPrefix
);
65 Ip6CleanPrefixListTable (IpSb
, &IpSb
->AutonomousPrefix
);
68 // It's tricky... If the LinkLocal address is O.K., add back the link-local
69 // prefix to the on-link prefix table.
71 if (IpSb
->LinkLocalOk
) {
72 Ip6CreatePrefixListEntry (
75 (UINT32
) IP6_INFINIT_LIFETIME
,
76 (UINT32
) IP6_INFINIT_LIFETIME
,
77 IP6_LINK_LOCAL_PREFIX_LENGTH
,
83 // All IPv6 children that use global unicast address as it's source address
84 // should be destryoed now. The survivers are those use the link-local address
85 // or the unspecified address as the source address.
86 // TODO: Conduct a check here.
89 &IpSb
->DefaultInterface
->AddressList
,
90 &IpSb
->DefaultInterface
->AddressCount
,
95 NET_LIST_FOR_EACH (Entry
, &IpSb
->Interfaces
) {
97 // remove all pending DAD entries for the global addresses.
99 IpIf
= NET_LIST_USER_STRUCT_S (Entry
, IP6_INTERFACE
, Link
, IP6_INTERFACE_SIGNATURE
);
101 NET_LIST_FOR_EACH_SAFE (Entry2
, Next
, &IpIf
->DupAddrDetectList
) {
102 DadEntry
= NET_LIST_USER_STRUCT_S (Entry2
, IP6_DAD_ENTRY
, Link
, IP6_DAD_ENTRY_SIGNATURE
);
104 if (!NetIp6IsLinkLocalAddr (&DadEntry
->AddressInfo
->Address
)) {
106 // Fail this DAD entry if the address is not link-local.
108 Ip6OnDADFinished (FALSE
, IpIf
, DadEntry
);
113 if (NewPolicy
== Ip6ConfigPolicyAutomatic
) {
115 // Set paramters to trigger router solicitation sending in timer handler.
117 IpSb
->RouterAdvertiseReceived
= FALSE
;
118 IpSb
->SolicitTimer
= IP6_MAX_RTR_SOLICITATIONS
;
122 IpSb
->Ticks
= (UINT32
) IP6_GET_TICKS (IP6_ONE_SECOND_IN_MS
);
128 The work function to trigger the DHCPv6 process to perform a stateful autoconfiguration.
130 @param[in] Instance Pointer to the IP6 config instance data.
131 @param[in] OtherInfoOnly If FALSE, get stateful address and other information
132 via DHCPv6. Otherwise, only get the other information.
134 @retval EFI_SUCCESS The operation finished successfully.
135 @retval EFI_UNSUPPORTED The DHCP6 driver is not available.
139 Ip6ConfigStartStatefulAutoConfig (
140 IN IP6_CONFIG_INSTANCE
*Instance
,
141 IN BOOLEAN OtherInfoOnly
146 EFI_DHCP6_CONFIG_DATA Dhcp6CfgData
;
147 EFI_DHCP6_PROTOCOL
*Dhcp6
;
148 EFI_DHCP6_PACKET_OPTION
*OptList
[1];
150 EFI_DHCP6_PACKET_OPTION
*Oro
;
151 EFI_DHCP6_RETRANSMISSION InfoReqReXmit
;
154 // A host must not invoke stateful address configuration if it is already
155 // participating in the statuful protocol as a result of an earlier advertisement.
157 if (Instance
->Dhcp6Handle
!= NULL
) {
161 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
163 Instance
->OtherInfoOnly
= OtherInfoOnly
;
165 Status
= NetLibCreateServiceChild (
168 &gEfiDhcp6ServiceBindingProtocolGuid
,
169 &Instance
->Dhcp6Handle
172 if (Status
== EFI_UNSUPPORTED
) {
174 // No DHCPv6 Service Binding protocol, register a notify.
176 if (Instance
->Dhcp6SbNotifyEvent
== NULL
) {
177 Instance
->Dhcp6SbNotifyEvent
= EfiCreateProtocolNotifyEvent (
178 &gEfiDhcp6ServiceBindingProtocolGuid
,
180 Ip6ConfigOnDhcp6SbInstalled
,
182 &Instance
->Registration
187 if (EFI_ERROR (Status
)) {
191 if (Instance
->Dhcp6SbNotifyEvent
!= NULL
) {
192 gBS
->CloseEvent (Instance
->Dhcp6SbNotifyEvent
);
195 Status
= gBS
->OpenProtocol (
196 Instance
->Dhcp6Handle
,
197 &gEfiDhcp6ProtocolGuid
,
198 (VOID
**) &Instance
->Dhcp6
,
201 EFI_OPEN_PROTOCOL_BY_DRIVER
203 ASSERT_EFI_ERROR (Status
);
205 Dhcp6
= Instance
->Dhcp6
;
206 Dhcp6
->Configure (Dhcp6
, NULL
);
209 // Set the exta options to send. Here we only want the option request option
212 Oro
= (EFI_DHCP6_PACKET_OPTION
*) OptBuf
;
213 Oro
->OpCode
= HTONS (IP6_CONFIG_DHCP6_OPTION_ORO
);
214 Oro
->OpLen
= HTONS (2);
215 *((UINT16
*) &Oro
->Data
[0]) = HTONS (IP6_CONFIG_DHCP6_OPTION_DNS_SERVERS
);
218 Status
= EFI_SUCCESS
;
220 if (!OtherInfoOnly
) {
222 // Get stateful address and other information via DHCPv6.
224 Dhcp6CfgData
.Dhcp6Callback
= NULL
;
225 Dhcp6CfgData
.CallbackContext
= NULL
;
226 Dhcp6CfgData
.OptionCount
= 1;
227 Dhcp6CfgData
.OptionList
= &OptList
[0];
228 Dhcp6CfgData
.IaDescriptor
.Type
= EFI_DHCP6_IA_TYPE_NA
;
229 Dhcp6CfgData
.IaDescriptor
.IaId
= Instance
->IaId
;
230 Dhcp6CfgData
.IaInfoEvent
= Instance
->Dhcp6Event
;
231 Dhcp6CfgData
.ReconfigureAccept
= FALSE
;
232 Dhcp6CfgData
.RapidCommit
= FALSE
;
233 Dhcp6CfgData
.SolicitRetransmission
= NULL
;
235 Status
= Dhcp6
->Configure (Dhcp6
, &Dhcp6CfgData
);
237 if (!EFI_ERROR (Status
)) {
239 if (IpSb
->LinkLocalOk
) {
240 Status
= Dhcp6
->Start (Dhcp6
);
242 IpSb
->Dhcp6NeedStart
= TRUE
;
248 // Only get other information via DHCPv6, this doesn't require a config
251 InfoReqReXmit
.Irt
= 4;
252 InfoReqReXmit
.Mrc
= 64;
253 InfoReqReXmit
.Mrt
= 60;
254 InfoReqReXmit
.Mrd
= 0;
256 if (IpSb
->LinkLocalOk
) {
257 Status
= Dhcp6
->InfoRequest (
264 Instance
->Dhcp6Event
,
265 Ip6ConfigOnDhcp6Reply
,
269 IpSb
->Dhcp6NeedInfoRequest
= TRUE
;
278 Signal the registered event. It is the callback routine for NetMapIterate.
280 @param[in] Map Points to the list of registered event.
281 @param[in] Item The registered event.
282 @param[in] Arg Not used.
287 Ip6ConfigSignalEvent (
289 IN NET_MAP_ITEM
*Item
,
293 gBS
->SignalEvent ((EFI_EVENT
) Item
->Key
);
299 Read the configuration data from variable storage according to the VarName and
300 gEfiIp6ConfigProtocolGuid. It checks the integrity of variable data. If the
301 data is corrupted, it clears the variable data to ZERO. Othewise, it outputs the
302 configuration data to IP6_CONFIG_INSTANCE.
304 @param[in] VarName The pointer to the variable name
305 @param[in, out] Instance The pointer to the IP6 config instance data.
307 @retval EFI_NOT_FOUND The variable can not be found or already corrupted.
308 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
309 @retval EFI_SUCCESS The configuration data was retrieved successfully.
313 Ip6ConfigReadConfigData (
315 IN OUT IP6_CONFIG_INSTANCE
*Instance
320 IP6_CONFIG_VARIABLE
*Variable
;
321 IP6_CONFIG_DATA_ITEM
*DataItem
;
323 IP6_CONFIG_DATA_RECORD DataRecord
;
327 // Try to read the configuration variable.
330 Status
= gRT
->GetVariable (
332 &gEfiIp6ConfigProtocolGuid
,
338 if (Status
== EFI_BUFFER_TOO_SMALL
) {
340 // Allocate buffer and read the config variable.
342 Variable
= AllocatePool (VarSize
);
343 if (Variable
== NULL
) {
344 return EFI_OUT_OF_RESOURCES
;
347 Status
= gRT
->GetVariable (
349 &gEfiIp6ConfigProtocolGuid
,
354 if (EFI_ERROR (Status
) || (UINT16
) (~NetblockChecksum ((UINT8
*) Variable
, (UINT32
) VarSize
)) != 0) {
356 // GetVariable still error or the variable is corrupted.
357 // Fall back to the default value.
362 // Remove the problematic variable and return EFI_NOT_FOUND, a new
363 // variable will be set again.
367 &gEfiIp6ConfigProtocolGuid
,
368 IP6_CONFIG_VARIABLE_ATTRIBUTE
,
373 return EFI_NOT_FOUND
;
377 // Get the IAID we use.
379 Instance
->IaId
= Variable
->IaId
;
381 for (Index
= 0; Index
< Variable
->DataRecordCount
; Index
++) {
383 CopyMem (&DataRecord
, &Variable
->DataRecord
[Index
], sizeof (DataRecord
));
385 DataItem
= &Instance
->DataItem
[DataRecord
.DataType
];
386 if (DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
) &&
387 (DataItem
->DataSize
!= DataRecord
.DataSize
)
390 // Perhaps a corrupted data record...
395 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
397 // This data item has variable length data.
399 DataItem
->Data
.Ptr
= AllocatePool (DataRecord
.DataSize
);
400 if (DataItem
->Data
.Ptr
== NULL
) {
402 // no memory resource
408 Data
= (CHAR8
*) Variable
+ DataRecord
.Offset
;
409 CopyMem (DataItem
->Data
.Ptr
, Data
, DataRecord
.DataSize
);
411 DataItem
->DataSize
= DataRecord
.DataSize
;
412 DataItem
->Status
= EFI_SUCCESS
;
423 Write the configuration data from IP6_CONFIG_INSTANCE to variable storage.
425 @param[in] VarName The pointer to the variable name.
426 @param[in] Instance The pointer to the IP6 configuration instance data.
428 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
429 @retval EFI_SUCCESS The configuration data is written successfully.
433 Ip6ConfigWriteConfigData (
435 IN IP6_CONFIG_INSTANCE
*Instance
440 IP6_CONFIG_DATA_ITEM
*DataItem
;
441 IP6_CONFIG_VARIABLE
*Variable
;
442 IP6_CONFIG_DATA_RECORD
*DataRecord
;
446 VarSize
= sizeof (IP6_CONFIG_VARIABLE
) - sizeof (IP6_CONFIG_DATA_RECORD
);
448 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
450 DataItem
= &Instance
->DataItem
[Index
];
451 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
453 VarSize
+= sizeof (IP6_CONFIG_DATA_RECORD
) + DataItem
->DataSize
;
457 Variable
= AllocatePool (VarSize
);
458 if (Variable
== NULL
) {
459 return EFI_OUT_OF_RESOURCES
;
462 Variable
->IaId
= Instance
->IaId
;
463 Heap
= (CHAR8
*) Variable
+ VarSize
;
464 Variable
->DataRecordCount
= 0;
466 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
468 DataItem
= &Instance
->DataItem
[Index
];
469 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_VOLATILE
) && !EFI_ERROR (DataItem
->Status
)) {
471 Heap
-= DataItem
->DataSize
;
472 CopyMem (Heap
, DataItem
->Data
.Ptr
, DataItem
->DataSize
);
474 DataRecord
= &Variable
->DataRecord
[Variable
->DataRecordCount
];
475 DataRecord
->DataType
= (EFI_IP6_CONFIG_DATA_TYPE
) Index
;
476 DataRecord
->DataSize
= DataItem
->DataSize
;
477 DataRecord
->Offset
= (UINT16
) (Heap
- (CHAR8
*) Variable
);
479 Variable
->DataRecordCount
++;
483 Variable
->Checksum
= 0;
484 Variable
->Checksum
= (UINT16
) ~NetblockChecksum ((UINT8
*) Variable
, (UINT32
) VarSize
);
486 Status
= gRT
->SetVariable (
488 &gEfiIp6ConfigProtocolGuid
,
489 IP6_CONFIG_VARIABLE_ATTRIBUTE
,
500 The work function for EfiIp6ConfigGetData() to get the interface information
501 of the communication device this IP6Config instance manages.
503 @param[in] Instance Pointer to the IP6 config instance data.
504 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in
505 bytes, the size of buffer required to store the specified
507 @param[in] Data The data buffer in which the configuration data is returned.
508 Ignored if DataSize is ZERO.
510 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified
511 configuration data, and the required size is
512 returned in DataSize.
513 @retval EFI_SUCCESS The specified configuration data was obtained.
518 IN IP6_CONFIG_INSTANCE
*Instance
,
519 IN OUT UINTN
*DataSize
,
520 IN VOID
*Data OPTIONAL
525 IP6_CONFIG_DATA_ITEM
*Item
;
526 EFI_IP6_CONFIG_INTERFACE_INFO
*IfInfo
;
530 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
531 Length
= sizeof (EFI_IP6_CONFIG_INTERFACE_INFO
);
534 // Calculate the required length, add the buffer size for AddressInfo and
537 Ip6BuildEfiAddressList (IpSb
, &AddressCount
, NULL
);
538 Ip6BuildEfiRouteTable (IpSb
->RouteTable
, &RouteCount
, NULL
);
540 Length
+= AddressCount
* sizeof (EFI_IP6_ADDRESS_INFO
) + RouteCount
* sizeof (EFI_IP6_ROUTE_TABLE
);
542 if (*DataSize
< Length
) {
544 return EFI_BUFFER_TOO_SMALL
;
548 // Copy the fixed size part of the interface info.
550 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeInterfaceInfo
];
551 IfInfo
= (EFI_IP6_CONFIG_INTERFACE_INFO
*) Data
;
552 CopyMem (IfInfo
, Item
->Data
.Ptr
, sizeof (EFI_IP6_CONFIG_INTERFACE_INFO
));
557 IfInfo
->AddressInfo
= (EFI_IP6_ADDRESS_INFO
*) (IfInfo
+ 1);
558 Ip6BuildEfiAddressList (IpSb
, &IfInfo
->AddressInfoCount
, &IfInfo
->AddressInfo
);
563 IfInfo
->RouteTable
= (EFI_IP6_ROUTE_TABLE
*) (IfInfo
->AddressInfo
+ IfInfo
->AddressInfoCount
);
564 Ip6BuildEfiRouteTable (IpSb
->RouteTable
, &IfInfo
->RouteCount
, &IfInfo
->RouteTable
);
566 if (IfInfo
->AddressInfoCount
== 0) {
567 IfInfo
->AddressInfo
= NULL
;
570 if (IfInfo
->RouteCount
== 0) {
571 IfInfo
->RouteTable
= NULL
;
578 The work function for EfiIp6ConfigSetData() to set the alternative inteface ID
579 for the communication device managed by this IP6Config instance, if the link local
580 IPv6 addresses generated from the interface ID based on the default source the
581 EFI IPv6 Protocol uses is a duplicate address.
583 @param[in] Instance Pointer to the IP6 configuration instance data.
584 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
585 @param[in] Data The data buffer to set.
587 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type,
589 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
590 network stack was set.
594 Ip6ConfigSetAltIfId (
595 IN IP6_CONFIG_INSTANCE
*Instance
,
600 EFI_IP6_CONFIG_INTERFACE_ID
*OldIfId
;
601 EFI_IP6_CONFIG_INTERFACE_ID
*NewIfId
;
602 IP6_CONFIG_DATA_ITEM
*DataItem
;
604 if (DataSize
!= sizeof (EFI_IP6_CONFIG_INTERFACE_ID
)) {
605 return EFI_BAD_BUFFER_SIZE
;
608 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeAltInterfaceId
];
609 OldIfId
= DataItem
->Data
.AltIfId
;
610 NewIfId
= (EFI_IP6_CONFIG_INTERFACE_ID
*) Data
;
612 CopyMem (OldIfId
, NewIfId
, DataSize
);
613 DataItem
->Status
= EFI_SUCCESS
;
619 The work function for EfiIp6ConfigSetData() to set the general configuration
620 policy for the EFI IPv6 network stack that is running on the communication device
621 managed by this IP6Config instance. The policy will affect other configuration settings.
623 @param[in] Instance Pointer to the IP6 config instance data.
624 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
625 @param[in] Data The data buffer to set.
627 @retval EFI_INVALID_PARAMETER The to be set policy is invalid.
628 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
629 @retval EFI_ABORTED The new policy equals the current policy.
630 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
631 network stack was set.
636 IN IP6_CONFIG_INSTANCE
*Instance
,
641 EFI_IP6_CONFIG_POLICY NewPolicy
;
642 IP6_CONFIG_DATA_ITEM
*DataItem
;
645 if (DataSize
!= sizeof (EFI_IP6_CONFIG_POLICY
)) {
646 return EFI_BAD_BUFFER_SIZE
;
649 NewPolicy
= *((EFI_IP6_CONFIG_POLICY
*) Data
);
651 if (NewPolicy
> Ip6ConfigPolicyAutomatic
) {
652 return EFI_INVALID_PARAMETER
;
655 if (NewPolicy
== Instance
->Policy
) {
660 if (NewPolicy
== Ip6ConfigPolicyAutomatic
) {
662 // Clean the ManualAddress, Gateway and DnsServers, shrink the variable
663 // data size, and fire up all the related events.
665 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
666 if (DataItem
->Data
.Ptr
!= NULL
) {
667 FreePool (DataItem
->Data
.Ptr
);
669 DataItem
->Data
.Ptr
= NULL
;
670 DataItem
->DataSize
= 0;
671 DataItem
->Status
= EFI_NOT_FOUND
;
672 NetMapIterate (&DataItem
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
674 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeGateway
];
675 if (DataItem
->Data
.Ptr
!= NULL
) {
676 FreePool (DataItem
->Data
.Ptr
);
678 DataItem
->Data
.Ptr
= NULL
;
679 DataItem
->DataSize
= 0;
680 DataItem
->Status
= EFI_NOT_FOUND
;
681 NetMapIterate (&DataItem
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
683 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
684 DataItem
->Data
.Ptr
= NULL
;
685 DataItem
->DataSize
= 0;
686 DataItem
->Status
= EFI_NOT_FOUND
;
687 NetMapIterate (&DataItem
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
690 // The policy is changed from automatic to manual. Stop the DHCPv6 process
691 // and destroy the DHCPv6 child.
693 if (Instance
->Dhcp6Handle
!= NULL
) {
694 Ip6ConfigDestroyDhcp6 (Instance
);
698 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
699 Ip6ConfigOnPolicyChanged (IpSb
, NewPolicy
);
701 Instance
->Policy
= NewPolicy
;
708 The work function for EfiIp6ConfigSetData() to set the number of consecutive
709 Neighbor Solicitation messages sent while performing Duplicate Address Detection
710 on a tentative address. A value of ZERO indicates that Duplicate Address Detection
711 will not be performed on a tentative address.
713 @param[in] Instance The Instance Pointer to the IP6 config instance data.
714 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
715 @param[in] Data The data buffer to set.
717 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
718 @retval EFI_ABORTED The new transmit count equals the current configuration.
719 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
720 network stack was set.
724 Ip6ConfigSetDadXmits (
725 IN IP6_CONFIG_INSTANCE
*Instance
,
730 EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS
*OldDadXmits
;
732 if (DataSize
!= sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS
)) {
733 return EFI_BAD_BUFFER_SIZE
;
736 OldDadXmits
= Instance
->DataItem
[Ip6ConfigDataTypeDupAddrDetectTransmits
].Data
.DadXmits
;
738 if ((*(UINT32
*) Data
) == OldDadXmits
->DupAddrDetectTransmits
) {
743 OldDadXmits
->DupAddrDetectTransmits
= *((UINT32
*) Data
);
749 The callback function for Ip6SetAddr. The prototype is defined
750 as IP6_DAD_CALLBACK. It is called after Duplicate Address Detection is performed
751 for the manual address set by Ip6ConfigSetMaunualAddress.
753 @param[in] IsDadPassed If TRUE, Duplicate Address Detection passed.
754 @param[in] TargetAddress The tentative IPv6 address to be checked.
755 @param[in] Context Pointer to the IP6 configuration instance data.
759 Ip6ManualAddrDadCallback (
760 IN BOOLEAN IsDadPassed
,
761 IN EFI_IPv6_ADDRESS
*TargetAddress
,
765 IP6_CONFIG_INSTANCE
*Instance
;
767 IP6_CONFIG_DATA_ITEM
*Item
;
768 EFI_IP6_CONFIG_MANUAL_ADDRESS
*ManualAddr
;
769 EFI_IP6_CONFIG_MANUAL_ADDRESS
*PassedAddr
;
774 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
775 NET_CHECK_SIGNATURE (Instance
, IP6_CONFIG_INSTANCE_SIGNATURE
);
776 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
779 for (Index
= 0; Index
< Item
->DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
); Index
++) {
781 // Find the original tag used to place into the NET_MAP.
783 ManualAddr
= Item
->Data
.ManualAddress
+ Index
;
784 if (EFI_IP6_EQUAL (TargetAddress
, &ManualAddr
->Address
)) {
789 ASSERT (Index
!= Item
->DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
));
792 NetMapInsertTail (&Instance
->DadPassedMap
, ManualAddr
, NULL
);
794 NetMapInsertTail (&Instance
->DadFailedMap
, ManualAddr
, NULL
);
797 DadPassCount
= NetMapGetCount (&Instance
->DadPassedMap
);
798 DadFailCount
= NetMapGetCount (&Instance
->DadFailedMap
);
800 if ((DadPassCount
+ DadFailCount
) == (Item
->DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
))) {
802 // All addresses have finished the configuration process.
804 if (DadFailCount
!= 0) {
806 // There is at least one duplicate address.
808 FreePool (Item
->Data
.Ptr
);
810 Item
->DataSize
= DadPassCount
* sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
);
811 if (Item
->DataSize
== 0) {
813 // All failed, bad luck.
815 Item
->Data
.Ptr
= NULL
;
816 Item
->Status
= EFI_NOT_FOUND
;
819 // Part of addresses are detected to be duplicates, so update the
820 // data with those passed.
822 PassedAddr
= (EFI_IP6_CONFIG_MANUAL_ADDRESS
*) AllocatePool (Item
->DataSize
);
823 ASSERT (PassedAddr
!= NULL
);
825 Item
->Data
.Ptr
= PassedAddr
;
826 Item
->Status
= EFI_SUCCESS
;
828 while (!NetMapIsEmpty (&Instance
->DadPassedMap
)) {
829 ManualAddr
= (EFI_IP6_CONFIG_MANUAL_ADDRESS
*) NetMapRemoveHead (&Instance
->DadPassedMap
, NULL
);
830 CopyMem (PassedAddr
, ManualAddr
, sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
));
835 ASSERT ((UINTN
) PassedAddr
- (UINTN
) Item
->Data
.Ptr
== Item
->DataSize
);
839 // All addresses are valid.
841 Item
->Status
= EFI_SUCCESS
;
845 // Remove the tags we put in the NET_MAPs.
847 while (!NetMapIsEmpty (&Instance
->DadFailedMap
)) {
848 NetMapRemoveHead (&Instance
->DadFailedMap
, NULL
);
851 while (!NetMapIsEmpty (&Instance
->DadPassedMap
)) {
852 NetMapRemoveHead (&Instance
->DadPassedMap
, NULL
);
856 // Signal the waiting events.
858 NetMapIterate (&Item
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
859 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
860 Ip6ConfigWriteConfigData (IpSb
->MacString
, Instance
);
865 The work function for EfiIp6ConfigSetData() to set the station addresses manually
866 for the EFI IPv6 network stack. It is only configurable when the policy is
867 Ip6ConfigPolicyManual.
869 @param[in] Instance Pointer to the IP6 configuration instance data.
870 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
871 @param[in] Data The data buffer to set.
873 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
874 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
875 under the current policy.
876 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
877 @retval EFI_OUT_OF_RESOURCES Fail to allocate resource to complete the operation.
878 @retval EFI_NOT_READY An asynchrous process is invoked to set the specified
879 configuration data, and the process is not finished.
880 @retval EFI_ABORTED The manual addresses to be set equal current
882 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
883 network stack was set.
887 Ip6ConfigSetMaunualAddress (
888 IN IP6_CONFIG_INSTANCE
*Instance
,
893 EFI_IP6_CONFIG_MANUAL_ADDRESS
*NewAddress
;
894 EFI_IP6_CONFIG_MANUAL_ADDRESS
*TmpAddress
;
895 IP6_CONFIG_DATA_ITEM
*DataItem
;
896 UINTN NewAddressCount
;
900 IP6_ADDRESS_INFO
*CurrentAddrInfo
;
901 IP6_ADDRESS_INFO
*Copy
;
902 LIST_ENTRY CurrentSourceList
;
903 UINT32 CurrentSourceCount
;
907 IP6_PREFIX_LIST_ENTRY
*PrefixEntry
;
911 ASSERT (Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
].Status
!= EFI_NOT_READY
);
913 if (((DataSize
% sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
)) != 0) || (DataSize
== 0)) {
914 return EFI_BAD_BUFFER_SIZE
;
917 if (Instance
->Policy
!= Ip6ConfigPolicyManual
) {
918 return EFI_WRITE_PROTECTED
;
921 NewAddressCount
= DataSize
/ sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS
);
922 NewAddress
= (EFI_IP6_CONFIG_MANUAL_ADDRESS
*) Data
;
924 for (Index1
= 0; Index1
< NewAddressCount
; Index1
++, NewAddress
++) {
926 if (NetIp6IsLinkLocalAddr (&NewAddress
->Address
) ||
927 !NetIp6IsValidUnicast (&NewAddress
->Address
) ||
928 (NewAddress
->PrefixLength
> 128)
931 // make sure the IPv6 address is unicast and not link-local address &&
932 // the prefix length is valid.
934 return EFI_INVALID_PARAMETER
;
937 TmpAddress
= NewAddress
+ 1;
938 for (Index2
= Index1
+ 1; Index2
< NewAddressCount
; Index2
++, TmpAddress
++) {
940 // Any two addresses in the array can't be equal.
942 if (EFI_IP6_EQUAL (&TmpAddress
->Address
, &NewAddress
->Address
)) {
944 return EFI_INVALID_PARAMETER
;
949 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
952 // Build the current source address list.
954 InitializeListHead (&CurrentSourceList
);
955 CurrentSourceCount
= 0;
957 NET_LIST_FOR_EACH (Entry
, &IpSb
->Interfaces
) {
958 IpIf
= NET_LIST_USER_STRUCT_S (Entry
, IP6_INTERFACE
, Link
, IP6_INTERFACE_SIGNATURE
);
960 NET_LIST_FOR_EACH (Entry2
, &IpIf
->AddressList
) {
961 CurrentAddrInfo
= NET_LIST_USER_STRUCT_S (Entry2
, IP6_ADDRESS_INFO
, Link
, IP6_ADDR_INFO_SIGNATURE
);
963 Copy
= AllocateCopyPool (sizeof (IP6_ADDRESS_INFO
), CurrentAddrInfo
);
968 InsertTailList (&CurrentSourceList
, &Copy
->Link
);
969 CurrentSourceCount
++;
974 // Update the value... a long journey starts
976 NewAddress
= AllocateCopyPool (DataSize
, Data
);
977 if (NewAddress
== NULL
) {
978 Ip6RemoveAddr (NULL
, &CurrentSourceList
, &CurrentSourceCount
, NULL
, 0);
980 return EFI_OUT_OF_RESOURCES
;
984 // Store the new data, and init the DataItem status to EFI_NOT_READY because
985 // we may have an asynchronous configuration process.
987 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
988 if (DataItem
->Data
.Ptr
!= NULL
) {
989 FreePool (DataItem
->Data
.Ptr
);
991 DataItem
->Data
.Ptr
= NewAddress
;
992 DataItem
->DataSize
= DataSize
;
993 DataItem
->Status
= EFI_NOT_READY
;
996 // Trigger DAD, it's an asynchronous process.
1000 for (Index1
= 0; Index1
< NewAddressCount
; Index1
++, NewAddress
++) {
1001 if (Ip6IsOneOfSetAddress (IpSb
, &NewAddress
->Address
, NULL
, &CurrentAddrInfo
)) {
1002 ASSERT (CurrentAddrInfo
!= NULL
);
1004 // Remove this already existing source address from the CurrentSourceList
1010 &CurrentSourceCount
,
1011 &CurrentAddrInfo
->Address
,
1016 // This manual address is already in use, see whether prefix length is changed.
1018 if (NewAddress
->PrefixLength
!= CurrentAddrInfo
->PrefixLength
) {
1020 // Remove the on-link prefix table, the route entry will be removed
1023 PrefixEntry
= Ip6FindPrefixListEntry (
1026 CurrentAddrInfo
->PrefixLength
,
1027 &CurrentAddrInfo
->Address
1029 if (PrefixEntry
!= NULL
) {
1030 Ip6DestroyPrefixListEntry (IpSb
, PrefixEntry
, TRUE
, FALSE
);
1034 // Save the prefix length.
1036 CurrentAddrInfo
->PrefixLength
= NewAddress
->PrefixLength
;
1041 // create a new on-link prefix entry.
1043 PrefixEntry
= Ip6FindPrefixListEntry (
1046 NewAddress
->PrefixLength
,
1047 &NewAddress
->Address
1049 if (PrefixEntry
== NULL
) {
1050 Ip6CreatePrefixListEntry (
1053 (UINT32
) IP6_INFINIT_LIFETIME
,
1054 (UINT32
) IP6_INFINIT_LIFETIME
,
1055 NewAddress
->PrefixLength
,
1056 &NewAddress
->Address
1060 CurrentAddrInfo
->IsAnycast
= NewAddress
->IsAnycast
;
1062 // Artificially mark this address passed DAD be'coz it is already in use.
1064 Ip6ManualAddrDadCallback (TRUE
, &NewAddress
->Address
, Instance
);
1072 // Set the new address, this will trigger DAD and activate the address if
1076 IpSb
->DefaultInterface
,
1077 &NewAddress
->Address
,
1078 NewAddress
->IsAnycast
,
1079 NewAddress
->PrefixLength
,
1080 (UINT32
) IP6_INFINIT_LIFETIME
,
1081 (UINT32
) IP6_INFINIT_LIFETIME
,
1082 Ip6ManualAddrDadCallback
,
1089 // Check the CurrentSourceList, it now contains those addresses currently in
1090 // use and will be removed.
1092 IpIf
= IpSb
->DefaultInterface
;
1094 while (!IsListEmpty (&CurrentSourceList
)) {
1097 CurrentAddrInfo
= NET_LIST_HEAD (&CurrentSourceList
, IP6_ADDRESS_INFO
, Link
);
1100 // This local address is going to be removed, the IP instances that are
1101 // currently using it will be destroyed.
1106 &IpIf
->AddressCount
,
1107 &CurrentAddrInfo
->Address
,
1112 // Remove the on-link prefix table, the route entry will be removed
1115 PrefixEntry
= Ip6FindPrefixListEntry (
1118 CurrentAddrInfo
->PrefixLength
,
1119 &CurrentAddrInfo
->Address
1121 if (PrefixEntry
!= NULL
) {
1122 Ip6DestroyPrefixListEntry (IpSb
, PrefixEntry
, TRUE
, FALSE
);
1125 RemoveEntryList (&CurrentAddrInfo
->Link
);
1126 FreePool (CurrentAddrInfo
);
1130 if (DataItem
->Status
== EFI_NOT_READY
) {
1132 // If DAD is disabled on this interface, the configuration process is
1133 // actually synchronous, and the data item's status will be changed to
1134 // the final status before we reach here, just check it.
1136 Status
= EFI_NOT_READY
;
1138 Status
= EFI_SUCCESS
;
1142 // No update is taken, reset the status to success and return EFI_ABORTED.
1144 DataItem
->Status
= EFI_SUCCESS
;
1145 Status
= EFI_ABORTED
;
1152 The work function for EfiIp6ConfigSetData() to set the gateway addresses manually
1153 for the EFI IPv6 network stack that is running on the communication device that
1154 this EFI IPv6 Configuration Protocol manages. It is not configurable when the policy is
1155 Ip6ConfigPolicyAutomatic. The gateway addresses must be unicast IPv6 addresses.
1157 @param[in] Instance The pointer to the IP6 config instance data.
1158 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1159 @param[in] Data The data buffer to set. This points to an array of
1160 EFI_IPv6_ADDRESS instances.
1162 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1163 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1164 under the current policy.
1165 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1166 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to complete the operation.
1167 @retval EFI_ABORTED The manual gateway addresses to be set equal the
1168 current configuration.
1169 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1170 network stack was set.
1174 Ip6ConfigSetGateway (
1175 IN IP6_CONFIG_INSTANCE
*Instance
,
1182 EFI_IPv6_ADDRESS
*OldGateway
;
1183 EFI_IPv6_ADDRESS
*NewGateway
;
1184 UINTN OldGatewayCount
;
1185 UINTN NewGatewayCount
;
1186 IP6_CONFIG_DATA_ITEM
*Item
;
1190 IP6_DEFAULT_ROUTER
*DefaultRouter
;
1193 if ((DataSize
% sizeof (EFI_IPv6_ADDRESS
) != 0) || (DataSize
== 0)) {
1194 return EFI_BAD_BUFFER_SIZE
;
1197 if (Instance
->Policy
!= Ip6ConfigPolicyManual
) {
1198 return EFI_WRITE_PROTECTED
;
1201 NewGateway
= (EFI_IPv6_ADDRESS
*) Data
;
1202 NewGatewayCount
= DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1203 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1205 if (!NetIp6IsValidUnicast (NewGateway
+ Index1
)) {
1207 return EFI_INVALID_PARAMETER
;
1210 for (Index2
= Index1
+ 1; Index2
< NewGatewayCount
; Index2
++) {
1211 if (EFI_IP6_EQUAL (NewGateway
+ Index1
, NewGateway
+ Index2
)) {
1212 return EFI_INVALID_PARAMETER
;
1217 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
1218 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeGateway
];
1219 OldGateway
= Item
->Data
.Gateway
;
1220 OldGatewayCount
= Item
->DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1224 if (NewGatewayCount
!= OldGatewayCount
) {
1225 Tmp
= AllocatePool (DataSize
);
1227 return EFI_OUT_OF_RESOURCES
;
1233 for (Index1
= 0; Index1
< OldGatewayCount
; Index1
++) {
1235 // Find the gateways that are no long in the new setting and remove them.
1237 for (Index2
= 0; Index2
< NewGatewayCount
; Index2
++) {
1238 if (EFI_IP6_EQUAL (OldGateway
+ Index1
, NewGateway
+ Index2
)) {
1244 if (Index2
== NewGatewayCount
) {
1246 // Remove this default router.
1248 DefaultRouter
= Ip6FindDefaultRouter (IpSb
, OldGateway
+ Index1
);
1249 if (DefaultRouter
!= NULL
) {
1250 Ip6DestroyDefaultRouter (IpSb
, DefaultRouter
);
1255 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1257 DefaultRouter
= Ip6FindDefaultRouter (IpSb
, NewGateway
+ Index1
);
1258 if (DefaultRouter
== NULL
) {
1259 Ip6CreateDefaultRouter (IpSb
, NewGateway
+ Index1
, IP6_INF_ROUTER_LIFETIME
);
1264 if (!OneRemoved
&& !OneAdded
) {
1265 Item
->Status
= EFI_SUCCESS
;
1270 if (Item
->Data
.Ptr
!= NULL
) {
1271 FreePool (Item
->Data
.Ptr
);
1273 Item
->Data
.Ptr
= Tmp
;
1276 CopyMem (Item
->Data
.Ptr
, Data
, DataSize
);
1277 Item
->DataSize
= DataSize
;
1278 Item
->Status
= EFI_SUCCESS
;
1284 The work function for EfiIp6ConfigSetData() to set the DNS server list for the
1285 EFI IPv6 network stack running on the communication device that this EFI IPv6
1286 Configuration Protocol manages. It is not configurable when the policy is
1287 Ip6ConfigPolicyAutomatic. The DNS server addresses must be unicast IPv6 addresses.
1289 @param[in] Instance The pointer to the IP6 config instance data.
1290 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1291 @param[in] Data The data buffer to set, points to an array of
1292 EFI_IPv6_ADDRESS instances.
1294 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1295 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1296 under the current policy.
1297 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1298 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
1299 @retval EFI_ABORTED The DNS server addresses to be set equal the current
1301 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1302 network stack was set.
1306 Ip6ConfigSetDnsServer (
1307 IN IP6_CONFIG_INSTANCE
*Instance
,
1315 EFI_IPv6_ADDRESS
*OldDns
;
1316 EFI_IPv6_ADDRESS
*NewDns
;
1319 IP6_CONFIG_DATA_ITEM
*Item
;
1323 if ((DataSize
% sizeof (EFI_IPv6_ADDRESS
) != 0) || (DataSize
== 0)) {
1324 return EFI_BAD_BUFFER_SIZE
;
1327 if (Instance
->Policy
!= Ip6ConfigPolicyManual
) {
1328 return EFI_WRITE_PROTECTED
;
1331 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
1332 NewDns
= (EFI_IPv6_ADDRESS
*) Data
;
1333 OldDns
= Item
->Data
.DnsServers
;
1334 NewDnsCount
= DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1335 OldDnsCount
= Item
->DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1338 if (NewDnsCount
!= OldDnsCount
) {
1339 Tmp
= AllocatePool (DataSize
);
1341 return EFI_OUT_OF_RESOURCES
;
1347 for (NewIndex
= 0; NewIndex
< NewDnsCount
; NewIndex
++) {
1349 if (!NetIp6IsValidUnicast (NewDns
+ NewIndex
)) {
1351 // The dns server address must be unicast.
1354 return EFI_INVALID_PARAMETER
;
1357 for (Index1
= NewIndex
+ 1; Index1
< NewDnsCount
; Index1
++) {
1358 if (EFI_IP6_EQUAL (NewDns
+ NewIndex
, NewDns
+ Index1
)) {
1360 return EFI_INVALID_PARAMETER
;
1366 // If any address in the new setting is not in the old settings, skip the
1367 // comparision below.
1372 for (OldIndex
= 0; OldIndex
< OldDnsCount
; OldIndex
++) {
1373 if (EFI_IP6_EQUAL (NewDns
+ NewIndex
, OldDns
+ OldIndex
)) {
1375 // If found break out.
1381 if (OldIndex
== OldDnsCount
) {
1386 if (!OneAdded
&& (DataSize
== Item
->DataSize
)) {
1388 // No new item is added and the size is the same.
1390 Item
->Status
= EFI_SUCCESS
;
1394 if (Item
->Data
.Ptr
!= NULL
) {
1395 FreePool (Item
->Data
.Ptr
);
1397 Item
->Data
.Ptr
= Tmp
;
1400 CopyMem (Item
->Data
.Ptr
, Data
, DataSize
);
1401 Item
->DataSize
= DataSize
;
1402 Item
->Status
= EFI_SUCCESS
;
1408 Generate the operational state of the interface this IP6 config instance manages
1409 and output in EFI_IP6_CONFIG_INTERFACE_INFO.
1411 @param[in] IpSb The pointer to the IP6 service binding instance.
1412 @param[out] IfInfo The pointer to the IP6 configuration interface information structure.
1416 Ip6ConfigInitIfInfo (
1417 IN IP6_SERVICE
*IpSb
,
1418 OUT EFI_IP6_CONFIG_INTERFACE_INFO
*IfInfo
1421 IfInfo
->Name
[0] = L
'e';
1422 IfInfo
->Name
[1] = L
't';
1423 IfInfo
->Name
[2] = L
'h';
1424 IfInfo
->Name
[3] = (CHAR16
) (L
'0' + IpSb
->Ip6ConfigInstance
.IfIndex
);
1425 IfInfo
->Name
[4] = 0;
1427 IfInfo
->IfType
= IpSb
->SnpMode
.IfType
;
1428 IfInfo
->HwAddressSize
= IpSb
->SnpMode
.HwAddressSize
;
1429 CopyMem (&IfInfo
->HwAddress
, &IpSb
->SnpMode
.CurrentAddress
, IfInfo
->HwAddressSize
);
1433 Parse DHCPv6 reply packet to get the DNS server list.
1434 It is the work function for Ip6ConfigOnDhcp6Reply and Ip6ConfigOnDhcp6Event.
1436 @param[in] Dhcp6 The pointer to the EFI_DHCP6_PROTOCOL instance.
1437 @param[in, out] Instance The pointer to the IP6 configuration instance data.
1438 @param[in] Reply The pointer to the DHCPv6 reply packet.
1440 @retval EFI_SUCCESS The DNS server address was retrieved from the reply packet.
1441 @retval EFI_NOT_READY The reply packet does not contain the DNS server option, or
1442 the DNS server address is not valid.
1446 Ip6ConfigParseDhcpReply (
1447 IN EFI_DHCP6_PROTOCOL
*Dhcp6
,
1448 IN OUT IP6_CONFIG_INSTANCE
*Instance
,
1449 IN EFI_DHCP6_PACKET
*Reply
1454 EFI_DHCP6_PACKET_OPTION
**OptList
;
1459 EFI_IPv6_ADDRESS
*DnsServer
;
1460 IP6_CONFIG_DATA_ITEM
*Item
;
1463 // A DHCPv6 reply packet is received as the response to our InfoRequest
1467 Status
= Dhcp6
->Parse (Dhcp6
, Reply
, &OptCount
, NULL
);
1468 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1469 return EFI_NOT_READY
;
1472 OptList
= AllocatePool (OptCount
* sizeof (EFI_DHCP6_PACKET_OPTION
*));
1473 if (OptList
== NULL
) {
1474 return EFI_NOT_READY
;
1477 Status
= Dhcp6
->Parse (Dhcp6
, Reply
, &OptCount
, OptList
);
1478 if (EFI_ERROR (Status
)) {
1479 Status
= EFI_NOT_READY
;
1483 Status
= EFI_SUCCESS
;
1485 for (Index
= 0; Index
< OptCount
; Index
++) {
1487 // Go through all the options to check the ones we are interested in.
1488 // The OpCode and Length are in network byte-order and may not be naturally
1491 CopyMem (&OpCode
, &OptList
[Index
]->OpCode
, sizeof (OpCode
));
1492 OpCode
= NTOHS (OpCode
);
1494 if (OpCode
== IP6_CONFIG_DHCP6_OPTION_DNS_SERVERS
) {
1495 CopyMem (&Length
, &OptList
[Index
]->OpLen
, sizeof (Length
));
1496 Length
= NTOHS (Length
);
1498 if ((Length
== 0) || ((Length
% sizeof (EFI_IPv6_ADDRESS
)) != 0)) {
1500 // The length should be a multiple of 16 bytes.
1502 Status
= EFI_NOT_READY
;
1507 // Validate the DnsServers: whether they are unicast addresses.
1509 DnsServer
= (EFI_IPv6_ADDRESS
*) OptList
[Index
]->Data
;
1510 for (Index2
= 0; Index2
< Length
/ sizeof (EFI_IPv6_ADDRESS
); Index2
++) {
1511 if (!NetIp6IsValidUnicast (DnsServer
)) {
1512 Status
= EFI_NOT_READY
;
1519 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
1521 if (Item
->DataSize
!= Length
) {
1522 if (Item
->Data
.Ptr
!= NULL
) {
1523 FreePool (Item
->Data
.Ptr
);
1526 Item
->Data
.Ptr
= AllocatePool (Length
);
1527 ASSERT (Item
->Data
.Ptr
!= NULL
);
1530 CopyMem (Item
->Data
.Ptr
, OptList
[Index
]->Data
, Length
);
1531 Item
->DataSize
= Length
;
1532 Item
->Status
= EFI_SUCCESS
;
1535 // Signal the waiting events.
1537 NetMapIterate (&Item
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
1550 The callback function for Ip6SetAddr. The prototype is defined
1551 as IP6_DAD_CALLBACK. It is called after Duplicate Address Detection is performed
1552 on the tentative address by DHCPv6 in Ip6ConfigOnDhcp6Event().
1554 @param[in] IsDadPassed If TRUE, Duplicate Address Detection passes.
1555 @param[in] TargetAddress The tentative IPv6 address to be checked.
1556 @param[in] Context Pointer to the IP6 configuration instance data.
1560 Ip6ConfigSetStatefulAddrCallback (
1561 IN BOOLEAN IsDadPassed
,
1562 IN EFI_IPv6_ADDRESS
*TargetAddress
,
1566 IP6_CONFIG_INSTANCE
*Instance
;
1568 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
1569 NET_CHECK_SIGNATURE (Instance
, IP6_CONFIG_INSTANCE_SIGNATURE
);
1572 // We should record the addresses that fail the DAD, and DECLINE them.
1576 // Decrease the count, no interests in those passed DAD.
1578 if (Instance
->FailedIaAddressCount
> 0 ) {
1579 Instance
->FailedIaAddressCount
--;
1585 IP6_COPY_ADDRESS (Instance
->DeclineAddress
+ Instance
->DeclineAddressCount
, TargetAddress
);
1586 Instance
->DeclineAddressCount
++;
1589 if (Instance
->FailedIaAddressCount
== Instance
->DeclineAddressCount
) {
1591 // The checking on all addresses are finished.
1593 if (Instance
->DeclineAddressCount
!= 0) {
1595 // Decline those duplicates.
1597 Instance
->Dhcp6
->Decline (
1599 Instance
->DeclineAddressCount
,
1600 Instance
->DeclineAddress
1604 if (Instance
->DeclineAddress
!= NULL
) {
1605 FreePool (Instance
->DeclineAddress
);
1607 Instance
->DeclineAddress
= NULL
;
1608 Instance
->DeclineAddressCount
= 0;
1613 The event handle routine when DHCPv6 process is finished or is updated.
1615 @param[in] Event Not used.
1616 @param[in] Context The pointer to the IP6 configuration instance data.
1621 Ip6ConfigOnDhcp6Event (
1626 IP6_CONFIG_INSTANCE
*Instance
;
1627 EFI_DHCP6_PROTOCOL
*Dhcp6
;
1629 EFI_DHCP6_MODE_DATA Dhcp6ModeData
;
1631 EFI_DHCP6_IA_ADDRESS
*IaAddr
;
1634 IP6_ADDRESS_INFO
*AddrInfo
;
1635 IP6_INTERFACE
*IpIf
;
1637 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
1639 if ((Instance
->Policy
!= Ip6ConfigPolicyAutomatic
) || Instance
->OtherInfoOnly
) {
1641 // IPv6 is not operating in the automatic policy now or
1642 // the DHCPv6 information request message exchange is aborted.
1648 // The stateful address autoconfiguration is done or updated.
1650 Dhcp6
= Instance
->Dhcp6
;
1652 Status
= Dhcp6
->GetModeData (Dhcp6
, &Dhcp6ModeData
, NULL
);
1653 if (EFI_ERROR (Status
)) {
1657 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
1658 IpIf
= IpSb
->DefaultInterface
;
1659 Ia
= Dhcp6ModeData
.Ia
;
1660 IaAddr
= Ia
->IaAddress
;
1662 if (Instance
->DeclineAddress
!= NULL
) {
1663 FreePool (Instance
->DeclineAddress
);
1666 Instance
->DeclineAddress
= (EFI_IPv6_ADDRESS
*) AllocatePool (Ia
->IaAddressCount
* sizeof (EFI_IPv6_ADDRESS
));
1667 if (Instance
->DeclineAddress
== NULL
) {
1671 Instance
->FailedIaAddressCount
= Ia
->IaAddressCount
;
1672 Instance
->DeclineAddressCount
= 0;
1674 for (Index
= 0; Index
< Ia
->IaAddressCount
; Index
++, IaAddr
++) {
1675 if (Ia
->IaAddress
[Index
].ValidLifetime
!= 0 && Ia
->State
== Dhcp6Bound
) {
1677 // Set this address, either it's a new address or with updated lifetimes.
1678 // An appropriate prefix length will be set.
1685 IaAddr
->ValidLifetime
,
1686 IaAddr
->PreferredLifetime
,
1687 Ip6ConfigSetStatefulAddrCallback
,
1692 // discard this address, artificially decrease the count as if this address
1695 if (Ip6IsOneOfSetAddress (IpSb
, &IaAddr
->IpAddress
, NULL
, &AddrInfo
)) {
1696 ASSERT (AddrInfo
!= NULL
);
1700 &IpIf
->AddressCount
,
1702 AddrInfo
->PrefixLength
1706 if (Instance
->FailedIaAddressCount
> 0) {
1707 Instance
->FailedIaAddressCount
--;
1713 // Parse the Reply packet to get the options we need.
1715 if (Dhcp6ModeData
.Ia
->ReplyPacket
!= NULL
) {
1716 Ip6ConfigParseDhcpReply (Dhcp6
, Instance
, Dhcp6ModeData
.Ia
->ReplyPacket
);
1721 FreePool (Dhcp6ModeData
.ClientId
);
1722 FreePool (Dhcp6ModeData
.Ia
);
1726 The event process routine when the DHCPv6 server is answered with a reply packet
1727 for an information request.
1729 @param[in] This Points to the EFI_DHCP6_PROTOCOL.
1730 @param[in] Context The pointer to the IP6 configuration instance data.
1731 @param[in] Packet The DHCPv6 reply packet.
1733 @retval EFI_SUCCESS The DNS server address was retrieved from the reply packet.
1734 @retval EFI_NOT_READY The reply packet does not contain the DNS server option, or
1735 the DNS server address is not valid.
1740 Ip6ConfigOnDhcp6Reply (
1741 IN EFI_DHCP6_PROTOCOL
*This
,
1743 IN EFI_DHCP6_PACKET
*Packet
1746 return Ip6ConfigParseDhcpReply (This
, (IP6_CONFIG_INSTANCE
*) Context
, Packet
);
1750 The event process routine when the DHCPv6 service binding protocol is installed
1753 @param[in] Event Not used.
1754 @param[in] Context The pointer to the IP6 config instance data.
1759 Ip6ConfigOnDhcp6SbInstalled (
1764 IP6_CONFIG_INSTANCE
*Instance
;
1766 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
1768 if ((Instance
->Dhcp6Handle
!= NULL
) || (Instance
->Policy
!= Ip6ConfigPolicyAutomatic
)) {
1770 // The DHCP6 child is already created or the policy is no longer AUTOMATIC.
1775 Ip6ConfigStartStatefulAutoConfig (Instance
, Instance
->OtherInfoOnly
);
1779 Set the configuration for the EFI IPv6 network stack running on the communication
1780 device this EFI IPv6 Configuration Protocol instance manages.
1782 This function is used to set the configuration data of type DataType for the EFI
1783 IPv6 network stack that is running on the communication device that this EFI IPv6
1784 Configuration Protocol instance manages.
1786 DataSize is used to calculate the count of structure instances in the Data for
1787 a DataType in which multiple structure instances are allowed.
1789 This function is always non-blocking. When setting some type of configuration data,
1790 an asynchronous process is invoked to check the correctness of the data, such as
1791 performing Duplicate Address Detection on the manually set local IPv6 addresses.
1792 EFI_NOT_READY is returned immediately to indicate that such an asynchronous process
1793 is invoked, and the process is not finished yet. The caller wanting to get the result
1794 of the asynchronous process is required to call RegisterDataNotify() to register an
1795 event on the specified configuration data. Once the event is signaled, the caller
1796 can call GetData() to obtain the configuration data and know the result.
1797 For other types of configuration data that do not require an asynchronous configuration
1798 process, the result of the operation is immediately returned.
1800 @param[in] This The pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
1801 @param[in] DataType The type of data to set.
1802 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1803 @param[in] Data The data buffer to set. The type of the data buffer is
1804 associated with the DataType.
1806 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1807 network stack was set successfully.
1808 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
1811 - One or more fields in Data do not match the requirement of the
1812 data type indicated by DataType.
1813 @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified
1814 configuration data cannot be set under the current policy.
1815 @retval EFI_ACCESS_DENIED Another set operation on the specified configuration
1816 data is already in process.
1817 @retval EFI_NOT_READY An asynchronous process was invoked to set the specified
1818 configuration data, and the process is not finished yet.
1819 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type
1820 indicated by DataType.
1821 @retval EFI_UNSUPPORTED This DataType is not supported.
1822 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1823 @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
1828 EfiIp6ConfigSetData (
1829 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
1830 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
1837 IP6_CONFIG_INSTANCE
*Instance
;
1840 if ((This
== NULL
) || (Data
== NULL
)) {
1841 return EFI_INVALID_PARAMETER
;
1844 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
1845 return EFI_UNSUPPORTED
;
1848 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
1849 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
1850 NET_CHECK_SIGNATURE (IpSb
, IP6_SERVICE_SIGNATURE
);
1852 if (IpSb
->LinkLocalDadFail
) {
1853 return EFI_DEVICE_ERROR
;
1856 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1858 Status
= Instance
->DataItem
[DataType
].Status
;
1859 if (Status
!= EFI_NOT_READY
) {
1861 if (Instance
->DataItem
[DataType
].SetData
== NULL
) {
1863 // This type of data is readonly.
1865 Status
= EFI_WRITE_PROTECTED
;
1868 Status
= Instance
->DataItem
[DataType
].SetData (Instance
, DataSize
, Data
);
1869 if (!EFI_ERROR (Status
)) {
1871 // Fire up the events registered with this type of data.
1873 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip6ConfigSignalEvent
, NULL
);
1874 Ip6ConfigWriteConfigData (IpSb
->MacString
, Instance
);
1875 } else if (Status
== EFI_ABORTED
) {
1877 // The SetData is aborted because the data to set is the same with
1878 // the one maintained.
1880 Status
= EFI_SUCCESS
;
1881 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip6ConfigSignalEvent
, NULL
);
1886 // Another asynchornous process is on the way.
1888 Status
= EFI_ACCESS_DENIED
;
1891 gBS
->RestoreTPL (OldTpl
);
1897 Get the configuration data for the EFI IPv6 network stack running on the communication
1898 device that this EFI IPv6 Configuration Protocol instance manages.
1900 This function returns the configuration data of type DataType for the EFI IPv6 network
1901 stack running on the communication device that this EFI IPv6 Configuration Protocol instance
1904 The caller is responsible for allocating the buffer used to return the specified
1905 configuration data. The required size will be returned to the caller if the size of
1906 the buffer is too small.
1908 EFI_NOT_READY is returned if the specified configuration data is not ready due to an
1909 asynchronous configuration process already in progress. The caller can call RegisterDataNotify()
1910 to register an event on the specified configuration data. Once the asynchronous configuration
1911 process is finished, the event will be signaled, and a subsequent GetData() call will return
1912 the specified configuration data.
1914 @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
1915 @param[in] DataType The type of data to get.
1916 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in bytes, the
1917 size of buffer required to store the specified configuration data.
1918 @param[in] Data The data buffer in which the configuration data is returned. The
1919 type of the data buffer is associated with the DataType.
1920 This is an optional parameter that may be NULL.
1922 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
1923 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
1926 - Data is NULL if *DataSize is not zero.
1927 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data,
1928 and the required size is returned in DataSize.
1929 @retval EFI_NOT_READY The specified configuration data is not ready due to an
1930 asynchronous configuration process already in progress.
1931 @retval EFI_NOT_FOUND The specified configuration data is not found.
1936 EfiIp6ConfigGetData (
1937 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
1938 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
1939 IN OUT UINTN
*DataSize
,
1940 IN VOID
*Data OPTIONAL
1945 IP6_CONFIG_INSTANCE
*Instance
;
1946 IP6_CONFIG_DATA_ITEM
*DataItem
;
1948 if ((This
== NULL
) || (DataSize
== NULL
) || ((*DataSize
!= 0) && (Data
== NULL
))) {
1949 return EFI_INVALID_PARAMETER
;
1952 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
1953 return EFI_NOT_FOUND
;
1956 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1958 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
1959 DataItem
= &Instance
->DataItem
[DataType
];
1961 Status
= Instance
->DataItem
[DataType
].Status
;
1962 if (!EFI_ERROR (Status
)) {
1964 if (DataItem
->GetData
!= NULL
) {
1966 Status
= DataItem
->GetData (Instance
, DataSize
, Data
);
1967 } else if (*DataSize
< Instance
->DataItem
[DataType
].DataSize
) {
1969 // Update the buffer length.
1971 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
1972 Status
= EFI_BUFFER_TOO_SMALL
;
1975 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
1976 CopyMem (Data
, Instance
->DataItem
[DataType
].Data
.Ptr
, *DataSize
);
1980 gBS
->RestoreTPL (OldTpl
);
1986 Register an event that is signaled whenever a configuration process on the specified
1987 configuration data is done.
1989 This function registers an event that is to be signaled whenever a configuration
1990 process on the specified configuration data is performed. An event can be registered
1991 for a different DataType simultaneously. The caller is responsible for determining
1992 which type of configuration data causes the signaling of the event in such an event.
1994 @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
1995 @param[in] DataType The type of data to unregister the event for.
1996 @param[in] Event The event to register.
1998 @retval EFI_SUCCESS The notification event for the specified configuration data is
2000 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
2001 @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not
2003 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
2004 @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
2009 EfiIp6ConfigRegisterDataNotify (
2010 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
2011 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
2017 IP6_CONFIG_INSTANCE
*Instance
;
2021 if ((This
== NULL
) || (Event
== NULL
)) {
2022 return EFI_INVALID_PARAMETER
;
2025 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
2026 return EFI_UNSUPPORTED
;
2029 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2031 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
2032 EventMap
= &Instance
->DataItem
[DataType
].EventMap
;
2035 // Check whether this event is already registered for this DataType.
2037 Item
= NetMapFindKey (EventMap
, Event
);
2040 Status
= NetMapInsertTail (EventMap
, Event
, NULL
);
2042 if (EFI_ERROR (Status
)) {
2044 Status
= EFI_OUT_OF_RESOURCES
;
2049 Status
= EFI_ACCESS_DENIED
;
2052 gBS
->RestoreTPL (OldTpl
);
2058 Remove a previously registered event for the specified configuration data.
2060 @param This The pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
2061 @param DataType The type of data to remove from the previously
2063 @param Event The event to be unregistered.
2065 @retval EFI_SUCCESS The event registered for the specified
2066 configuration data was removed.
2067 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
2068 @retval EFI_NOT_FOUND The Event has not been registered for the
2074 EfiIp6ConfigUnregisterDataNotify (
2075 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
2076 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
2082 IP6_CONFIG_INSTANCE
*Instance
;
2085 if ((This
== NULL
) || (Event
== NULL
)) {
2086 return EFI_INVALID_PARAMETER
;
2089 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
2090 return EFI_NOT_FOUND
;
2093 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2095 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
2097 Item
= NetMapFindKey (&Instance
->DataItem
[DataType
].EventMap
, Event
);
2100 NetMapRemoveItem (&Instance
->DataItem
[DataType
].EventMap
, Item
, NULL
);
2101 Status
= EFI_SUCCESS
;
2104 Status
= EFI_NOT_FOUND
;
2107 gBS
->RestoreTPL (OldTpl
);
2113 Initialize an IP6_CONFIG_INSTANCE.
2115 @param[out] Instance The buffer of IP6_CONFIG_INSTANCE to be initialized.
2117 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
2118 @retval EFI_SUCCESS The IP6_CONFIG_INSTANCE initialized successfully.
2122 Ip6ConfigInitInstance (
2123 OUT IP6_CONFIG_INSTANCE
*Instance
2127 IP6_CONFIG_INSTANCE
*TmpInstance
;
2132 IP6_CONFIG_DATA_ITEM
*DataItem
;
2134 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
2136 Instance
->Signature
= IP6_CONFIG_INSTANCE_SIGNATURE
;
2139 // Determine the index of this interface.
2142 NET_LIST_FOR_EACH (Entry
, &mIp6ConfigInstanceList
) {
2143 TmpInstance
= NET_LIST_USER_STRUCT_S (Entry
, IP6_CONFIG_INSTANCE
, Link
, IP6_CONFIG_INSTANCE_SIGNATURE
);
2145 if (TmpInstance
->IfIndex
> IfIndex
) {
2147 // There is a sequence hole because some interface is down.
2155 Instance
->IfIndex
= IfIndex
;
2156 NetListInsertBefore (Entry
, &Instance
->Link
);
2158 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
2160 // Initialize the event map for each data item.
2162 NetMapInit (&Instance
->DataItem
[Index
].EventMap
);
2166 // Initialize the NET_MAPs used for DAD on manually configured source addresses.
2168 NetMapInit (&Instance
->DadFailedMap
);
2169 NetMapInit (&Instance
->DadPassedMap
);
2172 // Initialize each data type: associate storage and set data size for the
2173 // fixed size data types, hook the SetData function, set the data attribute.
2175 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeInterfaceInfo
];
2176 DataItem
->GetData
= Ip6ConfigGetIfInfo
;
2177 DataItem
->Data
.Ptr
= &Instance
->InterfaceInfo
;
2178 DataItem
->DataSize
= sizeof (Instance
->InterfaceInfo
);
2179 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
| DATA_ATTRIB_VOLATILE
);
2180 Ip6ConfigInitIfInfo (IpSb
, &Instance
->InterfaceInfo
);
2182 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeAltInterfaceId
];
2183 DataItem
->SetData
= Ip6ConfigSetAltIfId
;
2184 DataItem
->Data
.Ptr
= &Instance
->AltIfId
;
2185 DataItem
->DataSize
= sizeof (Instance
->AltIfId
);
2186 DataItem
->Status
= EFI_NOT_FOUND
;
2187 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2189 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypePolicy
];
2190 DataItem
->SetData
= Ip6ConfigSetPolicy
;
2191 DataItem
->Data
.Ptr
= &Instance
->Policy
;
2192 DataItem
->DataSize
= sizeof (Instance
->Policy
);
2193 Instance
->Policy
= Ip6ConfigPolicyAutomatic
;
2194 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2196 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeDupAddrDetectTransmits
];
2197 DataItem
->SetData
= Ip6ConfigSetDadXmits
;
2198 DataItem
->Data
.Ptr
= &Instance
->DadXmits
;
2199 DataItem
->DataSize
= sizeof (Instance
->DadXmits
);
2200 Instance
->DadXmits
.DupAddrDetectTransmits
= IP6_CONFIG_DEFAULT_DAD_XMITS
;
2201 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2203 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
2204 DataItem
->SetData
= Ip6ConfigSetMaunualAddress
;
2205 DataItem
->Status
= EFI_NOT_FOUND
;
2207 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeGateway
];
2208 DataItem
->SetData
= Ip6ConfigSetGateway
;
2209 DataItem
->Status
= EFI_NOT_FOUND
;
2211 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
2212 DataItem
->SetData
= Ip6ConfigSetDnsServer
;
2213 DataItem
->Status
= EFI_NOT_FOUND
;
2216 // Create the event used for DHCP.
2218 Status
= gBS
->CreateEvent (
2221 Ip6ConfigOnDhcp6Event
,
2223 &Instance
->Dhcp6Event
2225 ASSERT_EFI_ERROR (Status
);
2227 Instance
->Configured
= TRUE
;
2230 // Try to read the config data from NV variable.
2232 Status
= Ip6ConfigReadConfigData (IpSb
->MacString
, Instance
);
2233 if (Status
== EFI_NOT_FOUND
) {
2235 // The NV variable is not set, so generate a random IAID, and write down the
2236 // fresh new configuration as the NV variable now.
2238 Instance
->IaId
= NET_RANDOM (NetRandomInitSeed ());
2240 for (Index
= 0; Index
< IpSb
->SnpMode
.HwAddressSize
; Index
++) {
2241 Instance
->IaId
|= (IpSb
->SnpMode
.CurrentAddress
.Addr
[Index
] << ((Index
<< 3) & 31));
2244 Ip6ConfigWriteConfigData (IpSb
->MacString
, Instance
);
2245 } else if (EFI_ERROR (Status
)) {
2249 Instance
->Ip6Config
.SetData
= EfiIp6ConfigSetData
;
2250 Instance
->Ip6Config
.GetData
= EfiIp6ConfigGetData
;
2251 Instance
->Ip6Config
.RegisterDataNotify
= EfiIp6ConfigRegisterDataNotify
;
2252 Instance
->Ip6Config
.UnregisterDataNotify
= EfiIp6ConfigUnregisterDataNotify
;
2256 // Publish the IP6 configuration form
2258 return Ip6ConfigFormInit (Instance
);
2262 Release an IP6_CONFIG_INSTANCE.
2264 @param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
2268 Ip6ConfigCleanInstance (
2269 IN OUT IP6_CONFIG_INSTANCE
*Instance
2273 IP6_CONFIG_DATA_ITEM
*DataItem
;
2275 if (Instance
->DeclineAddress
!= NULL
) {
2276 FreePool (Instance
->DeclineAddress
);
2279 if (!Instance
->Configured
) {
2283 if (Instance
->Dhcp6Handle
!= NULL
) {
2285 Ip6ConfigDestroyDhcp6 (Instance
);
2291 if (Instance
->Dhcp6Event
!= NULL
) {
2292 gBS
->CloseEvent (Instance
->Dhcp6Event
);
2295 NetMapClean (&Instance
->DadPassedMap
);
2296 NetMapClean (&Instance
->DadFailedMap
);
2298 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
2300 DataItem
= &Instance
->DataItem
[Index
];
2302 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
2303 if (DataItem
->Data
.Ptr
!= NULL
) {
2304 FreePool (DataItem
->Data
.Ptr
);
2306 DataItem
->Data
.Ptr
= NULL
;
2307 DataItem
->DataSize
= 0;
2310 NetMapClean (&Instance
->DataItem
[Index
].EventMap
);
2313 Ip6ConfigFormUnload (Instance
);
2315 RemoveEntryList (&Instance
->Link
);
2319 Destory the Dhcp6 child in IP6_CONFIG_INSTANCE and release the resources.
2321 @param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
2323 @retval EFI_SUCCESS The child was successfully destroyed.
2324 @retval Others Failed to destory the child.
2328 Ip6ConfigDestroyDhcp6 (
2329 IN OUT IP6_CONFIG_INSTANCE
*Instance
2334 EFI_DHCP6_PROTOCOL
*Dhcp6
;
2336 Dhcp6
= Instance
->Dhcp6
;
2337 ASSERT (Dhcp6
!= NULL
);
2339 Dhcp6
->Stop (Dhcp6
);
2340 Dhcp6
->Configure (Dhcp6
, NULL
);
2341 Instance
->Dhcp6
= NULL
;
2343 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
2346 // Close DHCPv6 protocol and destroy the child.
2348 Status
= gBS
->CloseProtocol (
2349 Instance
->Dhcp6Handle
,
2350 &gEfiDhcp6ProtocolGuid
,
2354 if (EFI_ERROR (Status
)) {
2358 Status
= NetLibDestroyServiceChild (
2361 &gEfiDhcp6ServiceBindingProtocolGuid
,
2362 Instance
->Dhcp6Handle
2365 Instance
->Dhcp6Handle
= NULL
;