xref: /netbsd-src/tests/net/can/t_can.c (revision ca7653601e7602f5f52a0aeb07477fbd4eee5276)
1 /*	$NetBSD: t_can.c,v 1.8 2021/08/20 20:25:28 andvar Exp $	*/
2 
3 /*-
4  * Copyright (c) 2017 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Manuel Bouyer
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND
20  * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY
24  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
26  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
28  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
30  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include <sys/cdefs.h>
34 #ifndef lint
35 __RCSID("$NetBSD: t_can.c,v 1.8 2021/08/20 20:25:28 andvar Exp $");
36 #endif /* not lint */
37 
38 #include <sys/types.h>
39 #include <sys/resource.h>
40 #include <sys/wait.h>
41 #include <sys/sockio.h>
42 #include <sys/param.h>
43 
44 #include <atf-c.h>
45 #include <assert.h>
46 #include <fcntl.h>
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <unistd.h>
51 
52 #include <net/if.h>
53 #include <netcan/can.h>
54 
55 #include <rump/rump.h>
56 #include <rump/rump_syscalls.h>
57 
58 #include "h_macros.h"
59 #include "h_canutils.h"
60 
61 ATF_TC(canlocreate);
ATF_TC_HEAD(canlocreate,tc)62 ATF_TC_HEAD(canlocreate, tc)
63 {
64 
65 	atf_tc_set_md_var(tc, "descr", "check CAN loopback create/destroy");
66 	atf_tc_set_md_var(tc, "timeout", "5");
67 }
68 
ATF_TC_BODY(canlocreate,tc)69 ATF_TC_BODY(canlocreate, tc)
70 {
71 	const char ifname[] = "canlo0";
72 	int s, rv;
73 	struct ifreq ifr;
74 
75 	rump_init();
76 	cancfg_rump_createif(ifname);
77 
78 	s = -1;
79 	if ((s = rump_sys_socket(AF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
80 		atf_tc_fail_errno("if config socket(2)");
81 	}
82 
83 	memset(&ifr, 0, sizeof(ifr));
84 	strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
85 
86 	if ((rv = rump_sys_ioctl(s, SIOCIFDESTROY, &ifr)) < 0) {
87 		atf_tc_fail_errno("if config destroy");
88 	}
89 }
90 
91 ATF_TC(cannoown);
ATF_TC_HEAD(cannoown,tc)92 ATF_TC_HEAD(cannoown, tc)
93 {
94 
95 	atf_tc_set_md_var(tc, "descr", "check that CAN sockets don't gets its own message");
96 	atf_tc_set_md_var(tc, "timeout", "5");
97 }
98 
ATF_TC_BODY(cannoown,tc)99 ATF_TC_BODY(cannoown, tc)
100 {
101 	const char ifname[] = "canlo0";
102 	int s, rv, v;
103 	socklen_t vlen;
104 	struct sockaddr_can sa;
105 	int ifindex;
106 	struct can_frame cf_send, cf_receive;
107 
108 	rump_init();
109 	cancfg_rump_createif(ifname);
110 
111 	if ((s = rump_sys_socket(AF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
112 		atf_tc_fail_errno("CAN socket");
113 	}
114 
115 	ifindex = can_bind(s, ifname);
116 
117 	/* check sockopt CAN_RAW_LOOPBACK */
118 	vlen = sizeof(v);
119 	if (rump_sys_getsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
120 	    &v, &vlen) < 0) {
121 		atf_tc_fail_errno("getsockopt(CAN_RAW_LOOPBACK)");
122 	}
123 	ATF_CHECK_MSG(vlen == sizeof(v), "getsockopt(CAN_RAW_LOOPBACK) returns wrong len %d", vlen);
124 	ATF_CHECK_MSG(v == 1, "CAN_RAW_LOOPBACK is not on by default");
125 
126 	/* check sockopt CAN_RAW_RECV_OWN_MSGS, and set it */
127 	vlen = sizeof(v);
128 	if (rump_sys_getsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
129 	    &v, &vlen) < 0) {
130 		atf_tc_fail_errno("getsockopt(CAN_RAW_RECV_OWN_MSGS)");
131 	}
132 	ATF_CHECK_MSG(vlen == sizeof(v), "getsockopt(CAN_RAW_RECV_OWN_MSGS) returns wrong len %d", vlen);
133 	ATF_CHECK_MSG(v == 0, "CAN_RAW_RECV_OWN_MSGS is not off by default");
134 
135 	/*
136 	 * send a single byte message, but make sure remaining payload is
137 	 * not 0.
138 	 */
139 
140 	memset(&cf_send, 0, sizeof(cf_send));
141 	cf_send.can_id = 1;
142 	cf_send.can_dlc = 1;
143 	cf_send.data[0] = 0xde;
144 	cf_send.data[1] = 0xad;
145 	cf_send.data[2] = 0xbe;
146 	cf_send.data[3] = 0xef;
147 
148 	if (rump_sys_write(s, &cf_send, sizeof(cf_send) - 7) < 0) {
149 		atf_tc_fail_errno("write");
150 	}
151 
152 	/* now try to read */
153 	if (can_recvfrom(s, &cf_receive, &rv, &sa) < 0) {
154 		if (errno ==  EWOULDBLOCK)
155 			return; /* expected timeout */
156 		atf_tc_fail_errno("can_recvfrom");
157 	}
158 
159 	ATF_CHECK_MSG(sa.can_ifindex == ifindex,
160 	   "recvfrom provided wrong ifindex %d (!= %d)",
161 	    sa.can_ifindex, ifindex);
162 	atf_tc_fail("we got our own message");
163 }
164 
165 ATF_TC(canwritelo);
ATF_TC_HEAD(canwritelo,tc)166 ATF_TC_HEAD(canwritelo, tc)
167 {
168 
169 	atf_tc_set_md_var(tc, "descr", "check that CAN sockets gets its own message via write");
170 	atf_tc_set_md_var(tc, "timeout", "5");
171 }
172 
ATF_TC_BODY(canwritelo,tc)173 ATF_TC_BODY(canwritelo, tc)
174 {
175 	const char ifname[] = "canlo0";
176 	int s, rv, v;
177 	socklen_t vlen;
178 	struct can_frame cf_send, cf_receive;
179 
180 	rump_init();
181 	cancfg_rump_createif(ifname);
182 
183 	s = can_socket_with_own();
184 
185 	can_bind(s, ifname);
186 
187 	/* check sockopt CAN_RAW_LOOPBACK */
188 	vlen = sizeof(v);
189 	if (rump_sys_getsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
190 	    &v, &vlen) < 0) {
191 		atf_tc_fail_errno("getsockopt(CAN_RAW_LOOPBACK)");
192 	}
193 	ATF_CHECK_MSG(vlen == sizeof(v), "getsockopt(CAN_RAW_LOOPBACK) returns wrong len %d", vlen);
194 	ATF_CHECK_MSG(v == 1, "CAN_RAW_LOOPBACK is not on by default");
195 
196 	/* check that sockopt CAN_RAW_RECV_OWN_MSGS is on */
197 	vlen = sizeof(v);
198 	if (rump_sys_getsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
199 	    &v, &vlen) < 0) {
200 		atf_tc_fail_errno("getsockopt(CAN_RAW_RECV_OWN_MSGS)");
201 	}
202 	ATF_CHECK_MSG(v == 1, "CAN_RAW_RECV_OWN_MSGS is not on");
203 
204 	/*
205 	 * send a single byte message, but make sure remaining payload is
206 	 * not 0.
207 	 */
208 
209 	memset(&cf_send, 0, sizeof(cf_send));
210 	cf_send.can_id = 1;
211 	cf_send.can_dlc = 1;
212 	cf_send.data[0] = 0xde;
213 	cf_send.data[1] = 0xad;
214 	cf_send.data[2] = 0xbe;
215 	cf_send.data[3] = 0xef;
216 
217 	if (rump_sys_write(s, &cf_send, sizeof(cf_send) - 7) < 0) {
218 		atf_tc_fail_errno("write");
219 	}
220 
221 	if (can_read(s, &cf_receive, &rv) < 0) {
222 		atf_tc_fail_errno("can_read");
223 	}
224 
225 	memset(&cf_send, 0, sizeof(cf_send));
226 	cf_send.can_id = 1;
227 	cf_send.can_dlc = 1;
228 	cf_send.data[0] = 0xde;
229 	/* other data[] are expected to be 0 */
230 
231 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive, sizeof(cf_send)) == 0,
232 	    "received packet is not what we sent");
233 }
234 
235 ATF_TC(canwriteunbound);
ATF_TC_HEAD(canwriteunbound,tc)236 ATF_TC_HEAD(canwriteunbound, tc)
237 {
238 
239 	atf_tc_set_md_var(tc, "descr", "check that write to unbound CAN sockets fails");
240 	atf_tc_set_md_var(tc, "timeout", "5");
241 }
242 
ATF_TC_BODY(canwriteunbound,tc)243 ATF_TC_BODY(canwriteunbound, tc)
244 {
245 	const char ifname[] = "canlo0";
246 	int s, rv;
247 	struct can_frame cf_send;
248 
249 	rump_init();
250 	cancfg_rump_createif(ifname);
251 
252 	s = -1;
253 	if ((s = rump_sys_socket(AF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
254 		atf_tc_fail_errno("CAN socket");
255 	}
256 
257 	/*
258 	 * send a single byte message.
259 	 * not 0.
260 	 */
261 
262 	memset(&cf_send, 0, sizeof(cf_send));
263 	cf_send.can_id = 1;
264 	cf_send.can_dlc = 1;
265 	cf_send.data[0] = 0xde;
266 
267 	rv = rump_sys_write(s, &cf_send, sizeof(cf_send) - 7);
268 	ATF_CHECK_MSG(rv < 0 && errno == EDESTADDRREQ,
269 	    "write to unbound socket didn't fail");
270 }
271 
272 ATF_TC(cansendtolo);
ATF_TC_HEAD(cansendtolo,tc)273 ATF_TC_HEAD(cansendtolo, tc)
274 {
275 
276 	atf_tc_set_md_var(tc, "descr", "check that CAN sockets gets its own message via sendto");
277 	atf_tc_set_md_var(tc, "timeout", "5");
278 }
279 
ATF_TC_BODY(cansendtolo,tc)280 ATF_TC_BODY(cansendtolo, tc)
281 {
282 	const char ifname[] = "canlo0";
283 	int s, rv;
284 	struct sockaddr_can sa;
285 	struct ifreq ifr;
286 	struct can_frame cf_send, cf_receive;
287 
288 	rump_init();
289 	cancfg_rump_createif(ifname);
290 
291 	s = can_socket_with_own();
292 
293 	strcpy(ifr.ifr_name, ifname );
294 	if ((rv = rump_sys_ioctl(s, SIOCGIFINDEX, &ifr)) < 0) {
295 		atf_tc_fail_errno("SIOCGIFINDEX");
296 	}
297 	ATF_CHECK_MSG(ifr.ifr_ifindex > 0, "%s index is %d (not > 0)",
298 	    ifname, ifr.ifr_ifindex);
299 
300 	sa.can_family = AF_CAN;
301 	sa.can_ifindex = ifr.ifr_ifindex;
302 
303 	/*
304 	 * send a single byte message, but make sure remaining payload is
305 	 * not 0.
306 	 */
307 
308 	memset(&cf_send, 0, sizeof(cf_send));
309 	cf_send.can_id = 1;
310 	cf_send.can_dlc = 1;
311 	cf_send.data[0] = 0xde;
312 	cf_send.data[1] = 0xad;
313 	cf_send.data[2] = 0xbe;
314 	cf_send.data[3] = 0xef;
315 
316 	if (rump_sys_sendto(s, &cf_send, sizeof(cf_send) - 7,
317 	    0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
318 		atf_tc_fail_errno("sendto");
319 	}
320 
321 	if (can_read(s, &cf_receive, &rv) < 0) {
322 		atf_tc_fail_errno("read");
323 	}
324 
325 	memset(&cf_send, 0, sizeof(cf_send));
326 	cf_send.can_id = 1;
327 	cf_send.can_dlc = 1;
328 	cf_send.data[0] = 0xde;
329 	/* other data[] are expected to be 0 */
330 
331 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive, sizeof(cf_send)) == 0,
332 	    "received packet is not what we sent");
333 }
334 
335 ATF_TC(cansendtowrite);
ATF_TC_HEAD(cansendtowrite,tc)336 ATF_TC_HEAD(cansendtowrite, tc)
337 {
338 
339 	atf_tc_set_md_var(tc, "descr", "check that write after sendto on unbound socket fails");
340 	atf_tc_set_md_var(tc, "timeout", "5");
341 }
342 
ATF_TC_BODY(cansendtowrite,tc)343 ATF_TC_BODY(cansendtowrite, tc)
344 {
345 	const char ifname[] = "canlo0";
346 	int s, rv;
347 	struct sockaddr_can sa;
348 	struct ifreq ifr;
349 	struct can_frame cf_send, cf_receive;
350 
351 	rump_init();
352 	cancfg_rump_createif(ifname);
353 
354 	s = can_socket_with_own();
355 
356 	strcpy(ifr.ifr_name, ifname );
357 	if ((rv = rump_sys_ioctl(s, SIOCGIFINDEX, &ifr)) < 0) {
358 		atf_tc_fail_errno("SIOCGIFINDEX");
359 	}
360 	ATF_CHECK_MSG(ifr.ifr_ifindex > 0, "%s index is %d (not > 0)",
361 	    ifname, ifr.ifr_ifindex);
362 
363 	sa.can_family = AF_CAN;
364 	sa.can_ifindex = ifr.ifr_ifindex;
365 
366 	/*
367 	 * send a single byte message.
368 	 * not 0.
369 	 */
370 
371 	memset(&cf_send, 0, sizeof(cf_send));
372 	cf_send.can_id = 1;
373 	cf_send.can_dlc = 1;
374 	cf_send.data[0] = 0xde;
375 
376 	if (rump_sys_sendto(s, &cf_send, sizeof(cf_send) - 7,
377 	    0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
378 		atf_tc_fail_errno("sendto");
379 	}
380 
381 	if (can_read(s, &cf_receive, &rv) < 0) {
382 		atf_tc_fail_errno("read");
383 	}
384 
385 	memset(&cf_send, 0, sizeof(cf_send));
386 	cf_send.can_id = 1;
387 	cf_send.can_dlc = 1;
388 	cf_send.data[0] = 0xde;
389 	/* other data[] are expected to be 0 */
390 
391 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive, sizeof(cf_send)) == 0,
392 	    "received packet is not what we sent");
393 
394 	rv = rump_sys_write(s, &cf_send, sizeof(cf_send) - 7);
395 	ATF_CHECK_MSG(rv < 0 && errno == EDESTADDRREQ,
396 	    "write to unbound socket didn't fail");
397 }
398 
399 ATF_TC(canreadlocal);
ATF_TC_HEAD(canreadlocal,tc)400 ATF_TC_HEAD(canreadlocal, tc)
401 {
402 
403 	atf_tc_set_md_var(tc, "descr", "check all CAN sockets get messages");
404 	atf_tc_set_md_var(tc, "timeout", "5");
405 }
406 
ATF_TC_BODY(canreadlocal,tc)407 ATF_TC_BODY(canreadlocal, tc)
408 {
409 	const char ifname[] = "canlo0";
410 	int s1, rv1;
411 	int s2, rv2;
412 	struct can_frame cf_send, cf_receive1, cf_receive2;
413 
414 	rump_init();
415 	cancfg_rump_createif(ifname);
416 
417 	memset(&cf_send, 0, sizeof(cf_send));
418 	cf_send.can_id = 1;
419 	cf_send.can_dlc = 8;
420 	cf_send.data[0] = 0xde;
421 	cf_send.data[1] = 0xad;
422 	cf_send.data[2] = 0xbe;
423 	cf_send.data[3] = 0xef;
424 
425 
426 	if ((s1 = rump_sys_socket(AF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
427 		atf_tc_fail_errno("CAN socket");
428 	}
429 
430 	/* create a second socket */
431 
432 	s2 = can_socket_with_own();
433 
434 	can_bind(s2, ifname);
435 
436 	/*
437 	 * send a single byte message, but make sure remaining payload is
438 	 * not 0.
439 	 */
440 
441 	if (rump_sys_write(s2, &cf_send, sizeof(cf_send)) < 0) {
442 		atf_tc_fail_errno("write");
443 	}
444 
445 	if (can_read(s2, &cf_receive2, &rv2) < 0) {
446 		atf_tc_fail_errno("can_read");
447 	}
448 
449 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive2, sizeof(cf_send)) == 0,
450 	    "received (2) packet is not what we sent");
451 
452 	/* now check first socket */
453 	if (can_read(s1, &cf_receive1, &rv1) < 0) {
454 		atf_tc_fail_errno("can_read");
455 	}
456 
457 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive1, sizeof(cf_send)) == 0,
458 	    "received (1) packet is not what we sent");
459 }
460 
461 ATF_TC(canrecvfrom);
ATF_TC_HEAD(canrecvfrom,tc)462 ATF_TC_HEAD(canrecvfrom, tc)
463 {
464 
465 	atf_tc_set_md_var(tc, "descr", "check that recvfrom gets the CAN interface");
466 	atf_tc_set_md_var(tc, "timeout", "5");
467 }
468 
ATF_TC_BODY(canrecvfrom,tc)469 ATF_TC_BODY(canrecvfrom, tc)
470 {
471 	const char ifname[] = "canlo0";
472 	int s1, rv1;
473 	int s2, rv2;
474 	struct can_frame cf_send, cf_receive1, cf_receive2;
475 	int ifindex;
476 	struct sockaddr_can sa;
477 
478 	rump_init();
479 	cancfg_rump_createif(ifname);
480 
481 	memset(&cf_send, 0, sizeof(cf_send));
482 	cf_send.can_id = 1;
483 	cf_send.can_dlc = 8;
484 	cf_send.data[0] = 0xde;
485 	cf_send.data[1] = 0xad;
486 	cf_send.data[2] = 0xbe;
487 	cf_send.data[3] = 0xef;
488 
489 
490 	s1 = -1;
491 	if ((s1 = rump_sys_socket(AF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
492 		atf_tc_fail_errno("CAN socket");
493 	}
494 
495 	/* create a second socket */
496 
497 	s2 = can_socket_with_own();
498 
499 	ifindex = can_bind(s2, ifname);
500 
501 	if (rump_sys_write(s2, &cf_send, sizeof(cf_send)) < 0) {
502 		atf_tc_fail_errno("write");
503 	}
504 
505 	if (can_read(s2, &cf_receive2, &rv2) < 0) {
506 		atf_tc_fail_errno("can_read");
507 	}
508 
509 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive2, sizeof(cf_send)) == 0,
510 	    "received (2) packet is not what we sent");
511 
512 	/* now check first socket */
513 	memset(&sa, 0, sizeof(sa));
514 	if (can_recvfrom(s1, &cf_receive1, &rv1, &sa) < 0) {
515 		atf_tc_fail_errno("can_recvfrom");
516 	}
517 
518 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive1, sizeof(cf_send)) == 0,
519 	    "recvfrom (1) packet is not what we sent");
520 	ATF_CHECK_MSG(sa.can_ifindex == ifindex,
521 	   "recvfrom provided wrong ifindex %d (!= %d)",
522 	    sa.can_ifindex, ifindex);
523 }
524 
525 ATF_TC(canbindfilter);
ATF_TC_HEAD(canbindfilter,tc)526 ATF_TC_HEAD(canbindfilter, tc)
527 {
528 
529 	atf_tc_set_md_var(tc, "descr", "check that socket bound to an interface doesn't get other interface's messages");
530 	atf_tc_set_md_var(tc, "timeout", "5");
531 }
532 
ATF_TC_BODY(canbindfilter,tc)533 ATF_TC_BODY(canbindfilter, tc)
534 {
535 	const char ifname[] = "canlo0";
536 	const char ifname2[] = "canlo1";
537 	int s1, rv1;
538 	int s2, rv2;
539 	struct sockaddr_can sa;
540 	int ifindex2;
541 	struct can_frame cf_send, cf_receive1, cf_receive2;
542 
543 	rump_init();
544 	cancfg_rump_createif(ifname);
545 	cancfg_rump_createif(ifname2);
546 
547 	memset(&cf_send, 0, sizeof(cf_send));
548 	cf_send.can_id = 1;
549 	cf_send.can_dlc = 8;
550 	cf_send.data[0] = 0xde;
551 	cf_send.data[1] = 0xad;
552 	cf_send.data[2] = 0xbe;
553 	cf_send.data[3] = 0xef;
554 
555 
556 	s1 = can_socket_with_own();
557 
558 	can_bind(s1, ifname);
559 
560 	/* create a second socket */
561 
562 	s2 = can_socket_with_own();
563 
564 	ifindex2 = can_bind(s2, ifname2);
565 
566 	if (rump_sys_write(s2, &cf_send, sizeof(cf_send)) < 0) {
567 		atf_tc_fail_errno("write");
568 	}
569 
570 	if (can_read(s2, &cf_receive2, &rv2) < 0) {
571 		atf_tc_fail_errno("read");
572 	}
573 
574 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive2, sizeof(cf_send)) == 0,
575 	    "received (2) packet is not what we sent");
576 
577 	/* now check first socket */
578 	if (can_recvfrom(s1, &cf_receive1, &rv1, &sa) < 0) {
579 		if (errno == EWOULDBLOCK) {
580 			/* expected case */
581 			return;
582 		}
583 		atf_tc_fail_errno("can_recvfrom");
584 	}
585 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive1, sizeof(cf_send)) == 0,
586 	    "recvfrom (1) packet is not what we sent");
587 	ATF_CHECK_MSG(sa.can_ifindex == ifindex2,
588 	   "recvfrom provided wrong ifindex %d (!= %d)",
589 	    sa.can_ifindex, ifindex2);
590 	atf_tc_fail("we got message from other interface");
591 }
592 
593 ATF_TC(cannoloop);
ATF_TC_HEAD(cannoloop,tc)594 ATF_TC_HEAD(cannoloop, tc)
595 {
596 
597 	atf_tc_set_md_var(tc, "descr", "check that disabling loopback works");
598 	atf_tc_set_md_var(tc, "timeout", "5");
599 }
600 
ATF_TC_BODY(cannoloop,tc)601 ATF_TC_BODY(cannoloop, tc)
602 {
603 	const char ifname[] = "canlo0";
604 	int s1, rv1;
605 	int s2, rv2;
606 	int v;
607 	socklen_t vlen;
608 	struct sockaddr_can sa;
609 	struct can_frame cf_send, cf_receive1, cf_receive2;
610 	socklen_t salen;
611 	int ifindex;
612 	fd_set rfds;
613 	struct timeval tmout;
614 
615 	rump_init();
616 	cancfg_rump_createif(ifname);
617 
618 	memset(&cf_send, 0, sizeof(cf_send));
619 	cf_send.can_id = 1;
620 	cf_send.can_dlc = 8;
621 	cf_send.data[0] = 0xde;
622 	cf_send.data[1] = 0xad;
623 	cf_send.data[2] = 0xbe;
624 	cf_send.data[3] = 0xef;
625 
626 
627 	s1 = can_socket_with_own();
628 	v = 0;
629 	if (rump_sys_setsockopt(s1, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
630 	    &v, sizeof(v)) < 0) {
631 		atf_tc_fail_errno("setsockopt(LOOPBACK)");
632 	}
633 	v = -1;
634 	vlen = sizeof(v);
635 	if (rump_sys_getsockopt(s1, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
636 	    &v, &vlen) < 0) {
637 		atf_tc_fail_errno("getsockopt(CAN_RAW_LOOPBACK)");
638 	}
639 	ATF_CHECK_MSG(vlen == sizeof(v), "getsockopt(CAN_RAW_LOOPBACK) returns wrong len %d", vlen);
640 	ATF_CHECK_MSG(v == 0, "CAN_RAW_LOOPBACK is not off");
641 
642 	ifindex = can_bind(s1, ifname);
643 
644 	/* create a second socket */
645 	s2 = can_socket_with_own();
646 
647 	if (rump_sys_write(s1, &cf_send, sizeof(cf_send)) < 0) {
648 		atf_tc_fail_errno("write");
649 	}
650 
651 
652 	/* now check the sockets */
653 	memset(&cf_receive1, 0, sizeof(cf_receive1));
654 	memset(&cf_receive2, 0, sizeof(cf_receive2));
655 	FD_ZERO(&rfds);
656 	FD_SET(s1, &rfds);
657 	FD_SET(s2, &rfds);
658 	/* we should receive no message; wait for 1 seconds */
659 	tmout.tv_sec = 1;
660 	tmout.tv_usec = 0;
661 	rv1 = rump_sys_select(MAX(s1,s2) + 1, &rfds, NULL, NULL, &tmout);
662 	switch(rv1) {
663 	case -1:
664 		atf_tc_fail_errno("select");
665 		break;
666 	case 0:
667 		/* timeout: expected case */
668 		return;
669 	default: break;
670 	}
671 	salen = sizeof(sa);
672 	ATF_CHECK_MSG(FD_ISSET(s1, &rfds) || FD_ISSET(s2, &rfds),
673 	   "select returns but s1 nor s2 is in set");
674 	if (FD_ISSET(s1, &rfds)) {
675 		if (( rv1 = rump_sys_recvfrom(s1, &cf_receive1,
676 		    sizeof(cf_receive1), 0,
677 		    (struct sockaddr *)&sa, &salen)) < 0) {
678 			atf_tc_fail_errno("recvfrom");
679 		}
680 
681 		ATF_CHECK_MSG(rv1 > 0, "short read on socket");
682 
683 		ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive1,
684 		    sizeof(cf_send)) == 0,
685 		    "recvfrom (1) packet is not what we sent");
686 		ATF_CHECK_MSG(sa.can_family == AF_CAN,
687 		    "recvfrom provided wrong %d family", sa.can_family);
688 		ATF_CHECK_MSG(salen == sizeof(sa),
689 		    "recvfrom provided wrong size %u (!= %zu)",
690 		    salen, sizeof(sa));
691 		ATF_CHECK_MSG(sa.can_ifindex == ifindex,
692 		   "recvfrom provided wrong ifindex %d (!= %d)",
693 		    sa.can_ifindex, ifindex);
694 		atf_tc_fail_nonfatal("we got message on s1");
695 	}
696 	if (FD_ISSET(s2, &rfds)) {
697 		if (( rv2 = rump_sys_recvfrom(s2, &cf_receive2,
698 		    sizeof(cf_receive2), 0,
699 		    (struct sockaddr *)&sa, &salen)) < 0) {
700 			atf_tc_fail_errno("recvfrom");
701 		}
702 
703 		ATF_CHECK_MSG(rv2 > 0, "short read on socket");
704 
705 		ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive2,
706 		    sizeof(cf_send)) == 0,
707 		    "recvfrom (2) packet is not what we sent");
708 		ATF_CHECK_MSG(sa.can_family == AF_CAN,
709 		    "recvfrom provided wrong %d family", sa.can_family);
710 		ATF_CHECK_MSG(salen == sizeof(sa),
711 		    "recvfrom provided wrong size %u (!= %zu)",
712 		    salen, sizeof(sa));
713 		ATF_CHECK_MSG(sa.can_ifindex == ifindex,
714 		   "recvfrom provided wrong ifindex %d (!= %d)",
715 		    sa.can_ifindex, ifindex);
716 		atf_tc_fail_nonfatal("we got message on s2");
717 	}
718 }
719 
720 ATF_TC(canbindunknown);
ATF_TC_HEAD(canbindunknown,tc)721 ATF_TC_HEAD(canbindunknown, tc)
722 {
723 
724 	atf_tc_set_md_var(tc, "descr", "check that bind to unknown interface fails");
725 	atf_tc_set_md_var(tc, "timeout", "5");
726 }
727 
ATF_TC_BODY(canbindunknown,tc)728 ATF_TC_BODY(canbindunknown, tc)
729 {
730 	struct sockaddr_can sa;
731 	int r, s;
732 
733 	rump_init();
734 
735 	s = can_socket_with_own();
736 
737 	sa.can_family = AF_CAN;
738 	sa.can_ifindex = 10; /* should not exist */
739 
740 	r = rump_sys_bind(s, (struct sockaddr *)&sa, sizeof(sa));
741 
742 	ATF_CHECK_MSG(r < 0, "bind() didn't fail (%d)", r);
743 }
744 
ATF_TP_ADD_TCS(tp)745 ATF_TP_ADD_TCS(tp)
746 {
747 
748         ATF_TP_ADD_TC(tp, canlocreate);
749         ATF_TP_ADD_TC(tp, cannoown);
750         ATF_TP_ADD_TC(tp, canwritelo);
751         ATF_TP_ADD_TC(tp, canwriteunbound);
752         ATF_TP_ADD_TC(tp, cansendtolo);
753         ATF_TP_ADD_TC(tp, cansendtowrite);
754         ATF_TP_ADD_TC(tp, canreadlocal);
755         ATF_TP_ADD_TC(tp, canrecvfrom);
756         ATF_TP_ADD_TC(tp, canbindfilter);
757         ATF_TP_ADD_TC(tp, cannoloop);
758         ATF_TP_ADD_TC(tp, canbindunknown);
759 	return atf_no_error();
760 }
761