| /** @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: | |
| PxeDhcp4Setup.c | |
| Abstract: | |
| **/ | |
| #include "PxeDhcp4.h" | |
| /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ | |
| EFI_STATUS | |
| EFIAPI | |
| PxeDhcp4Setup ( | |
| IN EFI_PXE_DHCP4_PROTOCOL *This, | |
| IN EFI_PXE_DHCP4_DATA *Data | |
| ) | |
| { | |
| PXE_DHCP4_PRIVATE_DATA *Private; | |
| DHCP4_HEADER *Packet; | |
| EFI_STATUS EfiStatus; | |
| UINT8 *OpLen; | |
| UINT8 *OpPtr; | |
| // | |
| // Return error if parameters are invalid. | |
| // | |
| if (This == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This); | |
| if (Private == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if (This->Data != NULL) { | |
| return EFI_ALREADY_STARTED; | |
| } | |
| if (Private->PxeBc == NULL) { | |
| return EFI_DEVICE_ERROR; | |
| } | |
| // | |
| // Check contents of provided Data structure. | |
| // | |
| if (Data != NULL) { | |
| // | |
| // Do protocol state checks first. | |
| // | |
| if (Data->SelectCompleted) { | |
| if (!Data->InitCompleted || !Data->SetupCompleted) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if (Data->IsBootp && !Data->IsAck) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| } else if (Data->InitCompleted) { | |
| if (!Data->SetupCompleted || Data->IsBootp || Data->IsAck) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| } else if (Data->SetupCompleted) { | |
| if (Data->IsBootp || Data->IsAck) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| } | |
| // | |
| // Do packet content checks. | |
| // | |
| if (Data->SetupCompleted) { | |
| // | |
| // %%TBD - check discover packet | |
| // | |
| } | |
| if (Data->SelectCompleted) { | |
| if (Data->IsBootp) { | |
| // | |
| // %%TBD - check offer packet | |
| // | |
| if (CompareMem ( | |
| &Data->Discover, | |
| &Data->Request, | |
| sizeof (DHCP4_PACKET) | |
| )) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| if (CompareMem ( | |
| &Data->Offer, | |
| &Data->AckNak, | |
| sizeof (DHCP4_PACKET) | |
| )) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| } else { | |
| // | |
| // %%TBD - check offer, request & acknak packets | |
| // | |
| } | |
| } | |
| } | |
| // | |
| // Allocate data structure. Return error | |
| // if there is not enough available memory. | |
| // | |
| This->Data = AllocatePool (sizeof (EFI_PXE_DHCP4_DATA)); | |
| if (This->Data == NULL) { | |
| return EFI_OUT_OF_RESOURCES; | |
| } | |
| // | |
| // Start PxeBc because we want to use its UdpWrite, UdpRead and | |
| // SetFilter calls. | |
| // | |
| EfiStatus = Private->PxeBc->Start (Private->PxeBc, FALSE); | |
| if (EFI_ERROR (EfiStatus)) { | |
| if (EfiStatus != EFI_ALREADY_STARTED) { | |
| FreePool (This->Data); | |
| This->Data = NULL; | |
| Private->PxeBc->Stop (Private->PxeBc); | |
| return EfiStatus; | |
| } | |
| Private->StopPxeBc = FALSE; | |
| } else { | |
| Private->StopPxeBc = TRUE; | |
| } | |
| // | |
| // Use new data. | |
| // | |
| if (Data != NULL) { | |
| CopyMem (This->Data, Data, sizeof (EFI_PXE_DHCP4_DATA)); | |
| return EFI_SUCCESS; | |
| } | |
| // | |
| // Initialize new public data structure. | |
| // | |
| ZeroMem (This->Data, sizeof (EFI_PXE_DHCP4_DATA)); | |
| // | |
| // Fill in default DHCP discover packet. | |
| // Check for MAC addresses of strange lengths, just in case. | |
| // | |
| Packet = &This->Data->Discover.dhcp4; | |
| Packet->op = BOOTP_REQUEST; | |
| Packet->htype = Private->Snp->Mode->IfType; | |
| if (Private->Snp->Mode->HwAddressSize > 16) { | |
| Packet->hlen = 16; | |
| } else { | |
| Packet->hlen = (UINT8) Private->Snp->Mode->HwAddressSize; | |
| } | |
| Packet->hops = 0; /* Set to zero per RFC 2131. */ | |
| if (Packet->hlen < sizeof Packet->xid) { | |
| if (Packet->hlen != 0) { | |
| CopyMem ( | |
| &Packet->xid, | |
| &Private->Snp->Mode->CurrentAddress, | |
| Packet->hlen | |
| ); | |
| } | |
| } else { | |
| CopyMem ( | |
| &Packet->xid, | |
| &Private->Snp->Mode->CurrentAddress.Addr[Packet->hlen - sizeof Packet->xid], | |
| sizeof Packet->xid | |
| ); | |
| } | |
| // | |
| // %%TBD - xid should be randomized | |
| // | |
| Packet->secs = htons (DHCP4_INITIAL_SECONDS); | |
| Packet->flags = htons (DHCP4_BROADCAST_FLAG); | |
| if (Packet->hlen != 0) { | |
| CopyMem (Packet->chaddr, &Private->Snp->Mode->CurrentAddress, Packet->hlen); | |
| } | |
| Packet->magik = htonl (DHCP4_MAGIK_NUMBER); | |
| OpPtr = Packet->options; | |
| *OpPtr++ = DHCP4_MESSAGE_TYPE; | |
| *OpPtr++ = 1; | |
| *OpPtr++ = DHCP4_MESSAGE_TYPE_DISCOVER; | |
| *OpPtr++ = DHCP4_MAX_MESSAGE_SIZE; | |
| *OpPtr++ = 2; | |
| *OpPtr++ = (UINT8) ((DHCP4_DEFAULT_MAX_MESSAGE_SIZE >> 8) & 0xFF); | |
| *OpPtr++ = (UINT8) (DHCP4_DEFAULT_MAX_MESSAGE_SIZE & 0xFF); | |
| *OpPtr++ = DHCP4_PARAMETER_REQUEST_LIST; | |
| OpLen = OpPtr; | |
| *OpPtr++ = 0; | |
| *OpPtr++ = DHCP4_SUBNET_MASK; | |
| *OpPtr++ = DHCP4_TIME_OFFSET; | |
| *OpPtr++ = DHCP4_ROUTER_LIST; | |
| *OpPtr++ = DHCP4_TIME_SERVERS; | |
| *OpPtr++ = DHCP4_NAME_SERVERS; | |
| *OpPtr++ = DHCP4_DNS_SERVERS; | |
| *OpPtr++ = DHCP4_HOST_NAME; | |
| *OpPtr++ = DHCP4_BOOT_FILE_SIZE; | |
| *OpPtr++ = DHCP4_MESSAGE_TYPE; | |
| *OpPtr++ = DHCP4_DOMAIN_NAME; | |
| *OpPtr++ = DHCP4_ROOT_PATH; | |
| *OpPtr++ = DHCP4_EXTENSION_PATH; | |
| *OpPtr++ = DHCP4_MAX_DATAGRAM_SIZE; | |
| *OpPtr++ = DHCP4_DEFAULT_TTL; | |
| *OpPtr++ = DHCP4_BROADCAST_ADDRESS; | |
| *OpPtr++ = DHCP4_NIS_DOMAIN_NAME; | |
| *OpPtr++ = DHCP4_NIS_SERVERS; | |
| *OpPtr++ = DHCP4_NTP_SERVERS; | |
| *OpPtr++ = DHCP4_VENDOR_SPECIFIC; | |
| *OpPtr++ = DHCP4_REQUESTED_IP_ADDRESS; | |
| *OpPtr++ = DHCP4_LEASE_TIME; | |
| *OpPtr++ = DHCP4_SERVER_IDENTIFIER; | |
| *OpPtr++ = DHCP4_RENEWAL_TIME; | |
| *OpPtr++ = DHCP4_REBINDING_TIME; | |
| *OpPtr++ = DHCP4_CLASS_IDENTIFIER; | |
| *OpPtr++ = DHCP4_TFTP_SERVER_NAME; | |
| *OpPtr++ = DHCP4_BOOTFILE; | |
| *OpPtr++ = 128; | |
| *OpPtr++ = 129; | |
| *OpPtr++ = 130; | |
| *OpPtr++ = 131; | |
| *OpPtr++ = 132; | |
| *OpPtr++ = 133; | |
| *OpPtr++ = 134; | |
| *OpPtr++ = 135; | |
| *OpLen = (UINT8) ((OpPtr - OpLen) - 1); | |
| *OpPtr++ = DHCP4_END; | |
| This->Data->SetupCompleted = TRUE; | |
| return EFI_SUCCESS; | |
| } | |
| /* eof - PxeDhcp4Setup.c */ |