]> git.proxmox.com Git - mirror_edk2.git/blob - EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4Release.c
Initial import.
[mirror_edk2.git] / EdkModulePkg / Universal / Network / PxeDhcp4 / Dxe / PxeDhcp4Release.c
1 /*++
2
3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
8
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12 Module Name:
13 PxeDhcp4Release.c
14
15 Abstract:
16 Transmit release packet, free allocations and shutdown PxeDhcp4.
17
18 --*/
19
20
21 #include "PxeDhcp4.h"
22
23 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
24 EFI_STATUS
25 EFIAPI
26 PxeDhcp4Release (
27 IN EFI_PXE_DHCP4_PROTOCOL *This
28 )
29 {
30 PXE_DHCP4_PRIVATE_DATA *Private;
31 EFI_IP_ADDRESS ServerIp;
32 EFI_IP_ADDRESS client_ip;
33 EFI_IP_ADDRESS gateway_ip;
34 EFI_IP_ADDRESS subnet_mask;
35 EFI_STATUS efi_status;
36 DHCP4_OP *op;
37 UINT8 op_list[20];
38
39 //
40 // Check for invalid parameters.
41 //
42 if (This == NULL) {
43 return EFI_INVALID_PARAMETER;
44 }
45 //
46 // Release does nothing if the protocol has never been setup.
47 //
48 if (This->Data == NULL) {
49 return EFI_NOT_STARTED;
50 }
51 //
52 // Fail if we do not have valid instance data.
53 //
54 Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);
55
56 if (Private == NULL) {
57 return EFI_INVALID_PARAMETER;
58 }
59
60 if (Private->PxeBc == NULL) {
61 return EFI_DEVICE_ERROR;
62 }
63 //
64 // If this is a BOOTP session and there is not a DHCP Ack
65 // packet, just release storage and return.
66 //
67 if (This->Data->IsBootp || !This->Data->IsAck) {
68 gBS->FreePool (This->Data);
69 This->Data = NULL;
70
71 if (Private->StopPxeBc) {
72 Private->PxeBc->Stop (Private->PxeBc);
73 }
74
75 return EFI_SUCCESS;
76 }
77 //
78 // Build option list for DHCP Release packet.
79 // If any errors occur, just release storage and return.
80 //
81 //
82 // Message type is first.
83 //
84 op_list[0] = DHCP4_MESSAGE_TYPE;
85 op_list[1] = 1;
86 op_list[2] = DHCP4_MESSAGE_TYPE_RELEASE;
87
88 //
89 // Followed by server identifier.
90 //
91 efi_status = find_opt (
92 &This->Data->Request,
93 DHCP4_SERVER_IDENTIFIER,
94 0,
95 &op
96 );
97
98 if (EFI_ERROR (efi_status)) {
99 gBS->FreePool (This->Data);
100 This->Data = NULL;
101
102 if (Private->StopPxeBc) {
103 Private->PxeBc->Stop (Private->PxeBc);
104 }
105
106 return EFI_SUCCESS;
107 }
108
109 if (op->len != 4) {
110 gBS->FreePool (This->Data);
111 This->Data = NULL;
112
113 if (Private->StopPxeBc) {
114 Private->PxeBc->Stop (Private->PxeBc);
115 }
116
117 return EFI_SUCCESS;
118 }
119
120 CopyMem (&ServerIp, op->data, 4);
121
122 op_list[3] = DHCP4_SERVER_IDENTIFIER;
123 op_list[4] = 4;
124 CopyMem (&op_list[5], &ServerIp, 4);
125
126 //
127 // Followed by end.
128 //
129 op_list[9] = DHCP4_END;
130
131 //
132 // We need a subnet mask for IP stack operation.
133 //
134 efi_status = find_opt (
135 &This->Data->AckNak,
136 DHCP4_SUBNET_MASK,
137 0,
138 &op
139 );
140
141 if (EFI_ERROR (efi_status)) {
142 gBS->FreePool (This->Data);
143 This->Data = NULL;
144
145 if (Private->StopPxeBc) {
146 Private->PxeBc->Stop (Private->PxeBc);
147 }
148
149 return EFI_SUCCESS;
150 }
151
152 if (op->len != 4) {
153 gBS->FreePool (This->Data);
154 This->Data = NULL;
155
156 if (Private->StopPxeBc) {
157 Private->PxeBc->Stop (Private->PxeBc);
158 }
159
160 return EFI_SUCCESS;
161 }
162
163 ZeroMem (&subnet_mask, sizeof (EFI_IP_ADDRESS));
164 CopyMem (&subnet_mask, op->data, 4);
165
166 //
167 // Gateway IP address may be needed.
168 //
169 ZeroMem (&gateway_ip, sizeof (EFI_IP_ADDRESS));
170 CopyMem (&gateway_ip, &This->Data->AckNak.dhcp4.giaddr, 4);
171
172 //
173 // Client IP address needed for IP stack operation.
174 //
175 ZeroMem (&client_ip, sizeof (EFI_IP_ADDRESS));
176 CopyMem (&client_ip, &This->Data->AckNak.dhcp4.yiaddr, 4);
177
178 //
179 // Enable UDP...
180 //
181 efi_status = start_udp (Private, &client_ip, &subnet_mask);
182
183 if (EFI_ERROR (efi_status)) {
184 gBS->FreePool (This->Data);
185 This->Data = NULL;
186
187 if (Private->StopPxeBc) {
188 Private->PxeBc->Stop (Private->PxeBc);
189 }
190
191 return efi_status;
192 }
193 //
194 // Gather information out of DHCP request packet needed for
195 // DHCP release packet.
196 //
197 //
198 // Setup DHCP Release packet.
199 //
200 CopyMem (&This->Data->Request.dhcp4.ciaddr, &client_ip, 4);
201
202 ZeroMem (&This->Data->Request.dhcp4.yiaddr, 12);
203
204 ZeroMem (&This->Data->Request.dhcp4.sname, 64 + 128);
205
206 This->Data->Request.dhcp4.hops = 0;
207 This->Data->Request.dhcp4.secs = 0;
208 This->Data->Request.dhcp4.flags = 0;
209
210 ZeroMem (
211 &This->Data->Request.dhcp4.options,
212 sizeof This->Data->Request.dhcp4.options
213 );
214
215 CopyMem (&This->Data->Request.dhcp4.options, op_list, 10);
216
217 //
218 // Transmit DHCP Release packet.
219 //
220 tx_udp (
221 Private,
222 &ServerIp,
223 &gateway_ip,
224 &client_ip,
225 &This->Data->Request,
226 DHCP4_MAX_PACKET_SIZE - (DHCP4_UDP_HEADER_SIZE + DHCP4_IP_HEADER_SIZE)
227 );
228
229 gBS->Stall (1000000); /* 1/10th second */
230
231 //
232 // Shutdown PXE BaseCode and release local storage.
233 //
234 stop_udp (Private);
235
236 gBS->FreePool (This->Data);
237 This->Data = NULL;
238
239 if (Private->StopPxeBc) {
240 Private->PxeBc->Stop (Private->PxeBc);
241 }
242
243 return EFI_SUCCESS;
244 }
245
246 /* eof - PxeDhcp4Release.c */