1 /** @file
2   Dhcp6 internal data structure and definition declaration.
3 
4   Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
5 
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions of the BSD License
8   which accompanies this distribution.  The full text of the license may be found at
9   http://opensource.org/licenses/bsd-license.php.
10 
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13 
14 **/
15 
16 #ifndef __EFI_DHCP6_IMPL_H__
17 #define __EFI_DHCP6_IMPL_H__
18 
19 
20 #include <Uefi.h>
21 
22 #include <IndustryStandard/Dhcp.h>
23 
24 #include <Protocol/Dhcp6.h>
25 #include <Protocol/Udp6.h>
26 #include <Protocol/Ip6Config.h>
27 #include <Protocol/ServiceBinding.h>
28 #include <Protocol/DriverBinding.h>
29 
30 #include <Library/UdpIoLib.h>
31 #include <Library/DebugLib.h>
32 #include <Library/BaseMemoryLib.h>
33 #include <Library/MemoryAllocationLib.h>
34 #include <Library/UefiBootServicesTableLib.h>
35 #include <Library/UefiRuntimeServicesTableLib.h>
36 #include <Library/UefiLib.h>
37 #include <Library/BaseLib.h>
38 #include <Library/NetLib.h>
39 #include <Library/PrintLib.h>
40 
41 
42 typedef struct _DHCP6_IA_CB    DHCP6_IA_CB;
43 typedef struct _DHCP6_INF_CB   DHCP6_INF_CB;
44 typedef struct _DHCP6_TX_CB    DHCP6_TX_CB;
45 typedef struct _DHCP6_SERVICE  DHCP6_SERVICE;
46 typedef struct _DHCP6_INSTANCE DHCP6_INSTANCE;
47 
48 #include "Dhcp6Utility.h"
49 #include "Dhcp6Io.h"
50 #include "Dhcp6Driver.h"
51 
52 #define DHCP6_SERVICE_SIGNATURE   SIGNATURE_32 ('D', 'H', '6', 'S')
53 #define DHCP6_INSTANCE_SIGNATURE  SIGNATURE_32 ('D', 'H', '6', 'I')
54 
55 #define DHCP6_PACKET_ALL          0
56 #define DHCP6_PACKET_STATEFUL     1
57 #define DHCP6_PACKET_STATELESS    2
58 
59 #define DHCP6_BASE_PACKET_SIZE    1024
60 
61 #define DHCP6_PORT_CLIENT         546
62 #define DHCP6_PORT_SERVER         547
63 
64 #define DHCP6_INSTANCE_FROM_THIS(Instance) CR ((Instance), DHCP6_INSTANCE, Dhcp6, DHCP6_INSTANCE_SIGNATURE)
65 #define DHCP6_SERVICE_FROM_THIS(Service)   CR ((Service), DHCP6_SERVICE, ServiceBinding, DHCP6_SERVICE_SIGNATURE)
66 
67 extern EFI_IPv6_ADDRESS           mAllDhcpRelayAndServersAddress;
68 extern EFI_IPv6_ADDRESS           mAllDhcpServersAddress;
69 extern EFI_DHCP6_PROTOCOL         gDhcp6ProtocolTemplate;
70 
71 //
72 // Control block for each IA.
73 //
74 struct _DHCP6_IA_CB {
75   EFI_DHCP6_IA                  *Ia;
76   UINT32                        T1;
77   UINT32                        T2;
78   UINT32                        AllExpireTime;
79   UINT32                        LeaseTime;
80 };
81 
82 //
83 // Control block for each transmitted message.
84 //
85 struct _DHCP6_TX_CB {
86   LIST_ENTRY                    Link;
87   UINT32                        Xid;
88   EFI_DHCP6_PACKET              *TxPacket;
89   EFI_DHCP6_RETRANSMISSION      RetryCtl;
90   UINT32                        RetryCnt;
91   UINT32                        RetryExp;
92   UINT32                        RetryLos;
93   UINT32                        TickTime;
94   UINT16                        *Elapsed;
95   BOOLEAN                       SolicitRetry;
96 };
97 
98 //
99 // Control block for each info-request message.
100 //
101 struct _DHCP6_INF_CB {
102   LIST_ENTRY                    Link;
103   UINT32                        Xid;
104   EFI_DHCP6_INFO_CALLBACK       ReplyCallback;
105   VOID                          *CallbackContext;
106   EFI_EVENT                     TimeoutEvent;
107 };
108 
109 //
110 // Control block for Dhcp6 instance, it's per configuration data.
111 //
112 struct _DHCP6_INSTANCE {
113   UINT32                        Signature;
114   EFI_HANDLE                    Handle;
115   DHCP6_SERVICE                 *Service;
116   LIST_ENTRY                    Link;
117   EFI_DHCP6_PROTOCOL            Dhcp6;
118   EFI_EVENT                     Timer;
119   EFI_DHCP6_CONFIG_DATA         *Config;
120   EFI_DHCP6_IA                  *CacheIa;
121   DHCP6_IA_CB                   IaCb;
122   LIST_ENTRY                    TxList;
123   LIST_ENTRY                    InfList;
124   EFI_DHCP6_PACKET              *AdSelect;
125   UINT8                         AdPref;
126   EFI_IPv6_ADDRESS              *Unicast;
127   volatile EFI_STATUS           UdpSts;
128   BOOLEAN                       InDestroy;
129   BOOLEAN                       MediaPresent;
130   //
131   // StartTime is used to calculate the 'elapsed-time' option. Refer to RFC3315,
132   // the elapsed-time is amount of time since the client began its current DHCP transaction.
133   //
134   UINT64                        StartTime;
135 };
136 
137 //
138 // Control block for Dhcp6 service, it's per Nic handle.
139 //
140 struct _DHCP6_SERVICE {
141   UINT32                        Signature;
142   EFI_HANDLE                    Controller;
143   EFI_HANDLE                    Image;
144   EFI_SERVICE_BINDING_PROTOCOL  ServiceBinding;
145   EFI_SIMPLE_NETWORK_PROTOCOL   *Snp;
146   EFI_IP6_CONFIG_PROTOCOL       *Ip6Cfg;
147   EFI_DHCP6_DUID                *ClientId;
148   UDP_IO                        *UdpIo;
149   UINT32                        Xid;
150   LIST_ENTRY                    Child;
151   UINTN                         NumOfChild;
152 };
153 
154 /**
155   Starts the DHCPv6 standard S.A.R.R. process.
156 
157   The Start() function starts the DHCPv6 standard process. This function can
158   be called only when the state of Dhcp6 instance is in the Dhcp6Init state.
159   If the DHCP process completes successfully, the state of the Dhcp6 instance
160   will be transferred through Dhcp6Selecting and Dhcp6Requesting to the
161   Dhcp6Bound state.
162   Refer to rfc-3315 for precise state transitions during this process. At the
163   time when each event occurs in this process, the callback function that was set
164   by EFI_DHCP6_PROTOCOL.Configure() will be called and the user can take this
165   opportunity to control the process.
166 
167   @param[in]  This              The pointer to Dhcp6 protocol.
168 
169   @retval EFI_SUCCESS           The DHCPv6 standard process has started, or it
170                                 completed when CompletionEvent was NULL.
171   @retval EFI_ACCESS_DENIED     The EFI DHCPv6 Child instance hasn't been configured.
172   @retval EFI_INVALID_PARAMETER This is NULL.
173   @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.
174   @retval EFI_TIMEOUT           The DHCPv6 configuration process failed because no
175                                 response was received from the server within the
176                                 specified timeout value.
177   @retval EFI_ABORTED           The user aborted the DHCPv6 process.
178   @retval EFI_ALREADY_STARTED   Some other Dhcp6 instance already started the DHCPv6
179                                 standard process.
180   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
181 
182 **/
183 EFI_STATUS
184 EFIAPI
185 EfiDhcp6Start (
186   IN EFI_DHCP6_PROTOCOL        *This
187   );
188 
189 /**
190   Stops the DHCPv6 standard S.A.R.R. process.
191 
192   The Stop() function is used to stop the DHCPv6 standard process. After this
193   function is called successfully, the state of Dhcp6 instance is transferred
194   into the Dhcp6Init. EFI_DHCP6_PROTOCOL.Configure() needs to be called
195   before DHCPv6 standard process can be started again. This function can be
196   called when the Dhcp6 instance is in any state.
197 
198   @param[in]  This              The pointer to the Dhcp6 protocol.
199 
200   @retval EFI_SUCCESS           The Dhcp6 instance is now in the Dhcp6Init state.
201   @retval EFI_INVALID_PARAMETER This is NULL.
202 
203 **/
204 EFI_STATUS
205 EFIAPI
206 EfiDhcp6Stop (
207   IN EFI_DHCP6_PROTOCOL        *This
208   );
209 
210 /**
211   Returns the current operating mode data for the Dhcp6 instance.
212 
213   The GetModeData() function returns the current operating mode and
214   cached data packet for the Dhcp6 instance.
215 
216   @param[in]  This              The pointer to the Dhcp6 protocol.
217   @param[out] Dhcp6ModeData     The pointer to the Dhcp6 mode data.
218   @param[out] Dhcp6ConfigData   The pointer to the Dhcp6 configure data.
219 
220   @retval EFI_SUCCESS           The mode data was returned.
221   @retval EFI_INVALID_PARAMETER This is NULL.
222   @retval EFI_ACCESS_DENIED     The EFI DHCPv6 Protocol instance has not
223                                 been configured when Dhcp6ConfigData is
224                                 not NULL.
225 **/
226 EFI_STATUS
227 EFIAPI
228 EfiDhcp6GetModeData (
229   IN  EFI_DHCP6_PROTOCOL       *This,
230   OUT EFI_DHCP6_MODE_DATA      *Dhcp6ModeData      OPTIONAL,
231   OUT EFI_DHCP6_CONFIG_DATA    *Dhcp6ConfigData    OPTIONAL
232   );
233 
234 /**
235   Initializes, changes, or resets the operational settings for the Dhcp6 instance.
236 
237   The Configure() function is used to initialize or clean up the configuration
238   data of the Dhcp6 instance:
239   - When Dhcp6CfgData is not NULL and Configure() is called successfully, the
240     configuration data will be initialized in the Dhcp6 instance and the state
241     of the configured IA will be transferred into Dhcp6Init.
242   - When Dhcp6CfgData is NULL and Configure() is called successfully, the
243     configuration data will be cleaned up and no IA will be associated with
244     the Dhcp6 instance.
245   To update the configuration data for an Dhcp6 instance, the original data
246   must be cleaned up before setting the new configuration data.
247 
248   @param[in]  This                   The pointer to the Dhcp6 protocol
249   @param[in]  Dhcp6CfgData           The pointer to the EFI_DHCP6_CONFIG_DATA.
250 
251   @retval EFI_SUCCESS           The Dhcp6 is configured successfully with the
252                                 Dhcp6Init state, or cleaned up the original
253                                 configuration setting.
254   @retval EFI_ACCESS_DENIED     The Dhcp6 instance has been already configured
255                                 when Dhcp6CfgData is not NULL.
256                                 The Dhcp6 instance has already started the
257                                 DHCPv6 S.A.R.R when Dhcp6CfgData is NULL.
258   @retval EFI_INVALID_PARAMETER Some of the parameter is invalid.
259   @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.
260   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
261 
262 **/
263 EFI_STATUS
264 EFIAPI
265 EfiDhcp6Configure (
266   IN EFI_DHCP6_PROTOCOL        *This,
267   IN EFI_DHCP6_CONFIG_DATA     *Dhcp6CfgData    OPTIONAL
268   );
269 
270 /**
271   Request configuration information without the assignment of any
272   Ia addresses of the client.
273 
274   The InfoRequest() function is used to request configuration information
275   without the assignment of any IPv6 address of the client. Client sends
276   out Information Request packet to obtain the required configuration
277   information, and DHCPv6 server responds with Reply packet containing
278   the information for the client. The received Reply packet will be passed
279   to the user by ReplyCallback function. If user returns EFI_NOT_READY from
280   ReplyCallback, the Dhcp6 instance will continue to receive other Reply
281   packets unless timeout according to the Retransmission parameter.
282   Otherwise, the Information Request exchange process will be finished
283   successfully if user returns EFI_SUCCESS from ReplyCallback.
284 
285   @param[in]  This              The pointer to the Dhcp6 protocol.
286   @param[in]  SendClientId      If TRUE, the DHCPv6 protocol instance will build Client
287                                 Identifier option and include it into Information Request
288                                 packet. Otherwise, Client Identifier option will not be included.
289   @param[in]  OptionRequest     The pointer to the buffer of option request options.
290   @param[in]  OptionCount       The option number in the OptionList.
291   @param[in]  OptionList        The list of appended options.
292   @param[in]  Retransmission    The pointer to the retransmission of the message.
293   @param[in]  TimeoutEvent      The event of timeout.
294   @param[in]  ReplyCallback     The callback function when a reply was received.
295   @param[in]  CallbackContext   The pointer to the parameter passed to the callback.
296 
297   @retval EFI_SUCCESS           The DHCPv6 information request exchange process
298                                 completed when TimeoutEvent is NULL. Information
299                                 Request packet has been sent to DHCPv6 server when
300                                 TimeoutEvent is not NULL.
301   @retval EFI_NO_RESPONSE       The DHCPv6 information request exchange process failed
302                                 because of no response, or not all requested-options
303                                 are responded to by DHCPv6 servers when Timeout happened.
304   @retval EFI_ABORTED           The DHCPv6 information request exchange process was aborted
305                                 by the user.
306   @retval EFI_INVALID_PARAMETER Some parameter is NULL.
307   @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.
308   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
309 
310 **/
311 EFI_STATUS
312 EFIAPI
313 EfiDhcp6InfoRequest (
314   IN EFI_DHCP6_PROTOCOL        *This,
315   IN BOOLEAN                   SendClientId,
316   IN EFI_DHCP6_PACKET_OPTION   *OptionRequest,
317   IN UINT32                    OptionCount,
318   IN EFI_DHCP6_PACKET_OPTION   *OptionList[]    OPTIONAL,
319   IN EFI_DHCP6_RETRANSMISSION  *Retransmission,
320   IN EFI_EVENT                 TimeoutEvent     OPTIONAL,
321   IN EFI_DHCP6_INFO_CALLBACK   ReplyCallback,
322   IN VOID                      *CallbackContext OPTIONAL
323   );
324 
325 /**
326   Manually extend the valid and preferred lifetimes for the IPv6 addresses
327   of the configured IA and update other configuration parameters by sending
328   Renew or Rebind packet.
329 
330   The RenewRebind() function is used to manually extend the valid and preferred
331   lifetimes for the IPv6 addresses of the configured IA and update other
332   configuration parameters by sending a Renew or Rebind packet.
333   - When RebindRequest is FALSE and the state of the configured IA is Dhcp6Bound,
334     it will send Renew packet to the previously DHCPv6 server and transfer the
335     state of the configured IA to Dhcp6Renewing. If valid Reply packet received,
336     the state transfers to Dhcp6Bound and the valid and preferred timer restarts.
337     If fails, the state transfers to Dhcp6Bound but the timer continues.
338   - When RebindRequest is TRUE and the state of the configured IA is Dhcp6Bound,
339     it will send a Rebind packet. If a valid Reply packet is received, the state transfers
340     to Dhcp6Bound, and the valid and preferred timer restarts. If it fails, the state
341     transfers to Dhcp6Init, and the IA can't be used.
342 
343   @param[in]  This              The pointer to the Dhcp6 protocol.
344   @param[in]  RebindRequest     If TRUE, Rebind packet will be sent and enter Dhcp6Rebinding state.
345                                 Otherwise, Renew packet will be sent and enter Dhcp6Renewing state.
346 
347   @retval EFI_SUCCESS           The DHCPv6 renew/rebind exchange process
348                                 completed and at least one IPv6 address of the
349                                 configured IA was bound again when
350                                 EFI_DHCP6_CONFIG_DATA.IaInfoEvent was NULL.
351                                 The EFI DHCPv6 Protocol instance has sent Renew
352                                 or Rebind packet when
353                                 EFI_DHCP6_CONFIG_DATA.IaInfoEvent is not NULL.
354   @retval EFI_ACCESS_DENIED     The Dhcp6 instance hasn't been configured, or the
355                                 state of the configured IA is not in Dhcp6Bound.
356   @retval EFI_ALREADY_STARTED   The state of the configured IA has already entered
357                                 Dhcp6Renewing when RebindRequest is FALSE.
358                                 The state of the configured IA has already entered
359                                 Dhcp6Rebinding when RebindRequest is TRUE.
360   @retval EFI_ABORTED           The DHCPv6 renew/rebind exchange process aborted
361                                 by user.
362   @retval EFI_NO_RESPONSE       The DHCPv6 renew/rebind exchange process failed
363                                 because of no response.
364   @retval EFI_NO_MAPPING        No IPv6 address has been bound to the configured
365                                 IA after the DHCPv6 renew/rebind exchange process.
366   @retval EFI_INVALID_PARAMETER Some parameter is NULL.
367   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
368 
369 **/
370 EFI_STATUS
371 EFIAPI
372 EfiDhcp6RenewRebind (
373   IN EFI_DHCP6_PROTOCOL        *This,
374   IN BOOLEAN                   RebindRequest
375   );
376 
377 /**
378   Inform that one or more addresses assigned by a server are already
379   in use by another node.
380 
381   The Decline() function is used to manually decline the assignment of
382   IPv6 addresses, which have been already used by another node. If all
383   IPv6 addresses of the configured IA are declined through this function,
384   the state of the IA will switch through Dhcp6Declining to Dhcp6Init.
385   Otherwise, the state of the IA will restore to Dhcp6Bound after the
386   declining process. The Decline() can only be called when the IA is in
387   Dhcp6Bound state. If the EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL,
388   this function is a blocking operation. It will return after the
389   declining process finishes, or aborted by user.
390 
391   @param[in]  This              The pointer to the Dhcp6 protocol.
392   @param[in]  AddressCount      The number of declining addresses.
393   @param[in]  Addresses         The pointer to the buffer stored the declining
394                                 addresses.
395 
396   @retval EFI_SUCCESS           The DHCPv6 decline exchange process completed
397                                 when EFI_DHCP6_CONFIG_DATA.IaInfoEvent was NULL.
398                                 The Dhcp6 instance has sent Decline packet when
399                                 EFI_DHCP6_CONFIG_DATA.IaInfoEvent is not NULL.
400   @retval EFI_ACCESS_DENIED     The Dhcp6 instance hasn't been configured, or the
401                                 state of the configured IA is not in Dhcp6Bound.
402   @retval EFI_ABORTED           The DHCPv6 decline exchange process was aborted by the user.
403   @retval EFI_NOT_FOUND         Any specified IPv6 address is not correlated with
404                                 the configured IA for this instance.
405   @retval EFI_INVALID_PARAMETER Some parameter is NULL.
406   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
407 
408 **/
409 EFI_STATUS
410 EFIAPI
411 EfiDhcp6Decline (
412   IN EFI_DHCP6_PROTOCOL        *This,
413   IN UINT32                    AddressCount,
414   IN EFI_IPv6_ADDRESS          *Addresses
415   );
416 
417 /**
418   Release one or more addresses associated with the configured Ia
419   for the current instance.
420 
421   The Release() function is used to manually release the one or more
422   IPv6 address. If AddressCount is zero, it will release all IPv6
423   addresses of the configured IA. If all IPv6 addresses of the IA are
424   released through this function, the state of the IA will switch
425   through Dhcp6Releasing to Dhcp6Init, otherwise, the state of the
426   IA will restore to Dhcp6Bound after the releasing process.
427   The Release() can only be called when the IA is in a Dhcp6Bound state.
428   If the EFI_DHCP6_CONFIG_DATA.IaInfoEvent is NULL, the function is
429   a blocking operation. It will return after the releasing process
430   finishes, or aborted by user.
431 
432   @param[in]  This              The pointer to the Dhcp6 protocol.
433   @param[in]  AddressCount      The number of releasing addresses.
434   @param[in]  Addresses         The pointer to the buffer stored the releasing
435                                 addresses.
436   @retval EFI_SUCCESS           The DHCPv6 release exchange process has
437                                 completed when EFI_DHCP6_CONFIG_DATA.IaInfoEvent
438                                 is NULL. The Dhcp6 instance has sent Release
439                                 packet when EFI_DHCP6_CONFIG_DATA.IaInfoEvent
440                                 is not NULL.
441   @retval EFI_ACCESS_DENIED     The Dhcp6 instance hasn't been configured, or the
442                                 state of the configured IA is not in Dhcp6Bound.
443   @retval EFI_ABORTED           The DHCPv6 release exchange process was aborted by the user.
444   @retval EFI_NOT_FOUND         Any specified IPv6 address is not correlated with
445                                 the configured IA for this instance.
446   @retval EFI_INVALID_PARAMETER Some parameter is NULL.
447   @retval EFI_DEVICE_ERROR      An unexpected system or network error occurred.
448 
449 **/
450 EFI_STATUS
451 EFIAPI
452 EfiDhcp6Release (
453   IN EFI_DHCP6_PROTOCOL        *This,
454   IN UINT32                    AddressCount,
455   IN EFI_IPv6_ADDRESS          *Addresses
456   );
457 
458 /**
459   Parse the option data in the Dhcp6 packet.
460 
461   The Parse() function is used to retrieve the option list in the DHCPv6 packet.
462 
463   @param[in]      This              The pointer to the Dhcp6 protocol.
464   @param[in]      Packet            The pointer to the Dhcp6 packet.
465   @param[in, out] OptionCount       The number of option in the packet.
466   @param[out]     PacketOptionList  The array of pointers to the each option in the packet.
467 
468   @retval EFI_SUCCESS           The packet was successfully parsed.
469   @retval EFI_INVALID_PARAMETER Some parameter is NULL.
470   @retval EFI_BUFFER_TOO_SMALL  *OptionCount is smaller than the number of options
471                                 that were found in the Packet.
472 
473 **/
474 EFI_STATUS
475 EFIAPI
476 EfiDhcp6Parse (
477   IN EFI_DHCP6_PROTOCOL        *This,
478   IN EFI_DHCP6_PACKET          *Packet,
479   IN OUT UINT32                *OptionCount,
480   OUT EFI_DHCP6_PACKET_OPTION  *PacketOptionList[]  OPTIONAL
481   );
482 
483 #endif
484