2 Functions implementation related with DHCPv4/v6 for DNS driver.
4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 This software and associated documentation (if any) is furnished
6 under a license and may only be used or copied in accordance
7 with the terms of the license. Except as permitted by such
8 license, no part of this software or documentation may be
9 reproduced, stored in a retrieval system, or transmitted in any
10 form or by any means without the express written consent of
18 This function initialize the DHCP4 message instance.
20 This function will pad each item of dhcp4 message packet.
22 @param Seed Pointer to the message instance of the DHCP4 packet.
23 @param InterfaceInfo Pointer to the EFI_IP4_CONFIG2_INTERFACE_INFO instance.
28 OUT EFI_DHCP4_PACKET
*Seed
,
29 IN EFI_IP4_CONFIG2_INTERFACE_INFO
*InterfaceInfo
32 EFI_DHCP4_HEADER
*Header
;
35 // Get IfType and HwAddressSize from SNP mode data.
37 Seed
->Size
= sizeof (EFI_DHCP4_PACKET
);
38 Seed
->Length
= sizeof (Seed
->Dhcp4
);
39 Header
= &Seed
->Dhcp4
.Header
;
40 ZeroMem (Header
, sizeof (EFI_DHCP4_HEADER
));
41 Header
->OpCode
= DHCP4_OPCODE_REQUEST
;
42 Header
->HwType
= InterfaceInfo
->IfType
;
43 Header
->HwAddrLen
= (UINT8
) InterfaceInfo
->HwAddressSize
;
44 CopyMem (Header
->ClientHwAddr
, &(InterfaceInfo
->HwAddress
), Header
->HwAddrLen
);
46 Seed
->Dhcp4
.Magik
= DHCP4_MAGIC
;
47 Seed
->Dhcp4
.Option
[0] = DHCP4_TAG_EOP
;
51 The common notify function.
53 @param[in] Event The event signaled.
54 @param[in] Context The context.
64 if ((Event
== NULL
) || (Context
== NULL
)) {
68 *((BOOLEAN
*) Context
) = TRUE
;
72 Parse the ACK to get required information
74 @param Dhcp4 The DHCP4 protocol.
75 @param Packet Packet waiting for parse.
76 @param DnsServerInfor The required Dns4 server information.
78 @retval EFI_SUCCESS The DNS information is got from the DHCP ACK.
79 @retval EFI_NO_MAPPING DHCP failed to acquire address and other information.
80 @retval EFI_DEVICE_ERROR Other errors as indicated.
81 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
86 IN EFI_DHCP4_PROTOCOL
*Dhcp4
,
87 IN EFI_DHCP4_PACKET
*Packet
,
88 IN DNS4_SERVER_INFOR
*DnsServerInfor
93 EFI_DHCP4_PACKET_OPTION
**OptionList
;
95 EFI_IPv4_ADDRESS
*ServerList
;
105 Status
= Dhcp4
->Parse (Dhcp4
, Packet
, &OptionCount
, OptionList
);
106 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
107 return EFI_DEVICE_ERROR
;
110 OptionList
= AllocatePool (OptionCount
* sizeof (EFI_DHCP4_PACKET_OPTION
*));
111 if (OptionList
== NULL
) {
112 return EFI_OUT_OF_RESOURCES
;
115 Status
= Dhcp4
->Parse (Dhcp4
, Packet
, &OptionCount
, OptionList
);
116 if (EFI_ERROR (Status
)) {
117 gBS
->FreePool (OptionList
);
118 return EFI_DEVICE_ERROR
;
121 Status
= EFI_NOT_FOUND
;
123 for (Index
= 0; Index
< OptionCount
; Index
++) {
125 // Get DNS server addresses
127 if (OptionList
[Index
]->OpCode
== DHCP4_TAG_DNS_SERVER
) {
129 if (((OptionList
[Index
]->Length
& 0x3) != 0) || (OptionList
[Index
]->Length
== 0)) {
130 Status
= EFI_DEVICE_ERROR
;
134 ServerCount
= OptionList
[Index
]->Length
/4;
135 ServerList
= AllocatePool (ServerCount
* sizeof (EFI_IPv4_ADDRESS
));
136 if (ServerList
== NULL
) {
137 return EFI_OUT_OF_RESOURCES
;
140 for(Count
=0; Count
< ServerCount
; Count
++){
141 CopyMem (ServerList
+ Count
, &OptionList
[Index
]->Data
[4 * Count
], sizeof (EFI_IPv4_ADDRESS
));
144 *(DnsServerInfor
->ServerCount
) = ServerCount
;
145 DnsServerInfor
->ServerList
= ServerList
;
147 Status
= EFI_SUCCESS
;
151 gBS
->FreePool (OptionList
);
157 EFI_DHCP6_INFO_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol
158 instance to intercept events that occurs in the DHCPv6 Information Request
161 @param This Pointer to the EFI_DHCP6_PROTOCOL instance that
162 is used to configure this callback function.
163 @param Context Pointer to the context that is initialized in
164 the EFI_DHCP6_PROTOCOL.InfoRequest().
165 @param Packet Pointer to Reply packet that has been received.
166 The EFI DHCPv6 Protocol instance is responsible
167 for freeing the buffer.
169 @retval EFI_SUCCESS The DNS information is got from the DHCP ACK.
170 @retval EFI_DEVICE_ERROR Other errors as indicated.
171 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
176 IN EFI_DHCP6_PROTOCOL
*This
,
178 IN EFI_DHCP6_PACKET
*Packet
183 EFI_DHCP6_PACKET_OPTION
**OptionList
;
184 DNS6_SERVER_INFOR
*DnsServerInfor
;
186 EFI_IPv6_ADDRESS
*ServerList
;
194 Status
= This
->Parse (This
, Packet
, &OptionCount
, NULL
);
195 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
196 return EFI_DEVICE_ERROR
;
199 OptionList
= AllocateZeroPool (OptionCount
* sizeof (EFI_DHCP6_PACKET_OPTION
*));
200 if (OptionList
== NULL
) {
201 return EFI_OUT_OF_RESOURCES
;
204 Status
= This
->Parse (This
, Packet
, &OptionCount
, OptionList
);
205 if (EFI_ERROR (Status
)) {
206 gBS
->FreePool (OptionList
);
207 return EFI_DEVICE_ERROR
;
210 DnsServerInfor
= (DNS6_SERVER_INFOR
*) Context
;
212 for (Index
= 0; Index
< OptionCount
; Index
++) {
213 OptionList
[Index
]->OpCode
= NTOHS (OptionList
[Index
]->OpCode
);
214 OptionList
[Index
]->OpLen
= NTOHS (OptionList
[Index
]->OpLen
);
217 // Get DNS server addresses from this reply packet.
219 if (OptionList
[Index
]->OpCode
== DHCP6_TAG_DNS_SERVER
) {
221 if (((OptionList
[Index
]->OpLen
& 0xf) != 0) || (OptionList
[Index
]->OpLen
== 0)) {
222 Status
= EFI_DEVICE_ERROR
;
223 gBS
->FreePool (OptionList
);
227 ServerCount
= OptionList
[Index
]->OpLen
/16;
228 ServerList
= AllocatePool (ServerCount
* sizeof (EFI_IPv6_ADDRESS
));
229 if (ServerList
== NULL
) {
230 gBS
->FreePool (OptionList
);
231 return EFI_OUT_OF_RESOURCES
;
234 for(Count
=0; Count
< ServerCount
; Count
++){
235 CopyMem (ServerList
+ Count
, &OptionList
[Index
]->Data
[16 * Count
], sizeof (EFI_IPv6_ADDRESS
));
238 *(DnsServerInfor
->ServerCount
) = ServerCount
;
239 DnsServerInfor
->ServerList
= ServerList
;
243 gBS
->FreePool (OptionList
);
250 Parse the DHCP ACK to get Dns4 server information.
252 @param Instance The DNS instance.
253 @param DnsServerCount Retrieved Dns4 server Ip count.
254 @param DnsServerList Retrieved Dns4 server Ip list.
256 @retval EFI_SUCCESS The Dns4 information is got from the DHCP ACK.
257 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
258 @retval EFI_NO_MEDIA There was a media error.
259 @retval Others Other errors as indicated.
263 GetDns4ServerFromDhcp4 (
264 IN DNS_INSTANCE
*Instance
,
265 OUT UINT32
*DnsServerCount
,
266 OUT EFI_IPv4_ADDRESS
**DnsServerList
271 EFI_HANDLE Controller
;
272 BOOLEAN MediaPresent
;
273 EFI_HANDLE MnpChildHandle
;
274 EFI_MANAGED_NETWORK_PROTOCOL
*Mnp
;
275 EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData
;
276 EFI_HANDLE Dhcp4Handle
;
277 EFI_DHCP4_PROTOCOL
*Dhcp4
;
278 EFI_IP4_CONFIG2_PROTOCOL
*Ip4Config2
;
281 EFI_IP4_CONFIG2_INTERFACE_INFO
*InterfaceInfo
;
282 EFI_DHCP4_PACKET SeedPacket
;
283 EFI_DHCP4_PACKET_OPTION
*ParaList
[2];
284 DNS4_SERVER_INFOR DnsServerInfor
;
286 EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN Token
;
290 Image
= Instance
->Service
->ImageHandle
;
291 Controller
= Instance
->Service
->ControllerHandle
;
293 MnpChildHandle
= NULL
;
302 InterfaceInfo
= NULL
;
304 ZeroMem (&MnpConfigData
, sizeof (EFI_MANAGED_NETWORK_CONFIG_DATA
));
306 ZeroMem (&DnsServerInfor
, sizeof (DNS4_SERVER_INFOR
));
308 ZeroMem (&Token
, sizeof (EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN
));
310 DnsServerInfor
.ServerCount
= DnsServerCount
;
318 NetLibDetectMedia (Controller
, &MediaPresent
);
324 // Create a Mnp child instance, get the protocol and config for it.
326 Status
= NetLibCreateServiceChild (
329 &gEfiManagedNetworkServiceBindingProtocolGuid
,
332 if (EFI_ERROR (Status
)) {
336 Status
= gBS
->OpenProtocol (
338 &gEfiManagedNetworkProtocolGuid
,
342 EFI_OPEN_PROTOCOL_BY_DRIVER
344 if (EFI_ERROR (Status
)) {
348 MnpConfigData
.ReceivedQueueTimeoutValue
= 0;
349 MnpConfigData
.TransmitQueueTimeoutValue
= 0;
350 MnpConfigData
.ProtocolTypeFilter
= IP4_ETHER_PROTO
;
351 MnpConfigData
.EnableUnicastReceive
= TRUE
;
352 MnpConfigData
.EnableMulticastReceive
= TRUE
;
353 MnpConfigData
.EnableBroadcastReceive
= TRUE
;
354 MnpConfigData
.EnablePromiscuousReceive
= FALSE
;
355 MnpConfigData
.FlushQueuesOnReset
= TRUE
;
356 MnpConfigData
.EnableReceiveTimestamps
= FALSE
;
357 MnpConfigData
.DisableBackgroundPolling
= FALSE
;
359 Status
= Mnp
->Configure(Mnp
, &MnpConfigData
);
360 if (EFI_ERROR (Status
)) {
365 // Create a DHCP4 child instance and get the protocol.
367 Status
= NetLibCreateServiceChild (
370 &gEfiDhcp4ServiceBindingProtocolGuid
,
373 if (EFI_ERROR (Status
)) {
377 Status
= gBS
->OpenProtocol (
379 &gEfiDhcp4ProtocolGuid
,
383 EFI_OPEN_PROTOCOL_BY_DRIVER
385 if (EFI_ERROR (Status
)) {
390 // Get Ip4Config2 instance info.
392 Status
= gBS
->HandleProtocol (Controller
, &gEfiIp4Config2ProtocolGuid
, (VOID
**) &Ip4Config2
);
393 if (EFI_ERROR (Status
)) {
397 Status
= Ip4Config2
->GetData (Ip4Config2
, Ip4Config2DataTypeInterfaceInfo
, &DataSize
, Data
);
398 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
402 Data
= AllocateZeroPool (DataSize
);
404 Status
= EFI_OUT_OF_RESOURCES
;
408 Status
= Ip4Config2
->GetData (Ip4Config2
, Ip4Config2DataTypeInterfaceInfo
, &DataSize
, Data
);
409 if (EFI_ERROR (Status
)) {
413 InterfaceInfo
= (EFI_IP4_CONFIG2_INTERFACE_INFO
*)Data
;
416 // Build required Token.
418 Status
= gBS
->CreateEvent (
423 &Token
.CompletionEvent
425 if (EFI_ERROR (Status
)) {
429 SetMem (&Token
.RemoteAddress
, sizeof (EFI_IPv4_ADDRESS
), 0xff);
431 Token
.RemotePort
= 67;
433 Token
.ListenPointCount
= 1;
435 Token
.ListenPoints
= AllocateZeroPool (Token
.ListenPointCount
* sizeof (EFI_DHCP4_LISTEN_POINT
));
436 if (Token
.ListenPoints
== NULL
) {
437 Status
= EFI_OUT_OF_RESOURCES
;
441 if (Instance
->Dns4CfgData
.UseDefaultSetting
) {
442 CopyMem (&(Token
.ListenPoints
[0].ListenAddress
), &(InterfaceInfo
->StationAddress
), sizeof (EFI_IPv4_ADDRESS
));
443 CopyMem (&(Token
.ListenPoints
[0].SubnetMask
), &(InterfaceInfo
->SubnetMask
), sizeof (EFI_IPv4_ADDRESS
));
445 CopyMem (&(Token
.ListenPoints
[0].ListenAddress
), &(Instance
->Dns4CfgData
.StationIp
), sizeof (EFI_IPv4_ADDRESS
));
446 CopyMem (&(Token
.ListenPoints
[0].SubnetMask
), &(Instance
->Dns4CfgData
.SubnetMask
), sizeof (EFI_IPv4_ADDRESS
));
449 Token
.ListenPoints
[0].ListenPort
= 68;
451 Token
.TimeoutValue
= DNS_TIME_TO_GETMAP
;
453 DnsInitSeedPacket (&SeedPacket
, InterfaceInfo
);
455 ParaList
[0] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION
));
456 if (ParaList
[0] == NULL
) {
457 Status
= EFI_OUT_OF_RESOURCES
;
461 ParaList
[0]->OpCode
= DHCP4_TAG_TYPE
;
462 ParaList
[0]->Length
= 1;
463 ParaList
[0]->Data
[0] = DHCP4_MSG_INFORM
;
465 ParaList
[1] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION
));
466 if (ParaList
[1] == NULL
) {
467 Status
= EFI_OUT_OF_RESOURCES
;
471 ParaList
[1]->OpCode
= DHCP4_TAG_PARA_LIST
;
472 ParaList
[1]->Length
= 1;
473 ParaList
[1]->Data
[0] = DHCP4_TAG_DNS_SERVER
;
475 Status
= Dhcp4
->Build (Dhcp4
, &SeedPacket
, 0, NULL
, 2, ParaList
, &Token
.Packet
);
477 Token
.Packet
->Dhcp4
.Header
.Xid
= HTONL(NET_RANDOM (NetRandomInitSeed ()));
479 Token
.Packet
->Dhcp4
.Header
.Reserved
= HTONS ((UINT16
)0x8000);
481 if (Instance
->Dns4CfgData
.UseDefaultSetting
) {
482 CopyMem (&(Token
.Packet
->Dhcp4
.Header
.ClientAddr
), &(InterfaceInfo
->StationAddress
), sizeof (EFI_IPv4_ADDRESS
));
484 CopyMem (&(Token
.Packet
->Dhcp4
.Header
.ClientAddr
), &(Instance
->Dns4CfgData
.StationIp
), sizeof (EFI_IPv4_ADDRESS
));
487 CopyMem (Token
.Packet
->Dhcp4
.Header
.ClientHwAddr
, &(InterfaceInfo
->HwAddress
), InterfaceInfo
->HwAddressSize
);
489 Token
.Packet
->Dhcp4
.Header
.HwAddrLen
= (UINT8
)(InterfaceInfo
->HwAddressSize
);
492 // TransmitReceive Token
494 Status
= Dhcp4
->TransmitReceive (Dhcp4
, &Token
);
495 if (EFI_ERROR (Status
)) {
503 Status
= Mnp
->Poll (Mnp
);
507 // Parse the ACK to get required information if received done.
509 if (IsDone
&& !EFI_ERROR (Token
.Status
)) {
510 for (Index
= 0; Index
< Token
.ResponseCount
; Index
++) {
511 Status
= ParseDhcp4Ack (Dhcp4
, &Token
.ResponseList
[Index
], &DnsServerInfor
);
512 if (!EFI_ERROR (Status
)) {
517 *DnsServerList
= DnsServerInfor
.ServerList
;
519 Status
= Token
.Status
;
528 for (Index
= 0; Index
< 2; Index
++) {
529 if (ParaList
[Index
] != NULL
) {
530 FreePool (ParaList
[Index
]);
534 if (Token
.ListenPoints
) {
535 FreePool (Token
.ListenPoints
);
539 FreePool (Token
.Packet
);
542 if (Token
.ResponseList
!= NULL
) {
543 FreePool (Token
.ResponseList
);
546 if (Token
.CompletionEvent
!= NULL
) {
547 gBS
->CloseEvent (Token
.CompletionEvent
);
552 Dhcp4
->Configure (Dhcp4
, NULL
);
556 &gEfiDhcp4ProtocolGuid
,
562 if (Dhcp4Handle
!= NULL
) {
563 NetLibDestroyServiceChild (
566 &gEfiDhcp4ServiceBindingProtocolGuid
,
572 Mnp
->Configure (Mnp
, NULL
);
576 &gEfiManagedNetworkProtocolGuid
,
582 NetLibDestroyServiceChild (
585 &gEfiManagedNetworkServiceBindingProtocolGuid
,
593 Parse the DHCP ACK to get Dns6 server information.
595 @param Image The handle of the driver image.
596 @param Controller The handle of the controller.
597 @param DnsServerCount Retrieved Dns6 server Ip count.
598 @param DnsServerList Retrieved Dns6 server Ip list.
600 @retval EFI_SUCCESS The Dns6 information is got from the DHCP ACK.
601 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
602 @retval EFI_NO_MEDIA There was a media error.
603 @retval Others Other errors as indicated.
607 GetDns6ServerFromDhcp6 (
609 IN EFI_HANDLE Controller
,
610 OUT UINT32
*DnsServerCount
,
611 OUT EFI_IPv6_ADDRESS
**DnsServerList
614 EFI_HANDLE Dhcp6Handle
;
615 EFI_DHCP6_PROTOCOL
*Dhcp6
;
617 EFI_STATUS TimerStatus
;
618 EFI_DHCP6_PACKET_OPTION
*Oro
;
619 EFI_DHCP6_RETRANSMISSION InfoReqReXmit
;
621 BOOLEAN MediaPresent
;
622 DNS6_SERVER_INFOR DnsServerInfor
;
629 ZeroMem (&DnsServerInfor
, sizeof (DNS6_SERVER_INFOR
));
631 DnsServerInfor
.ServerCount
= DnsServerCount
;
634 // Check media status before doing DHCP.
637 NetLibDetectMedia (Controller
, &MediaPresent
);
643 // Create a DHCP6 child instance and get the protocol.
645 Status
= NetLibCreateServiceChild (
648 &gEfiDhcp6ServiceBindingProtocolGuid
,
651 if (EFI_ERROR (Status
)) {
655 Status
= gBS
->OpenProtocol (
657 &gEfiDhcp6ProtocolGuid
,
661 EFI_OPEN_PROTOCOL_BY_DRIVER
663 if (EFI_ERROR (Status
)) {
667 Oro
= AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION
) + 1);
669 Status
= EFI_OUT_OF_RESOURCES
;
674 // Ask the server to reply with DNS options.
675 // All members in EFI_DHCP6_PACKET_OPTION are in network order.
677 Oro
->OpCode
= HTONS (DHCP6_TAG_DNS_REQUEST
);
678 Oro
->OpLen
= HTONS (2);
679 Oro
->Data
[1] = DHCP6_TAG_DNS_SERVER
;
681 InfoReqReXmit
.Irt
= 4;
682 InfoReqReXmit
.Mrc
= 1;
683 InfoReqReXmit
.Mrt
= 10;
684 InfoReqReXmit
.Mrd
= 30;
686 Status
= Dhcp6
->InfoRequest (
697 if (Status
== EFI_NO_MAPPING
) {
698 Status
= gBS
->CreateEvent (EVT_TIMER
, TPL_CALLBACK
, NULL
, NULL
, &Timer
);
699 if (EFI_ERROR (Status
)) {
703 Status
= gBS
->SetTimer (
706 DNS_TIME_TO_GETMAP
* TICKS_PER_SECOND
709 if (EFI_ERROR (Status
)) {
714 TimerStatus
= gBS
->CheckEvent (Timer
);
715 if (!EFI_ERROR (TimerStatus
)) {
716 Status
= Dhcp6
->InfoRequest (
728 } while (TimerStatus
== EFI_NOT_READY
);
731 *DnsServerList
= DnsServerInfor
.ServerList
;
740 gBS
->CloseEvent (Timer
);
746 &gEfiDhcp6ProtocolGuid
,
752 NetLibDestroyServiceChild (
755 &gEfiDhcp6ServiceBindingProtocolGuid
,