+++ /dev/null
-/*++\r
-\r
-Copyright (c) 2006, Intel Corporation \r
-All rights reserved. This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
-\r
-Module Name:\r
- PxeDhcp4RenewRebind.c\r
- \r
-Abstract:\r
-\r
---*/\r
-\r
-\r
-#include "PxeDhcp4.h"\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-STATIC\r
-INTN\r
-acknak_verify (\r
- IN PXE_DHCP4_PRIVATE_DATA *Private,\r
- IN DHCP4_PACKET *tx_pkt,\r
- IN DHCP4_PACKET *rx_pkt,\r
- IN UINTN rx_pkt_size\r
- )\r
-/*++\r
-Routine Description:\r
-\r
-Parameters:\r
-\r
-Returns:\r
- -2 = ignore, stop waiting\r
- -1 = ignore, keep waiting\r
- 0 = accept, keep waiting\r
- 1 = accept, stop waiting\r
---*/\r
-{\r
- EFI_STATUS efi_status;\r
- DHCP4_OP *msg_type_op;\r
- DHCP4_OP *srvid_op;\r
- DHCP4_OP *renew_op;\r
- DHCP4_OP *rebind_op;\r
- DHCP4_OP *lease_time_op;\r
- UINT32 magik;\r
-\r
- //\r
- // Verify parameters. Unused parameters are also touched\r
- // to make the compiler happy.\r
- //\r
- ASSERT (Private);\r
- ASSERT (rx_pkt);\r
-\r
- if (Private == NULL || rx_pkt == NULL) {\r
- return -2;\r
- }\r
-\r
- tx_pkt = tx_pkt;\r
- rx_pkt_size = rx_pkt_size;\r
-\r
- //\r
- // This must be a DHCP Ack message.\r
- //\r
- magik = htonl (DHCP4_MAGIK_NUMBER);\r
-\r
- if (CompareMem (&rx_pkt->dhcp4.magik, &magik, 4)) {\r
- return -1;\r
- }\r
-\r
- efi_status = find_opt (rx_pkt, DHCP4_MESSAGE_TYPE, 0, &msg_type_op);\r
-\r
- if (EFI_ERROR (efi_status)) {\r
- return -1;\r
- }\r
-\r
- if (msg_type_op->len != 1) {\r
- return -1;\r
- }\r
-\r
- if (msg_type_op->data[0] != DHCP4_MESSAGE_TYPE_ACK) {\r
- return -1;\r
- }\r
- //\r
- // There must be a server identifier.\r
- //\r
- efi_status = find_opt (rx_pkt, DHCP4_SERVER_IDENTIFIER, 0, &srvid_op);\r
-\r
- if (EFI_ERROR (efi_status)) {\r
- return -1;\r
- }\r
-\r
- if (srvid_op->len != 4) {\r
- return -1;\r
- }\r
- //\r
- // There should be a renewal time.\r
- // If there is not, we will default to the 7/8 of the rebinding time.\r
- //\r
- efi_status = find_opt (rx_pkt, DHCP4_RENEWAL_TIME, 0, &renew_op);\r
-\r
- if (EFI_ERROR (efi_status)) {\r
- renew_op = NULL;\r
- } else if (renew_op->len != 4) {\r
- renew_op = NULL;\r
- }\r
- //\r
- // There should be a rebinding time.\r
- // If there is not, we will default to 7/8 of the lease time.\r
- //\r
- efi_status = find_opt (rx_pkt, DHCP4_REBINDING_TIME, 0, &rebind_op);\r
-\r
- if (EFI_ERROR (efi_status)) {\r
- rebind_op = NULL;\r
- } else if (rebind_op->len != 4) {\r
- rebind_op = NULL;\r
- }\r
- //\r
- // There should be a lease time.\r
- // If there is not, we will default to one week.\r
- //\r
- efi_status = find_opt (rx_pkt, DHCP4_LEASE_TIME, 0, &lease_time_op);\r
-\r
- if (EFI_ERROR (efi_status)) {\r
- lease_time_op = NULL;\r
- } else if (lease_time_op->len != 4) {\r
- lease_time_op = NULL;\r
- }\r
- //\r
- // Packet looks good. Double check the renew, rebind and lease times.\r
- //\r
- CopyMem (&Private->ServerIp, srvid_op->data, 4);\r
-\r
- if (renew_op != NULL) {\r
- CopyMem (&Private->RenewTime, renew_op->data, 4);\r
- Private->RenewTime = htonl (Private->RenewTime);\r
- } else {\r
- Private->RenewTime = 0;\r
- }\r
-\r
- if (rebind_op != NULL) {\r
- CopyMem (&Private->RebindTime, rebind_op->data, 4);\r
- Private->RebindTime = htonl (Private->RebindTime);\r
- } else {\r
- Private->RebindTime = 0;\r
- }\r
-\r
- if (lease_time_op != NULL) {\r
- CopyMem (&Private->LeaseTime, lease_time_op->data, 4);\r
- Private->LeaseTime = htonl (Private->LeaseTime);\r
- } else {\r
- Private->LeaseTime = 0;\r
- }\r
-\r
- if (Private->LeaseTime < 60) {\r
- Private->LeaseTime = 7 * 86400;\r
- }\r
-\r
- if (Private->RebindTime < 52 || Private->RebindTime >= Private->LeaseTime) {\r
- Private->RebindTime = Private->LeaseTime / 2 + Private->LeaseTime / 4 + Private->LeaseTime / 8;\r
- }\r
-\r
- if (Private->RenewTime < 45 || Private->RenewTime >= Private->RebindTime) {\r
- Private->RenewTime = Private->RebindTime / 2 + Private->RebindTime / 4 + Private->RebindTime / 8;\r
- }\r
-\r
- return 1;\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-renew_rebind (\r
- IN EFI_PXE_DHCP4_PROTOCOL *This,\r
- IN UINTN seconds_timeout,\r
- IN BOOLEAN renew\r
- )\r
-{\r
- PXE_DHCP4_PRIVATE_DATA *Private;\r
- EFI_IP_ADDRESS ServerIp;\r
- EFI_IP_ADDRESS client_ip;\r
- EFI_IP_ADDRESS subnet_mask;\r
- EFI_IP_ADDRESS gateway_ip;\r
- DHCP4_PACKET Request;\r
- DHCP4_PACKET AckNak;\r
- DHCP4_OP *op;\r
- EFI_STATUS efi_status;\r
-\r
- //\r
- // Check for invalid parameters.\r
- //\r
- if (This == NULL || seconds_timeout < DHCP4_MIN_SECONDS || seconds_timeout > DHCP4_MAX_SECONDS) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // Check for proper protocol state.\r
- //\r
- if (This->Data == NULL) {\r
- return EFI_NOT_STARTED;\r
- }\r
-\r
- if (!This->Data->SelectCompleted) {\r
- return EFI_NOT_READY;\r
- }\r
-\r
- if (This->Data->IsBootp) {\r
- return EFI_SUCCESS;\r
- }\r
-\r
- if (!This->Data->IsAck) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
- //\r
- // Get pointer to instance data.\r
- //\r
- Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);\r
-\r
- if (Private == NULL) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (Private->PxeBc == NULL) {\r
- return EFI_DEVICE_ERROR;\r
- }\r
- //\r
- // Copy Discover packet to temporary request packet\r
- // to be used for Renew/Rebind operation.\r
- //\r
- CopyMem (&Request, &This->Data->Discover, sizeof (DHCP4_PACKET));\r
-\r
- CopyMem (&Request.dhcp4.ciaddr, &This->Data->AckNak.dhcp4.yiaddr, 4);\r
-\r
- Request.dhcp4.flags = 0; /* Reply does not need to be broadcast. */\r
-\r
- //\r
- // Change message type from discover to request.\r
- //\r
- efi_status = find_opt (&Request, DHCP4_MESSAGE_TYPE, 0, &op);\r
-\r
- if (EFI_ERROR (efi_status)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (op->len != 1) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- op->data[0] = DHCP4_MESSAGE_TYPE_REQUEST;\r
-\r
- //\r
- // Need a subnet mask.\r
- //\r
- efi_status = find_opt (\r
- &This->Data->AckNak,\r
- DHCP4_SUBNET_MASK,\r
- 0,\r
- &op\r
- );\r
-\r
- if (EFI_ERROR (efi_status)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (op->len != 4) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- ZeroMem (&subnet_mask, sizeof (EFI_IP_ADDRESS));\r
- CopyMem (&subnet_mask, op->data, 4);\r
-\r
- //\r
- // Need a server IP address (renew) or a broadcast\r
- // IP address (rebind).\r
- //\r
- ZeroMem (&gateway_ip, sizeof (EFI_IP_ADDRESS));\r
-\r
- if (renew) {\r
- efi_status = find_opt (\r
- &This->Data->AckNak,\r
- DHCP4_SERVER_IDENTIFIER,\r
- 0,\r
- &op\r
- );\r
-\r
- if (EFI_ERROR (efi_status)) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- if (op->len != 4) {\r
- return EFI_INVALID_PARAMETER;\r
- }\r
-\r
- ZeroMem (&ServerIp, sizeof (EFI_IP_ADDRESS));\r
- CopyMem (&ServerIp, op->data, 4);\r
-\r
- //\r
- //\r
- //\r
- if (CompareMem (&This->Data->AckNak.dhcp4.giaddr, &gateway_ip, 4)) {\r
- CopyMem (&gateway_ip, &This->Data->AckNak.dhcp4.giaddr, 4);\r
- }\r
- } else {\r
- SetMem (&ServerIp, sizeof (EFI_IP_ADDRESS), 0xFF);\r
- }\r
- //\r
- // Need a client IP address.\r
- //\r
- ZeroMem (&client_ip, sizeof (EFI_IP_ADDRESS));\r
- CopyMem (&client_ip, &Request.dhcp4.ciaddr, 4);\r
-\r
- //\r
- //\r
- //\r
- efi_status = gBS->HandleProtocol (\r
- Private->Handle,\r
- &gEfiPxeDhcp4CallbackProtocolGuid,\r
- (VOID *) &Private->callback\r
- );\r
-\r
- if (EFI_ERROR (efi_status)) {\r
- Private->callback = NULL;\r
- }\r
-\r
- Private->function = renew ? EFI_PXE_DHCP4_FUNCTION_RENEW : EFI_PXE_DHCP4_FUNCTION_REBIND;\r
-\r
- //\r
- // Transimit DHCP request and wait for DHCP ack...\r
- //\r
- efi_status = tx_rx_udp (\r
- Private,\r
- &ServerIp,\r
- &gateway_ip,\r
- &client_ip,\r
- &subnet_mask,\r
- &Request,\r
- &AckNak,\r
- &acknak_verify,\r
- seconds_timeout\r
- );\r
-\r
- if (EFI_ERROR (efi_status)) {\r
- Private->callback = NULL;\r
- return efi_status;\r
- }\r
- //\r
- // Copy server identifier, renewal time and rebinding time\r
- // from temporary ack/nak packet into cached ack/nak packet.\r
- //\r
- efi_status = find_opt (\r
- &This->Data->AckNak,\r
- DHCP4_SERVER_IDENTIFIER,\r
- 0,\r
- &op\r
- );\r
-\r
- if (!EFI_ERROR (efi_status)) {\r
- if (op->len == 4) {\r
- CopyMem (op->data, &Private->ServerIp, 4);\r
- }\r
- }\r
-\r
- efi_status = find_opt (&This->Data->AckNak, DHCP4_RENEWAL_TIME, 0, &op);\r
-\r
- if (!EFI_ERROR (efi_status)) {\r
- if (op->len == 4) {\r
- CopyMem (op->data, &Private->RenewTime, 4);\r
- }\r
- }\r
-\r
- efi_status = find_opt (&This->Data->AckNak, DHCP4_REBINDING_TIME, 0, &op);\r
-\r
- if (!EFI_ERROR (efi_status)) {\r
- if (op->len == 4) {\r
- CopyMem (op->data, &Private->RebindTime, 4);\r
- }\r
- }\r
-\r
- Private->callback = NULL;\r
- return efi_status;\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-EFI_STATUS\r
-EFIAPI\r
-PxeDhcp4Renew (\r
- IN EFI_PXE_DHCP4_PROTOCOL *This,\r
- IN UINTN seconds_timeout\r
- )\r
-{\r
- return renew_rebind (This, seconds_timeout, TRUE);\r
-}\r
-\r
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
-EFI_STATUS\r
-EFIAPI\r
-PxeDhcp4Rebind (\r
- IN EFI_PXE_DHCP4_PROTOCOL *This,\r
- IN UINTN seconds_timeout\r
- )\r
-{\r
- return renew_rebind (This, seconds_timeout, FALSE);\r
-}\r
-\r
-/* eof - PxeDhcp4RenewRebind.c */\r