1 /*
2  * Copyright (c) 2019 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_REGISTER(net_test, CONFIG_NET_SOCKETS_LOG_LEVEL);
9 
10 #include <stdio.h>
11 #include <zephyr/ztest_assert.h>
12 
13 #include <zephyr/net/net_ip.h>
14 #include <zephyr/net/ethernet.h>
15 #include <zephyr/net/socket.h>
16 #include <zephyr/net/socketcan.h>
17 
18 struct test_case {
19 	int family;
20 	int type;
21 	int proto;
22 };
23 
24 static const struct test_result {
25 	struct test_case test_case;
26 	int result;
27 	int error;
28 } expected_result[] = {
29 	{
30 		/* 0 */
31 		.test_case.family = AF_INET,
32 		.test_case.type = SOCK_DGRAM,
33 		.test_case.proto = IPPROTO_UDP,
34 		.result = 0,
35 	},
36 	{
37 		/* 1 */
38 		.test_case.family = AF_INET6,
39 		.test_case.type = SOCK_DGRAM,
40 		.test_case.proto = IPPROTO_UDP,
41 		.result = 0,
42 	},
43 	{
44 		/* 2 */
45 		/* This test will not increase the called func count */
46 		.test_case.family = AF_UNSPEC,
47 		.test_case.type = 0,
48 		.test_case.proto = 0,
49 		.result = -1,
50 		.error = EAFNOSUPPORT,
51 	},
52 	{
53 		/* 3 */
54 		.test_case.family = AF_INET,
55 		.test_case.type = SOCK_DGRAM,
56 		.test_case.proto = 0,
57 		.result = 0,
58 	},
59 	{
60 		/* 4 */
61 		.test_case.family = AF_INET6,
62 		.test_case.type = SOCK_DGRAM,
63 		.test_case.proto = 0,
64 		.result = 0,
65 	},
66 	{
67 		/* 5 */
68 		.test_case.family = AF_INET,
69 		.test_case.type = SOCK_DGRAM,
70 		.test_case.proto = IPPROTO_UDP,
71 		.result = 0,
72 	},
73 	{
74 		/* 6 */
75 		.test_case.family = AF_INET6,
76 		.test_case.type = SOCK_DGRAM,
77 		.test_case.proto = IPPROTO_UDP,
78 		.result = 0,
79 	},
80 	{
81 		/* 7 */
82 		.test_case.family = AF_INET,
83 		.test_case.type = SOCK_DGRAM,
84 		.test_case.proto = IPPROTO_UDP,
85 		.result = 0,
86 	},
87 	{
88 		/* 8 */
89 		.test_case.family = AF_INET6,
90 		.test_case.type = SOCK_DGRAM,
91 		.test_case.proto = IPPROTO_UDP,
92 		.result = 0,
93 	},
94 	{
95 		/* 9 */
96 		.test_case.family = AF_INET6,
97 		.test_case.type = SOCK_STREAM,
98 		.test_case.proto = IPPROTO_UDP,
99 		.result = -1,
100 		.error = EOPNOTSUPP,
101 	},
102 	{
103 		/* 10 */
104 		.test_case.family = AF_PACKET,
105 		.test_case.type = SOCK_RAW,
106 		.test_case.proto = htons(ETH_P_ALL),
107 		.result = 0,
108 	},
109 	{
110 		/* 11 */
111 		.test_case.family = AF_CAN,
112 		.test_case.type = SOCK_RAW,
113 		.test_case.proto = CAN_RAW,
114 		.result = 0,
115 	},
116 	{
117 		/* 12 */
118 		.test_case.family = AF_INET6,
119 		.test_case.type = SOCK_STREAM,
120 		.test_case.proto = IPPROTO_TLS_1_2,
121 		.result = 0,
122 	},
123 	{
124 		/* 13 */
125 		.test_case.family = AF_INET,
126 		.test_case.type = SOCK_DGRAM,
127 		.test_case.proto = IPPROTO_DTLS_1_0,
128 		.result = 0,
129 	},
130 	{
131 		/* 14 */
132 		.test_case.family = AF_CAN,
133 		.test_case.type = SOCK_RAW,
134 		.test_case.proto = IPPROTO_RAW,
135 		.result = -1,
136 		.error = EAFNOSUPPORT,
137 	},
138 	{
139 		/* 15 */
140 		.test_case.family = AF_INET,
141 		.test_case.type = SOCK_DGRAM,
142 		.test_case.proto = 254,
143 		.result = -1,
144 		.error = EPROTONOSUPPORT,
145 	},
146 	{
147 		/* 16 */
148 		.test_case.family = AF_PACKET,
149 		.test_case.type = SOCK_RAW,
150 		.test_case.proto = htons(ETH_P_IEEE802154),
151 		.result = 0,
152 	},
153 	{
154 		/* 17 */
155 		.test_case.family = AF_PACKET,
156 		.test_case.type = SOCK_DGRAM,
157 		.test_case.proto = htons(ETH_P_IEEE802154),
158 		.result = 0,
159 	},
160 };
161 
162 static int current_test;
163 static int func_called;
164 static int failed_family = 2; /* The number of tests that are checked
165 			       * by generic socket code like the test
166 			       * number 3
167 			       */
168 
socket_test(int family,int type,int proto)169 static int socket_test(int family, int type, int proto)
170 {
171 	struct net_context *ctx;
172 	int ret;
173 
174 	func_called++;
175 
176 	ret = net_context_get(family, type, proto, &ctx);
177 	if (ret < 0) {
178 		errno = -ret;
179 		return -1;
180 	}
181 
182 	return 0;
183 }
184 
socket_test_ok(int family,int type,int proto)185 static int socket_test_ok(int family, int type, int proto)
186 {
187 	func_called++;
188 	return 0;
189 }
190 
is_tls(int family,int type,int proto)191 static bool is_tls(int family, int type, int proto)
192 {
193 	if ((family == AF_INET || family == AF_INET6) &&
194 	    (((proto >= IPPROTO_TLS_1_0) && (proto <= IPPROTO_TLS_1_2)) ||
195 	     (proto >= IPPROTO_DTLS_1_0 && proto <= IPPROTO_DTLS_1_2))) {
196 		return true;
197 	}
198 
199 	return false;
200 }
201 
is_packet(int family,int type,int proto)202 static bool is_packet(int family, int type, int proto)
203 {
204 	proto = ntohs(proto);
205 
206 	if (((type == SOCK_RAW) && (proto == ETH_P_ALL || proto == ETH_P_IEEE802154)) ||
207 	    ((type == SOCK_DGRAM) && (proto > 0))) {
208 		return true;
209 	}
210 
211 	return false;
212 }
213 
is_can(int family,int type,int proto)214 static bool is_can(int family, int type, int proto)
215 {
216 	if (type != SOCK_RAW || proto != CAN_RAW) {
217 		return false;
218 	}
219 
220 	return true;
221 }
222 
is_ip(int family,int type,int proto)223 static bool is_ip(int family, int type, int proto)
224 {
225 	if (family != AF_INET && family != AF_INET6) {
226 		return false;
227 	}
228 
229 	return true;
230 }
231 
232 #define TEST_SOCKET_PRIO 40
233 
234 NET_SOCKET_REGISTER(af_inet,   TEST_SOCKET_PRIO, AF_INET,   is_ip,      socket_test);
235 NET_SOCKET_REGISTER(af_inet6,  TEST_SOCKET_PRIO, AF_INET6,  is_ip,      socket_test);
236 NET_SOCKET_REGISTER(af_can2,   TEST_SOCKET_PRIO, AF_CAN,    is_ip,      socket_test);
237 
238 /* For these socket families, we return ok always for now */
239 NET_SOCKET_REGISTER(tls,       TEST_SOCKET_PRIO, AF_UNSPEC, is_tls,    socket_test_ok);
240 NET_SOCKET_REGISTER(af_packet, TEST_SOCKET_PRIO, AF_PACKET, is_packet, socket_test_ok);
241 NET_SOCKET_REGISTER(af_can,    TEST_SOCKET_PRIO, AF_CAN,    is_can,    socket_test_ok);
242 
ZTEST(net_socket_register,test_create_sockets)243 ZTEST(net_socket_register, test_create_sockets)
244 {
245 	int i, fd, ok_tests = 0, failed_tests = 0;
246 
247 	for (i = 0; i < ARRAY_SIZE(expected_result); i++, current_test++) {
248 		errno = 0;
249 
250 		fd = zsock_socket(expected_result[i].test_case.family,
251 				  expected_result[i].test_case.type,
252 				  expected_result[i].test_case.proto);
253 
254 		if (errno == EPROTONOSUPPORT) {
255 			func_called--;
256 			continue;
257 		}
258 
259 		zassert_equal(fd, expected_result[i].result,
260 			      "[%d] Invalid result (expecting %d got %d, "
261 			      "errno %d)", i, expected_result[i].result, fd,
262 			      errno);
263 		if (expected_result[i].result < 0) {
264 			zassert_equal(errno, expected_result[i].error,
265 				      "[%d] Invalid errno (%d vs %d)", i,
266 				      errno, expected_result[i].error);
267 		}
268 
269 		if (expected_result[i].result == 0) {
270 			ok_tests++;
271 		} else {
272 			failed_tests++;
273 		}
274 
275 		if (fd >= 0) {
276 			zsock_close(fd);
277 		}
278 	}
279 
280 	zassert_equal(ok_tests + failed_tests - failed_family, func_called,
281 		      "Invalid num of tests failed (%d vs %d)",
282 		      ok_tests + failed_tests - failed_family, func_called);
283 }
284 
285 ZTEST_SUITE(net_socket_register, NULL, NULL, NULL, NULL, NULL);
286