2 The implementation of EFI IPv6 Configuration Protocol.
4 Copyright (c) 2009 - 2014, 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
= (UINT32
) 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 // If the new address's prefix length is not specified, just use the previous configured
1017 // prefix length for this address.
1019 if (NewAddress
->PrefixLength
== 0) {
1020 NewAddress
->PrefixLength
= CurrentAddrInfo
->PrefixLength
;
1024 // This manual address is already in use, see whether prefix length is changed.
1026 if (NewAddress
->PrefixLength
!= CurrentAddrInfo
->PrefixLength
) {
1028 // Remove the on-link prefix table, the route entry will be removed
1031 PrefixEntry
= Ip6FindPrefixListEntry (
1034 CurrentAddrInfo
->PrefixLength
,
1035 &CurrentAddrInfo
->Address
1037 if (PrefixEntry
!= NULL
) {
1038 Ip6DestroyPrefixListEntry (IpSb
, PrefixEntry
, TRUE
, FALSE
);
1042 // Save the prefix length.
1044 CurrentAddrInfo
->PrefixLength
= NewAddress
->PrefixLength
;
1049 // create a new on-link prefix entry.
1051 PrefixEntry
= Ip6FindPrefixListEntry (
1054 NewAddress
->PrefixLength
,
1055 &NewAddress
->Address
1057 if (PrefixEntry
== NULL
) {
1058 Ip6CreatePrefixListEntry (
1061 (UINT32
) IP6_INFINIT_LIFETIME
,
1062 (UINT32
) IP6_INFINIT_LIFETIME
,
1063 NewAddress
->PrefixLength
,
1064 &NewAddress
->Address
1068 CurrentAddrInfo
->IsAnycast
= NewAddress
->IsAnycast
;
1070 // Artificially mark this address passed DAD be'coz it is already in use.
1072 Ip6ManualAddrDadCallback (TRUE
, &NewAddress
->Address
, Instance
);
1080 // Set the new address, this will trigger DAD and activate the address if
1084 IpSb
->DefaultInterface
,
1085 &NewAddress
->Address
,
1086 NewAddress
->IsAnycast
,
1087 NewAddress
->PrefixLength
,
1088 (UINT32
) IP6_INFINIT_LIFETIME
,
1089 (UINT32
) IP6_INFINIT_LIFETIME
,
1090 Ip6ManualAddrDadCallback
,
1097 // Check the CurrentSourceList, it now contains those addresses currently in
1098 // use and will be removed.
1100 IpIf
= IpSb
->DefaultInterface
;
1102 while (!IsListEmpty (&CurrentSourceList
)) {
1105 CurrentAddrInfo
= NET_LIST_HEAD (&CurrentSourceList
, IP6_ADDRESS_INFO
, Link
);
1108 // This local address is going to be removed, the IP instances that are
1109 // currently using it will be destroyed.
1114 &IpIf
->AddressCount
,
1115 &CurrentAddrInfo
->Address
,
1120 // Remove the on-link prefix table, the route entry will be removed
1123 PrefixEntry
= Ip6FindPrefixListEntry (
1126 CurrentAddrInfo
->PrefixLength
,
1127 &CurrentAddrInfo
->Address
1129 if (PrefixEntry
!= NULL
) {
1130 Ip6DestroyPrefixListEntry (IpSb
, PrefixEntry
, TRUE
, FALSE
);
1133 RemoveEntryList (&CurrentAddrInfo
->Link
);
1134 FreePool (CurrentAddrInfo
);
1138 if (DataItem
->Status
== EFI_NOT_READY
) {
1140 // If DAD is disabled on this interface, the configuration process is
1141 // actually synchronous, and the data item's status will be changed to
1142 // the final status before we reach here, just check it.
1144 Status
= EFI_NOT_READY
;
1146 Status
= EFI_SUCCESS
;
1150 // No update is taken, reset the status to success and return EFI_ABORTED.
1152 DataItem
->Status
= EFI_SUCCESS
;
1153 Status
= EFI_ABORTED
;
1160 The work function for EfiIp6ConfigSetData() to set the gateway addresses manually
1161 for the EFI IPv6 network stack that is running on the communication device that
1162 this EFI IPv6 Configuration Protocol manages. It is not configurable when the policy is
1163 Ip6ConfigPolicyAutomatic. The gateway addresses must be unicast IPv6 addresses.
1165 @param[in] Instance The pointer to the IP6 config instance data.
1166 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1167 @param[in] Data The data buffer to set. This points to an array of
1168 EFI_IPv6_ADDRESS instances.
1170 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1171 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1172 under the current policy.
1173 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1174 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to complete the operation.
1175 @retval EFI_ABORTED The manual gateway addresses to be set equal the
1176 current configuration.
1177 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1178 network stack was set.
1182 Ip6ConfigSetGateway (
1183 IN IP6_CONFIG_INSTANCE
*Instance
,
1190 EFI_IPv6_ADDRESS
*OldGateway
;
1191 EFI_IPv6_ADDRESS
*NewGateway
;
1192 UINTN OldGatewayCount
;
1193 UINTN NewGatewayCount
;
1194 IP6_CONFIG_DATA_ITEM
*Item
;
1198 IP6_DEFAULT_ROUTER
*DefaultRouter
;
1201 if ((DataSize
% sizeof (EFI_IPv6_ADDRESS
) != 0) || (DataSize
== 0)) {
1202 return EFI_BAD_BUFFER_SIZE
;
1205 if (Instance
->Policy
!= Ip6ConfigPolicyManual
) {
1206 return EFI_WRITE_PROTECTED
;
1209 NewGateway
= (EFI_IPv6_ADDRESS
*) Data
;
1210 NewGatewayCount
= DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1211 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1213 if (!NetIp6IsValidUnicast (NewGateway
+ Index1
)) {
1215 return EFI_INVALID_PARAMETER
;
1218 for (Index2
= Index1
+ 1; Index2
< NewGatewayCount
; Index2
++) {
1219 if (EFI_IP6_EQUAL (NewGateway
+ Index1
, NewGateway
+ Index2
)) {
1220 return EFI_INVALID_PARAMETER
;
1225 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
1226 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeGateway
];
1227 OldGateway
= Item
->Data
.Gateway
;
1228 OldGatewayCount
= Item
->DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1232 if (NewGatewayCount
!= OldGatewayCount
) {
1233 Tmp
= AllocatePool (DataSize
);
1235 return EFI_OUT_OF_RESOURCES
;
1241 for (Index1
= 0; Index1
< OldGatewayCount
; Index1
++) {
1243 // Find the gateways that are no long in the new setting and remove them.
1245 for (Index2
= 0; Index2
< NewGatewayCount
; Index2
++) {
1246 if (EFI_IP6_EQUAL (OldGateway
+ Index1
, NewGateway
+ Index2
)) {
1252 if (Index2
== NewGatewayCount
) {
1254 // Remove this default router.
1256 DefaultRouter
= Ip6FindDefaultRouter (IpSb
, OldGateway
+ Index1
);
1257 if (DefaultRouter
!= NULL
) {
1258 Ip6DestroyDefaultRouter (IpSb
, DefaultRouter
);
1263 for (Index1
= 0; Index1
< NewGatewayCount
; Index1
++) {
1265 DefaultRouter
= Ip6FindDefaultRouter (IpSb
, NewGateway
+ Index1
);
1266 if (DefaultRouter
== NULL
) {
1267 Ip6CreateDefaultRouter (IpSb
, NewGateway
+ Index1
, IP6_INF_ROUTER_LIFETIME
);
1272 if (!OneRemoved
&& !OneAdded
) {
1273 Item
->Status
= EFI_SUCCESS
;
1278 if (Item
->Data
.Ptr
!= NULL
) {
1279 FreePool (Item
->Data
.Ptr
);
1281 Item
->Data
.Ptr
= Tmp
;
1284 CopyMem (Item
->Data
.Ptr
, Data
, DataSize
);
1285 Item
->DataSize
= DataSize
;
1286 Item
->Status
= EFI_SUCCESS
;
1292 The work function for EfiIp6ConfigSetData() to set the DNS server list for the
1293 EFI IPv6 network stack running on the communication device that this EFI IPv6
1294 Configuration Protocol manages. It is not configurable when the policy is
1295 Ip6ConfigPolicyAutomatic. The DNS server addresses must be unicast IPv6 addresses.
1297 @param[in] Instance The pointer to the IP6 config instance data.
1298 @param[in] DataSize The size of the buffer pointed to by Data in bytes.
1299 @param[in] Data The data buffer to set, points to an array of
1300 EFI_IPv6_ADDRESS instances.
1302 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type.
1303 @retval EFI_WRITE_PROTECTED The specified configuration data cannot be set
1304 under the current policy.
1305 @retval EFI_INVALID_PARAMETER One or more fields in Data is invalid.
1306 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
1307 @retval EFI_ABORTED The DNS server addresses to be set equal the current
1309 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1310 network stack was set.
1314 Ip6ConfigSetDnsServer (
1315 IN IP6_CONFIG_INSTANCE
*Instance
,
1323 EFI_IPv6_ADDRESS
*OldDns
;
1324 EFI_IPv6_ADDRESS
*NewDns
;
1327 IP6_CONFIG_DATA_ITEM
*Item
;
1331 if ((DataSize
% sizeof (EFI_IPv6_ADDRESS
) != 0) || (DataSize
== 0)) {
1332 return EFI_BAD_BUFFER_SIZE
;
1335 if (Instance
->Policy
!= Ip6ConfigPolicyManual
) {
1336 return EFI_WRITE_PROTECTED
;
1339 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
1340 NewDns
= (EFI_IPv6_ADDRESS
*) Data
;
1341 OldDns
= Item
->Data
.DnsServers
;
1342 NewDnsCount
= DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1343 OldDnsCount
= Item
->DataSize
/ sizeof (EFI_IPv6_ADDRESS
);
1346 if (NewDnsCount
!= OldDnsCount
) {
1347 Tmp
= AllocatePool (DataSize
);
1349 return EFI_OUT_OF_RESOURCES
;
1355 for (NewIndex
= 0; NewIndex
< NewDnsCount
; NewIndex
++) {
1357 if (!NetIp6IsValidUnicast (NewDns
+ NewIndex
)) {
1359 // The dns server address must be unicast.
1362 return EFI_INVALID_PARAMETER
;
1365 for (Index1
= NewIndex
+ 1; Index1
< NewDnsCount
; Index1
++) {
1366 if (EFI_IP6_EQUAL (NewDns
+ NewIndex
, NewDns
+ Index1
)) {
1368 return EFI_INVALID_PARAMETER
;
1374 // If any address in the new setting is not in the old settings, skip the
1375 // comparision below.
1380 for (OldIndex
= 0; OldIndex
< OldDnsCount
; OldIndex
++) {
1381 if (EFI_IP6_EQUAL (NewDns
+ NewIndex
, OldDns
+ OldIndex
)) {
1383 // If found break out.
1389 if (OldIndex
== OldDnsCount
) {
1394 if (!OneAdded
&& (DataSize
== Item
->DataSize
)) {
1396 // No new item is added and the size is the same.
1398 Item
->Status
= EFI_SUCCESS
;
1402 if (Item
->Data
.Ptr
!= NULL
) {
1403 FreePool (Item
->Data
.Ptr
);
1405 Item
->Data
.Ptr
= Tmp
;
1408 CopyMem (Item
->Data
.Ptr
, Data
, DataSize
);
1409 Item
->DataSize
= DataSize
;
1410 Item
->Status
= EFI_SUCCESS
;
1416 Generate the operational state of the interface this IP6 config instance manages
1417 and output in EFI_IP6_CONFIG_INTERFACE_INFO.
1419 @param[in] IpSb The pointer to the IP6 service binding instance.
1420 @param[out] IfInfo The pointer to the IP6 configuration interface information structure.
1424 Ip6ConfigInitIfInfo (
1425 IN IP6_SERVICE
*IpSb
,
1426 OUT EFI_IP6_CONFIG_INTERFACE_INFO
*IfInfo
1429 IfInfo
->Name
[0] = L
'e';
1430 IfInfo
->Name
[1] = L
't';
1431 IfInfo
->Name
[2] = L
'h';
1432 IfInfo
->Name
[3] = (CHAR16
) (L
'0' + IpSb
->Ip6ConfigInstance
.IfIndex
);
1433 IfInfo
->Name
[4] = 0;
1435 IfInfo
->IfType
= IpSb
->SnpMode
.IfType
;
1436 IfInfo
->HwAddressSize
= IpSb
->SnpMode
.HwAddressSize
;
1437 CopyMem (&IfInfo
->HwAddress
, &IpSb
->SnpMode
.CurrentAddress
, IfInfo
->HwAddressSize
);
1441 Parse DHCPv6 reply packet to get the DNS server list.
1442 It is the work function for Ip6ConfigOnDhcp6Reply and Ip6ConfigOnDhcp6Event.
1444 @param[in] Dhcp6 The pointer to the EFI_DHCP6_PROTOCOL instance.
1445 @param[in, out] Instance The pointer to the IP6 configuration instance data.
1446 @param[in] Reply The pointer to the DHCPv6 reply packet.
1448 @retval EFI_SUCCESS The DNS server address was retrieved from the reply packet.
1449 @retval EFI_NOT_READY The reply packet does not contain the DNS server option, or
1450 the DNS server address is not valid.
1454 Ip6ConfigParseDhcpReply (
1455 IN EFI_DHCP6_PROTOCOL
*Dhcp6
,
1456 IN OUT IP6_CONFIG_INSTANCE
*Instance
,
1457 IN EFI_DHCP6_PACKET
*Reply
1462 EFI_DHCP6_PACKET_OPTION
**OptList
;
1467 EFI_IPv6_ADDRESS
*DnsServer
;
1468 IP6_CONFIG_DATA_ITEM
*Item
;
1471 // A DHCPv6 reply packet is received as the response to our InfoRequest
1475 Status
= Dhcp6
->Parse (Dhcp6
, Reply
, &OptCount
, NULL
);
1476 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1477 return EFI_NOT_READY
;
1480 OptList
= AllocatePool (OptCount
* sizeof (EFI_DHCP6_PACKET_OPTION
*));
1481 if (OptList
== NULL
) {
1482 return EFI_NOT_READY
;
1485 Status
= Dhcp6
->Parse (Dhcp6
, Reply
, &OptCount
, OptList
);
1486 if (EFI_ERROR (Status
)) {
1487 Status
= EFI_NOT_READY
;
1491 Status
= EFI_SUCCESS
;
1493 for (Index
= 0; Index
< OptCount
; Index
++) {
1495 // Go through all the options to check the ones we are interested in.
1496 // The OpCode and Length are in network byte-order and may not be naturally
1499 CopyMem (&OpCode
, &OptList
[Index
]->OpCode
, sizeof (OpCode
));
1500 OpCode
= NTOHS (OpCode
);
1502 if (OpCode
== IP6_CONFIG_DHCP6_OPTION_DNS_SERVERS
) {
1503 CopyMem (&Length
, &OptList
[Index
]->OpLen
, sizeof (Length
));
1504 Length
= NTOHS (Length
);
1506 if ((Length
== 0) || ((Length
% sizeof (EFI_IPv6_ADDRESS
)) != 0)) {
1508 // The length should be a multiple of 16 bytes.
1510 Status
= EFI_NOT_READY
;
1515 // Validate the DnsServers: whether they are unicast addresses.
1517 DnsServer
= (EFI_IPv6_ADDRESS
*) OptList
[Index
]->Data
;
1518 for (Index2
= 0; Index2
< Length
/ sizeof (EFI_IPv6_ADDRESS
); Index2
++) {
1519 if (!NetIp6IsValidUnicast (DnsServer
)) {
1520 Status
= EFI_NOT_READY
;
1527 Item
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
1529 if (Item
->DataSize
!= Length
) {
1530 if (Item
->Data
.Ptr
!= NULL
) {
1531 FreePool (Item
->Data
.Ptr
);
1534 Item
->Data
.Ptr
= AllocatePool (Length
);
1535 ASSERT (Item
->Data
.Ptr
!= NULL
);
1538 CopyMem (Item
->Data
.Ptr
, OptList
[Index
]->Data
, Length
);
1539 Item
->DataSize
= Length
;
1540 Item
->Status
= EFI_SUCCESS
;
1543 // Signal the waiting events.
1545 NetMapIterate (&Item
->EventMap
, Ip6ConfigSignalEvent
, NULL
);
1558 The callback function for Ip6SetAddr. The prototype is defined
1559 as IP6_DAD_CALLBACK. It is called after Duplicate Address Detection is performed
1560 on the tentative address by DHCPv6 in Ip6ConfigOnDhcp6Event().
1562 @param[in] IsDadPassed If TRUE, Duplicate Address Detection passes.
1563 @param[in] TargetAddress The tentative IPv6 address to be checked.
1564 @param[in] Context Pointer to the IP6 configuration instance data.
1568 Ip6ConfigSetStatefulAddrCallback (
1569 IN BOOLEAN IsDadPassed
,
1570 IN EFI_IPv6_ADDRESS
*TargetAddress
,
1574 IP6_CONFIG_INSTANCE
*Instance
;
1576 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
1577 NET_CHECK_SIGNATURE (Instance
, IP6_CONFIG_INSTANCE_SIGNATURE
);
1580 // We should record the addresses that fail the DAD, and DECLINE them.
1584 // Decrease the count, no interests in those passed DAD.
1586 if (Instance
->FailedIaAddressCount
> 0 ) {
1587 Instance
->FailedIaAddressCount
--;
1593 IP6_COPY_ADDRESS (Instance
->DeclineAddress
+ Instance
->DeclineAddressCount
, TargetAddress
);
1594 Instance
->DeclineAddressCount
++;
1597 if (Instance
->FailedIaAddressCount
== Instance
->DeclineAddressCount
) {
1599 // The checking on all addresses are finished.
1601 if (Instance
->DeclineAddressCount
!= 0) {
1603 // Decline those duplicates.
1605 if (Instance
->Dhcp6
!= NULL
) {
1606 Instance
->Dhcp6
->Decline (
1608 Instance
->DeclineAddressCount
,
1609 Instance
->DeclineAddress
1614 if (Instance
->DeclineAddress
!= NULL
) {
1615 FreePool (Instance
->DeclineAddress
);
1617 Instance
->DeclineAddress
= NULL
;
1618 Instance
->DeclineAddressCount
= 0;
1623 The event handle routine when DHCPv6 process is finished or is updated.
1625 @param[in] Event Not used.
1626 @param[in] Context The pointer to the IP6 configuration instance data.
1631 Ip6ConfigOnDhcp6Event (
1636 IP6_CONFIG_INSTANCE
*Instance
;
1637 EFI_DHCP6_PROTOCOL
*Dhcp6
;
1639 EFI_DHCP6_MODE_DATA Dhcp6ModeData
;
1641 EFI_DHCP6_IA_ADDRESS
*IaAddr
;
1644 IP6_ADDRESS_INFO
*AddrInfo
;
1645 IP6_INTERFACE
*IpIf
;
1647 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
1649 if ((Instance
->Policy
!= Ip6ConfigPolicyAutomatic
) || Instance
->OtherInfoOnly
) {
1651 // IPv6 is not operating in the automatic policy now or
1652 // the DHCPv6 information request message exchange is aborted.
1658 // The stateful address autoconfiguration is done or updated.
1660 Dhcp6
= Instance
->Dhcp6
;
1662 Status
= Dhcp6
->GetModeData (Dhcp6
, &Dhcp6ModeData
, NULL
);
1663 if (EFI_ERROR (Status
)) {
1667 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
1668 IpIf
= IpSb
->DefaultInterface
;
1669 Ia
= Dhcp6ModeData
.Ia
;
1670 IaAddr
= Ia
->IaAddress
;
1672 if (Instance
->DeclineAddress
!= NULL
) {
1673 FreePool (Instance
->DeclineAddress
);
1676 Instance
->DeclineAddress
= (EFI_IPv6_ADDRESS
*) AllocatePool (Ia
->IaAddressCount
* sizeof (EFI_IPv6_ADDRESS
));
1677 if (Instance
->DeclineAddress
== NULL
) {
1681 Instance
->FailedIaAddressCount
= Ia
->IaAddressCount
;
1682 Instance
->DeclineAddressCount
= 0;
1684 for (Index
= 0; Index
< Ia
->IaAddressCount
; Index
++, IaAddr
++) {
1685 if (Ia
->IaAddress
[Index
].ValidLifetime
!= 0 && Ia
->State
== Dhcp6Bound
) {
1687 // Set this address, either it's a new address or with updated lifetimes.
1688 // An appropriate prefix length will be set.
1695 IaAddr
->ValidLifetime
,
1696 IaAddr
->PreferredLifetime
,
1697 Ip6ConfigSetStatefulAddrCallback
,
1702 // discard this address, artificially decrease the count as if this address
1705 if (Ip6IsOneOfSetAddress (IpSb
, &IaAddr
->IpAddress
, NULL
, &AddrInfo
)) {
1706 ASSERT (AddrInfo
!= NULL
);
1710 &IpIf
->AddressCount
,
1712 AddrInfo
->PrefixLength
1716 if (Instance
->FailedIaAddressCount
> 0) {
1717 Instance
->FailedIaAddressCount
--;
1723 // Parse the Reply packet to get the options we need.
1725 if (Dhcp6ModeData
.Ia
->ReplyPacket
!= NULL
) {
1726 Ip6ConfigParseDhcpReply (Dhcp6
, Instance
, Dhcp6ModeData
.Ia
->ReplyPacket
);
1731 FreePool (Dhcp6ModeData
.ClientId
);
1732 FreePool (Dhcp6ModeData
.Ia
);
1736 The event process routine when the DHCPv6 server is answered with a reply packet
1737 for an information request.
1739 @param[in] This Points to the EFI_DHCP6_PROTOCOL.
1740 @param[in] Context The pointer to the IP6 configuration instance data.
1741 @param[in] Packet The DHCPv6 reply packet.
1743 @retval EFI_SUCCESS The DNS server address was retrieved from the reply packet.
1744 @retval EFI_NOT_READY The reply packet does not contain the DNS server option, or
1745 the DNS server address is not valid.
1750 Ip6ConfigOnDhcp6Reply (
1751 IN EFI_DHCP6_PROTOCOL
*This
,
1753 IN EFI_DHCP6_PACKET
*Packet
1756 return Ip6ConfigParseDhcpReply (This
, (IP6_CONFIG_INSTANCE
*) Context
, Packet
);
1760 The event process routine when the DHCPv6 service binding protocol is installed
1763 @param[in] Event Not used.
1764 @param[in] Context The pointer to the IP6 config instance data.
1769 Ip6ConfigOnDhcp6SbInstalled (
1774 IP6_CONFIG_INSTANCE
*Instance
;
1776 Instance
= (IP6_CONFIG_INSTANCE
*) Context
;
1778 if ((Instance
->Dhcp6Handle
!= NULL
) || (Instance
->Policy
!= Ip6ConfigPolicyAutomatic
)) {
1780 // The DHCP6 child is already created or the policy is no longer AUTOMATIC.
1785 Ip6ConfigStartStatefulAutoConfig (Instance
, Instance
->OtherInfoOnly
);
1789 Set the configuration for the EFI IPv6 network stack running on the communication
1790 device this EFI IPv6 Configuration Protocol instance manages.
1792 This function is used to set the configuration data of type DataType for the EFI
1793 IPv6 network stack that is running on the communication device that this EFI IPv6
1794 Configuration Protocol instance manages.
1796 DataSize is used to calculate the count of structure instances in the Data for
1797 a DataType in which multiple structure instances are allowed.
1799 This function is always non-blocking. When setting some type of configuration data,
1800 an asynchronous process is invoked to check the correctness of the data, such as
1801 performing Duplicate Address Detection on the manually set local IPv6 addresses.
1802 EFI_NOT_READY is returned immediately to indicate that such an asynchronous process
1803 is invoked, and the process is not finished yet. The caller wanting to get the result
1804 of the asynchronous process is required to call RegisterDataNotify() to register an
1805 event on the specified configuration data. Once the event is signaled, the caller
1806 can call GetData() to obtain the configuration data and know the result.
1807 For other types of configuration data that do not require an asynchronous configuration
1808 process, the result of the operation is immediately returned.
1810 @param[in] This The pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
1811 @param[in] DataType The type of data to set.
1812 @param[in] DataSize Size of the buffer pointed to by Data in bytes.
1813 @param[in] Data The data buffer to set. The type of the data buffer is
1814 associated with the DataType.
1816 @retval EFI_SUCCESS The specified configuration data for the EFI IPv6
1817 network stack was set successfully.
1818 @retval EFI_INVALID_PARAMETER One or more of the following are TRUE:
1821 - One or more fields in Data do not match the requirement of the
1822 data type indicated by DataType.
1823 @retval EFI_WRITE_PROTECTED The specified configuration data is read-only or the specified
1824 configuration data cannot be set under the current policy.
1825 @retval EFI_ACCESS_DENIED Another set operation on the specified configuration
1826 data is already in process.
1827 @retval EFI_NOT_READY An asynchronous process was invoked to set the specified
1828 configuration data, and the process is not finished yet.
1829 @retval EFI_BAD_BUFFER_SIZE The DataSize does not match the size of the type
1830 indicated by DataType.
1831 @retval EFI_UNSUPPORTED This DataType is not supported.
1832 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
1833 @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
1838 EfiIp6ConfigSetData (
1839 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
1840 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
1847 IP6_CONFIG_INSTANCE
*Instance
;
1850 if ((This
== NULL
) || (Data
== NULL
)) {
1851 return EFI_INVALID_PARAMETER
;
1854 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
1855 return EFI_UNSUPPORTED
;
1858 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
1859 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
1860 NET_CHECK_SIGNATURE (IpSb
, IP6_SERVICE_SIGNATURE
);
1862 if (IpSb
->LinkLocalDadFail
) {
1863 return EFI_DEVICE_ERROR
;
1866 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1868 Status
= Instance
->DataItem
[DataType
].Status
;
1869 if (Status
!= EFI_NOT_READY
) {
1871 if (Instance
->DataItem
[DataType
].SetData
== NULL
) {
1873 // This type of data is readonly.
1875 Status
= EFI_WRITE_PROTECTED
;
1878 Status
= Instance
->DataItem
[DataType
].SetData (Instance
, DataSize
, Data
);
1879 if (!EFI_ERROR (Status
)) {
1881 // Fire up the events registered with this type of data.
1883 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip6ConfigSignalEvent
, NULL
);
1884 Ip6ConfigWriteConfigData (IpSb
->MacString
, Instance
);
1885 } else if (Status
== EFI_ABORTED
) {
1887 // The SetData is aborted because the data to set is the same with
1888 // the one maintained.
1890 Status
= EFI_SUCCESS
;
1891 NetMapIterate (&Instance
->DataItem
[DataType
].EventMap
, Ip6ConfigSignalEvent
, NULL
);
1896 // Another asynchornous process is on the way.
1898 Status
= EFI_ACCESS_DENIED
;
1901 gBS
->RestoreTPL (OldTpl
);
1907 Get the configuration data for the EFI IPv6 network stack running on the communication
1908 device that this EFI IPv6 Configuration Protocol instance manages.
1910 This function returns the configuration data of type DataType for the EFI IPv6 network
1911 stack running on the communication device that this EFI IPv6 Configuration Protocol instance
1914 The caller is responsible for allocating the buffer used to return the specified
1915 configuration data. The required size will be returned to the caller if the size of
1916 the buffer is too small.
1918 EFI_NOT_READY is returned if the specified configuration data is not ready due to an
1919 asynchronous configuration process already in progress. The caller can call RegisterDataNotify()
1920 to register an event on the specified configuration data. Once the asynchronous configuration
1921 process is finished, the event will be signaled, and a subsequent GetData() call will return
1922 the specified configuration data.
1924 @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
1925 @param[in] DataType The type of data to get.
1926 @param[in, out] DataSize On input, in bytes, the size of Data. On output, in bytes, the
1927 size of buffer required to store the specified configuration data.
1928 @param[in] Data The data buffer in which the configuration data is returned. The
1929 type of the data buffer is associated with the DataType.
1930 This is an optional parameter that may be NULL.
1932 @retval EFI_SUCCESS The specified configuration data was obtained successfully.
1933 @retval EFI_INVALID_PARAMETER One or more of the followings are TRUE:
1936 - Data is NULL if *DataSize is not zero.
1937 @retval EFI_BUFFER_TOO_SMALL The size of Data is too small for the specified configuration data,
1938 and the required size is returned in DataSize.
1939 @retval EFI_NOT_READY The specified configuration data is not ready due to an
1940 asynchronous configuration process already in progress.
1941 @retval EFI_NOT_FOUND The specified configuration data is not found.
1946 EfiIp6ConfigGetData (
1947 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
1948 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
1949 IN OUT UINTN
*DataSize
,
1950 IN VOID
*Data OPTIONAL
1955 IP6_CONFIG_INSTANCE
*Instance
;
1956 IP6_CONFIG_DATA_ITEM
*DataItem
;
1958 if ((This
== NULL
) || (DataSize
== NULL
) || ((*DataSize
!= 0) && (Data
== NULL
))) {
1959 return EFI_INVALID_PARAMETER
;
1962 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
1963 return EFI_NOT_FOUND
;
1966 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1968 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
1969 DataItem
= &Instance
->DataItem
[DataType
];
1971 Status
= Instance
->DataItem
[DataType
].Status
;
1972 if (!EFI_ERROR (Status
)) {
1974 if (DataItem
->GetData
!= NULL
) {
1976 Status
= DataItem
->GetData (Instance
, DataSize
, Data
);
1977 } else if (*DataSize
< Instance
->DataItem
[DataType
].DataSize
) {
1979 // Update the buffer length.
1981 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
1982 Status
= EFI_BUFFER_TOO_SMALL
;
1985 *DataSize
= Instance
->DataItem
[DataType
].DataSize
;
1986 CopyMem (Data
, Instance
->DataItem
[DataType
].Data
.Ptr
, *DataSize
);
1990 gBS
->RestoreTPL (OldTpl
);
1996 Register an event that is signaled whenever a configuration process on the specified
1997 configuration data is done.
1999 This function registers an event that is to be signaled whenever a configuration
2000 process on the specified configuration data is performed. An event can be registered
2001 for a different DataType simultaneously. The caller is responsible for determining
2002 which type of configuration data causes the signaling of the event in such an event.
2004 @param[in] This Pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
2005 @param[in] DataType The type of data to unregister the event for.
2006 @param[in] Event The event to register.
2008 @retval EFI_SUCCESS The notification event for the specified configuration data is
2010 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
2011 @retval EFI_UNSUPPORTED The configuration data type specified by DataType is not
2013 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
2014 @retval EFI_ACCESS_DENIED The Event is already registered for the DataType.
2019 EfiIp6ConfigRegisterDataNotify (
2020 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
2021 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
2027 IP6_CONFIG_INSTANCE
*Instance
;
2031 if ((This
== NULL
) || (Event
== NULL
)) {
2032 return EFI_INVALID_PARAMETER
;
2035 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
2036 return EFI_UNSUPPORTED
;
2039 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2041 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
2042 EventMap
= &Instance
->DataItem
[DataType
].EventMap
;
2045 // Check whether this event is already registered for this DataType.
2047 Item
= NetMapFindKey (EventMap
, Event
);
2050 Status
= NetMapInsertTail (EventMap
, Event
, NULL
);
2052 if (EFI_ERROR (Status
)) {
2054 Status
= EFI_OUT_OF_RESOURCES
;
2059 Status
= EFI_ACCESS_DENIED
;
2062 gBS
->RestoreTPL (OldTpl
);
2068 Remove a previously registered event for the specified configuration data.
2070 @param This The pointer to the EFI_IP6_CONFIG_PROTOCOL instance.
2071 @param DataType The type of data to remove from the previously
2073 @param Event The event to be unregistered.
2075 @retval EFI_SUCCESS The event registered for the specified
2076 configuration data was removed.
2077 @retval EFI_INVALID_PARAMETER This is NULL or Event is NULL.
2078 @retval EFI_NOT_FOUND The Event has not been registered for the
2084 EfiIp6ConfigUnregisterDataNotify (
2085 IN EFI_IP6_CONFIG_PROTOCOL
*This
,
2086 IN EFI_IP6_CONFIG_DATA_TYPE DataType
,
2092 IP6_CONFIG_INSTANCE
*Instance
;
2095 if ((This
== NULL
) || (Event
== NULL
)) {
2096 return EFI_INVALID_PARAMETER
;
2099 if (DataType
>= Ip6ConfigDataTypeMaximum
) {
2100 return EFI_NOT_FOUND
;
2103 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2105 Instance
= IP6_CONFIG_INSTANCE_FROM_PROTOCOL (This
);
2107 Item
= NetMapFindKey (&Instance
->DataItem
[DataType
].EventMap
, Event
);
2110 NetMapRemoveItem (&Instance
->DataItem
[DataType
].EventMap
, Item
, NULL
);
2111 Status
= EFI_SUCCESS
;
2114 Status
= EFI_NOT_FOUND
;
2117 gBS
->RestoreTPL (OldTpl
);
2123 Initialize an IP6_CONFIG_INSTANCE.
2125 @param[out] Instance The buffer of IP6_CONFIG_INSTANCE to be initialized.
2127 @retval EFI_OUT_OF_RESOURCES Failed to allocate resources to complete the operation.
2128 @retval EFI_SUCCESS The IP6_CONFIG_INSTANCE initialized successfully.
2132 Ip6ConfigInitInstance (
2133 OUT IP6_CONFIG_INSTANCE
*Instance
2137 IP6_CONFIG_INSTANCE
*TmpInstance
;
2142 IP6_CONFIG_DATA_ITEM
*DataItem
;
2144 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
2146 Instance
->Signature
= IP6_CONFIG_INSTANCE_SIGNATURE
;
2149 // Determine the index of this interface.
2152 NET_LIST_FOR_EACH (Entry
, &mIp6ConfigInstanceList
) {
2153 TmpInstance
= NET_LIST_USER_STRUCT_S (Entry
, IP6_CONFIG_INSTANCE
, Link
, IP6_CONFIG_INSTANCE_SIGNATURE
);
2155 if (TmpInstance
->IfIndex
> IfIndex
) {
2157 // There is a sequence hole because some interface is down.
2165 Instance
->IfIndex
= IfIndex
;
2166 NetListInsertBefore (Entry
, &Instance
->Link
);
2168 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
2170 // Initialize the event map for each data item.
2172 NetMapInit (&Instance
->DataItem
[Index
].EventMap
);
2176 // Initialize the NET_MAPs used for DAD on manually configured source addresses.
2178 NetMapInit (&Instance
->DadFailedMap
);
2179 NetMapInit (&Instance
->DadPassedMap
);
2182 // Initialize each data type: associate storage and set data size for the
2183 // fixed size data types, hook the SetData function, set the data attribute.
2185 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeInterfaceInfo
];
2186 DataItem
->GetData
= Ip6ConfigGetIfInfo
;
2187 DataItem
->Data
.Ptr
= &Instance
->InterfaceInfo
;
2188 DataItem
->DataSize
= sizeof (Instance
->InterfaceInfo
);
2189 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
| DATA_ATTRIB_VOLATILE
);
2190 Ip6ConfigInitIfInfo (IpSb
, &Instance
->InterfaceInfo
);
2192 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeAltInterfaceId
];
2193 DataItem
->SetData
= Ip6ConfigSetAltIfId
;
2194 DataItem
->Data
.Ptr
= &Instance
->AltIfId
;
2195 DataItem
->DataSize
= sizeof (Instance
->AltIfId
);
2196 DataItem
->Status
= EFI_NOT_FOUND
;
2197 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2199 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypePolicy
];
2200 DataItem
->SetData
= Ip6ConfigSetPolicy
;
2201 DataItem
->Data
.Ptr
= &Instance
->Policy
;
2202 DataItem
->DataSize
= sizeof (Instance
->Policy
);
2203 Instance
->Policy
= Ip6ConfigPolicyAutomatic
;
2204 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2206 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeDupAddrDetectTransmits
];
2207 DataItem
->SetData
= Ip6ConfigSetDadXmits
;
2208 DataItem
->Data
.Ptr
= &Instance
->DadXmits
;
2209 DataItem
->DataSize
= sizeof (Instance
->DadXmits
);
2210 Instance
->DadXmits
.DupAddrDetectTransmits
= IP6_CONFIG_DEFAULT_DAD_XMITS
;
2211 SET_DATA_ATTRIB (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
);
2213 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeManualAddress
];
2214 DataItem
->SetData
= Ip6ConfigSetMaunualAddress
;
2215 DataItem
->Status
= EFI_NOT_FOUND
;
2217 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeGateway
];
2218 DataItem
->SetData
= Ip6ConfigSetGateway
;
2219 DataItem
->Status
= EFI_NOT_FOUND
;
2221 DataItem
= &Instance
->DataItem
[Ip6ConfigDataTypeDnsServer
];
2222 DataItem
->SetData
= Ip6ConfigSetDnsServer
;
2223 DataItem
->Status
= EFI_NOT_FOUND
;
2226 // Create the event used for DHCP.
2228 Status
= gBS
->CreateEvent (
2231 Ip6ConfigOnDhcp6Event
,
2233 &Instance
->Dhcp6Event
2235 ASSERT_EFI_ERROR (Status
);
2237 Instance
->Configured
= TRUE
;
2240 // Try to read the config data from NV variable.
2242 Status
= Ip6ConfigReadConfigData (IpSb
->MacString
, Instance
);
2243 if (Status
== EFI_NOT_FOUND
) {
2245 // The NV variable is not set, so generate a random IAID, and write down the
2246 // fresh new configuration as the NV variable now.
2248 Instance
->IaId
= NET_RANDOM (NetRandomInitSeed ());
2250 for (Index
= 0; Index
< IpSb
->SnpMode
.HwAddressSize
; Index
++) {
2251 Instance
->IaId
|= (IpSb
->SnpMode
.CurrentAddress
.Addr
[Index
] << ((Index
<< 3) & 31));
2254 Ip6ConfigWriteConfigData (IpSb
->MacString
, Instance
);
2255 } else if (EFI_ERROR (Status
)) {
2259 Instance
->Ip6Config
.SetData
= EfiIp6ConfigSetData
;
2260 Instance
->Ip6Config
.GetData
= EfiIp6ConfigGetData
;
2261 Instance
->Ip6Config
.RegisterDataNotify
= EfiIp6ConfigRegisterDataNotify
;
2262 Instance
->Ip6Config
.UnregisterDataNotify
= EfiIp6ConfigUnregisterDataNotify
;
2266 // Publish the IP6 configuration form
2268 return Ip6ConfigFormInit (Instance
);
2272 Release an IP6_CONFIG_INSTANCE.
2274 @param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
2278 Ip6ConfigCleanInstance (
2279 IN OUT IP6_CONFIG_INSTANCE
*Instance
2283 IP6_CONFIG_DATA_ITEM
*DataItem
;
2285 if (Instance
->DeclineAddress
!= NULL
) {
2286 FreePool (Instance
->DeclineAddress
);
2289 if (!Instance
->Configured
) {
2293 if (Instance
->Dhcp6Handle
!= NULL
) {
2295 Ip6ConfigDestroyDhcp6 (Instance
);
2301 if (Instance
->Dhcp6Event
!= NULL
) {
2302 gBS
->CloseEvent (Instance
->Dhcp6Event
);
2305 NetMapClean (&Instance
->DadPassedMap
);
2306 NetMapClean (&Instance
->DadFailedMap
);
2308 for (Index
= 0; Index
< Ip6ConfigDataTypeMaximum
; Index
++) {
2310 DataItem
= &Instance
->DataItem
[Index
];
2312 if (!DATA_ATTRIB_SET (DataItem
->Attribute
, DATA_ATTRIB_SIZE_FIXED
)) {
2313 if (DataItem
->Data
.Ptr
!= NULL
) {
2314 FreePool (DataItem
->Data
.Ptr
);
2316 DataItem
->Data
.Ptr
= NULL
;
2317 DataItem
->DataSize
= 0;
2320 NetMapClean (&Instance
->DataItem
[Index
].EventMap
);
2323 Ip6ConfigFormUnload (Instance
);
2325 RemoveEntryList (&Instance
->Link
);
2329 Destroy the Dhcp6 child in IP6_CONFIG_INSTANCE and release the resources.
2331 @param[in, out] Instance The buffer of IP6_CONFIG_INSTANCE to be freed.
2333 @retval EFI_SUCCESS The child was successfully destroyed.
2334 @retval Others Failed to destroy the child.
2338 Ip6ConfigDestroyDhcp6 (
2339 IN OUT IP6_CONFIG_INSTANCE
*Instance
2344 EFI_DHCP6_PROTOCOL
*Dhcp6
;
2346 Dhcp6
= Instance
->Dhcp6
;
2347 ASSERT (Dhcp6
!= NULL
);
2349 Dhcp6
->Stop (Dhcp6
);
2350 Dhcp6
->Configure (Dhcp6
, NULL
);
2351 Instance
->Dhcp6
= NULL
;
2353 IpSb
= IP6_SERVICE_FROM_IP6_CONFIG_INSTANCE (Instance
);
2356 // Close DHCPv6 protocol and destroy the child.
2358 Status
= gBS
->CloseProtocol (
2359 Instance
->Dhcp6Handle
,
2360 &gEfiDhcp6ProtocolGuid
,
2364 if (EFI_ERROR (Status
)) {
2368 Status
= NetLibDestroyServiceChild (
2371 &gEfiDhcp6ServiceBindingProtocolGuid
,
2372 Instance
->Dhcp6Handle
2375 Instance
->Dhcp6Handle
= NULL
;