X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FUniversal%2FNetwork%2FDhcp4Dxe%2FDhcp4Io.c;h=4728b94c5803110d05bb2209032ef28643183841;hp=19b897ae0d20b4b9448b50948d6f18017978cd20;hb=c0fd7f734e2d33e22215899b40a47b843129541d;hpb=e48e37fce2611df7a52aff271835ff72ee396d9b diff --git a/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Io.c b/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Io.c index 19b897ae0d..4728b94c58 100644 --- a/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Io.c +++ b/MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Io.c @@ -1,22 +1,8 @@ /** @file + EFI DHCP protocol implementation. -Copyright (c) 2006 - 2007, Intel Corporation -All rights reserved. This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. - -Module Name: - - Dhcp4Io.c - -Abstract: - - EFI DHCP protocol implementation - +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -30,9 +16,10 @@ UINT32 mDhcp4DefaultTimeout[4] = { 4, 8, 16, 32 }; Send an initial DISCOVER or REQUEST message according to the DHCP service's current state. - @param DhcpSb The DHCP service instance + @param[in] DhcpSb The DHCP service instance @retval EFI_SUCCESS The request has been sent + @retval other Some error occurs when sending the request. **/ EFI_STATUS @@ -44,6 +31,11 @@ DhcpInitRequest ( ASSERT ((DhcpSb->DhcpState == Dhcp4Init) || (DhcpSb->DhcpState == Dhcp4InitReboot)); + // + // Clear initial time to make sure that elapsed-time is set to 0 for first Discover or REQUEST message. + // + DhcpSb->ActiveChild->ElaspedTime= 0; + if (DhcpSb->DhcpState == Dhcp4Init) { DhcpSetState (DhcpSb, Dhcp4Selecting, FALSE); Status = DhcpSendMessage (DhcpSb, NULL, NULL, DHCP_MSG_DISCOVER, NULL); @@ -72,17 +64,16 @@ DhcpInitRequest ( proper return value is selected to let the caller continue the normal process. - @param DhcpSb The DHCP service instance - @param Event The event as defined in the spec - @param Packet The current packet trigger the event - @param NewPacket The user's return new packet + @param[in] DhcpSb The DHCP service instance + @param[in] Event The event as defined in the spec + @param[in] Packet The current packet trigger the event + @param[out] NewPacket The user's return new packet @retval EFI_NOT_READY Direct the caller to continue collecting the offer. @retval EFI_SUCCESS The user function returns success. @retval EFI_ABORTED The user function ask it to abort. **/ -STATIC EFI_STATUS DhcpCallUser ( IN DHCP_SERVICE *DhcpSb, @@ -141,9 +132,7 @@ DhcpCallUser ( Notify the user about the operation result. @param DhcpSb DHCP service instance - @param Which which notify function to signal - - @return None + @param Which Which notify function to signal **/ VOID @@ -159,14 +148,16 @@ DhcpNotifyUser ( } if ((Child->CompletionEvent != NULL) && - ((Which == DHCP_NOTIFY_COMPLETION) || (Which == DHCP_NOTIFY_ALL))) { + ((Which == DHCP_NOTIFY_COMPLETION) || (Which == DHCP_NOTIFY_ALL)) + ) { gBS->SignalEvent (Child->CompletionEvent); Child->CompletionEvent = NULL; } if ((Child->RenewRebindEvent != NULL) && - ((Which == DHCP_NOTIFY_RENEWREBIND) || (Which == DHCP_NOTIFY_ALL))) { + ((Which == DHCP_NOTIFY_RENEWREBIND) || (Which == DHCP_NOTIFY_ALL)) + ) { gBS->SignalEvent (Child->RenewRebindEvent); Child->RenewRebindEvent = NULL; @@ -192,9 +183,9 @@ DhcpNotifyUser ( **/ EFI_STATUS DhcpSetState ( - IN DHCP_SERVICE *DhcpSb, - IN INTN State, - IN BOOLEAN CallUser + IN OUT DHCP_SERVICE *DhcpSb, + IN INTN State, + IN BOOLEAN CallUser ) { EFI_STATUS Status; @@ -235,7 +226,7 @@ DhcpSetState ( DhcpSb->CurRetry = 0; DhcpSb->PacketToLive = 0; - + DhcpSb->LastTimeout = 0; DhcpSb->DhcpState = State; return EFI_SUCCESS; } @@ -247,13 +238,10 @@ DhcpSetState ( @param DhcpSb The DHCP service instance. - @return None - **/ -STATIC VOID DhcpSetTransmitTimer ( - IN DHCP_SERVICE *DhcpSb + IN OUT DHCP_SERVICE *DhcpSb ) { UINT32 *Times; @@ -271,10 +259,9 @@ DhcpSetTransmitTimer ( } DhcpSb->PacketToLive = Times[DhcpSb->CurRetry]; + DhcpSb->LastTimeout = DhcpSb->PacketToLive; - if (DhcpSb->DhcpState == Dhcp4Selecting) { - DhcpSb->WaitOffer = DhcpSb->PacketToLive; - } + return; } /** @@ -285,15 +272,11 @@ DhcpSetTransmitTimer ( @param DhcpSb The DHCP service instance @param Para The DHCP parameter extracted from the server's response. - - @return None - **/ -STATIC VOID DhcpComputeLease ( - IN DHCP_SERVICE *DhcpSb, - IN DHCP_PARAMETER *Para + IN OUT DHCP_SERVICE *DhcpSb, + IN DHCP_PARAMETER *Para ) { ASSERT (Para != NULL); @@ -321,16 +304,17 @@ DhcpComputeLease ( DHCP driver needs this port to unicast packet to the server such as DHCP release. - @param UdpIo The UDP IO port to configure - @param Context The opaque parameter to the function. + @param[in] UdpIo The UDP IO to configure + @param[in] Context Dhcp service instance. @retval EFI_SUCCESS The UDP IO port is successfully configured. @retval Others It failed to configure the port. **/ EFI_STATUS +EFIAPI DhcpConfigLeaseIoPort ( - IN UDP_IO_PORT *UdpIo, + IN UDP_IO *UdpIo, IN VOID *Context ) { @@ -365,7 +349,7 @@ DhcpConfigLeaseIoPort ( ZeroMem (&UdpConfigData.RemoteAddress, sizeof (EFI_IPv4_ADDRESS)); - Status = UdpIo->Udp->Configure (UdpIo->Udp, &UdpConfigData); + Status = UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfigData); if (EFI_ERROR (Status)) { return Status; @@ -380,7 +364,7 @@ DhcpConfigLeaseIoPort ( Ip = HTONL (DhcpSb->Para->Router); CopyMem (&Gateway, &Ip, sizeof (EFI_IPv4_ADDRESS)); - UdpIo->Udp->Routes (UdpIo->Udp, FALSE, &Subnet, &Subnet, &Gateway); + UdpIo->Protocol.Udp4->Routes (UdpIo->Protocol.Udp4, FALSE, &Subnet, &Subnet, &Gateway); } return EFI_SUCCESS; @@ -398,14 +382,11 @@ DhcpConfigLeaseIoPort ( @retval EFI_SUCCESS The lease is recorded. **/ -STATIC EFI_STATUS DhcpLeaseAcquired ( - IN DHCP_SERVICE *DhcpSb + IN OUT DHCP_SERVICE *DhcpSb ) { - INTN Class; - DhcpSb->ClientAddr = EFI_NTOHL (DhcpSb->Selected->Dhcp4.Header.YourAddr); if (DhcpSb->Para != NULL) { @@ -414,12 +395,11 @@ DhcpLeaseAcquired ( } if (DhcpSb->Netmask == 0) { - Class = NetGetIpClass (DhcpSb->ClientAddr); - DhcpSb->Netmask = mIp4AllMasks[Class << 3]; + return EFI_ABORTED; } if (DhcpSb->LeaseIoPort != NULL) { - UdpIoFreePort (DhcpSb->LeaseIoPort); + UdpIoFreeIo (DhcpSb->LeaseIoPort); } // @@ -427,10 +407,11 @@ DhcpLeaseAcquired ( // and transmit unicast packet with it as source address. Don't // start receive on this port, the queued packet will be timeout. // - DhcpSb->LeaseIoPort = UdpIoCreatePort ( + DhcpSb->LeaseIoPort = UdpIoCreateIo ( DhcpSb->Controller, DhcpSb->Image, DhcpConfigLeaseIoPort, + UDP_IO_UDP4_VERSION, DhcpSb ); @@ -451,8 +432,6 @@ DhcpLeaseAcquired ( @param DhcpSb The DHCP instance service. - @return None - **/ VOID DhcpCleanLease ( @@ -462,20 +441,21 @@ DhcpCleanLease ( DhcpSb->DhcpState = Dhcp4Init; DhcpSb->Xid = DhcpSb->Xid + 1; DhcpSb->ClientAddr = 0; + DhcpSb->Netmask = 0; DhcpSb->ServerAddr = 0; if (DhcpSb->LastOffer != NULL) { - gBS->FreePool (DhcpSb->LastOffer); + FreePool (DhcpSb->LastOffer); DhcpSb->LastOffer = NULL; } if (DhcpSb->Selected != NULL) { - gBS->FreePool (DhcpSb->Selected); + FreePool (DhcpSb->Selected); DhcpSb->Selected = NULL; } if (DhcpSb->Para != NULL) { - gBS->FreePool (DhcpSb->Para); + FreePool (DhcpSb->Para); DhcpSb->Para = NULL; } @@ -485,20 +465,25 @@ DhcpCleanLease ( DhcpSb->ExtraRefresh = FALSE; if (DhcpSb->LeaseIoPort != NULL) { - UdpIoFreePort (DhcpSb->LeaseIoPort); + UdpIoFreeIo (DhcpSb->LeaseIoPort); DhcpSb->LeaseIoPort = NULL; } if (DhcpSb->LastPacket != NULL) { - NetbufFree (DhcpSb->LastPacket); + FreePool (DhcpSb->LastPacket); DhcpSb->LastPacket = NULL; } DhcpSb->PacketToLive = 0; + DhcpSb->LastTimeout = 0; DhcpSb->CurRetry = 0; DhcpSb->MaxRetries = 0; - DhcpSb->WaitOffer = 0; DhcpSb->LeaseLife = 0; + + // + // Clean active config data. + // + DhcpCleanConfigure (&DhcpSb->ActiveConfig); } @@ -507,12 +492,11 @@ DhcpCleanLease ( of BOOTP, the lease is recorded and user notified. If the offer is of DHCP, it will request the offer from the server. - @param DhcpSb The DHCP service instance. + @param[in] DhcpSb The DHCP service instance. @retval EFI_SUCCESS One of the offer is selected. **/ -STATIC EFI_STATUS DhcpChooseOffer ( IN DHCP_SERVICE *DhcpSb @@ -525,11 +509,6 @@ DhcpChooseOffer ( ASSERT (DhcpSb->LastOffer != NULL); - // - // Stop waiting more offers - // - DhcpSb->WaitOffer = 0; - // // User will cache previous offers if he wants to select // from multiple offers. If user provides an invalid packet, @@ -548,7 +527,7 @@ DhcpChooseOffer ( TempPacket = (EFI_DHCP4_PACKET *) AllocatePool (NewPacket->Size); if (TempPacket != NULL) { CopyMem (TempPacket, NewPacket, NewPacket->Size); - gBS->FreePool (Selected); + FreePool (Selected); Selected = TempPacket; } } @@ -593,13 +572,10 @@ DhcpChooseOffer ( to this is: only call DhcpEndSession at the highest level, such as DhcpInput, DhcpOnTimerTick...At the other level, just return error. - @param DhcpSb The DHCP service instance - @param Status The result of the DHCP process. - - @return None + @param[in] DhcpSb The DHCP service instance + @param[in] Status The result of the DHCP process. **/ -STATIC VOID DhcpEndSession ( IN DHCP_SERVICE *DhcpSb, @@ -622,16 +598,15 @@ DhcpEndSession ( /** Handle packets in DHCP select state. - @param DhcpSb The DHCP service instance - @param Packet The DHCP packet received - @param Para The DHCP parameter extracted from the packet. That - is, all the option value that we care. + @param[in] DhcpSb The DHCP service instance + @param[in] Packet The DHCP packet received + @param[in] Para The DHCP parameter extracted from the packet. That + is, all the option value that we care. @retval EFI_SUCCESS The packet is successfully processed. @retval Others Some error occured. **/ -STATIC EFI_STATUS DhcpHandleSelect ( IN DHCP_SERVICE *DhcpSb, @@ -650,7 +625,8 @@ DhcpHandleSelect ( // Don't return a error for these two case otherwise the session is ended. // if (!DHCP_IS_BOOTP (Para) && - ((Para->DhcpType != DHCP_MSG_OFFER) || (Para->ServerId == 0))) { + ((Para->DhcpType != DHCP_MSG_OFFER) || (Para->ServerId == 0)) + ) { goto ON_EXIT; } @@ -664,7 +640,7 @@ DhcpHandleSelect ( if (Status == EFI_SUCCESS) { if (DhcpSb->LastOffer != NULL) { - gBS->FreePool (DhcpSb->LastOffer); + FreePool (DhcpSb->LastOffer); } DhcpSb->LastOffer = Packet; @@ -673,7 +649,7 @@ DhcpHandleSelect ( } else if (Status == EFI_NOT_READY) { if (DhcpSb->LastOffer != NULL) { - gBS->FreePool (DhcpSb->LastOffer); + FreePool (DhcpSb->LastOffer); } DhcpSb->LastOffer = Packet; @@ -689,7 +665,7 @@ DhcpHandleSelect ( return EFI_SUCCESS; ON_EXIT: - gBS->FreePool (Packet); + FreePool (Packet); return Status; } @@ -697,16 +673,15 @@ ON_EXIT: /** Handle packets in DHCP request state. - @param DhcpSb The DHCP service instance - @param Packet The DHCP packet received - @param Para The DHCP parameter extracted from the packet. That - is, all the option value that we care. + @param[in] DhcpSb The DHCP service instance + @param[in] Packet The DHCP packet received + @param[in] Para The DHCP parameter extracted from the packet. That + is, all the option value that we care. @retval EFI_SUCCESS The packet is successfully processed. @retval Others Some error occured. **/ -STATIC EFI_STATUS DhcpHandleRequest ( IN DHCP_SERVICE *DhcpSb, @@ -728,8 +703,9 @@ DhcpHandleRequest ( // Ignore the BOOTP message and DHCP messages other than DHCP ACK/NACK. // if (DHCP_IS_BOOTP (Para) || - (Para->ServerId != DhcpSb->Para->ServerId) || - ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK))) { + (Para->ServerId != DhcpSb->Para->ServerId) || + ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK)) + ) { Status = EFI_SUCCESS; goto ON_EXIT; @@ -775,14 +751,14 @@ DhcpHandleRequest ( DhcpSb->IoStatus = EFI_SUCCESS; DhcpNotifyUser (DhcpSb, DHCP_NOTIFY_COMPLETION); - gBS->FreePool (Packet); + FreePool (Packet); return EFI_SUCCESS; REJECT: DhcpSendMessage (DhcpSb, DhcpSb->Selected, DhcpSb->Para, DHCP_MSG_DECLINE, Message); ON_EXIT: - gBS->FreePool (Packet); + FreePool (Packet); return Status; } @@ -790,16 +766,15 @@ ON_EXIT: /** Handle packets in DHCP renew/rebound state. - @param DhcpSb The DHCP service instance - @param Packet The DHCP packet received - @param Para The DHCP parameter extracted from the packet. That - is, all the option value that we care. + @param[in] DhcpSb The DHCP service instance + @param[in] Packet The DHCP packet received + @param[in] Para The DHCP parameter extracted from the packet. That + is, all the option value that we care. @retval EFI_SUCCESS The packet is successfully processed. @retval Others Some error occured. **/ -STATIC EFI_STATUS DhcpHandleRenewRebind ( IN DHCP_SERVICE *DhcpSb, @@ -820,8 +795,9 @@ DhcpHandleRenewRebind ( // Ignore the BOOTP message and DHCP messages other than DHCP ACK/NACK // if (DHCP_IS_BOOTP (Para) || - (Para->ServerId != DhcpSb->Para->ServerId) || - ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK))) { + (Para->ServerId != DhcpSb->Para->ServerId) || + ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK)) + ) { Status = EFI_SUCCESS; goto ON_EXIT; @@ -858,7 +834,7 @@ DhcpHandleRenewRebind ( DhcpSb->LeaseLife = 0; DhcpSetState (DhcpSb, Dhcp4Bound, TRUE); - if (DhcpSb->ExtraRefresh) { + if (DhcpSb->ExtraRefresh != 0) { DhcpSb->ExtraRefresh = FALSE; DhcpSb->IoStatus = EFI_SUCCESS; @@ -866,7 +842,7 @@ DhcpHandleRenewRebind ( } ON_EXIT: - gBS->FreePool (Packet); + FreePool (Packet); return Status; } @@ -874,16 +850,15 @@ ON_EXIT: /** Handle packets in DHCP reboot state. - @param DhcpSb The DHCP service instance - @param Packet The DHCP packet received - @param Para The DHCP parameter extracted from the packet. That - is, all the option value that we care. + @param[in] DhcpSb The DHCP service instance + @param[in] Packet The DHCP packet received + @param[in] Para The DHCP parameter extracted from the packet. That + is, all the option value that we care. @retval EFI_SUCCESS The packet is successfully processed. @retval Others Some error occured. **/ -STATIC EFI_STATUS DhcpHandleReboot ( IN DHCP_SERVICE *DhcpSb, @@ -900,7 +875,8 @@ DhcpHandleReboot ( // Ignore the BOOTP message and DHCP messages other than DHCP ACK/NACK // if (DHCP_IS_BOOTP (Para) || - ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK))) { + ((Para->DhcpType != DHCP_MSG_ACK) && (Para->DhcpType != DHCP_MSG_NAK)) + ) { Status = EFI_SUCCESS; goto ON_EXIT; @@ -935,18 +911,14 @@ DhcpHandleReboot ( // // OK, get the parameter from server, record the lease // - DhcpSb->Para = AllocatePool (sizeof (DHCP_PARAMETER)); - + DhcpSb->Para = AllocateCopyPool (sizeof (DHCP_PARAMETER), Para); if (DhcpSb->Para == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } DhcpSb->Selected = Packet; - CopyMem (DhcpSb->Para, Para, sizeof (*DhcpSb->Para)); - Status = DhcpLeaseAcquired (DhcpSb); - if (EFI_ERROR (Status)) { return Status; } @@ -956,27 +928,26 @@ DhcpHandleReboot ( return EFI_SUCCESS; ON_EXIT: - gBS->FreePool (Packet); + FreePool (Packet); return Status; } /** - Handle the received DHCP packets. This function drivers the DHCP + Handle the received DHCP packets. This function drives the DHCP state machine. @param UdpPacket The UDP packets received. - @param Points The local/remote UDP access points + @param EndPoint The local/remote UDP access point @param IoStatus The status of the UDP receive @param Context The opaque parameter to the function. - @return None - **/ VOID +EFIAPI DhcpInput ( NET_BUF *UdpPacket, - UDP_POINTS *Points, + UDP_END_POINT *EndPoint, EFI_STATUS IoStatus, VOID *Context ) @@ -992,11 +963,11 @@ DhcpInput ( DhcpSb = (DHCP_SERVICE *) Context; // - // Don't restart receive if error occurs or DHCP is destoried. + // Don't restart receive if error occurs or DHCP is destroyed. // if (EFI_ERROR (IoStatus)) { return ; - } else if (DhcpSb->ServiceState == DHCP_DESTORY) { + } else if (DhcpSb->ServiceState == DHCP_DESTROY) { NetbufFree (UdpPacket); return ; } @@ -1037,7 +1008,7 @@ DhcpInput ( // if ((Head->OpCode != BOOTP_REPLY) || (NTOHL (Head->Xid) != DhcpSb->Xid) || - !NET_MAC_EQUAL (&DhcpSb->Mac, Head->ClientHwAddr, DhcpSb->HwLen)) { + (CompareMem (DhcpSb->ClientAddressSendOut, Head->ClientHwAddr, Head->HwAddrLen) != 0)) { goto RESTART; } @@ -1078,7 +1049,7 @@ DhcpInput ( // // Ignore the packet in INITREBOOT, INIT and BOUND states // - gBS->FreePool (Packet); + FreePool (Packet); Status = EFI_SUCCESS; break; @@ -1093,13 +1064,14 @@ DhcpInput ( } if (Para != NULL) { - gBS->FreePool (Para); + FreePool (Para); } Packet = NULL; if (EFI_ERROR (Status)) { NetbufFree (UdpPacket); + UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0); DhcpEndSession (DhcpSb, Status); return ; } @@ -1108,7 +1080,7 @@ RESTART: NetbufFree (UdpPacket); if (Packet != NULL) { - gBS->FreePool (Packet); + FreePool (Packet); } Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0); @@ -1118,39 +1090,20 @@ RESTART: } } - -/** - Release the packet. - - @param Arg The packet to release - - @return None - -**/ -VOID -DhcpReleasePacket ( - IN VOID *Arg - ) -{ - gBS->FreePool (Arg); -} - - /** Release the net buffer when packet is sent. @param UdpPacket The UDP packets received. - @param Points The local/remote UDP access points + @param EndPoint The local/remote UDP access point @param IoStatus The status of the UDP receive @param Context The opaque parameter to the function. - @return None - **/ VOID +EFIAPI DhcpOnPacketSent ( NET_BUF *Packet, - UDP_POINTS *Points, + UDP_END_POINT *EndPoint, EFI_STATUS IoStatus, VOID *Context ) @@ -1166,16 +1119,17 @@ DhcpOnPacketSent ( the state (as defined in Figure 5. of the same RFC) before sending a DHCP message. The table is adjusted accordingly. - @param DhcpSb The DHCP service instance - @param Seed The seed packet which the new packet is based on - @param Para The DHCP parameter of the Seed packet - @param Type The message type to send - @param Msg The human readable message to include in the packet - sent. + @param[in] DhcpSb The DHCP service instance + @param[in] Seed The seed packet which the new packet is based on + @param[in] Para The DHCP parameter of the Seed packet + @param[in] Type The message type to send + @param[in] Msg The human readable message to include in the packet + sent. @retval EFI_OUT_OF_RESOURCES Failed to allocate resources for the packet @retval EFI_ACCESS_DENIED Failed to transmit the packet through UDP @retval EFI_SUCCESS The message is sent + @retval other Other error occurs **/ EFI_STATUS @@ -1192,8 +1146,8 @@ DhcpSendMessage ( EFI_DHCP4_PACKET *NewPacket; EFI_DHCP4_HEADER *Head; EFI_DHCP4_HEADER *SeedHead; - UDP_IO_PORT *UdpIo; - UDP_POINTS EndPoint; + UDP_IO *UdpIo; + UDP_END_POINT EndPoint; NET_BUF *Wrap; NET_FRAGMENT Frag; EFI_STATUS Status; @@ -1243,12 +1197,23 @@ DhcpSendMessage ( EFI_IP4 (Head->ClientAddr) = HTONL (DhcpSb->ClientAddr); CopyMem (Head->ClientHwAddr, DhcpSb->Mac.Addr, DhcpSb->HwLen); + if ((Type == DHCP_MSG_DECLINE) || (Type == DHCP_MSG_RELEASE)) { + Head->Seconds = 0; + } else if ((Type == DHCP_MSG_REQUEST) && (DhcpSb->DhcpState == Dhcp4Requesting)) { + // + // Use the same value as the original DHCPDISCOVER message. + // + Head->Seconds = DhcpSb->LastPacket->Dhcp4.Header.Seconds; + } else { + SetElapsedTime(&Head->Seconds, DhcpSb->ActiveChild); + } + // // Append the DHCP message type // Packet->Dhcp4.Magik = DHCP_OPTION_MAGIC; Buf = Packet->Dhcp4.Option; - Buf = DhcpAppendOption (Buf, DHCP_TAG_TYPE, 1, &Type); + Buf = DhcpAppendOption (Buf, DHCP4_TAG_MSG_TYPE, 1, &Type); // // Append the serverid option if necessary: @@ -1257,12 +1222,13 @@ DhcpSendMessage ( // 3. DHCP request to confirm one lease. // if ((Type == DHCP_MSG_DECLINE) || (Type == DHCP_MSG_RELEASE) || - ((Type == DHCP_MSG_REQUEST) && (DhcpSb->DhcpState == Dhcp4Requesting))) { + ((Type == DHCP_MSG_REQUEST) && (DhcpSb->DhcpState == Dhcp4Requesting)) + ) { ASSERT ((Para != NULL) && (Para->ServerId != 0)); IpAddr = HTONL (Para->ServerId); - Buf = DhcpAppendOption (Buf, DHCP_TAG_SERVER_ID, 4, (UINT8 *) &IpAddr); + Buf = DhcpAppendOption (Buf, DHCP4_TAG_SERVER_ID, 4, (UINT8 *) &IpAddr); } // @@ -1288,7 +1254,7 @@ DhcpSendMessage ( } if (IpAddr != 0) { - Buf = DhcpAppendOption (Buf, DHCP_TAG_REQUEST_IP, 4, (UINT8 *) &IpAddr); + Buf = DhcpAppendOption (Buf, DHCP4_TAG_REQUEST_IP, 4, (UINT8 *) &IpAddr); } // @@ -1298,7 +1264,7 @@ DhcpSendMessage ( // if ((Type != DHCP_MSG_DECLINE) && (Type != DHCP_MSG_RELEASE)) { MaxMsg = HTONS (0xFF00); - Buf = DhcpAppendOption (Buf, DHCP_TAG_MAXMSG, 2, (UINT8 *) &MaxMsg); + Buf = DhcpAppendOption (Buf, DHCP4_TAG_MAXMSG, 2, (UINT8 *) &MaxMsg); } // @@ -1306,7 +1272,7 @@ DhcpSendMessage ( // if (Msg != NULL) { Len = MIN ((UINT32) AsciiStrLen ((CHAR8 *) Msg), 255); - Buf = DhcpAppendOption (Buf, DHCP_TAG_MESSAGE, (UINT16) Len, Msg); + Buf = DhcpAppendOption (Buf, DHCP4_TAG_MESSAGE, (UINT16) Len, Msg); } // @@ -1319,7 +1285,7 @@ DhcpSendMessage ( // if it is a DHCP decline or DHCP release . // if (((Type == DHCP_MSG_DECLINE) || (Type == DHCP_MSG_RELEASE)) && - (Config->OptionList[Index]->OpCode != DHCP_TAG_CLIENT_ID)) { + (Config->OptionList[Index]->OpCode != DHCP4_TAG_CLIENT_ID)) { continue; } @@ -1332,7 +1298,7 @@ DhcpSendMessage ( } } - *(Buf++) = DHCP_TAG_EOP; + *(Buf++) = DHCP4_TAG_EOP; Packet->Length += (UINT32) (Buf - Packet->Dhcp4.Option); // @@ -1352,24 +1318,33 @@ DhcpSendMessage ( } if (EFI_ERROR (Status)) { - gBS->FreePool (Packet); + FreePool (Packet); return Status; } if (NewPacket != NULL) { - gBS->FreePool (Packet); + FreePool (Packet); Packet = NewPacket; } + // + // Save the Client Address will be sent out + // + CopyMem ( + &DhcpSb->ClientAddressSendOut[0], + &Packet->Dhcp4.Header.ClientHwAddr[0], + Packet->Dhcp4.Header.HwAddrLen + ); + // // Wrap it into a netbuf then send it. // Frag.Bulk = (UINT8 *) &Packet->Dhcp4.Header; Frag.Len = Packet->Length; - Wrap = NetbufFromExt (&Frag, 1, 0, 0, DhcpReleasePacket, Packet); + Wrap = NetbufFromExt (&Frag, 1, 0, 0, DhcpDummyExtFree, NULL); if (Wrap == NULL) { - gBS->FreePool (Packet); + FreePool (Packet); return EFI_OUT_OF_RESOURCES; } @@ -1377,31 +1352,38 @@ DhcpSendMessage ( // Save it as the last sent packet for retransmission // if (DhcpSb->LastPacket != NULL) { - NetbufFree (DhcpSb->LastPacket); + FreePool (DhcpSb->LastPacket); } - NET_GET_REF (Wrap); - DhcpSb->LastPacket = Wrap; + DhcpSb->LastPacket = Packet; DhcpSetTransmitTimer (DhcpSb); // // Broadcast the message, unless we know the server address. // Use the lease UdpIo port to send the unicast packet. // - EndPoint.RemoteAddr = 0xffffffff; - EndPoint.LocalAddr = 0; - EndPoint.RemotePort = DHCP_SERVER_PORT; - EndPoint.LocalPort = DHCP_CLIENT_PORT; - UdpIo = DhcpSb->UdpIo; + EndPoint.RemoteAddr.Addr[0] = 0xffffffff; + EndPoint.LocalAddr.Addr[0] = 0; + EndPoint.RemotePort = DHCP_SERVER_PORT; + EndPoint.LocalPort = DHCP_CLIENT_PORT; + UdpIo = DhcpSb->UdpIo; if ((DhcpSb->DhcpState == Dhcp4Renewing) || (Type == DHCP_MSG_RELEASE)) { - EndPoint.RemoteAddr = DhcpSb->ServerAddr; - EndPoint.LocalAddr = DhcpSb->ClientAddr; - UdpIo = DhcpSb->LeaseIoPort; + EndPoint.RemoteAddr.Addr[0] = DhcpSb->ServerAddr; + EndPoint.LocalAddr.Addr[0] = DhcpSb->ClientAddr; + UdpIo = DhcpSb->LeaseIoPort; } ASSERT (UdpIo != NULL); - Status = UdpIoSendDatagram (UdpIo, Wrap, &EndPoint, 0, DhcpOnPacketSent, DhcpSb); + + Status = UdpIoSendDatagram ( + UdpIo, + Wrap, + &EndPoint, + NULL, + DhcpOnPacketSent, + DhcpSb + ); if (EFI_ERROR (Status)) { NetbufFree (Wrap); @@ -1416,7 +1398,7 @@ DhcpSendMessage ( Retransmit a saved packet. Only DISCOVER and REQUEST messages will be retransmitted. - @param DhcpSb The DHCP service instance + @param[in] DhcpSb The DHCP service instance @retval EFI_ACCESS_DENIED Failed to transmit packet through UDP port @retval EFI_SUCCESS The packet is retransmitted. @@ -1427,41 +1409,60 @@ DhcpRetransmit ( IN DHCP_SERVICE *DhcpSb ) { - UDP_IO_PORT *UdpIo; - UDP_POINTS EndPoint; + UDP_IO *UdpIo; + UDP_END_POINT EndPoint; + NET_BUF *Wrap; + NET_FRAGMENT Frag; EFI_STATUS Status; ASSERT (DhcpSb->LastPacket != NULL); + // + // For REQUEST message in Dhcp4Requesting state, do not change the secs fields. + // + if (DhcpSb->DhcpState != Dhcp4Requesting) { + SetElapsedTime(&DhcpSb->LastPacket->Dhcp4.Header.Seconds, DhcpSb->ActiveChild); + } + + // + // Wrap it into a netbuf then send it. + // + Frag.Bulk = (UINT8 *) &DhcpSb->LastPacket->Dhcp4.Header; + Frag.Len = DhcpSb->LastPacket->Length; + Wrap = NetbufFromExt (&Frag, 1, 0, 0, DhcpDummyExtFree, NULL); + + if (Wrap == NULL) { + return EFI_OUT_OF_RESOURCES; + } + // // Broadcast the message, unless we know the server address. // - EndPoint.RemotePort = DHCP_SERVER_PORT; - EndPoint.LocalPort = DHCP_CLIENT_PORT; - EndPoint.RemoteAddr = 0xffffffff; - EndPoint.LocalAddr = 0; - UdpIo = DhcpSb->UdpIo; + EndPoint.RemotePort = DHCP_SERVER_PORT; + EndPoint.LocalPort = DHCP_CLIENT_PORT; + EndPoint.RemoteAddr.Addr[0] = 0xffffffff; + EndPoint.LocalAddr.Addr[0] = 0; + UdpIo = DhcpSb->UdpIo; if (DhcpSb->DhcpState == Dhcp4Renewing) { - EndPoint.RemoteAddr = DhcpSb->ServerAddr; - EndPoint.LocalAddr = DhcpSb->ClientAddr; - UdpIo = DhcpSb->LeaseIoPort; + EndPoint.RemoteAddr.Addr[0] = DhcpSb->ServerAddr; + EndPoint.LocalAddr.Addr[0] = DhcpSb->ClientAddr; + UdpIo = DhcpSb->LeaseIoPort; } ASSERT (UdpIo != NULL); - NET_GET_REF (DhcpSb->LastPacket); Status = UdpIoSendDatagram ( UdpIo, - DhcpSb->LastPacket, + Wrap, &EndPoint, - 0, + NULL, DhcpOnPacketSent, DhcpSb ); if (EFI_ERROR (Status)) { - NET_PUT_REF (DhcpSb->LastPacket); + NetbufFree (Wrap); return EFI_ACCESS_DENIED; } @@ -1476,10 +1477,8 @@ DhcpRetransmit ( and lease to determine the time to renew and rebind the lease. DhcpOnTimerTick will be called once every second. - @param Event The timer event - @param Context The context, which is the DHCP service instance. - - @return None + @param[in] Event The timer event + @param[in] Context The context, which is the DHCP service instance. **/ VOID @@ -1489,36 +1488,44 @@ DhcpOnTimerTick ( IN VOID *Context ) { + LIST_ENTRY *Entry; + LIST_ENTRY *Next; DHCP_SERVICE *DhcpSb; DHCP_PROTOCOL *Instance; EFI_STATUS Status; - + DhcpSb = (DHCP_SERVICE *) Context; Instance = DhcpSb->ActiveChild; // - // Check the time to wait offer + // 0xffff is the maximum supported value for elapsed time according to RFC. // - if ((DhcpSb->WaitOffer > 0) && (--DhcpSb->WaitOffer == 0)) { - // - // OK, offer collection finished, select a offer - // - ASSERT (DhcpSb->DhcpState == Dhcp4Selecting); - - if (DhcpSb->LastOffer == NULL) { - goto END_SESSION; - } - - if (EFI_ERROR (DhcpChooseOffer (DhcpSb))) { - goto END_SESSION; - } + if (Instance != NULL && Instance->ElaspedTime < 0xffff) { + Instance->ElaspedTime++; } - + // // Check the retransmit timer // if ((DhcpSb->PacketToLive > 0) && (--DhcpSb->PacketToLive == 0)) { + // + // Select offer at each timeout if any offer received. + // + if (DhcpSb->DhcpState == Dhcp4Selecting && DhcpSb->LastOffer != NULL) { + + Status = DhcpChooseOffer (DhcpSb); + + if (EFI_ERROR(Status)) { + if (DhcpSb->LastOffer != NULL) { + FreePool (DhcpSb->LastOffer); + DhcpSb->LastOffer = NULL; + } + } else { + goto ON_EXIT; + } + } + if (++DhcpSb->CurRetry < DhcpSb->MaxRetries) { // // Still has another try @@ -1526,17 +1533,14 @@ DhcpOnTimerTick ( DhcpRetransmit (DhcpSb); DhcpSetTransmitTimer (DhcpSb); - } else { - if (!DHCP_CONNECTED (DhcpSb->DhcpState)) { - goto END_SESSION; - } + } else if (DHCP_CONNECTED (DhcpSb->DhcpState)) { // // Retransmission failed, if the DHCP request is initiated by // user, adjust the current state according to the lease life. // Otherwise do nothing to wait the lease to timeout // - if (DhcpSb->ExtraRefresh) { + if (DhcpSb->ExtraRefresh != 0) { Status = EFI_SUCCESS; if (DhcpSb->LeaseLife < DhcpSb->T1) { @@ -1556,9 +1560,11 @@ DhcpOnTimerTick ( DhcpSb->IoStatus = EFI_TIMEOUT; DhcpNotifyUser (DhcpSb, DHCP_NOTIFY_RENEWREBIND); } + } else { + goto END_SESSION; } } - + // // If an address has been acquired, check whether need to // refresh or whether it has expired. @@ -1570,7 +1576,7 @@ DhcpOnTimerTick ( // Don't timeout the lease, only count the life if user is // requesting extra renew/rebind. Adjust the state after that. // - if (DhcpSb->ExtraRefresh) { + if (DhcpSb->ExtraRefresh != 0) { return ; } @@ -1588,6 +1594,10 @@ DhcpOnTimerTick ( goto END_SESSION; } + if (Instance != NULL) { + Instance->ElaspedTime= 0; + } + Status = DhcpSendMessage ( DhcpSb, DhcpSb->Selected, @@ -1608,6 +1618,10 @@ DhcpOnTimerTick ( goto END_SESSION; } + if (Instance != NULL) { + Instance->ElaspedTime= 0; + } + Status = DhcpSendMessage ( DhcpSb, DhcpSb->Selected, @@ -1622,12 +1636,14 @@ DhcpOnTimerTick ( } } +ON_EXIT: // + // Iterate through all the DhcpSb Children. // - // - if ((Instance != NULL) && (Instance->Token != NULL)) { + NET_LIST_FOR_EACH_SAFE (Entry, Next, &DhcpSb->Children) { + Instance = NET_LIST_USER_STRUCT (Entry, DHCP_PROTOCOL, Link); Instance->Timeout--; - if (Instance->Timeout == 0) { + if (Instance->Timeout == 0 && Instance->Token != NULL) { PxeDhcpDone (Instance); } }