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