2 Functions implementation related with DHCPv4/v6 for DNS driver.
4 Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
12 This function initialize the DHCP4 message instance.
14 This function will pad each item of dhcp4 message packet.
16 @param Seed Pointer to the message instance of the DHCP4 packet.
17 @param InterfaceInfo Pointer to the EFI_IP4_CONFIG2_INTERFACE_INFO instance.
22 OUT EFI_DHCP4_PACKET
*Seed
,
23 IN EFI_IP4_CONFIG2_INTERFACE_INFO
*InterfaceInfo
26 EFI_DHCP4_HEADER
*Header
;
29 // Get IfType and HwAddressSize from SNP mode data.
31 Seed
->Size
= sizeof (EFI_DHCP4_PACKET
);
32 Seed
->Length
= sizeof (Seed
->Dhcp4
);
33 Header
= &Seed
->Dhcp4
.Header
;
34 ZeroMem (Header
, sizeof (EFI_DHCP4_HEADER
));
35 Header
->OpCode
= DHCP4_OPCODE_REQUEST
;
36 Header
->HwType
= InterfaceInfo
->IfType
;
37 Header
->HwAddrLen
= (UINT8
) InterfaceInfo
->HwAddressSize
;
38 CopyMem (Header
->ClientHwAddr
, &(InterfaceInfo
->HwAddress
), Header
->HwAddrLen
);
40 Seed
->Dhcp4
.Magik
= DHCP4_MAGIC
;
41 Seed
->Dhcp4
.Option
[0] = DHCP4_TAG_EOP
;
45 The common notify function.
47 @param[in] Event The event signaled.
48 @param[in] Context The context.
58 if ((Event
== NULL
) || (Context
== NULL
)) {
62 *((BOOLEAN
*) Context
) = TRUE
;
66 Parse the ACK to get required information
68 @param Dhcp4 The DHCP4 protocol.
69 @param Packet Packet waiting for parse.
70 @param DnsServerInfor The required Dns4 server information.
72 @retval EFI_SUCCESS The DNS information is got from the DHCP ACK.
73 @retval EFI_NO_MAPPING DHCP failed to acquire address and other information.
74 @retval EFI_DEVICE_ERROR Other errors as indicated.
75 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
80 IN EFI_DHCP4_PROTOCOL
*Dhcp4
,
81 IN EFI_DHCP4_PACKET
*Packet
,
82 IN DNS4_SERVER_INFOR
*DnsServerInfor
87 EFI_DHCP4_PACKET_OPTION
**OptionList
;
89 EFI_IPv4_ADDRESS
*ServerList
;
99 Status
= Dhcp4
->Parse (Dhcp4
, Packet
, &OptionCount
, OptionList
);
100 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
101 return EFI_DEVICE_ERROR
;
104 OptionList
= AllocatePool (OptionCount
* sizeof (EFI_DHCP4_PACKET_OPTION
*));
105 if (OptionList
== NULL
) {
106 return EFI_OUT_OF_RESOURCES
;
109 Status
= Dhcp4
->Parse (Dhcp4
, Packet
, &OptionCount
, OptionList
);
110 if (EFI_ERROR (Status
)) {
111 gBS
->FreePool (OptionList
);
112 return EFI_DEVICE_ERROR
;
115 Status
= EFI_NOT_FOUND
;
117 for (Index
= 0; Index
< OptionCount
; Index
++) {
119 // Get DNS server addresses
121 if (OptionList
[Index
]->OpCode
== DHCP4_TAG_DNS_SERVER
) {
123 if (((OptionList
[Index
]->Length
& 0x3) != 0) || (OptionList
[Index
]->Length
== 0)) {
124 Status
= EFI_DEVICE_ERROR
;
128 ServerCount
= OptionList
[Index
]->Length
/4;
129 ServerList
= AllocatePool (ServerCount
* sizeof (EFI_IPv4_ADDRESS
));
130 if (ServerList
== NULL
) {
131 return EFI_OUT_OF_RESOURCES
;
134 for(Count
=0; Count
< ServerCount
; Count
++){
135 CopyMem (ServerList
+ Count
, &OptionList
[Index
]->Data
[4 * Count
], sizeof (EFI_IPv4_ADDRESS
));
138 *(DnsServerInfor
->ServerCount
) = ServerCount
;
139 DnsServerInfor
->ServerList
= ServerList
;
141 Status
= EFI_SUCCESS
;
145 gBS
->FreePool (OptionList
);
151 EFI_DHCP6_INFO_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol
152 instance to intercept events that occurs in the DHCPv6 Information Request
155 @param This Pointer to the EFI_DHCP6_PROTOCOL instance that
156 is used to configure this callback function.
157 @param Context Pointer to the context that is initialized in
158 the EFI_DHCP6_PROTOCOL.InfoRequest().
159 @param Packet Pointer to Reply packet that has been received.
160 The EFI DHCPv6 Protocol instance is responsible
161 for freeing the buffer.
163 @retval EFI_SUCCESS The DNS information is got from the DHCP ACK.
164 @retval EFI_DEVICE_ERROR Other errors as indicated.
165 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
170 IN EFI_DHCP6_PROTOCOL
*This
,
172 IN EFI_DHCP6_PACKET
*Packet
177 EFI_DHCP6_PACKET_OPTION
**OptionList
;
178 DNS6_SERVER_INFOR
*DnsServerInfor
;
180 EFI_IPv6_ADDRESS
*ServerList
;
188 Status
= This
->Parse (This
, Packet
, &OptionCount
, NULL
);
189 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
190 return EFI_DEVICE_ERROR
;
193 OptionList
= AllocateZeroPool (OptionCount
* sizeof (EFI_DHCP6_PACKET_OPTION
*));
194 if (OptionList
== NULL
) {
195 return EFI_OUT_OF_RESOURCES
;
198 Status
= This
->Parse (This
, Packet
, &OptionCount
, OptionList
);
199 if (EFI_ERROR (Status
)) {
200 gBS
->FreePool (OptionList
);
201 return EFI_DEVICE_ERROR
;
204 DnsServerInfor
= (DNS6_SERVER_INFOR
*) Context
;
206 for (Index
= 0; Index
< OptionCount
; Index
++) {
207 OptionList
[Index
]->OpCode
= NTOHS (OptionList
[Index
]->OpCode
);
208 OptionList
[Index
]->OpLen
= NTOHS (OptionList
[Index
]->OpLen
);
211 // Get DNS server addresses from this reply packet.
213 if (OptionList
[Index
]->OpCode
== DHCP6_TAG_DNS_SERVER
) {
215 if (((OptionList
[Index
]->OpLen
& 0xf) != 0) || (OptionList
[Index
]->OpLen
== 0)) {
216 Status
= EFI_DEVICE_ERROR
;
217 gBS
->FreePool (OptionList
);
221 ServerCount
= OptionList
[Index
]->OpLen
/16;
222 ServerList
= AllocatePool (ServerCount
* sizeof (EFI_IPv6_ADDRESS
));
223 if (ServerList
== NULL
) {
224 gBS
->FreePool (OptionList
);
225 return EFI_OUT_OF_RESOURCES
;
228 for(Count
=0; Count
< ServerCount
; Count
++){
229 CopyMem (ServerList
+ Count
, &OptionList
[Index
]->Data
[16 * Count
], sizeof (EFI_IPv6_ADDRESS
));
232 *(DnsServerInfor
->ServerCount
) = ServerCount
;
233 DnsServerInfor
->ServerList
= ServerList
;
237 gBS
->FreePool (OptionList
);
244 Parse the DHCP ACK to get Dns4 server information.
246 @param Instance The DNS instance.
247 @param DnsServerCount Retrieved Dns4 server Ip count.
248 @param DnsServerList Retrieved Dns4 server Ip list.
250 @retval EFI_SUCCESS The Dns4 information is got from the DHCP ACK.
251 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
252 @retval EFI_NO_MEDIA There was a media error.
253 @retval Others Other errors as indicated.
257 GetDns4ServerFromDhcp4 (
258 IN DNS_INSTANCE
*Instance
,
259 OUT UINT32
*DnsServerCount
,
260 OUT EFI_IPv4_ADDRESS
**DnsServerList
265 EFI_HANDLE Controller
;
266 EFI_STATUS MediaStatus
;
267 EFI_HANDLE MnpChildHandle
;
268 EFI_MANAGED_NETWORK_PROTOCOL
*Mnp
;
269 EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData
;
270 EFI_HANDLE Dhcp4Handle
;
271 EFI_DHCP4_PROTOCOL
*Dhcp4
;
272 EFI_IP4_CONFIG2_PROTOCOL
*Ip4Config2
;
275 EFI_IP4_CONFIG2_INTERFACE_INFO
*InterfaceInfo
;
276 EFI_DHCP4_PACKET SeedPacket
;
277 EFI_DHCP4_PACKET_OPTION
*ParaList
[2];
278 DNS4_SERVER_INFOR DnsServerInfor
;
280 EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN Token
;
284 Image
= Instance
->Service
->ImageHandle
;
285 Controller
= Instance
->Service
->ControllerHandle
;
287 MnpChildHandle
= NULL
;
296 InterfaceInfo
= NULL
;
298 ZeroMem ((UINT8
*) ParaList
, sizeof (ParaList
));
300 ZeroMem (&MnpConfigData
, sizeof (EFI_MANAGED_NETWORK_CONFIG_DATA
));
302 ZeroMem (&DnsServerInfor
, sizeof (DNS4_SERVER_INFOR
));
304 ZeroMem (&Token
, sizeof (EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN
));
306 DnsServerInfor
.ServerCount
= DnsServerCount
;
313 MediaStatus
= EFI_SUCCESS
;
314 NetLibDetectMediaWaitTimeout (Controller
, DNS_CHECK_MEDIA_GET_DHCP_WAITING_TIME
, &MediaStatus
);
315 if (MediaStatus
!= EFI_SUCCESS
) {
320 // Create a Mnp child instance, get the protocol and config for it.
322 Status
= NetLibCreateServiceChild (
325 &gEfiManagedNetworkServiceBindingProtocolGuid
,
328 if (EFI_ERROR (Status
)) {
332 Status
= gBS
->OpenProtocol (
334 &gEfiManagedNetworkProtocolGuid
,
338 EFI_OPEN_PROTOCOL_BY_DRIVER
340 if (EFI_ERROR (Status
)) {
344 MnpConfigData
.ReceivedQueueTimeoutValue
= 0;
345 MnpConfigData
.TransmitQueueTimeoutValue
= 0;
346 MnpConfigData
.ProtocolTypeFilter
= IP4_ETHER_PROTO
;
347 MnpConfigData
.EnableUnicastReceive
= TRUE
;
348 MnpConfigData
.EnableMulticastReceive
= TRUE
;
349 MnpConfigData
.EnableBroadcastReceive
= TRUE
;
350 MnpConfigData
.EnablePromiscuousReceive
= FALSE
;
351 MnpConfigData
.FlushQueuesOnReset
= TRUE
;
352 MnpConfigData
.EnableReceiveTimestamps
= FALSE
;
353 MnpConfigData
.DisableBackgroundPolling
= FALSE
;
355 Status
= Mnp
->Configure(Mnp
, &MnpConfigData
);
356 if (EFI_ERROR (Status
)) {
361 // Create a DHCP4 child instance and get the protocol.
363 Status
= NetLibCreateServiceChild (
366 &gEfiDhcp4ServiceBindingProtocolGuid
,
369 if (EFI_ERROR (Status
)) {
373 Status
= gBS
->OpenProtocol (
375 &gEfiDhcp4ProtocolGuid
,
379 EFI_OPEN_PROTOCOL_BY_DRIVER
381 if (EFI_ERROR (Status
)) {
386 // Get Ip4Config2 instance info.
388 Status
= gBS
->HandleProtocol (Controller
, &gEfiIp4Config2ProtocolGuid
, (VOID
**) &Ip4Config2
);
389 if (EFI_ERROR (Status
)) {
393 Status
= Ip4Config2
->GetData (Ip4Config2
, Ip4Config2DataTypeInterfaceInfo
, &DataSize
, Data
);
394 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
398 Data
= AllocateZeroPool (DataSize
);
400 Status
= EFI_OUT_OF_RESOURCES
;
404 Status
= Ip4Config2
->GetData (Ip4Config2
, Ip4Config2DataTypeInterfaceInfo
, &DataSize
, Data
);
405 if (EFI_ERROR (Status
)) {
409 InterfaceInfo
= (EFI_IP4_CONFIG2_INTERFACE_INFO
*)Data
;
412 // Build required Token.
414 Status
= gBS
->CreateEvent (
419 &Token
.CompletionEvent
421 if (EFI_ERROR (Status
)) {
425 SetMem (&Token
.RemoteAddress
, sizeof (EFI_IPv4_ADDRESS
), 0xff);
427 Token
.RemotePort
= 67;
429 Token
.ListenPointCount
= 1;
431 Token
.ListenPoints
= AllocateZeroPool (Token
.ListenPointCount
* sizeof (EFI_DHCP4_LISTEN_POINT
));
432 if (Token
.ListenPoints
== NULL
) {
433 Status
= EFI_OUT_OF_RESOURCES
;
437 if (Instance
->Dns4CfgData
.UseDefaultSetting
) {
438 CopyMem (&(Token
.ListenPoints
[0].ListenAddress
), &(InterfaceInfo
->StationAddress
), sizeof (EFI_IPv4_ADDRESS
));
439 CopyMem (&(Token
.ListenPoints
[0].SubnetMask
), &(InterfaceInfo
->SubnetMask
), sizeof (EFI_IPv4_ADDRESS
));
441 CopyMem (&(Token
.ListenPoints
[0].ListenAddress
), &(Instance
->Dns4CfgData
.StationIp
), sizeof (EFI_IPv4_ADDRESS
));
442 CopyMem (&(Token
.ListenPoints
[0].SubnetMask
), &(Instance
->Dns4CfgData
.SubnetMask
), sizeof (EFI_IPv4_ADDRESS
));
445 Token
.ListenPoints
[0].ListenPort
= 68;
447 Token
.TimeoutValue
= DNS_TIME_TO_GETMAP
;
449 DnsInitSeedPacket (&SeedPacket
, InterfaceInfo
);
451 ParaList
[0] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION
));
452 if (ParaList
[0] == NULL
) {
453 Status
= EFI_OUT_OF_RESOURCES
;
457 ParaList
[0]->OpCode
= DHCP4_TAG_TYPE
;
458 ParaList
[0]->Length
= 1;
459 ParaList
[0]->Data
[0] = DHCP4_MSG_REQUEST
;
461 ParaList
[1] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION
));
462 if (ParaList
[1] == NULL
) {
463 Status
= EFI_OUT_OF_RESOURCES
;
467 ParaList
[1]->OpCode
= DHCP4_TAG_PARA_LIST
;
468 ParaList
[1]->Length
= 1;
469 ParaList
[1]->Data
[0] = DHCP4_TAG_DNS_SERVER
;
471 Status
= Dhcp4
->Build (Dhcp4
, &SeedPacket
, 0, NULL
, 2, ParaList
, &Token
.Packet
);
473 Token
.Packet
->Dhcp4
.Header
.Xid
= HTONL(NET_RANDOM (NetRandomInitSeed ()));
475 Token
.Packet
->Dhcp4
.Header
.Reserved
= HTONS ((UINT16
)0x8000);
477 if (Instance
->Dns4CfgData
.UseDefaultSetting
) {
478 CopyMem (&(Token
.Packet
->Dhcp4
.Header
.ClientAddr
), &(InterfaceInfo
->StationAddress
), sizeof (EFI_IPv4_ADDRESS
));
480 CopyMem (&(Token
.Packet
->Dhcp4
.Header
.ClientAddr
), &(Instance
->Dns4CfgData
.StationIp
), sizeof (EFI_IPv4_ADDRESS
));
483 CopyMem (Token
.Packet
->Dhcp4
.Header
.ClientHwAddr
, &(InterfaceInfo
->HwAddress
), InterfaceInfo
->HwAddressSize
);
485 Token
.Packet
->Dhcp4
.Header
.HwAddrLen
= (UINT8
)(InterfaceInfo
->HwAddressSize
);
488 // TransmitReceive Token
490 Status
= Dhcp4
->TransmitReceive (Dhcp4
, &Token
);
491 if (EFI_ERROR (Status
)) {
499 Status
= Mnp
->Poll (Mnp
);
503 // Parse the ACK to get required information if received done.
505 if (IsDone
&& !EFI_ERROR (Token
.Status
)) {
506 for (Index
= 0; Index
< Token
.ResponseCount
; Index
++) {
507 Status
= ParseDhcp4Ack (Dhcp4
, &Token
.ResponseList
[Index
], &DnsServerInfor
);
508 if (!EFI_ERROR (Status
)) {
513 *DnsServerList
= DnsServerInfor
.ServerList
;
515 Status
= Token
.Status
;
524 for (Index
= 0; Index
< 2; Index
++) {
525 if (ParaList
[Index
] != NULL
) {
526 FreePool (ParaList
[Index
]);
530 if (Token
.ListenPoints
) {
531 FreePool (Token
.ListenPoints
);
535 FreePool (Token
.Packet
);
538 if (Token
.ResponseList
!= NULL
) {
539 FreePool (Token
.ResponseList
);
542 if (Token
.CompletionEvent
!= NULL
) {
543 gBS
->CloseEvent (Token
.CompletionEvent
);
548 Dhcp4
->Configure (Dhcp4
, NULL
);
552 &gEfiDhcp4ProtocolGuid
,
558 if (Dhcp4Handle
!= NULL
) {
559 NetLibDestroyServiceChild (
562 &gEfiDhcp4ServiceBindingProtocolGuid
,
568 Mnp
->Configure (Mnp
, NULL
);
572 &gEfiManagedNetworkProtocolGuid
,
578 NetLibDestroyServiceChild (
581 &gEfiManagedNetworkServiceBindingProtocolGuid
,
589 Parse the DHCP ACK to get Dns6 server information.
591 @param Image The handle of the driver image.
592 @param Controller The handle of the controller.
593 @param DnsServerCount Retrieved Dns6 server Ip count.
594 @param DnsServerList Retrieved Dns6 server Ip list.
596 @retval EFI_SUCCESS The Dns6 information is got from the DHCP ACK.
597 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
598 @retval EFI_NO_MEDIA There was a media error.
599 @retval Others Other errors as indicated.
603 GetDns6ServerFromDhcp6 (
605 IN EFI_HANDLE Controller
,
606 OUT UINT32
*DnsServerCount
,
607 OUT EFI_IPv6_ADDRESS
**DnsServerList
610 EFI_HANDLE Dhcp6Handle
;
611 EFI_DHCP6_PROTOCOL
*Dhcp6
;
613 EFI_STATUS TimerStatus
;
614 EFI_DHCP6_PACKET_OPTION
*Oro
;
615 EFI_DHCP6_RETRANSMISSION InfoReqReXmit
;
617 EFI_STATUS MediaStatus
;
618 DNS6_SERVER_INFOR DnsServerInfor
;
625 ZeroMem (&DnsServerInfor
, sizeof (DNS6_SERVER_INFOR
));
627 DnsServerInfor
.ServerCount
= DnsServerCount
;
630 // Check media status before doing DHCP.
632 MediaStatus
= EFI_SUCCESS
;
633 NetLibDetectMediaWaitTimeout (Controller
, DNS_CHECK_MEDIA_GET_DHCP_WAITING_TIME
, &MediaStatus
);
634 if (MediaStatus
!= EFI_SUCCESS
) {
639 // Create a DHCP6 child instance and get the protocol.
641 Status
= NetLibCreateServiceChild (
644 &gEfiDhcp6ServiceBindingProtocolGuid
,
647 if (EFI_ERROR (Status
)) {
651 Status
= gBS
->OpenProtocol (
653 &gEfiDhcp6ProtocolGuid
,
657 EFI_OPEN_PROTOCOL_BY_DRIVER
659 if (EFI_ERROR (Status
)) {
663 Oro
= AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION
) + 1);
665 Status
= EFI_OUT_OF_RESOURCES
;
670 // Ask the server to reply with DNS options.
671 // All members in EFI_DHCP6_PACKET_OPTION are in network order.
673 Oro
->OpCode
= HTONS (DHCP6_TAG_DNS_REQUEST
);
674 Oro
->OpLen
= HTONS (2);
675 Oro
->Data
[1] = DHCP6_TAG_DNS_SERVER
;
677 InfoReqReXmit
.Irt
= 4;
678 InfoReqReXmit
.Mrc
= 1;
679 InfoReqReXmit
.Mrt
= 10;
680 InfoReqReXmit
.Mrd
= 30;
682 Status
= Dhcp6
->InfoRequest (
693 if (Status
== EFI_NO_MAPPING
) {
694 Status
= gBS
->CreateEvent (EVT_TIMER
, TPL_CALLBACK
, NULL
, NULL
, &Timer
);
695 if (EFI_ERROR (Status
)) {
699 Status
= gBS
->SetTimer (
702 DNS_TIME_TO_GETMAP
* TICKS_PER_SECOND
705 if (EFI_ERROR (Status
)) {
710 TimerStatus
= gBS
->CheckEvent (Timer
);
711 if (!EFI_ERROR (TimerStatus
)) {
712 Status
= Dhcp6
->InfoRequest (
724 } while (TimerStatus
== EFI_NOT_READY
);
727 *DnsServerList
= DnsServerInfor
.ServerList
;
736 gBS
->CloseEvent (Timer
);
742 &gEfiDhcp6ProtocolGuid
,
748 NetLibDestroyServiceChild (
751 &gEfiDhcp6ServiceBindingProtocolGuid
,