1 /** @file
2  *  @brief DHCPv4 Client Handler
3  */
4 
5 /*
6  * Copyright (c) 2016 Intel Corporation
7  *
8  * SPDX-License-Identifier: Apache-2.0
9  */
10 
11 #ifndef ZEPHYR_INCLUDE_NET_DHCPV4_H_
12 #define ZEPHYR_INCLUDE_NET_DHCPV4_H_
13 
14 #include <zephyr/sys/slist.h>
15 #include <zephyr/types.h>
16 
17 #ifdef __cplusplus
18 extern "C" {
19 #endif
20 
21 /**
22  * @brief DHCPv4
23  * @defgroup dhcpv4 DHCPv4
24  * @since 1.7
25  * @version 0.8.0
26  * @ingroup networking
27  * @{
28  */
29 
30 /** @cond INTERNAL_HIDDEN */
31 
32 /** Current state of DHCPv4 client address negotiation.
33  *
34  * Additions removals and reorders in this definition must be
35  * reflected within corresponding changes to net_dhcpv4_state_name.
36  */
37 enum net_dhcpv4_state {
38 	NET_DHCPV4_DISABLED,
39 	NET_DHCPV4_INIT,
40 	NET_DHCPV4_SELECTING,
41 	NET_DHCPV4_REQUESTING,
42 	NET_DHCPV4_RENEWING,
43 	NET_DHCPV4_REBINDING,
44 	NET_DHCPV4_BOUND,
45 	NET_DHCPV4_DECLINE,
46 } __packed;
47 
48 /** @endcond */
49 
50 /**
51  * @brief DHCPv4 message types
52  *
53  * These enumerations represent RFC2131 defined msy type codes, hence
54  * they should not be renumbered.
55  *
56  * Additions, removald and reorders in this definition must be reflected
57  * within corresponding changes to net_dhcpv4_msg_type_name.
58  */
59 enum net_dhcpv4_msg_type {
60 	NET_DHCPV4_MSG_TYPE_DISCOVER	= 1, /**< Discover message */
61 	NET_DHCPV4_MSG_TYPE_OFFER	= 2, /**< Offer message */
62 	NET_DHCPV4_MSG_TYPE_REQUEST	= 3, /**< Request message */
63 	NET_DHCPV4_MSG_TYPE_DECLINE	= 4, /**< Decline message */
64 	NET_DHCPV4_MSG_TYPE_ACK		= 5, /**< Acknowledge message */
65 	NET_DHCPV4_MSG_TYPE_NAK		= 6, /**< Negative acknowledge message */
66 	NET_DHCPV4_MSG_TYPE_RELEASE	= 7, /**< Release message */
67 	NET_DHCPV4_MSG_TYPE_INFORM	= 8, /**< Inform message */
68 };
69 
70 struct net_dhcpv4_option_callback;
71 
72 /**
73  * @typedef net_dhcpv4_option_callback_handler_t
74  * @brief Define the application callback handler function signature
75  *
76  * @param cb Original struct net_dhcpv4_option_callback owning this handler
77  * @param length The length of data returned by the server. If this is
78  *		 greater than cb->max_length, only cb->max_length bytes
79  *		 will be available in cb->data
80  * @param msg_type Type of DHCP message that triggered the callback
81  * @param iface The interface on which the DHCP message was received
82  *
83  * Note: cb pointer can be used to retrieve private data through
84  * CONTAINER_OF() if original struct net_dhcpv4_option_callback is stored in
85  * another private structure.
86  */
87 typedef void (*net_dhcpv4_option_callback_handler_t)(struct net_dhcpv4_option_callback *cb,
88 						     size_t length,
89 						     enum net_dhcpv4_msg_type msg_type,
90 						     struct net_if *iface);
91 
92 /** @cond INTERNAL_HIDDEN */
93 
94 /**
95  * @brief DHCP option callback structure
96  *
97  * Used to register a callback in the DHCPv4 client callback list.
98  * As many callbacks as needed can be added as long as each of them
99  * are unique pointers of struct net_dhcpv4_option_callback.
100  * Beware such structure should not be allocated on stack.
101  *
102  * Note: To help setting it, see net_dhcpv4_init_option_callback() below
103  */
104 struct net_dhcpv4_option_callback {
105 	/** This is meant to be used internally and the user should not
106 	 * mess with it.
107 	 */
108 	sys_snode_t node;
109 
110 	/** Actual callback function being called when relevant. */
111 	net_dhcpv4_option_callback_handler_t handler;
112 
113 	/** The DHCP option this callback is attached to. */
114 	uint8_t option;
115 
116 	/** Maximum length of data buffer. */
117 	size_t max_length;
118 
119 	/** Pointer to a buffer of size max_length that is used to store the
120 	 * option data.
121 	 */
122 	void *data;
123 };
124 
125 /** @endcond */
126 
127 /**
128  * @brief Helper to initialize a struct net_dhcpv4_option_callback properly
129  * @param callback A valid Application's callback structure pointer.
130  * @param handler A valid handler function pointer.
131  * @param option The DHCP option the callback responds to.
132  * @param data A pointer to a buffer for max_length bytes.
133  * @param max_length The maximum length of the data returned.
134  */
net_dhcpv4_init_option_callback(struct net_dhcpv4_option_callback * callback,net_dhcpv4_option_callback_handler_t handler,uint8_t option,void * data,size_t max_length)135 static inline void net_dhcpv4_init_option_callback(struct net_dhcpv4_option_callback *callback,
136 						   net_dhcpv4_option_callback_handler_t handler,
137 						   uint8_t option,
138 						   void *data,
139 						   size_t max_length)
140 {
141 	__ASSERT(callback, "Callback pointer should not be NULL");
142 	__ASSERT(handler, "Callback handler pointer should not be NULL");
143 	__ASSERT(data, "Data pointer should not be NULL");
144 
145 	callback->handler = handler;
146 	callback->option = option;
147 	callback->data = data;
148 	callback->max_length = max_length;
149 }
150 
151 /**
152  * @brief Add an application callback.
153  * @param cb A valid application's callback structure pointer.
154  * @return 0 if successful, negative errno code on failure.
155  */
156 int net_dhcpv4_add_option_callback(struct net_dhcpv4_option_callback *cb);
157 
158 /**
159  * @brief Remove an application callback.
160  * @param cb A valid application's callback structure pointer.
161  * @return 0 if successful, negative errno code on failure.
162  */
163 int net_dhcpv4_remove_option_callback(struct net_dhcpv4_option_callback *cb);
164 
165 /**
166  * @brief Helper to initialize a struct net_dhcpv4_option_callback for encapsulated vendor-specific
167  * options properly
168  * @param callback A valid Application's callback structure pointer.
169  * @param handler A valid handler function pointer.
170  * @param option The DHCP encapsulated vendor-specific option the callback responds to.
171  * @param data A pointer to a buffer for max_length bytes.
172  * @param max_length The maximum length of the data returned.
173  */
174 static inline void
net_dhcpv4_init_option_vendor_callback(struct net_dhcpv4_option_callback * callback,net_dhcpv4_option_callback_handler_t handler,uint8_t option,void * data,size_t max_length)175 net_dhcpv4_init_option_vendor_callback(struct net_dhcpv4_option_callback *callback,
176 				       net_dhcpv4_option_callback_handler_t handler, uint8_t option,
177 				       void *data, size_t max_length)
178 {
179 	__ASSERT(callback, "Callback pointer should not be NULL");
180 	__ASSERT(handler, "Callback handler pointer should not be NULL");
181 	__ASSERT(data, "Data pointer should not be NULL");
182 
183 	callback->handler = handler;
184 	callback->option = option;
185 	callback->data = data;
186 	callback->max_length = max_length;
187 }
188 
189 /**
190  * @brief Add an application callback for encapsulated vendor-specific options.
191  * @param cb A valid application's callback structure pointer.
192  * @return 0 if successful, negative errno code on failure.
193  */
194 int net_dhcpv4_add_option_vendor_callback(struct net_dhcpv4_option_callback *cb);
195 
196 /**
197  * @brief Remove an application callback for encapsulated vendor-specific options.
198  * @param cb A valid application's callback structure pointer.
199  * @return 0 if successful, negative errno code on failure.
200  */
201 int net_dhcpv4_remove_option_vendor_callback(struct net_dhcpv4_option_callback *cb);
202 
203 /**
204  *  @brief Start DHCPv4 client on an iface
205  *
206  *  @details Start DHCPv4 client on a given interface. DHCPv4 client
207  *  will start negotiation for IPv4 address. Once the negotiation is
208  *  success IPv4 address details will be added to interface.
209  *
210  *  @param iface A valid pointer on an interface
211  */
212 void net_dhcpv4_start(struct net_if *iface);
213 
214 /**
215  *  @brief Stop DHCPv4 client on an iface
216  *
217  *  @details Stop DHCPv4 client on a given interface. DHCPv4 client
218  *  will remove all configuration obtained from a DHCP server from the
219  *  interface and stop any further negotiation with the server.
220  *
221  *  @param iface A valid pointer on an interface
222  */
223 void net_dhcpv4_stop(struct net_if *iface);
224 
225 /**
226  *  @brief Restart DHCPv4 client on an iface
227  *
228  *  @details Restart DHCPv4 client on a given interface. DHCPv4 client
229  *  will restart the state machine without any of the initial delays
230  *  used in start.
231  *
232  *  @param iface A valid pointer on an interface
233  */
234 void net_dhcpv4_restart(struct net_if *iface);
235 
236 /** @cond INTERNAL_HIDDEN */
237 
238 /**
239  *  @brief DHCPv4 state name
240  *
241  *  @internal
242  */
243 const char *net_dhcpv4_state_name(enum net_dhcpv4_state state);
244 
245 /** @endcond */
246 
247 /**
248  * @brief Return a text representation of the msg_type
249  *
250  * @param msg_type The msg_type to be converted to text
251  * @return A text representation of msg_type
252  */
253 const char *net_dhcpv4_msg_type_name(enum net_dhcpv4_msg_type msg_type);
254 
255 /**
256  * @}
257  */
258 
259 #ifdef __cplusplus
260 }
261 #endif
262 
263 #endif /* ZEPHYR_INCLUDE_NET_DHCPV4_H_ */
264