mirror of https://github.com/acidanthera/audk.git
248 lines
5.5 KiB
C
248 lines
5.5 KiB
C
/** @file
|
|
|
|
Copyright (c) 2004, 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:
|
|
PxeDhcp4Release.c
|
|
|
|
Abstract:
|
|
Transmit release packet, free allocations and shutdown PxeDhcp4.
|
|
|
|
|
|
**/
|
|
|
|
|
|
#include "PxeDhcp4.h"
|
|
|
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PxeDhcp4Release (
|
|
IN EFI_PXE_DHCP4_PROTOCOL *This
|
|
)
|
|
{
|
|
PXE_DHCP4_PRIVATE_DATA *Private;
|
|
EFI_IP_ADDRESS ServerIp;
|
|
EFI_IP_ADDRESS client_ip;
|
|
EFI_IP_ADDRESS gateway_ip;
|
|
EFI_IP_ADDRESS subnet_mask;
|
|
EFI_STATUS efi_status;
|
|
DHCP4_OP *op;
|
|
UINT8 op_list[20];
|
|
|
|
//
|
|
// Check for invalid parameters.
|
|
//
|
|
if (This == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
//
|
|
// Release does nothing if the protocol has never been setup.
|
|
//
|
|
if (This->Data == NULL) {
|
|
return EFI_NOT_STARTED;
|
|
}
|
|
//
|
|
// Fail if we do not have valid instance data.
|
|
//
|
|
Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);
|
|
|
|
if (Private == NULL) {
|
|
return EFI_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (Private->PxeBc == NULL) {
|
|
return EFI_DEVICE_ERROR;
|
|
}
|
|
//
|
|
// If this is a BOOTP session and there is not a DHCP Ack
|
|
// packet, just release storage and return.
|
|
//
|
|
if (This->Data->IsBootp || !This->Data->IsAck) {
|
|
gBS->FreePool (This->Data);
|
|
This->Data = NULL;
|
|
|
|
if (Private->StopPxeBc) {
|
|
Private->PxeBc->Stop (Private->PxeBc);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
//
|
|
// Build option list for DHCP Release packet.
|
|
// If any errors occur, just release storage and return.
|
|
//
|
|
//
|
|
// Message type is first.
|
|
//
|
|
op_list[0] = DHCP4_MESSAGE_TYPE;
|
|
op_list[1] = 1;
|
|
op_list[2] = DHCP4_MESSAGE_TYPE_RELEASE;
|
|
|
|
//
|
|
// Followed by server identifier.
|
|
//
|
|
efi_status = find_opt (
|
|
&This->Data->Request,
|
|
DHCP4_SERVER_IDENTIFIER,
|
|
0,
|
|
&op
|
|
);
|
|
|
|
if (EFI_ERROR (efi_status)) {
|
|
gBS->FreePool (This->Data);
|
|
This->Data = NULL;
|
|
|
|
if (Private->StopPxeBc) {
|
|
Private->PxeBc->Stop (Private->PxeBc);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
if (op->len != 4) {
|
|
gBS->FreePool (This->Data);
|
|
This->Data = NULL;
|
|
|
|
if (Private->StopPxeBc) {
|
|
Private->PxeBc->Stop (Private->PxeBc);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
CopyMem (&ServerIp, op->data, 4);
|
|
|
|
op_list[3] = DHCP4_SERVER_IDENTIFIER;
|
|
op_list[4] = 4;
|
|
CopyMem (&op_list[5], &ServerIp, 4);
|
|
|
|
//
|
|
// Followed by end.
|
|
//
|
|
op_list[9] = DHCP4_END;
|
|
|
|
//
|
|
// We need a subnet mask for IP stack operation.
|
|
//
|
|
efi_status = find_opt (
|
|
&This->Data->AckNak,
|
|
DHCP4_SUBNET_MASK,
|
|
0,
|
|
&op
|
|
);
|
|
|
|
if (EFI_ERROR (efi_status)) {
|
|
gBS->FreePool (This->Data);
|
|
This->Data = NULL;
|
|
|
|
if (Private->StopPxeBc) {
|
|
Private->PxeBc->Stop (Private->PxeBc);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
if (op->len != 4) {
|
|
gBS->FreePool (This->Data);
|
|
This->Data = NULL;
|
|
|
|
if (Private->StopPxeBc) {
|
|
Private->PxeBc->Stop (Private->PxeBc);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
ZeroMem (&subnet_mask, sizeof (EFI_IP_ADDRESS));
|
|
CopyMem (&subnet_mask, op->data, 4);
|
|
|
|
//
|
|
// Gateway IP address may be needed.
|
|
//
|
|
ZeroMem (&gateway_ip, sizeof (EFI_IP_ADDRESS));
|
|
CopyMem (&gateway_ip, &This->Data->AckNak.dhcp4.giaddr, 4);
|
|
|
|
//
|
|
// Client IP address needed for IP stack operation.
|
|
//
|
|
ZeroMem (&client_ip, sizeof (EFI_IP_ADDRESS));
|
|
CopyMem (&client_ip, &This->Data->AckNak.dhcp4.yiaddr, 4);
|
|
|
|
//
|
|
// Enable UDP...
|
|
//
|
|
efi_status = start_udp (Private, &client_ip, &subnet_mask);
|
|
|
|
if (EFI_ERROR (efi_status)) {
|
|
gBS->FreePool (This->Data);
|
|
This->Data = NULL;
|
|
|
|
if (Private->StopPxeBc) {
|
|
Private->PxeBc->Stop (Private->PxeBc);
|
|
}
|
|
|
|
return efi_status;
|
|
}
|
|
//
|
|
// Gather information out of DHCP request packet needed for
|
|
// DHCP release packet.
|
|
//
|
|
//
|
|
// Setup DHCP Release packet.
|
|
//
|
|
CopyMem (&This->Data->Request.dhcp4.ciaddr, &client_ip, 4);
|
|
|
|
ZeroMem (&This->Data->Request.dhcp4.yiaddr, 12);
|
|
|
|
ZeroMem (&This->Data->Request.dhcp4.sname, 64 + 128);
|
|
|
|
This->Data->Request.dhcp4.hops = 0;
|
|
This->Data->Request.dhcp4.secs = 0;
|
|
This->Data->Request.dhcp4.flags = 0;
|
|
|
|
ZeroMem (
|
|
&This->Data->Request.dhcp4.options,
|
|
sizeof This->Data->Request.dhcp4.options
|
|
);
|
|
|
|
CopyMem (&This->Data->Request.dhcp4.options, op_list, 10);
|
|
|
|
//
|
|
// Transmit DHCP Release packet.
|
|
//
|
|
tx_udp (
|
|
Private,
|
|
&ServerIp,
|
|
&gateway_ip,
|
|
&client_ip,
|
|
&This->Data->Request,
|
|
DHCP4_MAX_PACKET_SIZE - (DHCP4_UDP_HEADER_SIZE + DHCP4_IP_HEADER_SIZE)
|
|
);
|
|
|
|
gBS->Stall (1000000); /* 1/10th second */
|
|
|
|
//
|
|
// Shutdown PXE BaseCode and release local storage.
|
|
//
|
|
stop_udp (Private);
|
|
|
|
gBS->FreePool (This->Data);
|
|
This->Data = NULL;
|
|
|
|
if (Private->StopPxeBc) {
|
|
Private->PxeBc->Stop (Private->PxeBc);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/* eof - PxeDhcp4Release.c */
|