2 Functions implementation related with DHCPv4/v6 for DNS driver.
4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
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 ((UINT8
*) ParaList
, sizeof (ParaList
));
306 ZeroMem (&MnpConfigData
, sizeof (EFI_MANAGED_NETWORK_CONFIG_DATA
));
308 ZeroMem (&DnsServerInfor
, sizeof (DNS4_SERVER_INFOR
));
310 ZeroMem (&Token
, sizeof (EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN
));
312 DnsServerInfor
.ServerCount
= DnsServerCount
;
320 NetLibDetectMedia (Controller
, &MediaPresent
);
326 // Create a Mnp child instance, get the protocol and config for it.
328 Status
= NetLibCreateServiceChild (
331 &gEfiManagedNetworkServiceBindingProtocolGuid
,
334 if (EFI_ERROR (Status
)) {
338 Status
= gBS
->OpenProtocol (
340 &gEfiManagedNetworkProtocolGuid
,
344 EFI_OPEN_PROTOCOL_BY_DRIVER
346 if (EFI_ERROR (Status
)) {
350 MnpConfigData
.ReceivedQueueTimeoutValue
= 0;
351 MnpConfigData
.TransmitQueueTimeoutValue
= 0;
352 MnpConfigData
.ProtocolTypeFilter
= IP4_ETHER_PROTO
;
353 MnpConfigData
.EnableUnicastReceive
= TRUE
;
354 MnpConfigData
.EnableMulticastReceive
= TRUE
;
355 MnpConfigData
.EnableBroadcastReceive
= TRUE
;
356 MnpConfigData
.EnablePromiscuousReceive
= FALSE
;
357 MnpConfigData
.FlushQueuesOnReset
= TRUE
;
358 MnpConfigData
.EnableReceiveTimestamps
= FALSE
;
359 MnpConfigData
.DisableBackgroundPolling
= FALSE
;
361 Status
= Mnp
->Configure(Mnp
, &MnpConfigData
);
362 if (EFI_ERROR (Status
)) {
367 // Create a DHCP4 child instance and get the protocol.
369 Status
= NetLibCreateServiceChild (
372 &gEfiDhcp4ServiceBindingProtocolGuid
,
375 if (EFI_ERROR (Status
)) {
379 Status
= gBS
->OpenProtocol (
381 &gEfiDhcp4ProtocolGuid
,
385 EFI_OPEN_PROTOCOL_BY_DRIVER
387 if (EFI_ERROR (Status
)) {
392 // Get Ip4Config2 instance info.
394 Status
= gBS
->HandleProtocol (Controller
, &gEfiIp4Config2ProtocolGuid
, (VOID
**) &Ip4Config2
);
395 if (EFI_ERROR (Status
)) {
399 Status
= Ip4Config2
->GetData (Ip4Config2
, Ip4Config2DataTypeInterfaceInfo
, &DataSize
, Data
);
400 if (EFI_ERROR (Status
) && Status
!= EFI_BUFFER_TOO_SMALL
) {
404 Data
= AllocateZeroPool (DataSize
);
406 Status
= EFI_OUT_OF_RESOURCES
;
410 Status
= Ip4Config2
->GetData (Ip4Config2
, Ip4Config2DataTypeInterfaceInfo
, &DataSize
, Data
);
411 if (EFI_ERROR (Status
)) {
415 InterfaceInfo
= (EFI_IP4_CONFIG2_INTERFACE_INFO
*)Data
;
418 // Build required Token.
420 Status
= gBS
->CreateEvent (
425 &Token
.CompletionEvent
427 if (EFI_ERROR (Status
)) {
431 SetMem (&Token
.RemoteAddress
, sizeof (EFI_IPv4_ADDRESS
), 0xff);
433 Token
.RemotePort
= 67;
435 Token
.ListenPointCount
= 1;
437 Token
.ListenPoints
= AllocateZeroPool (Token
.ListenPointCount
* sizeof (EFI_DHCP4_LISTEN_POINT
));
438 if (Token
.ListenPoints
== NULL
) {
439 Status
= EFI_OUT_OF_RESOURCES
;
443 if (Instance
->Dns4CfgData
.UseDefaultSetting
) {
444 CopyMem (&(Token
.ListenPoints
[0].ListenAddress
), &(InterfaceInfo
->StationAddress
), sizeof (EFI_IPv4_ADDRESS
));
445 CopyMem (&(Token
.ListenPoints
[0].SubnetMask
), &(InterfaceInfo
->SubnetMask
), sizeof (EFI_IPv4_ADDRESS
));
447 CopyMem (&(Token
.ListenPoints
[0].ListenAddress
), &(Instance
->Dns4CfgData
.StationIp
), sizeof (EFI_IPv4_ADDRESS
));
448 CopyMem (&(Token
.ListenPoints
[0].SubnetMask
), &(Instance
->Dns4CfgData
.SubnetMask
), sizeof (EFI_IPv4_ADDRESS
));
451 Token
.ListenPoints
[0].ListenPort
= 68;
453 Token
.TimeoutValue
= DNS_TIME_TO_GETMAP
;
455 DnsInitSeedPacket (&SeedPacket
, InterfaceInfo
);
457 ParaList
[0] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION
));
458 if (ParaList
[0] == NULL
) {
459 Status
= EFI_OUT_OF_RESOURCES
;
463 ParaList
[0]->OpCode
= DHCP4_TAG_TYPE
;
464 ParaList
[0]->Length
= 1;
465 ParaList
[0]->Data
[0] = DHCP4_MSG_INFORM
;
467 ParaList
[1] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION
));
468 if (ParaList
[1] == NULL
) {
469 Status
= EFI_OUT_OF_RESOURCES
;
473 ParaList
[1]->OpCode
= DHCP4_TAG_PARA_LIST
;
474 ParaList
[1]->Length
= 1;
475 ParaList
[1]->Data
[0] = DHCP4_TAG_DNS_SERVER
;
477 Status
= Dhcp4
->Build (Dhcp4
, &SeedPacket
, 0, NULL
, 2, ParaList
, &Token
.Packet
);
479 Token
.Packet
->Dhcp4
.Header
.Xid
= HTONL(NET_RANDOM (NetRandomInitSeed ()));
481 Token
.Packet
->Dhcp4
.Header
.Reserved
= HTONS ((UINT16
)0x8000);
483 if (Instance
->Dns4CfgData
.UseDefaultSetting
) {
484 CopyMem (&(Token
.Packet
->Dhcp4
.Header
.ClientAddr
), &(InterfaceInfo
->StationAddress
), sizeof (EFI_IPv4_ADDRESS
));
486 CopyMem (&(Token
.Packet
->Dhcp4
.Header
.ClientAddr
), &(Instance
->Dns4CfgData
.StationIp
), sizeof (EFI_IPv4_ADDRESS
));
489 CopyMem (Token
.Packet
->Dhcp4
.Header
.ClientHwAddr
, &(InterfaceInfo
->HwAddress
), InterfaceInfo
->HwAddressSize
);
491 Token
.Packet
->Dhcp4
.Header
.HwAddrLen
= (UINT8
)(InterfaceInfo
->HwAddressSize
);
494 // TransmitReceive Token
496 Status
= Dhcp4
->TransmitReceive (Dhcp4
, &Token
);
497 if (EFI_ERROR (Status
)) {
505 Status
= Mnp
->Poll (Mnp
);
509 // Parse the ACK to get required information if received done.
511 if (IsDone
&& !EFI_ERROR (Token
.Status
)) {
512 for (Index
= 0; Index
< Token
.ResponseCount
; Index
++) {
513 Status
= ParseDhcp4Ack (Dhcp4
, &Token
.ResponseList
[Index
], &DnsServerInfor
);
514 if (!EFI_ERROR (Status
)) {
519 *DnsServerList
= DnsServerInfor
.ServerList
;
521 Status
= Token
.Status
;
530 for (Index
= 0; Index
< 2; Index
++) {
531 if (ParaList
[Index
] != NULL
) {
532 FreePool (ParaList
[Index
]);
536 if (Token
.ListenPoints
) {
537 FreePool (Token
.ListenPoints
);
541 FreePool (Token
.Packet
);
544 if (Token
.ResponseList
!= NULL
) {
545 FreePool (Token
.ResponseList
);
548 if (Token
.CompletionEvent
!= NULL
) {
549 gBS
->CloseEvent (Token
.CompletionEvent
);
554 Dhcp4
->Configure (Dhcp4
, NULL
);
558 &gEfiDhcp4ProtocolGuid
,
564 if (Dhcp4Handle
!= NULL
) {
565 NetLibDestroyServiceChild (
568 &gEfiDhcp4ServiceBindingProtocolGuid
,
574 Mnp
->Configure (Mnp
, NULL
);
578 &gEfiManagedNetworkProtocolGuid
,
584 NetLibDestroyServiceChild (
587 &gEfiManagedNetworkServiceBindingProtocolGuid
,
595 Parse the DHCP ACK to get Dns6 server information.
597 @param Image The handle of the driver image.
598 @param Controller The handle of the controller.
599 @param DnsServerCount Retrieved Dns6 server Ip count.
600 @param DnsServerList Retrieved Dns6 server Ip list.
602 @retval EFI_SUCCESS The Dns6 information is got from the DHCP ACK.
603 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
604 @retval EFI_NO_MEDIA There was a media error.
605 @retval Others Other errors as indicated.
609 GetDns6ServerFromDhcp6 (
611 IN EFI_HANDLE Controller
,
612 OUT UINT32
*DnsServerCount
,
613 OUT EFI_IPv6_ADDRESS
**DnsServerList
616 EFI_HANDLE Dhcp6Handle
;
617 EFI_DHCP6_PROTOCOL
*Dhcp6
;
619 EFI_STATUS TimerStatus
;
620 EFI_DHCP6_PACKET_OPTION
*Oro
;
621 EFI_DHCP6_RETRANSMISSION InfoReqReXmit
;
623 BOOLEAN MediaPresent
;
624 DNS6_SERVER_INFOR DnsServerInfor
;
631 ZeroMem (&DnsServerInfor
, sizeof (DNS6_SERVER_INFOR
));
633 DnsServerInfor
.ServerCount
= DnsServerCount
;
636 // Check media status before doing DHCP.
639 NetLibDetectMedia (Controller
, &MediaPresent
);
645 // Create a DHCP6 child instance and get the protocol.
647 Status
= NetLibCreateServiceChild (
650 &gEfiDhcp6ServiceBindingProtocolGuid
,
653 if (EFI_ERROR (Status
)) {
657 Status
= gBS
->OpenProtocol (
659 &gEfiDhcp6ProtocolGuid
,
663 EFI_OPEN_PROTOCOL_BY_DRIVER
665 if (EFI_ERROR (Status
)) {
669 Oro
= AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION
) + 1);
671 Status
= EFI_OUT_OF_RESOURCES
;
676 // Ask the server to reply with DNS options.
677 // All members in EFI_DHCP6_PACKET_OPTION are in network order.
679 Oro
->OpCode
= HTONS (DHCP6_TAG_DNS_REQUEST
);
680 Oro
->OpLen
= HTONS (2);
681 Oro
->Data
[1] = DHCP6_TAG_DNS_SERVER
;
683 InfoReqReXmit
.Irt
= 4;
684 InfoReqReXmit
.Mrc
= 1;
685 InfoReqReXmit
.Mrt
= 10;
686 InfoReqReXmit
.Mrd
= 30;
688 Status
= Dhcp6
->InfoRequest (
699 if (Status
== EFI_NO_MAPPING
) {
700 Status
= gBS
->CreateEvent (EVT_TIMER
, TPL_CALLBACK
, NULL
, NULL
, &Timer
);
701 if (EFI_ERROR (Status
)) {
705 Status
= gBS
->SetTimer (
708 DNS_TIME_TO_GETMAP
* TICKS_PER_SECOND
711 if (EFI_ERROR (Status
)) {
716 TimerStatus
= gBS
->CheckEvent (Timer
);
717 if (!EFI_ERROR (TimerStatus
)) {
718 Status
= Dhcp6
->InfoRequest (
730 } while (TimerStatus
== EFI_NOT_READY
);
733 *DnsServerList
= DnsServerInfor
.ServerList
;
742 gBS
->CloseEvent (Timer
);
748 &gEfiDhcp6ProtocolGuid
,
754 NetLibDestroyServiceChild (
757 &gEfiDhcp6ServiceBindingProtocolGuid
,