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[420] = {
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 /* [53] DHCP Message Type: OFFER */
74 0x35, 0x01, 0x02,
75 /* [1] Subnet Mask: 255.255.255.0 */
76 0x01, 0x04, 0xff, 0xff, 0xff, 0x00,
77 /* [58] Renewal Time Value: (21600s) 6 hours */
78 0x3a, 0x04, 0x00, 0x00, 0x54, 0x60,
79 /* [59] Rebinding Time Value: (37800s) 1 hour 30 min */
80 0x3b, 0x04, 0x00, 0x00, 0x93, 0xa8,
81 /* [51] IP Address Lease Time: (43200s) 12 hours */
82 0x33, 0x04, 0x00, 0x00, 0xa8, 0xc0,
83 /* [54] DHCP Server Identifier: 10.184.9.1 */
84 0x36, 0x04, 0x0a, 0xb8, 0x09, 0x01,
85 /* [3] Router: 10.237.72.1 */
86 0x03, 0x04, 0x0a, 0xed, 0x48, 0x01,
87 /* [15] Domain Name: fi.intel.com */
88 0x0f, 0x0d, 0x66, 0x69, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00,
89 /* [6] Domain Name Server: 10.248.2.1 163.33.253.68 10.184.9.1 */
90 0x06, 0x0c, 0x0a, 0xf8, 0x02, 0x01, 0xa3, 0x21, 0xfd, 0x44, 0x0a, 0xb8, 0x09, 0x01,
91 /* [119] Domain Search Option: fi.intel.com ger.corp.intel.com corp.intel.com intel.com */
92 0x77, 0x3d, 0x02, 0x66, 0x69, 0x05, 0x69, 0x6e,
93 0x74, 0x65, 0x6c, 0x03, 0x63, 0x6f, 0x6d, 0x00,
94 0x03, 0x67, 0x65, 0x72, 0x04, 0x63, 0x6f, 0x72,
95 0x70, 0x05, 0x69, 0x6e, 0x74, 0x65, 0x6c, 0x03,
96 0x63, 0x6f, 0x6d, 0x00, 0x04, 0x63, 0x6f, 0x72,
97 0x70, 0x05, 0x69, 0x6e, 0x74, 0x65, 0x6c, 0x03,
98 0x63, 0x6f, 0x6d, 0x00, 0x05, 0x69, 0x6e, 0x74,
99 0x65, 0x6c, 0x03, 0x63, 0x6f, 0x6d, 0x00,
100 /* [44] NetBIOS Name Servers: 163.33.7.86, 143.182.250.105 */
101 0x2c, 0x08, 0xa3, 0x21, 0x07, 0x56, 0x8f, 0xb6, 0xfa, 0x69,
102 /* [43] Encapsulated vendor specific information */
103 0x2b, 0x0a,
104 /* [1]: "string" */
105 0x01, 0x07, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x00,
106 /* End marker */
107 0xff,
108 /* [43] Encapsulated vendor specific information */
109 0x2b, 0x0f,
110 /* [2]: single byte of value 1 */
111 0x02, 0x01, 0x01,
112 /* [3]: zero-length option */
113 0x03, 0x00,
114 /* [254]: invalid option (size longer than remainder of opt 43 size) */
115 0xfe, 0x10, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
116 /* [43] Too short encapsulated vendor option (only single byte) */
117 0x2b, 0x01,
118 /* [254]: invalid option (no length in opt 43) */
119 0xfe,
120 /* [70] POP3 Server: 198.51.100.16 */
121 0x46, 0x04, 0xc6, 0x33, 0x64, 0x10,
122 /* End marker */
123 0xff
124 };
125
126 /* Sample DHCPv4 ACK */
127 static const unsigned char ack[420] = {
128 0x02, 0x01, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130 0x0a, 0xed, 0x48, 0x9e, 0x00, 0x00, 0x00, 0x00,
131 0x0a, 0xed, 0x48, 0x03, 0x00, 0x00, 0x5E, 0x00,
132 0x53, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
134 0x00, 0x00, 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,
158 /* Magic cookie: DHCP */
159 0x63, 0x82, 0x53, 0x63,
160 /* [53] DHCP Message Type: ACK */
161 0x35, 0x01, 0x05,
162 /* [58] Renewal Time Value: (21600s) 6 hours */
163 0x3a, 0x04, 0x00, 0x00, 0x54, 0x60,
164 /* [59] Rebinding Time Value: (37800s) 1 hour 30 min */
165 0x3b, 0x04, 0x00, 0x00, 0x93, 0xa8,
166 /* [51] IP Address Lease Time: (43200s) 12 hours */
167 0x33, 0x04, 0x00, 0x00, 0xa8, 0xc0,
168 /* [54] DHCP Server Identifier: 10.184.9.1 */
169 0x36, 0x04, 0x0a, 0xb8, 0x09, 0x01,
170 /* [1] Subnet Mask: 255.255.255.0 */
171 0x01, 0x04, 0xff, 0xff, 0xff, 0x00,
172 /* [3] Router: 10.237.72.1 */
173 0x03, 0x04, 0x0a, 0xed, 0x48, 0x01,
174 /* [15] Domain Name: fi.intel.com */
175 0x0f, 0x0d, 0x66, 0x69, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x00,
176 /* [6] Domain Name Server: 10.248.2.1 163.33.253.68 10.184.9.1 */
177 0x06, 0x0c, 0x0a, 0xf8, 0x02, 0x01, 0xa3, 0x21, 0xfd, 0x44, 0x0a, 0xb8, 0x09, 0x01,
178 /* [119] Domain Search Option: fi.intel.com ger.corp.intel.com corp.intel.com intel.com */
179 0x77, 0x3d, 0x02, 0x66, 0x69, 0x05, 0x69, 0x6e,
180 0x74, 0x65, 0x6c, 0x03, 0x63, 0x6f, 0x6d, 0x00,
181 0x03, 0x67, 0x65, 0x72, 0x04, 0x63, 0x6f, 0x72,
182 0x70, 0x05, 0x69, 0x6e, 0x74, 0x65, 0x6c, 0x03,
183 0x63, 0x6f, 0x6d, 0x00, 0x04, 0x63, 0x6f, 0x72,
184 0x70, 0x05, 0x69, 0x6e, 0x74, 0x65, 0x6c, 0x03,
185 0x63, 0x6f, 0x6d, 0x00, 0x05, 0x69, 0x6e, 0x74,
186 0x65, 0x6c, 0x03, 0x63, 0x6f, 0x6d, 0x00,
187 /* [44] NetBIOS Name Servers: 163.33.7.86, 143.182.250.105 */
188 0x2c, 0x08, 0xa3, 0x21, 0x07, 0x56, 0x8f, 0xb6, 0xfa, 0x69,
189 /* [43] Encapsulated vendor specific information */
190 0x2b, 0x0a,
191 /* [1]: "string" */
192 0x01, 0x07, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x00,
193 /* End marker */
194 0xff,
195 /* [43] Encapsulated vendor specific information */
196 0x2b, 0x0f,
197 /* [2]: single byte of value 1 */
198 0x02, 0x01, 0x01,
199 /* [3]: zero-length option */
200 0x03, 0x00,
201 /* [254]: invalid option (size longer than remainder of opt 43 size) */
202 0xfe, 0x10, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
203 /* [43] Too short encapsulated vendor option (only single byte) */
204 0x2b, 0x01,
205 /* [254]: invalid option (no length in opt 43) */
206 0xfe,
207 /* [70] POP3 Server: 198.51.100.16 */
208 0x46, 0x04, 0xc6, 0x33, 0x64, 0x10,
209 /* End marker */
210 0xff
211 };
212
213 static const struct in_addr server_addr = { { { 192, 0, 2, 1 } } };
214 static const struct in_addr client_addr = { { { 255, 255, 255, 255 } } };
215
216 #define SERVER_PORT 67
217 #define CLIENT_PORT 68
218 #define MSG_TYPE 53
219 #define DISCOVER 1
220 #define REQUEST 3
221 #define OPTION_DOMAIN 15
222 #define OPTION_POP3 70
223 #define OPTION_VENDOR_STRING 1
224 #define OPTION_VENDOR_BYTE 2
225 #define OPTION_VENDOR_EMPTY 3
226 #define OPTION_INVALID 254
227
228 struct dhcp_msg {
229 uint32_t xid;
230 uint8_t type;
231 };
232
233 static struct k_sem test_lock;
234
235 #define WAIT_TIME K_SECONDS(CONFIG_NET_DHCPV4_INITIAL_DELAY_MAX + 1)
236
237 struct net_dhcpv4_context {
238 uint8_t mac_addr[sizeof(struct net_eth_addr)];
239 struct net_linkaddr ll_addr;
240 };
241
net_dhcpv4_dev_init(const struct device * dev)242 static int net_dhcpv4_dev_init(const struct device *dev)
243 {
244 struct net_dhcpv4_context *net_dhcpv4_context = dev->data;
245
246 net_dhcpv4_context = net_dhcpv4_context;
247
248 return 0;
249 }
250
net_dhcpv4_get_mac(const struct device * dev)251 static uint8_t *net_dhcpv4_get_mac(const struct device *dev)
252 {
253 struct net_dhcpv4_context *context = dev->data;
254
255 if (context->mac_addr[2] == 0x00) {
256 /* 00-00-5E-00-53-xx Documentation RFC 7042 */
257 context->mac_addr[0] = 0x00;
258 context->mac_addr[1] = 0x00;
259 context->mac_addr[2] = 0x5E;
260 context->mac_addr[3] = 0x00;
261 context->mac_addr[4] = 0x53;
262 context->mac_addr[5] = 0x01;
263 }
264
265 return context->mac_addr;
266 }
267
net_dhcpv4_iface_init(struct net_if * iface)268 static void net_dhcpv4_iface_init(struct net_if *iface)
269 {
270 uint8_t *mac = net_dhcpv4_get_mac(net_if_get_device(iface));
271
272 net_if_set_link_addr(iface, mac, 6, NET_LINK_ETHERNET);
273 }
274
prepare_dhcp_offer(struct net_if * iface,uint32_t xid)275 struct net_pkt *prepare_dhcp_offer(struct net_if *iface, uint32_t xid)
276 {
277 struct net_pkt *pkt;
278
279 pkt = net_pkt_alloc_with_buffer(iface, sizeof(offer), AF_INET,
280 IPPROTO_UDP, K_FOREVER);
281 if (!pkt) {
282 return NULL;
283 }
284
285 net_pkt_set_ipv4_ttl(pkt, 0xFF);
286
287 if (net_ipv4_create(pkt, &server_addr, &client_addr) ||
288 net_udp_create(pkt, htons(SERVER_PORT), htons(CLIENT_PORT))) {
289 goto fail;
290 }
291
292 if (net_pkt_write(pkt, offer, 4)) {
293 goto fail;
294 }
295
296 /* Update xid from the client request */
297 if (net_pkt_write_be32(pkt, xid)) {
298 goto fail;
299 }
300
301 if (net_pkt_write(pkt, offer + 8, sizeof(offer) - 8)) {
302 goto fail;
303 }
304
305 net_pkt_cursor_init(pkt);
306
307 net_ipv4_finalize(pkt, IPPROTO_UDP);
308
309 return pkt;
310
311 fail:
312 net_pkt_unref(pkt);
313 return NULL;
314 }
315
prepare_dhcp_ack(struct net_if * iface,uint32_t xid)316 struct net_pkt *prepare_dhcp_ack(struct net_if *iface, uint32_t xid)
317 {
318 struct net_pkt *pkt;
319
320 pkt = net_pkt_alloc_with_buffer(iface, sizeof(offer), AF_INET,
321 IPPROTO_UDP, K_FOREVER);
322 if (!pkt) {
323 return NULL;
324 }
325
326 net_pkt_set_ipv4_ttl(pkt, 0xFF);
327
328 if (net_ipv4_create(pkt, &server_addr, &client_addr) ||
329 net_udp_create(pkt, htons(SERVER_PORT), htons(CLIENT_PORT))) {
330 goto fail;
331 }
332
333 if (net_pkt_write(pkt, ack, 4)) {
334 goto fail;
335 }
336
337 /* Update xid from the client request */
338 if (net_pkt_write_be32(pkt, xid)) {
339 goto fail;
340 }
341
342 if (net_pkt_write(pkt, ack + 8, sizeof(ack) - 8)) {
343 goto fail;
344 }
345
346 net_pkt_cursor_init(pkt);
347
348 net_ipv4_finalize(pkt, IPPROTO_UDP);
349
350 return pkt;
351
352 fail:
353 net_pkt_unref(pkt);
354 return NULL;
355 }
356
parse_dhcp_message(struct net_pkt * pkt,struct dhcp_msg * msg)357 static int parse_dhcp_message(struct net_pkt *pkt, struct dhcp_msg *msg)
358 {
359 /* Skip IPv4 and UDP headers */
360 if (net_pkt_skip(pkt, NET_IPV4UDPH_LEN)) {
361 return 0;
362 }
363
364 /* Skip DHCPv4 headers (size of op, htype, hlen, hops) */
365 if (net_pkt_skip(pkt, 4)) {
366 return 0;
367 }
368
369 if (net_pkt_read_be32(pkt, &msg->xid)) {
370 return 0;
371 }
372
373 /* Skip DHCPv4 Options (size of op, htype, ... cookie) */
374 if (net_pkt_skip(pkt, 36 + 64 + 128 + 4)) {
375 return 0;
376 }
377
378 while (1) {
379 uint8_t length = 0U;
380 uint8_t type;
381
382 if (net_pkt_read_u8(pkt, &type)) {
383 return 0;
384 }
385
386 if (type == MSG_TYPE) {
387 if (net_pkt_skip(pkt, 1)) {
388 return 0;
389 }
390
391 if (net_pkt_read_u8(pkt, &msg->type)) {
392 return 0;
393 }
394
395 return 1;
396 }
397
398 if (net_pkt_read_u8(pkt, &length)) {
399 return 0;
400 }
401
402 if (length && net_pkt_skip(pkt, length)) {
403 return 0;
404 }
405 }
406
407 return 0;
408 }
409
tester_send(const struct device * dev,struct net_pkt * pkt)410 static int tester_send(const struct device *dev, struct net_pkt *pkt)
411 {
412 struct net_pkt *rpkt;
413 struct dhcp_msg msg;
414
415 (void)memset(&msg, 0, sizeof(msg));
416
417 if (!pkt->frags) {
418 TC_PRINT("No data to send!\n");
419
420 return -ENODATA;
421 }
422
423 parse_dhcp_message(pkt, &msg);
424
425 if (msg.type == DISCOVER) {
426 /* Reply with DHCPv4 offer message */
427 rpkt = prepare_dhcp_offer(net_pkt_iface(pkt), msg.xid);
428 if (!rpkt) {
429 return -EINVAL;
430 }
431 } else if (msg.type == REQUEST) {
432 /* Reply with DHCPv4 ACK message */
433 rpkt = prepare_dhcp_ack(net_pkt_iface(pkt), msg.xid);
434 if (!rpkt) {
435 return -EINVAL;
436 }
437 } else {
438 /* Invalid message type received */
439 return -EINVAL;
440 }
441
442 if (net_recv_data(net_pkt_iface(rpkt), rpkt)) {
443 net_pkt_unref(rpkt);
444
445 return -EINVAL;
446 }
447
448 return 0;
449 }
450
451 struct net_dhcpv4_context net_dhcpv4_context_data;
452
453 static struct dummy_api net_dhcpv4_if_api = {
454 .iface_api.init = net_dhcpv4_iface_init,
455 .send = tester_send,
456 };
457
458 NET_DEVICE_INIT(net_dhcpv4_test, "net_dhcpv4_test",
459 net_dhcpv4_dev_init, NULL,
460 &net_dhcpv4_context_data, NULL,
461 CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
462 &net_dhcpv4_if_api, DUMMY_L2,
463 NET_L2_GET_CTX_TYPE(DUMMY_L2), 127);
464
465 static struct net_mgmt_event_callback rx_cb;
466 static struct net_mgmt_event_callback dns_cb;
467 static struct net_mgmt_event_callback dhcp_cb;
468 #ifdef CONFIG_NET_DHCPV4_OPTION_CALLBACKS
469 static struct net_dhcpv4_option_callback opt_domain_cb;
470 static struct net_dhcpv4_option_callback opt_pop3_cb;
471 static struct net_dhcpv4_option_callback opt_invalid_cb;
472 static uint8_t buffer[15];
473 #endif
474 #ifdef CONFIG_NET_DHCPV4_OPTION_CALLBACKS_VENDOR_SPECIFIC
475 static struct net_dhcpv4_option_callback opt_vs_string_cb;
476 static struct net_dhcpv4_option_callback opt_vs_byte_cb;
477 static struct net_dhcpv4_option_callback opt_vs_empty_cb;
478 static struct net_dhcpv4_option_callback opt_vs_invalid_cb;
479 #endif
480 static int event_count;
481
receiver_cb(struct net_mgmt_event_callback * cb,uint32_t nm_event,struct net_if * iface)482 static void receiver_cb(struct net_mgmt_event_callback *cb,
483 uint32_t nm_event, struct net_if *iface)
484 {
485 if (nm_event != NET_EVENT_IPV4_ADDR_ADD &&
486 nm_event != NET_EVENT_DNS_SERVER_ADD &&
487 nm_event != NET_EVENT_DNS_SERVER_DEL &&
488 nm_event != NET_EVENT_IPV4_DHCP_START &&
489 nm_event != NET_EVENT_IPV4_DHCP_BOUND) {
490 /* Spurious callback. */
491 return;
492 }
493
494 event_count++;
495
496 k_sem_give(&test_lock);
497 }
498
499 #ifdef CONFIG_NET_DHCPV4_OPTION_CALLBACKS
500
option_domain_cb(struct net_dhcpv4_option_callback * cb,size_t length,enum net_dhcpv4_msg_type msg_type,struct net_if * iface)501 static void option_domain_cb(struct net_dhcpv4_option_callback *cb,
502 size_t length,
503 enum net_dhcpv4_msg_type msg_type,
504 struct net_if *iface)
505 {
506 char expectation[] = "fi.intel.com";
507
508 zassert_equal(cb->option, OPTION_DOMAIN, "Unexpected option value");
509 zassert_equal(length, sizeof(expectation), "Incorrect data length");
510 zassert_mem_equal(buffer, expectation, sizeof(expectation),
511 "Incorrect buffer contents");
512
513 event_count++;
514
515 k_sem_give(&test_lock);
516 }
517
option_pop3_cb(struct net_dhcpv4_option_callback * cb,size_t length,enum net_dhcpv4_msg_type msg_type,struct net_if * iface)518 static void option_pop3_cb(struct net_dhcpv4_option_callback *cb,
519 size_t length,
520 enum net_dhcpv4_msg_type msg_type,
521 struct net_if *iface)
522 {
523 uint8_t expectation[4];
524
525 expectation[0] = 198;
526 expectation[1] = 51;
527 expectation[2] = 100;
528 expectation[3] = 16;
529
530 zassert_equal(cb->option, OPTION_POP3, "Unexpected option value");
531 zassert_equal(length, sizeof(expectation), "Incorrect data length");
532 zassert_mem_equal(buffer, expectation, sizeof(expectation),
533 "Incorrect buffer contents");
534
535 event_count++;
536
537 k_sem_give(&test_lock);
538 }
539
option_invalid_cb(struct net_dhcpv4_option_callback * cb,size_t length,enum net_dhcpv4_msg_type msg_type,struct net_if * iface)540 static void option_invalid_cb(struct net_dhcpv4_option_callback *cb,
541 size_t length,
542 enum net_dhcpv4_msg_type msg_type,
543 struct net_if *iface)
544 {
545 /* This function should never be called. If it is, the parser took a wrong turn. */
546 zassert_true(false, "Unexpected callback - incorrect parsing of vendor sepcific options");
547 }
548
549 #ifdef CONFIG_NET_DHCPV4_OPTION_CALLBACKS_VENDOR_SPECIFIC
550
vendor_specific_string_cb(struct net_dhcpv4_option_callback * cb,size_t length,enum net_dhcpv4_msg_type msg_type,struct net_if * iface)551 static void vendor_specific_string_cb(struct net_dhcpv4_option_callback *cb,
552 size_t length,
553 enum net_dhcpv4_msg_type msg_type,
554 struct net_if *iface)
555 {
556 char expectation[] = "string";
557
558 zassert_equal(cb->option, OPTION_VENDOR_STRING,
559 "Unexpected vendor specific option value");
560 zassert_equal(length, sizeof(expectation), "Incorrect data length");
561 zassert_mem_equal(buffer, expectation, sizeof(expectation), "Incorrect buffer contents");
562
563 event_count++;
564
565 k_sem_give(&test_lock);
566 }
567
vendor_specific_byte_cb(struct net_dhcpv4_option_callback * cb,size_t length,enum net_dhcpv4_msg_type msg_type,struct net_if * iface)568 static void vendor_specific_byte_cb(struct net_dhcpv4_option_callback *cb,
569 size_t length,
570 enum net_dhcpv4_msg_type msg_type,
571 struct net_if *iface)
572 {
573 zassert_equal(cb->option, OPTION_VENDOR_BYTE,
574 "Unexpected vendor specific option value");
575 zassert_equal(length, 1, "Incorrect data length");
576 zassert_equal(buffer[0], 1, "Incorrect buffer contents");
577
578 event_count++;
579
580 k_sem_give(&test_lock);
581 }
582
vendor_specific_empty_cb(struct net_dhcpv4_option_callback * cb,size_t length,enum net_dhcpv4_msg_type msg_type,struct net_if * iface)583 static void vendor_specific_empty_cb(struct net_dhcpv4_option_callback *cb,
584 size_t length,
585 enum net_dhcpv4_msg_type msg_type,
586 struct net_if *iface)
587 {
588 zassert_equal(cb->option, OPTION_VENDOR_EMPTY,
589 "Unexpected vendor specific option value");
590 zassert_equal(length, 0, "Incorrect data length");
591
592 event_count++;
593
594 k_sem_give(&test_lock);
595 }
596
597 #endif /* CONFIG_NET_DHCPV4_OPTION_CALLBACKS_VENDOR_SPECIFIC */
598
599 #endif /* CONFIG_NET_DHCPV4_OPTION_CALLBACKS */
600
ZTEST(dhcpv4_tests,test_dhcp)601 ZTEST(dhcpv4_tests, test_dhcp)
602 {
603 struct net_if *iface;
604
605 k_sem_init(&test_lock, 0, UINT_MAX);
606
607 net_mgmt_init_event_callback(&rx_cb, receiver_cb,
608 NET_EVENT_IPV4_ADDR_ADD);
609
610 net_mgmt_add_event_callback(&rx_cb);
611
612 net_mgmt_init_event_callback(&dns_cb, receiver_cb,
613 NET_EVENT_DNS_SERVER_ADD |
614 NET_EVENT_DNS_SERVER_DEL);
615
616 net_mgmt_add_event_callback(&dns_cb);
617
618 net_mgmt_init_event_callback(&dhcp_cb, receiver_cb,
619 NET_EVENT_IPV4_DHCP_START |
620 NET_EVENT_IPV4_DHCP_BOUND);
621
622 net_mgmt_add_event_callback(&dhcp_cb);
623
624 #ifdef CONFIG_NET_DHCPV4_OPTION_CALLBACKS
625 net_dhcpv4_init_option_callback(&opt_domain_cb, option_domain_cb,
626 OPTION_DOMAIN, buffer,
627 sizeof(buffer));
628
629 net_dhcpv4_add_option_callback(&opt_domain_cb);
630
631 net_dhcpv4_init_option_callback(&opt_pop3_cb, option_pop3_cb,
632 OPTION_POP3, buffer,
633 sizeof(buffer));
634
635 net_dhcpv4_add_option_callback(&opt_pop3_cb);
636
637 net_dhcpv4_init_option_callback(&opt_invalid_cb, option_invalid_cb,
638 OPTION_INVALID, buffer,
639 sizeof(buffer));
640
641 net_dhcpv4_add_option_callback(&opt_invalid_cb);
642 #endif /* CONFIG_NET_DHCPV4_OPTION_CALLBACKS */
643
644 #ifdef CONFIG_NET_DHCPV4_OPTION_CALLBACKS_VENDOR_SPECIFIC
645 net_dhcpv4_init_option_vendor_callback(&opt_vs_string_cb, vendor_specific_string_cb,
646 OPTION_VENDOR_STRING, buffer,
647 sizeof(buffer));
648
649 net_dhcpv4_add_option_vendor_callback(&opt_vs_string_cb);
650
651 net_dhcpv4_init_option_vendor_callback(&opt_vs_byte_cb, vendor_specific_byte_cb,
652 OPTION_VENDOR_BYTE, buffer,
653 sizeof(buffer));
654
655 net_dhcpv4_add_option_vendor_callback(&opt_vs_byte_cb);
656
657 net_dhcpv4_init_option_vendor_callback(&opt_vs_empty_cb, vendor_specific_empty_cb,
658 OPTION_VENDOR_EMPTY, buffer,
659 sizeof(buffer));
660
661 net_dhcpv4_add_option_vendor_callback(&opt_vs_empty_cb);
662
663 net_dhcpv4_init_option_vendor_callback(&opt_vs_invalid_cb, option_invalid_cb,
664 OPTION_INVALID, buffer,
665 sizeof(buffer));
666
667 net_dhcpv4_add_option_vendor_callback(&opt_vs_invalid_cb);
668
669
670 #endif /* CONFIG_NET_DHCPV4_OPTION_CALLBACKS_VENDOR_SPECIFIC */
671
672 iface = net_if_get_first_by_type(&NET_L2_GET_NAME(DUMMY));
673 if (!iface) {
674 zassert_true(false, "Interface not available");
675 }
676
677 net_dhcpv4_start(iface);
678
679 #ifdef CONFIG_NET_DHCPV4_OPTION_CALLBACKS_VENDOR_SPECIFIC
680 while (event_count < 16) {
681 #elif defined(CONFIG_NET_DHCPV4_OPTION_CALLBACKS)
682 while (event_count < 10) {
683 #else
684 while (event_count < 5) {
685 #endif
686 if (k_sem_take(&test_lock, WAIT_TIME)) {
687 zassert_true(false, "Timeout while waiting");
688 }
689 }
690 }
691
692 /**test case main entry */
693 ZTEST_SUITE(dhcpv4_tests, NULL, NULL, NULL, NULL, NULL);
694