1 /* main.c - Application main entry point */
2
3 /*
4 * Copyright (c) 2016 Intel Corporation
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 */
8
9 #include <zephyr/logging/log.h>
10 LOG_MODULE_REGISTER(net_test, CONFIG_NET_DHCPV4_LOG_LEVEL);
11
12 #include <zephyr/kernel.h>
13 #include <zephyr/linker/sections.h>
14
15 #include <zephyr/types.h>
16 #include <stddef.h>
17 #include <string.h>
18 #include <stdio.h>
19 #include <errno.h>
20 #include <zephyr/device.h>
21 #include <zephyr/init.h>
22 #include <zephyr/net/net_core.h>
23 #include <zephyr/net/net_pkt.h>
24 #include <zephyr/net/net_ip.h>
25 #include <zephyr/net/dhcpv4.h>
26 #include <zephyr/net/ethernet.h>
27 #include <zephyr/net/net_mgmt.h>
28 #include <zephyr/net/dummy.h>
29
30 #include "ipv4.h"
31 #include "udp_internal.h"
32
33 #include <zephyr/tc_util.h>
34 #include <zephyr/ztest.h>
35
36 #define NET_LOG_ENABLED 1
37 #include "net_private.h"
38
39 /* Sample DHCP offer (420 bytes) */
40 static const unsigned char offer[] = {
41 0x02, 0x01, 0x06, 0x00, 0x00, 0x00,
42 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
43 0x00, 0x00, 0x0a, 0xed, 0x48, 0x9e, 0x0a, 0xb8,
44 0x09, 0x01, 0x0a, 0xed, 0x48, 0x02, 0x00, 0x00,
45 0x5E, 0x00, 0x53, 0x01, 0x00, 0x00, 0x00, 0x00,
46 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
47 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
53 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
54 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
55 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
56 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
57 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
59 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
67 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
68 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
70 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71 /* Magic cookie: DHCP */
72 0x63, 0x82, 0x53, 0x63,
73 /* [0] Pad option */
74 0x00,
75 /* [53] DHCP Message Type: OFFER */
76 0x35, 0x01, 0x02,
77 /* [1] Subnet Mask: 255.255.255.0 */
78 0x01, 0x04, 0xff, 0xff, 0xff, 0x00,
79 /* [58] Renewal Time Value: (21600s) 6 hours */
80 0x3a, 0x04, 0x00, 0x00, 0x54, 0x60,
81 /* [59] Rebinding Time Value: (37800s) 1 hour 30 min */
82 0x3b, 0x04, 0x00, 0x00, 0x93, 0xa8,
83 /* [51] IP Address Lease Time: (43200s) 12 hours */
84 0x33, 0x04, 0x00, 0x00, 0xa8, 0xc0,
85 /* [54] DHCP Server Identifier: 10.184.9.1 */
86 0x36, 0x04, 0x0a, 0xb8, 0x09, 0x01,
87 /* [3] Router: 10.237.72.1 */
88 0x03, 0x04, 0x0a, 0xed, 0x48, 0x01,
89 /* [15] Domain Name: fi.intel.com */
90 0x0f, 0x0d, 0x66, 0x69, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00,
91 /* [6] Domain Name Server: 10.248.2.1 163.33.253.68 10.184.9.1 */
92 0x06, 0x0c, 0x0a, 0xf8, 0x02, 0x01, 0xa3, 0x21, 0xfd, 0x44, 0x0a, 0xb8, 0x09, 0x01,
93 /* [119] Domain Search Option: fi.intel.com ger.corp.intel.com corp.intel.com intel.com */
94 0x77, 0x3d, 0x02, 0x66, 0x69, 0x05, 0x69, 0x6e,
95 0x74, 0x65, 0x6c, 0x03, 0x63, 0x6f, 0x6d, 0x00,
96 0x03, 0x67, 0x65, 0x72, 0x04, 0x63, 0x6f, 0x72,
97 0x70, 0x05, 0x69, 0x6e, 0x74, 0x65, 0x6c, 0x03,
98 0x63, 0x6f, 0x6d, 0x00, 0x04, 0x63, 0x6f, 0x72,
99 0x70, 0x05, 0x69, 0x6e, 0x74, 0x65, 0x6c, 0x03,
100 0x63, 0x6f, 0x6d, 0x00, 0x05, 0x69, 0x6e, 0x74,
101 0x65, 0x6c, 0x03, 0x63, 0x6f, 0x6d, 0x00,
102 /* [44] NetBIOS Name Servers: 163.33.7.86, 143.182.250.105 */
103 0x2c, 0x08, 0xa3, 0x21, 0x07, 0x56, 0x8f, 0xb6, 0xfa, 0x69,
104 /* [43] Encapsulated vendor specific information */
105 0x2b, 0x0a,
106 /* [1]: "string" */
107 0x01, 0x07, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x00,
108 /* End marker */
109 0xff,
110 /* [43] Encapsulated vendor specific information */
111 0x2b, 0x0f,
112 /* [2]: single byte of value 1 */
113 0x02, 0x01, 0x01,
114 /* [3]: zero-length option */
115 0x03, 0x00,
116 /* [254]: invalid option (size longer than remainder of opt 43 size) */
117 0xfe, 0x10, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
118 /* [43] Too short encapsulated vendor option (only single byte) */
119 0x2b, 0x01,
120 /* [254]: invalid option (no length in opt 43) */
121 0xfe,
122 /* [70] POP3 Server: 198.51.100.16 */
123 0x46, 0x04, 0xc6, 0x33, 0x64, 0x10,
124 /* End marker */
125 0xff
126 };
127
128 /* Sample DHCPv4 ACK */
129 static const unsigned char ack[] = {
130 0x02, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
131 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 0x0a, 0xed, 0x48, 0x9e, 0x00, 0x00, 0x00, 0x00,
133 0x0a, 0xed, 0x48, 0x03, 0x00, 0x00, 0x5E, 0x00,
134 0x53, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
135 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
136 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
138 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
139 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
142 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
144 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
145 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
150 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
152 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
153 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
156 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
158 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
159 0x00, 0x00, 0x00, 0x00,
160 /* Magic cookie: DHCP */
161 0x63, 0x82, 0x53, 0x63,
162 /* [0] Pad option */
163 0x00,
164 /* [53] DHCP Message Type: ACK */
165 0x35, 0x01, 0x05,
166 /* [58] Renewal Time Value: (21600s) 6 hours */
167 0x3a, 0x04, 0x00, 0x00, 0x54, 0x60,
168 /* [59] Rebinding Time Value: (37800s) 1 hour 30 min */
169 0x3b, 0x04, 0x00, 0x00, 0x93, 0xa8,
170 /* [51] IP Address Lease Time: (43200s) 12 hours */
171 0x33, 0x04, 0x00, 0x00, 0xa8, 0xc0,
172 /* [54] DHCP Server Identifier: 10.184.9.1 */
173 0x36, 0x04, 0x0a, 0xb8, 0x09, 0x01,
174 /* [1] Subnet Mask: 255.255.255.0 */
175 0x01, 0x04, 0xff, 0xff, 0xff, 0x00,
176 /* [3] Router: 10.237.72.1 */
177 0x03, 0x04, 0x0a, 0xed, 0x48, 0x01,
178 /* [15] Domain Name: fi.intel.com */
179 0x0f, 0x0d, 0x66, 0x69, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00,
180 /* [6] Domain Name Server: 10.248.2.1 163.33.253.68 10.184.9.1 */
181 0x06, 0x0c, 0x0a, 0xf8, 0x02, 0x01, 0xa3, 0x21, 0xfd, 0x44, 0x0a, 0xb8, 0x09, 0x01,
182 /* [119] Domain Search Option: fi.intel.com ger.corp.intel.com corp.intel.com intel.com */
183 0x77, 0x3d, 0x02, 0x66, 0x69, 0x05, 0x69, 0x6e,
184 0x74, 0x65, 0x6c, 0x03, 0x63, 0x6f, 0x6d, 0x00,
185 0x03, 0x67, 0x65, 0x72, 0x04, 0x63, 0x6f, 0x72,
186 0x70, 0x05, 0x69, 0x6e, 0x74, 0x65, 0x6c, 0x03,
187 0x63, 0x6f, 0x6d, 0x00, 0x04, 0x63, 0x6f, 0x72,
188 0x70, 0x05, 0x69, 0x6e, 0x74, 0x65, 0x6c, 0x03,
189 0x63, 0x6f, 0x6d, 0x00, 0x05, 0x69, 0x6e, 0x74,
190 0x65, 0x6c, 0x03, 0x63, 0x6f, 0x6d, 0x00,
191 /* [44] NetBIOS Name Servers: 163.33.7.86, 143.182.250.105 */
192 0x2c, 0x08, 0xa3, 0x21, 0x07, 0x56, 0x8f, 0xb6, 0xfa, 0x69,
193 /* [43] Encapsulated vendor specific information */
194 0x2b, 0x0a,
195 /* [1]: "string" */
196 0x01, 0x07, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x00,
197 /* End marker */
198 0xff,
199 /* [43] Encapsulated vendor specific information */
200 0x2b, 0x0f,
201 /* [2]: single byte of value 1 */
202 0x02, 0x01, 0x01,
203 /* [3]: zero-length option */
204 0x03, 0x00,
205 /* [254]: invalid option (size longer than remainder of opt 43 size) */
206 0xfe, 0x10, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
207 /* [43] Too short encapsulated vendor option (only single byte) */
208 0x2b, 0x01,
209 /* [254]: invalid option (no length in opt 43) */
210 0xfe,
211 /* [70] POP3 Server: 198.51.100.16 */
212 0x46, 0x04, 0xc6, 0x33, 0x64, 0x10,
213 /* End marker */
214 0xff
215 };
216
217 static const struct in_addr server_addr = { { { 192, 0, 2, 1 } } };
218 static const struct in_addr client_addr = { { { 255, 255, 255, 255 } } };
219
220 #define SERVER_PORT 67
221 #define CLIENT_PORT 68
222 #define MSG_TYPE 53
223 #define DISCOVER 1
224 #define REQUEST 3
225 #define OPTION_DOMAIN 15
226 #define OPTION_POP3 70
227 #define OPTION_VENDOR_STRING 1
228 #define OPTION_VENDOR_BYTE 2
229 #define OPTION_VENDOR_EMPTY 3
230 #define OPTION_INVALID 254
231
232 struct dhcp_msg {
233 uint32_t xid;
234 uint8_t type;
235 };
236
237 static uint32_t offer_xid;
238 static uint32_t request_xid;
239
240 #define EVT_ADDR_ADD BIT(0)
241 #define EVT_ADDR_DEL BIT(1)
242 #define EVT_DNS_SERVER1_ADD BIT(2)
243 #define EVT_DNS_SERVER2_ADD BIT(3)
244 #define EVT_DNS_SERVER3_ADD BIT(4)
245 #define EVT_DHCP_START BIT(5)
246 #define EVT_DHCP_BOUND BIT(6)
247 #define EVT_DHCP_STOP BIT(7)
248 #define EVT_OPTION_DOMAIN BIT(8)
249 #define EVT_OPTION_POP3 BIT(9)
250 #define EVT_VENDOR_STRING BIT(10)
251 #define EVT_VENDOR_BYTE BIT(11)
252 #define EVT_VENDOR_EMPTY BIT(12)
253 #define EVT_DHCP_OFFER BIT(13)
254 #define EVT_DHCP_ACK BIT(14)
255 #define EVT_DNS_SERVER1_DEL BIT(15)
256 #define EVT_DNS_SERVER2_DEL BIT(16)
257 #define EVT_DNS_SERVER3_DEL BIT(17)
258
259 static K_EVENT_DEFINE(events);
260
261 #define WAIT_TIME K_SECONDS(CONFIG_NET_DHCPV4_INITIAL_DELAY_MAX + 1)
262
263 struct net_dhcpv4_context {
264 uint8_t mac_addr[sizeof(struct net_eth_addr)];
265 struct net_linkaddr ll_addr;
266 };
267
net_dhcpv4_dev_init(const struct device * dev)268 static int net_dhcpv4_dev_init(const struct device *dev)
269 {
270 ARG_UNUSED(dev);
271
272 return 0;
273 }
274
net_dhcpv4_get_mac(const struct device * dev)275 static uint8_t *net_dhcpv4_get_mac(const struct device *dev)
276 {
277 struct net_dhcpv4_context *context = dev->data;
278
279 if (context->mac_addr[2] == 0x00) {
280 /* 00-00-5E-00-53-xx Documentation RFC 7042 */
281 context->mac_addr[0] = 0x00;
282 context->mac_addr[1] = 0x00;
283 context->mac_addr[2] = 0x5E;
284 context->mac_addr[3] = 0x00;
285 context->mac_addr[4] = 0x53;
286 context->mac_addr[5] = 0x01;
287 }
288
289 return context->mac_addr;
290 }
291
net_dhcpv4_iface_init(struct net_if * iface)292 static void net_dhcpv4_iface_init(struct net_if *iface)
293 {
294 uint8_t *mac = net_dhcpv4_get_mac(net_if_get_device(iface));
295
296 net_if_set_link_addr(iface, mac, 6, NET_LINK_ETHERNET);
297 }
298
prepare_dhcp_offer(struct net_if * iface,uint32_t xid)299 struct net_pkt *prepare_dhcp_offer(struct net_if *iface, uint32_t xid)
300 {
301 struct net_pkt *pkt;
302
303 pkt = net_pkt_alloc_with_buffer(iface, sizeof(offer), AF_INET,
304 IPPROTO_UDP, K_FOREVER);
305 if (!pkt) {
306 return NULL;
307 }
308
309 net_pkt_set_ipv4_ttl(pkt, 0xFF);
310
311 if (net_ipv4_create(pkt, &server_addr, &client_addr) ||
312 net_udp_create(pkt, htons(SERVER_PORT), htons(CLIENT_PORT))) {
313 goto fail;
314 }
315
316 if (net_pkt_write(pkt, offer, 4)) {
317 goto fail;
318 }
319
320 /* Update xid from the client request */
321 if (net_pkt_write_be32(pkt, xid)) {
322 goto fail;
323 }
324
325 if (net_pkt_write(pkt, offer + 8, sizeof(offer) - 8)) {
326 goto fail;
327 }
328
329 net_pkt_cursor_init(pkt);
330
331 net_ipv4_finalize(pkt, IPPROTO_UDP);
332
333 offer_xid = xid;
334
335 return pkt;
336
337 fail:
338 net_pkt_unref(pkt);
339 return NULL;
340 }
341
prepare_dhcp_ack(struct net_if * iface,uint32_t xid)342 struct net_pkt *prepare_dhcp_ack(struct net_if *iface, uint32_t xid)
343 {
344 struct net_pkt *pkt;
345
346 pkt = net_pkt_alloc_with_buffer(iface, sizeof(offer), AF_INET,
347 IPPROTO_UDP, K_FOREVER);
348 if (!pkt) {
349 return NULL;
350 }
351
352 net_pkt_set_ipv4_ttl(pkt, 0xFF);
353
354 if (net_ipv4_create(pkt, &server_addr, &client_addr) ||
355 net_udp_create(pkt, htons(SERVER_PORT), htons(CLIENT_PORT))) {
356 goto fail;
357 }
358
359 if (net_pkt_write(pkt, ack, 4)) {
360 goto fail;
361 }
362
363 /* Update xid from the client request */
364 if (net_pkt_write_be32(pkt, xid)) {
365 goto fail;
366 }
367
368 if (net_pkt_write(pkt, ack + 8, sizeof(ack) - 8)) {
369 goto fail;
370 }
371
372 net_pkt_cursor_init(pkt);
373
374 net_ipv4_finalize(pkt, IPPROTO_UDP);
375
376 return pkt;
377
378 fail:
379 net_pkt_unref(pkt);
380 return NULL;
381 }
382
parse_dhcp_message(struct net_pkt * pkt,struct dhcp_msg * msg)383 static int parse_dhcp_message(struct net_pkt *pkt, struct dhcp_msg *msg)
384 {
385 /* Skip IPv4 and UDP headers */
386 if (net_pkt_skip(pkt, NET_IPV4UDPH_LEN)) {
387 return 0;
388 }
389
390 /* Skip DHCPv4 headers (size of op, htype, hlen, hops) */
391 if (net_pkt_skip(pkt, 4)) {
392 return 0;
393 }
394
395 if (net_pkt_read_be32(pkt, &msg->xid)) {
396 return 0;
397 }
398
399 /* Skip DHCPv4 Options (size of op, htype, ... cookie) */
400 if (net_pkt_skip(pkt, 36 + 64 + 128 + 4)) {
401 return 0;
402 }
403
404 while (1) {
405 uint8_t length = 0U;
406 uint8_t type;
407
408 if (net_pkt_read_u8(pkt, &type)) {
409 return 0;
410 }
411
412 if (type == MSG_TYPE) {
413 if (net_pkt_skip(pkt, 1)) {
414 return 0;
415 }
416
417 if (net_pkt_read_u8(pkt, &msg->type)) {
418 return 0;
419 }
420
421 if (msg->type == NET_DHCPV4_MSG_TYPE_REQUEST) {
422 request_xid = msg->xid;
423 }
424
425 return 1;
426 }
427
428 if (net_pkt_read_u8(pkt, &length)) {
429 return 0;
430 }
431
432 if (length && net_pkt_skip(pkt, length)) {
433 return 0;
434 }
435 }
436
437 return 0;
438 }
439
tester_send(const struct device * dev,struct net_pkt * pkt)440 static int tester_send(const struct device *dev, struct net_pkt *pkt)
441 {
442 struct net_pkt *rpkt;
443 struct dhcp_msg msg;
444
445 (void)memset(&msg, 0, sizeof(msg));
446
447 if (!pkt->frags) {
448 TC_PRINT("No data to send!\n");
449
450 return -ENODATA;
451 }
452
453 parse_dhcp_message(pkt, &msg);
454
455 if (msg.type == DISCOVER) {
456 /* Reply with DHCPv4 offer message */
457 rpkt = prepare_dhcp_offer(net_pkt_iface(pkt), msg.xid);
458 if (!rpkt) {
459 return -EINVAL;
460 }
461 k_event_post(&events, EVT_DHCP_OFFER);
462 } else if (msg.type == REQUEST) {
463 /* Reply with DHCPv4 ACK message */
464 rpkt = prepare_dhcp_ack(net_pkt_iface(pkt), msg.xid);
465 if (!rpkt) {
466 return -EINVAL;
467 }
468 k_event_post(&events, EVT_DHCP_ACK);
469 } else {
470 /* Invalid message type received */
471 return -EINVAL;
472 }
473
474 if (net_recv_data(net_pkt_iface(rpkt), rpkt)) {
475 net_pkt_unref(rpkt);
476
477 return -EINVAL;
478 }
479
480 return 0;
481 }
482
483 struct net_dhcpv4_context net_dhcpv4_context_data;
484
485 static struct dummy_api net_dhcpv4_if_api = {
486 .iface_api.init = net_dhcpv4_iface_init,
487 .send = tester_send,
488 };
489
490 NET_DEVICE_INIT(net_dhcpv4_test, "net_dhcpv4_test",
491 net_dhcpv4_dev_init, NULL,
492 &net_dhcpv4_context_data, NULL,
493 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
494 &net_dhcpv4_if_api, DUMMY_L2,
495 NET_L2_GET_CTX_TYPE(DUMMY_L2), 127);
496
497 #ifdef CONFIG_NET_DHCPV4_OPTION_CALLBACKS
498 static struct net_dhcpv4_option_callback opt_domain_cb;
499 static struct net_dhcpv4_option_callback opt_pop3_cb;
500 static struct net_dhcpv4_option_callback opt_invalid_cb;
501 static uint8_t buffer[15];
502 #endif
503 #ifdef CONFIG_NET_DHCPV4_OPTION_CALLBACKS_VENDOR_SPECIFIC
504 static struct net_dhcpv4_option_callback opt_vs_string_cb;
505 static struct net_dhcpv4_option_callback opt_vs_byte_cb;
506 static struct net_dhcpv4_option_callback opt_vs_empty_cb;
507 static struct net_dhcpv4_option_callback opt_vs_invalid_cb;
508 #endif
509
receiver_cb(uint64_t nm_event,struct net_if * iface,void * info,size_t info_length,void * user_data)510 static void receiver_cb(uint64_t nm_event, struct net_if *iface, void *info, size_t info_length,
511 void *user_data)
512 {
513 const struct in_addr ip_addr = { { { 10, 237, 72, 158 } } };
514 const struct in_addr dns_addrs[3] = {
515 { { { 10, 248, 2, 1 } } },
516 { { { 163, 33, 253, 68 } } },
517 { { { 10, 184, 9, 1 } } },
518 };
519
520 ARG_UNUSED(iface);
521 ARG_UNUSED(user_data);
522
523 switch (nm_event) {
524 case NET_EVENT_IPV4_ADDR_ADD:
525 zassert_equal(info_length, sizeof(struct in_addr));
526 zassert_mem_equal(info, &ip_addr, sizeof(struct in_addr));
527 k_event_post(&events, EVT_ADDR_ADD);
528 break;
529 case NET_EVENT_IPV4_ADDR_DEL:
530 k_event_post(&events, EVT_ADDR_DEL);
531 break;
532 case NET_EVENT_DNS_SERVER_ADD:
533 zassert_equal(info_length, sizeof(struct sockaddr));
534 if (net_sin(info)->sin_addr.s_addr == dns_addrs[0].s_addr) {
535 k_event_post(&events, EVT_DNS_SERVER1_ADD);
536 } else if (net_sin(info)->sin_addr.s_addr == dns_addrs[1].s_addr) {
537 k_event_post(&events, EVT_DNS_SERVER2_ADD);
538 } else if (net_sin(info)->sin_addr.s_addr == dns_addrs[2].s_addr) {
539 k_event_post(&events, EVT_DNS_SERVER3_ADD);
540 } else {
541 zassert_unreachable("Unknown DNS server");
542 }
543 break;
544 case NET_EVENT_DNS_SERVER_DEL:
545 zassert_equal(info_length, sizeof(struct sockaddr));
546 if (net_sin(info)->sin_addr.s_addr == dns_addrs[0].s_addr) {
547 k_event_post(&events, EVT_DNS_SERVER1_DEL);
548 } else if (net_sin(info)->sin_addr.s_addr == dns_addrs[1].s_addr) {
549 k_event_post(&events, EVT_DNS_SERVER2_DEL);
550 } else if (net_sin(info)->sin_addr.s_addr == dns_addrs[2].s_addr) {
551 k_event_post(&events, EVT_DNS_SERVER3_DEL);
552 } else {
553 zassert_unreachable("Unknown DNS server");
554 }
555 break;
556 case NET_EVENT_IPV4_DHCP_START:
557 k_event_post(&events, EVT_DHCP_START);
558 break;
559 case NET_EVENT_IPV4_DHCP_BOUND:
560 k_event_post(&events, EVT_DHCP_BOUND);
561 break;
562 case NET_EVENT_IPV4_DHCP_STOP:
563 k_event_post(&events, EVT_DHCP_STOP);
564 break;
565 }
566 }
567
568 NET_MGMT_REGISTER_EVENT_HANDLER(rx_cb, NET_EVENT_IPV4_ADDR_ADD | NET_EVENT_IPV4_ADDR_DEL,
569 receiver_cb, NULL);
570 NET_MGMT_REGISTER_EVENT_HANDLER(dns_cb, NET_EVENT_DNS_SERVER_ADD | NET_EVENT_DNS_SERVER_DEL,
571 receiver_cb, NULL);
572 NET_MGMT_REGISTER_EVENT_HANDLER(dhcp_cb,
573 NET_EVENT_IPV4_DHCP_START | NET_EVENT_IPV4_DHCP_BOUND |
574 NET_EVENT_IPV4_DHCP_STOP,
575 receiver_cb, NULL);
576
577 #ifdef CONFIG_NET_DHCPV4_OPTION_CALLBACKS
578
option_domain_cb(struct net_dhcpv4_option_callback * cb,size_t length,enum net_dhcpv4_msg_type msg_type,struct net_if * iface)579 static void option_domain_cb(struct net_dhcpv4_option_callback *cb,
580 size_t length,
581 enum net_dhcpv4_msg_type msg_type,
582 struct net_if *iface)
583 {
584 static const char expectation[] = "fi.intel.com";
585
586 ARG_UNUSED(msg_type);
587 ARG_UNUSED(iface);
588
589 zassert_equal(cb->option, OPTION_DOMAIN, "Unexpected option value");
590 zassert_equal(length, sizeof(expectation), "Incorrect data length");
591 zassert_mem_equal(buffer, expectation, sizeof(expectation),
592 "Incorrect buffer contents");
593
594 k_event_post(&events, EVT_OPTION_DOMAIN);
595 }
596
option_pop3_cb(struct net_dhcpv4_option_callback * cb,size_t length,enum net_dhcpv4_msg_type msg_type,struct net_if * iface)597 static void option_pop3_cb(struct net_dhcpv4_option_callback *cb,
598 size_t length,
599 enum net_dhcpv4_msg_type msg_type,
600 struct net_if *iface)
601 {
602 static const uint8_t expectation[4] = { 198, 51, 100, 16 };
603
604 ARG_UNUSED(msg_type);
605 ARG_UNUSED(iface);
606
607 zassert_equal(cb->option, OPTION_POP3, "Unexpected option value");
608 zassert_equal(length, sizeof(expectation), "Incorrect data length");
609 zassert_mem_equal(buffer, expectation, sizeof(expectation),
610 "Incorrect buffer contents");
611
612 k_event_post(&events, EVT_OPTION_POP3);
613 }
614
option_invalid_cb(struct net_dhcpv4_option_callback * cb,size_t length,enum net_dhcpv4_msg_type msg_type,struct net_if * iface)615 static void option_invalid_cb(struct net_dhcpv4_option_callback *cb,
616 size_t length,
617 enum net_dhcpv4_msg_type msg_type,
618 struct net_if *iface)
619 {
620 ARG_UNUSED(cb);
621 ARG_UNUSED(length);
622 ARG_UNUSED(msg_type);
623 ARG_UNUSED(iface);
624
625 /* This function should never be called. If it is, the parser took a wrong turn. */
626 zassert_unreachable("Unexpected callback - incorrect parsing of vendor sepcific options");
627 }
628
629 #ifdef CONFIG_NET_DHCPV4_OPTION_CALLBACKS_VENDOR_SPECIFIC
630
vendor_specific_string_cb(struct net_dhcpv4_option_callback * cb,size_t length,enum net_dhcpv4_msg_type msg_type,struct net_if * iface)631 static void vendor_specific_string_cb(struct net_dhcpv4_option_callback *cb,
632 size_t length,
633 enum net_dhcpv4_msg_type msg_type,
634 struct net_if *iface)
635 {
636 static const char expectation[] = "string";
637
638 ARG_UNUSED(msg_type);
639 ARG_UNUSED(iface);
640
641 zassert_equal(cb->option, OPTION_VENDOR_STRING,
642 "Unexpected vendor specific option value");
643 zassert_equal(length, sizeof(expectation), "Incorrect data length");
644 zassert_mem_equal(buffer, expectation, sizeof(expectation), "Incorrect buffer contents");
645
646 k_event_post(&events, EVT_VENDOR_STRING);
647 }
648
vendor_specific_byte_cb(struct net_dhcpv4_option_callback * cb,size_t length,enum net_dhcpv4_msg_type msg_type,struct net_if * iface)649 static void vendor_specific_byte_cb(struct net_dhcpv4_option_callback *cb,
650 size_t length,
651 enum net_dhcpv4_msg_type msg_type,
652 struct net_if *iface)
653 {
654 ARG_UNUSED(msg_type);
655 ARG_UNUSED(iface);
656
657 zassert_equal(cb->option, OPTION_VENDOR_BYTE,
658 "Unexpected vendor specific option value");
659 zassert_equal(length, 1, "Incorrect data length");
660 zassert_equal(buffer[0], 1, "Incorrect buffer contents");
661
662 k_event_post(&events, EVT_VENDOR_BYTE);
663 }
664
vendor_specific_empty_cb(struct net_dhcpv4_option_callback * cb,size_t length,enum net_dhcpv4_msg_type msg_type,struct net_if * iface)665 static void vendor_specific_empty_cb(struct net_dhcpv4_option_callback *cb,
666 size_t length,
667 enum net_dhcpv4_msg_type msg_type,
668 struct net_if *iface)
669 {
670 ARG_UNUSED(msg_type);
671 ARG_UNUSED(iface);
672
673 zassert_equal(cb->option, OPTION_VENDOR_EMPTY,
674 "Unexpected vendor specific option value");
675 zassert_equal(length, 0, "Incorrect data length");
676
677 k_event_post(&events, EVT_VENDOR_EMPTY);
678 }
679
680 #endif /* CONFIG_NET_DHCPV4_OPTION_CALLBACKS_VENDOR_SPECIFIC */
681
682 #endif /* CONFIG_NET_DHCPV4_OPTION_CALLBACKS */
683
ZTEST(dhcpv4_tests,test_dhcp)684 ZTEST(dhcpv4_tests, test_dhcp)
685 {
686 struct net_if *iface;
687 uint32_t evt;
688
689 #ifdef CONFIG_NET_DHCPV4_OPTION_CALLBACKS
690 net_dhcpv4_init_option_callback(&opt_domain_cb, option_domain_cb,
691 OPTION_DOMAIN, buffer,
692 sizeof(buffer));
693
694 net_dhcpv4_add_option_callback(&opt_domain_cb);
695
696 net_dhcpv4_init_option_callback(&opt_pop3_cb, option_pop3_cb,
697 OPTION_POP3, buffer,
698 sizeof(buffer));
699
700 net_dhcpv4_add_option_callback(&opt_pop3_cb);
701
702 net_dhcpv4_init_option_callback(&opt_invalid_cb, option_invalid_cb,
703 OPTION_INVALID, buffer,
704 sizeof(buffer));
705
706 net_dhcpv4_add_option_callback(&opt_invalid_cb);
707 #endif /* CONFIG_NET_DHCPV4_OPTION_CALLBACKS */
708
709 #ifdef CONFIG_NET_DHCPV4_OPTION_CALLBACKS_VENDOR_SPECIFIC
710 net_dhcpv4_init_option_vendor_callback(&opt_vs_string_cb, vendor_specific_string_cb,
711 OPTION_VENDOR_STRING, buffer,
712 sizeof(buffer));
713
714 net_dhcpv4_add_option_vendor_callback(&opt_vs_string_cb);
715
716 net_dhcpv4_init_option_vendor_callback(&opt_vs_byte_cb, vendor_specific_byte_cb,
717 OPTION_VENDOR_BYTE, buffer,
718 sizeof(buffer));
719
720 net_dhcpv4_add_option_vendor_callback(&opt_vs_byte_cb);
721
722 net_dhcpv4_init_option_vendor_callback(&opt_vs_empty_cb, vendor_specific_empty_cb,
723 OPTION_VENDOR_EMPTY, buffer,
724 sizeof(buffer));
725
726 net_dhcpv4_add_option_vendor_callback(&opt_vs_empty_cb);
727
728 net_dhcpv4_init_option_vendor_callback(&opt_vs_invalid_cb, option_invalid_cb,
729 OPTION_INVALID, buffer,
730 sizeof(buffer));
731
732 net_dhcpv4_add_option_vendor_callback(&opt_vs_invalid_cb);
733
734
735 #endif /* CONFIG_NET_DHCPV4_OPTION_CALLBACKS_VENDOR_SPECIFIC */
736
737 iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY));
738 if (!iface) {
739 zassert_true(false, "Interface not available");
740 }
741
742 for (int loop = 0; loop < 2; ++loop) {
743 LOG_DBG("Running DHCPv4 loop %d", loop);
744 net_dhcpv4_start(iface);
745
746 evt = k_event_wait(&events, EVT_DHCP_START, false, WAIT_TIME);
747 zassert_equal(evt, EVT_DHCP_START, "Missing DHCP start");
748
749 #ifdef CONFIG_NET_DHCPV4_OPTION_CALLBACKS
750 evt = k_event_wait_all(&events, EVT_OPTION_DOMAIN | EVT_OPTION_POP3, false,
751 WAIT_TIME);
752 zassert_equal(evt, EVT_OPTION_DOMAIN | EVT_OPTION_POP3,
753 "Missing DHCP option(s) %08x", evt);
754 #endif
755
756 #ifdef CONFIG_NET_DHCPV4_OPTION_CALLBACKS_VENDOR_SPECIFIC
757 evt = k_event_wait_all(&events,
758 EVT_VENDOR_STRING | EVT_VENDOR_BYTE | EVT_VENDOR_EMPTY,
759 false, WAIT_TIME);
760 zassert_equal(evt, EVT_VENDOR_STRING | EVT_VENDOR_BYTE | EVT_VENDOR_EMPTY,
761 "Missing DHCP vendor option(s) %08x", evt);
762 #endif
763
764 evt = k_event_wait_all(&events,
765 EVT_DNS_SERVER1_ADD | EVT_DNS_SERVER2_ADD |
766 EVT_DNS_SERVER3_ADD,
767 false, WAIT_TIME);
768 zassert_equal(evt,
769 EVT_DNS_SERVER1_ADD | EVT_DNS_SERVER2_ADD |
770 EVT_DNS_SERVER3_ADD,
771 "Missing DNS server(s) %08x", evt);
772
773 evt = k_event_wait(&events, EVT_DHCP_BOUND, false, WAIT_TIME);
774 zassert_equal(evt, EVT_DHCP_BOUND, "Missing DHCP bound");
775
776 if (loop == 0 || !IS_ENABLED(CONFIG_NET_DHCPV4_INIT_REBOOT)) {
777 evt = k_event_wait_all(&events, EVT_DHCP_OFFER | EVT_DHCP_ACK, false,
778 WAIT_TIME);
779 zassert_equal(evt, EVT_DHCP_OFFER | EVT_DHCP_ACK,
780 "Missing offer or ack %08x", evt);
781
782 /* Verify that Request xid matched Offer xid. */
783 zassert_equal(offer_xid, request_xid,
784 "Offer/Request xid mismatch, "
785 "Offer 0x%08x, Request 0x%08x",
786 offer_xid, request_xid);
787 } else {
788 /* An init-reboot was done */
789 evt = k_event_wait(&events, EVT_DHCP_OFFER | EVT_DHCP_ACK, false,
790 WAIT_TIME);
791 zassert_equal(evt, EVT_DHCP_ACK, "Ack only expected %08x", evt);
792 }
793
794 /* Clear all events */
795 k_event_set(&events, 0U);
796
797 net_dhcpv4_stop(iface);
798
799 evt = k_event_wait_all(&events,
800 EVT_DHCP_STOP | EVT_ADDR_DEL |
801 EVT_DNS_SERVER1_DEL | EVT_DNS_SERVER2_DEL |
802 EVT_DNS_SERVER3_DEL,
803 false, WAIT_TIME);
804 zassert_equal(evt,
805 EVT_DHCP_STOP | EVT_ADDR_DEL |
806 EVT_DNS_SERVER1_DEL | EVT_DNS_SERVER2_DEL |
807 EVT_DNS_SERVER3_DEL,
808 "Missing DHCP stop or deleted address");
809 }
810 }
811
812 /**test case main entry */
813 ZTEST_SUITE(dhcpv4_tests, NULL, NULL, NULL, NULL, NULL);
814