1 /* main.c - Application main entry point */
2 
3 /*
4  * Copyright (c) 2016 Intel Corporation
5  * Copyright (c) 2023 Nordic Semiconductor ASA
6  *
7  * SPDX-License-Identifier: Apache-2.0
8  */
9 
10 #include <zephyr/logging/log.h>
11 LOG_MODULE_REGISTER(net_test, CONFIG_NET_ICMPV6_LOG_LEVEL);
12 
13 #include <errno.h>
14 #include <zephyr/types.h>
15 #include <stddef.h>
16 #include <string.h>
17 #include <zephyr/sys/printk.h>
18 #include <zephyr/linker/sections.h>
19 
20 #include <zephyr/tc_util.h>
21 
22 #include <zephyr/net_buf.h>
23 #include <zephyr/net/dummy.h>
24 #include <zephyr/net/ethernet.h>
25 #include <zephyr/net/icmp.h>
26 
27 #include "ipv6.h"
28 #include "net_private.h"
29 #include "icmpv6.h"
30 #include <zephyr/ztest.h>
31 
32 static struct net_if *test_iface;
33 static int handler_called;
34 static int handler_status;
35 
36 #define TEST_MSG "foobar devnull"
37 
38 #define ICMPV6_MSG_SIZE 104
39 
40 static uint8_t icmpv6_echo_req[] =
41 	"\x60\x02\xea\x12\x00\x40\x3a\x40\xfe\x80\x00\x00\x00\x00\x00\x00" \
42 	"\xda\xcb\x8a\xff\xfe\x34\xc8\xf3\xfe\x80\x00\x00\x00\x00\x00\x00" \
43 	"\xec\x88\x2d\x63\xfd\x67\x31\x66\x80\x00\xa4\x24\x0b\x95\x00\x01" \
44 	"\x97\x78\x0f\x5c\x00\x00\x00\x00\xf7\x72\x00\x00\x00\x00\x00\x00" \
45 	"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \
46 	"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" \
47 	"\x30\x31\x32\x33\x34\x35\x36\x37";
48 
49 static uint8_t icmpv6_echo_rep[] =
50 	"\x60\x09\x23\xa0\x00\x40\x3a\x40\xfe\x80\x00\x00\x00\x00\x00\x00" \
51 	"\xec\x88\x2d\x63\xfd\x67\x31\x66\xfe\x80\x00\x00\x00\x00\x00\x00" \
52 	"\xda\xcb\x8a\xff\xfe\x34\xc8\xf3\x81\x00\xa3\x24\x0b\x95\x00\x01" \
53 	"\x97\x78\x0f\x5c\x00\x00\x00\x00\xf7\x72\x00\x00\x00\x00\x00\x00" \
54 	"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \
55 	"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" \
56 	"\x30\x31\x32\x33\x34\x35\x36\x37";
57 
58 static uint8_t icmpv6_inval_chksum[] =
59 	"\x60\x09\x23\xa0\x00\x40\x3a\x40\xfe\x80\x00\x00\x00\x00\x00\x00" \
60 	"\xec\x88\x2d\x63\xfd\x67\x31\x66\xfe\x80\x00\x00\x00\x00\x00\x00" \
61 	"\xda\xcb\x8a\xff\xfe\x34\xc8\xf3\x00\x00\xa3\x24\x0b\x95\x00\x01" \
62 	"\x97\x78\x0f\x5c\x00\x00\x00\x00\xf7\x72\x00\x00\x00\x00\x00\x00" \
63 	"\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f" \
64 	"\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f" \
65 	"\x30\x31\x32\x33\x34\x35\x36\x37";
66 
67 struct net_icmpv6_context {
68 	uint8_t mac_addr[sizeof(struct net_eth_addr)];
69 	struct net_linkaddr ll_addr;
70 };
71 
72 static struct net_icmpv6_context net_icmpv6_context_data;
73 
net_icmpv6_dev_init(const struct device * dev)74 static int net_icmpv6_dev_init(const struct device *dev)
75 {
76 	struct net_icmpv6_context *net_icmpv6_context = dev->data;
77 
78 	net_icmpv6_context = net_icmpv6_context;
79 
80 	return 0;
81 }
82 
net_icmpv6_get_mac(const struct device * dev)83 static uint8_t *net_icmpv6_get_mac(const struct device *dev)
84 {
85 	struct net_icmpv6_context *context = dev->data;
86 
87 	if (context->mac_addr[2] == 0x00) {
88 		/* 00-00-5E-00-53-xx Documentation RFC 7042 */
89 		context->mac_addr[0] = 0x00;
90 		context->mac_addr[1] = 0x00;
91 		context->mac_addr[2] = 0x5E;
92 		context->mac_addr[3] = 0x00;
93 		context->mac_addr[4] = 0x53;
94 		context->mac_addr[5] = 0x01;
95 	}
96 
97 	return context->mac_addr;
98 }
99 
net_icmpv6_iface_init(struct net_if * iface)100 static void net_icmpv6_iface_init(struct net_if *iface)
101 {
102 	uint8_t *mac = net_icmpv6_get_mac(net_if_get_device(iface));
103 
104 	net_if_set_link_addr(iface, mac, 6, NET_LINK_ETHERNET);
105 }
106 
tester_send(const struct device * dev,struct net_pkt * pkt)107 static int tester_send(const struct device *dev, struct net_pkt *pkt)
108 {
109 	net_pkt_unref(pkt);
110 	return 0;
111 }
112 
113 static struct dummy_api net_icmpv6_if_api = {
114 	.iface_api.init = net_icmpv6_iface_init,
115 	.send = tester_send,
116 };
117 
118 NET_DEVICE_INIT(net_icmpv6_test, "net_icmpv6_test",
119 		net_icmpv6_dev_init, NULL,
120 		&net_icmpv6_context_data, NULL,
121 		CONFIG_KERNEL_INIT_PRIORITY_DEFAULT,
122 		&net_icmpv6_if_api, DUMMY_L2,
123 		NET_L2_GET_CTX_TYPE(DUMMY_L2), 127);
124 
handle_test_msg(struct net_icmp_ctx * ctx,struct net_pkt * pkt,struct net_icmp_ip_hdr * hdr,struct net_icmp_hdr * icmp_hdr,void * user_data)125 static int handle_test_msg(struct net_icmp_ctx *ctx,
126 			   struct net_pkt *pkt,
127 			   struct net_icmp_ip_hdr *hdr,
128 			   struct net_icmp_hdr *icmp_hdr,
129 			   void *user_data)
130 {
131 	ARG_UNUSED(ctx);
132 	ARG_UNUSED(hdr);
133 	ARG_UNUSED(icmp_hdr);
134 	ARG_UNUSED(user_data);
135 
136 	struct net_buf *last = net_buf_frag_last(pkt->buffer);
137 	int ret;
138 
139 	if (last->len != ICMPV6_MSG_SIZE) {
140 		handler_status = -EINVAL;
141 		ret = -EINVAL;
142 	} else {
143 		handler_status = 0;
144 		ret = 0;
145 	}
146 
147 	handler_called++;
148 
149 	return ret;
150 }
151 
create_pkt(uint8_t * data,int len,struct net_ipv6_hdr ** hdr)152 static struct net_pkt *create_pkt(uint8_t *data, int len,
153 				  struct net_ipv6_hdr **hdr)
154 {
155 	struct net_pkt *pkt;
156 
157 	pkt = net_pkt_alloc_with_buffer(NULL, ICMPV6_MSG_SIZE,
158 					AF_UNSPEC, 0, K_SECONDS(1));
159 	zassert_not_null(pkt, "Allocation failed");
160 
161 	net_pkt_set_iface(pkt, test_iface);
162 	net_pkt_set_family(pkt, AF_INET6);
163 	net_pkt_set_ip_hdr_len(pkt, sizeof(struct net_ipv6_hdr));
164 
165 	net_pkt_write(pkt, data, len);
166 
167 	net_pkt_cursor_init(pkt);
168 	*hdr = net_pkt_cursor_get_pos(pkt);
169 	net_pkt_set_overwrite(pkt, true);
170 	net_pkt_skip(pkt, sizeof(struct net_ipv6_hdr));
171 
172 	/* The cursor should be at the start of the ICMPv6 header */
173 
174 	return pkt;
175 }
176 
ZTEST(icmpv6_fn,test_icmpv6)177 ZTEST(icmpv6_fn, test_icmpv6)
178 {
179 	struct net_icmp_ctx ctx1;
180 	struct net_icmp_ctx ctx2;
181 	struct net_ipv6_hdr *hdr;
182 	struct net_pkt *pkt;
183 	int ret;
184 
185 	ret = net_icmp_init_ctx(&ctx1, NET_ICMPV6_ECHO_REPLY,
186 				0, handle_test_msg);
187 	zassert_equal(ret, 0, "Cannot register %s handler (%d)",
188 		      STRINGIFY(NET_ICMPV6_ECHO_REPLY), ret);
189 
190 	ret = net_icmp_init_ctx(&ctx2, NET_ICMPV6_ECHO_REQUEST,
191 				0, handle_test_msg);
192 	zassert_equal(ret, 0, "Cannot register %s handler (%d)",
193 		      STRINGIFY(NET_ICMPV6_ECHO_REQUEST), ret);
194 
195 	pkt = create_pkt(icmpv6_inval_chksum, ICMPV6_MSG_SIZE, &hdr);
196 	zassert_not_null(pkt, "Cannot create pkt");
197 
198 	ret = net_icmpv6_input(pkt, hdr);
199 
200 	/**TESTPOINT: Check input*/
201 	zassert_true(ret == NET_DROP, "Callback not called properly");
202 
203 	handler_status = -1;
204 
205 	pkt = create_pkt(icmpv6_echo_rep, ICMPV6_MSG_SIZE, &hdr);
206 	zassert_not_null(pkt, "Cannot create pkt");
207 
208 	ret = net_icmpv6_input(pkt, hdr);
209 
210 	/**TESTPOINT: Check input*/
211 	zassert_true(!(ret == NET_DROP || handler_status != 0),
212 		     "Callback not called properly");
213 
214 	handler_status = -1;
215 
216 	pkt = create_pkt(icmpv6_echo_req, ICMPV6_MSG_SIZE, &hdr);
217 	zassert_not_null(pkt, "Cannot create pkt");
218 
219 	ret = net_icmpv6_input(pkt, hdr);
220 
221 	/**TESTPOINT: Check input*/
222 	zassert_true(!(ret == NET_DROP || handler_status != 0),
223 			"Callback not called properly");
224 
225 	/**TESTPOINT: Check input*/
226 	zassert_true(!(handler_called != 2), "Callbacks not called properly");
227 
228 	ret = net_icmp_cleanup_ctx(&ctx1);
229 	zassert_equal(ret, 0, "Cannot unregister handler (%d)", ret);
230 
231 	ret = net_icmp_cleanup_ctx(&ctx2);
232 	zassert_equal(ret, 0, "Cannot unregister handler (%d)", ret);
233 }
234 
setup(void)235 static void *setup(void)
236 {
237 	if (IS_ENABLED(CONFIG_NET_TC_THREAD_COOPERATIVE)) {
238 		k_thread_priority_set(k_current_get(),
239 				K_PRIO_COOP(CONFIG_NUM_COOP_PRIORITIES - 1));
240 	} else {
241 		k_thread_priority_set(k_current_get(), K_PRIO_PREEMPT(9));
242 	}
243 
244 	test_iface = net_if_lookup_by_dev(DEVICE_GET(net_icmpv6_test));
245 
246 	return NULL;
247 }
248 
249 /**test case main entry*/
250 ZTEST_SUITE(icmpv6_fn, NULL, setup, NULL, NULL, NULL);
251