Home | History | Annotate | Line # | Download | only in can
t_can.c revision 1.1.2.6
      1 /*	$NetBSD: t_can.c,v 1.1.2.6 2017/02/05 12:18:20 bouyer 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.1.2.6 2017/02/05 12:18:20 bouyer 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);
     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 
     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);
     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 
     99 ATF_TC_BODY(cannoown, tc)
    100 {
    101 	const char ifname[] = "canlo0";
    102 	int s, rv, v, vlen;
    103 	struct sockaddr_can sa;
    104 	socklen_t salen;
    105 	int ifindex;
    106 	struct can_frame cf_send, cf_receive;
    107 	fd_set rfds;
    108 	struct timeval tmout;
    109 
    110 	rump_init();
    111 	cancfg_rump_createif(ifname);
    112 
    113 	if ((s = rump_sys_socket(AF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
    114 		atf_tc_fail_errno("CAN socket");
    115 	}
    116 
    117 	ifindex = can_bind(s, ifname);
    118 
    119 	/* check sockopt CAN_RAW_LOOPBACK */
    120 	vlen = sizeof(v);
    121 	if (rump_sys_getsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
    122 	    &v, &vlen) < 0) {
    123 		atf_tc_fail_errno("getsockopt(CAN_RAW_LOOPBACK)");
    124 	}
    125 	ATF_CHECK_MSG(vlen == sizeof(v), "getsockopt(CAN_RAW_LOOPBACK) returns wrong len %d", vlen);
    126 	ATF_CHECK_MSG(v == 1, "CAN_RAW_LOOPBACK is not on by default");
    127 
    128 	/* check sockopt CAN_RAW_RECV_OWN_MSGS, and set it */
    129 	vlen = sizeof(v);
    130 	if (rump_sys_getsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
    131 	    &v, &vlen) < 0) {
    132 		atf_tc_fail_errno("getsockopt(CAN_RAW_RECV_OWN_MSGS)");
    133 	}
    134 	ATF_CHECK_MSG(vlen == sizeof(v), "getsockopt(CAN_RAW_RECV_OWN_MSGS) returns wrong len %d", vlen);
    135 	ATF_CHECK_MSG(v == 0, "CAN_RAW_RECV_OWN_MSGS is not off by default");
    136 
    137 	/*
    138 	 * send a single byte message, but make sure remaining payload is
    139 	 * not 0.
    140 	 */
    141 
    142 	memset(&cf_send, 0, sizeof(cf_send));
    143 	cf_send.can_id = 1;
    144 	cf_send.can_dlc = 1;
    145 	cf_send.data[0] = 0xde;
    146 	cf_send.data[1] = 0xad;
    147 	cf_send.data[2] = 0xbe;
    148 	cf_send.data[3] = 0xef;
    149 
    150 	if (rump_sys_write(s, &cf_send, sizeof(cf_send) - 7) < 0) {
    151 		atf_tc_fail_errno("write");
    152 	}
    153 
    154 	/* now try to read */
    155 	if (can_recvfrom(s, &cf_receive, &rv, &sa) < 0) {
    156 		if (errno ==  EWOULDBLOCK)
    157 			return; /* expected timeout */
    158 		atf_tc_fail_errno("can_recvfrom");
    159 	}
    160 
    161 	ATF_CHECK_MSG(sa.can_ifindex == ifindex,
    162 	   "recvfrom provided wrong ifindex %d (!= %d)",
    163 	    sa.can_ifindex, ifindex);
    164 	atf_tc_fail("we got our own message");
    165 }
    166 
    167 ATF_TC(canwritelo);
    168 ATF_TC_HEAD(canwritelo, tc)
    169 {
    170 
    171 	atf_tc_set_md_var(tc, "descr", "check that CAN sockets gets its own message via write");
    172 	atf_tc_set_md_var(tc, "timeout", "5");
    173 }
    174 
    175 ATF_TC_BODY(canwritelo, tc)
    176 {
    177 	const char ifname[] = "canlo0";
    178 	int s, rv, v, vlen;
    179 	struct can_frame cf_send, cf_receive;
    180 
    181 	rump_init();
    182 	cancfg_rump_createif(ifname);
    183 
    184 	s = can_socket_with_own();
    185 
    186 	can_bind(s, ifname);
    187 
    188 	/* check sockopt CAN_RAW_LOOPBACK */
    189 	vlen = sizeof(v);
    190 	if (rump_sys_getsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
    191 	    &v, &vlen) < 0) {
    192 		atf_tc_fail_errno("getsockopt(CAN_RAW_LOOPBACK)");
    193 	}
    194 	ATF_CHECK_MSG(vlen == sizeof(v), "getsockopt(CAN_RAW_LOOPBACK) returns wrong len %d", vlen);
    195 	ATF_CHECK_MSG(v == 1, "CAN_RAW_LOOPBACK is not on by default");
    196 
    197 	/* check that sockopt CAN_RAW_RECV_OWN_MSGS is on */
    198 	vlen = sizeof(v);
    199 	if (rump_sys_getsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
    200 	    &v, &vlen) < 0) {
    201 		atf_tc_fail_errno("getsockopt(CAN_RAW_RECV_OWN_MSGS)");
    202 	}
    203 	ATF_CHECK_MSG(v == 1, "CAN_RAW_RECV_OWN_MSGS is not on");
    204 
    205 	/*
    206 	 * send a single byte message, but make sure remaining payload is
    207 	 * not 0.
    208 	 */
    209 
    210 	memset(&cf_send, 0, sizeof(cf_send));
    211 	cf_send.can_id = 1;
    212 	cf_send.can_dlc = 1;
    213 	cf_send.data[0] = 0xde;
    214 	cf_send.data[1] = 0xad;
    215 	cf_send.data[2] = 0xbe;
    216 	cf_send.data[3] = 0xef;
    217 
    218 	if (rump_sys_write(s, &cf_send, sizeof(cf_send) - 7) < 0) {
    219 		atf_tc_fail_errno("write");
    220 	}
    221 
    222 	if (can_read(s, &cf_receive, &rv) < 0) {
    223 		atf_tc_fail_errno("can_read");
    224 	}
    225 
    226 	memset(&cf_send, 0, sizeof(cf_send));
    227 	cf_send.can_id = 1;
    228 	cf_send.can_dlc = 1;
    229 	cf_send.data[0] = 0xde;
    230 	/* other data[] are expected to be 0 */
    231 
    232 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive, sizeof(cf_send)) == 0,
    233 	    "received packet is not what we sent");
    234 }
    235 
    236 ATF_TC(canwriteunbound);
    237 ATF_TC_HEAD(canwriteunbound, tc)
    238 {
    239 
    240 	atf_tc_set_md_var(tc, "descr", "check that write to unbound CAN sockets fails");
    241 	atf_tc_set_md_var(tc, "timeout", "5");
    242 }
    243 
    244 ATF_TC_BODY(canwriteunbound, tc)
    245 {
    246 	const char ifname[] = "canlo0";
    247 	int s, rv;
    248 	struct sockaddr_can sa;
    249 	struct can_frame cf_send;
    250 
    251 	rump_init();
    252 	cancfg_rump_createif(ifname);
    253 
    254 	s = -1;
    255 	if ((s = rump_sys_socket(AF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
    256 		atf_tc_fail_errno("CAN socket");
    257 	}
    258 
    259 	/*
    260 	 * send a single byte message.
    261 	 * not 0.
    262 	 */
    263 
    264 	memset(&cf_send, 0, sizeof(cf_send));
    265 	cf_send.can_id = 1;
    266 	cf_send.can_dlc = 1;
    267 	cf_send.data[0] = 0xde;
    268 
    269 	rv = rump_sys_write(s, &cf_send, sizeof(cf_send) - 7);
    270 	ATF_CHECK_MSG(rv < 0 && errno == EDESTADDRREQ,
    271 	    "write to unbound socket didn't fail");
    272 }
    273 
    274 ATF_TC(cansendtolo);
    275 ATF_TC_HEAD(cansendtolo, tc)
    276 {
    277 
    278 	atf_tc_set_md_var(tc, "descr", "check that CAN sockets gets its own message via sendto");
    279 	atf_tc_set_md_var(tc, "timeout", "5");
    280 }
    281 
    282 ATF_TC_BODY(cansendtolo, tc)
    283 {
    284 	const char ifname[] = "canlo0";
    285 	int s, v, rv;
    286 	struct sockaddr_can sa;
    287 	struct ifreq ifr;
    288 	struct can_frame cf_send, cf_receive;
    289 
    290 	rump_init();
    291 	cancfg_rump_createif(ifname);
    292 
    293 	s = can_socket_with_own();
    294 
    295 	strcpy(ifr.ifr_name, ifname );
    296 	if ((rv = rump_sys_ioctl(s, SIOCGIFINDEX, &ifr)) < 0) {
    297 		atf_tc_fail_errno("SIOCGIFINDEX");
    298 	}
    299 	ATF_CHECK_MSG(ifr.ifr_ifindex > 0, "%s index is %d (not > 0)",
    300 	    ifname, ifr.ifr_ifindex);
    301 
    302 	sa.can_family = AF_CAN;
    303 	sa.can_ifindex = ifr.ifr_ifindex;
    304 
    305 	/*
    306 	 * send a single byte message, but make sure remaining payload is
    307 	 * not 0.
    308 	 */
    309 
    310 	memset(&cf_send, 0, sizeof(cf_send));
    311 	cf_send.can_id = 1;
    312 	cf_send.can_dlc = 1;
    313 	cf_send.data[0] = 0xde;
    314 	cf_send.data[1] = 0xad;
    315 	cf_send.data[2] = 0xbe;
    316 	cf_send.data[3] = 0xef;
    317 
    318 	if (rump_sys_sendto(s, &cf_send, sizeof(cf_send) - 7,
    319 	    0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
    320 		atf_tc_fail_errno("sendto");
    321 	}
    322 
    323 	if (can_read(s, &cf_receive, &rv) < 0) {
    324 		atf_tc_fail_errno("read");
    325 	}
    326 
    327 	memset(&cf_send, 0, sizeof(cf_send));
    328 	cf_send.can_id = 1;
    329 	cf_send.can_dlc = 1;
    330 	cf_send.data[0] = 0xde;
    331 	/* other data[] are expected to be 0 */
    332 
    333 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive, sizeof(cf_send)) == 0,
    334 	    "received packet is not what we sent");
    335 }
    336 
    337 ATF_TC(cansendtowrite);
    338 ATF_TC_HEAD(cansendtowrite, tc)
    339 {
    340 
    341 	atf_tc_set_md_var(tc, "descr", "check that write after sendto on unbound socket fails");
    342 	atf_tc_set_md_var(tc, "timeout", "5");
    343 }
    344 
    345 ATF_TC_BODY(cansendtowrite, tc)
    346 {
    347 	const char ifname[] = "canlo0";
    348 	int s, rv, v;
    349 	struct sockaddr_can sa;
    350 	struct ifreq ifr;
    351 	struct can_frame cf_send, cf_receive;
    352 
    353 	rump_init();
    354 	cancfg_rump_createif(ifname);
    355 
    356 	s = can_socket_with_own();
    357 
    358 	strcpy(ifr.ifr_name, ifname );
    359 	if ((rv = rump_sys_ioctl(s, SIOCGIFINDEX, &ifr)) < 0) {
    360 		atf_tc_fail_errno("SIOCGIFINDEX");
    361 	}
    362 	ATF_CHECK_MSG(ifr.ifr_ifindex > 0, "%s index is %d (not > 0)",
    363 	    ifname, ifr.ifr_ifindex);
    364 
    365 	sa.can_family = AF_CAN;
    366 	sa.can_ifindex = ifr.ifr_ifindex;
    367 
    368 	/*
    369 	 * send a single byte message.
    370 	 * not 0.
    371 	 */
    372 
    373 	memset(&cf_send, 0, sizeof(cf_send));
    374 	cf_send.can_id = 1;
    375 	cf_send.can_dlc = 1;
    376 	cf_send.data[0] = 0xde;
    377 
    378 	if (rump_sys_sendto(s, &cf_send, sizeof(cf_send) - 7,
    379 	    0, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
    380 		atf_tc_fail_errno("sendto");
    381 	}
    382 
    383 	if (can_read(s, &cf_receive, &rv) < 0) {
    384 		atf_tc_fail_errno("read");
    385 	}
    386 
    387 	memset(&cf_send, 0, sizeof(cf_send));
    388 	cf_send.can_id = 1;
    389 	cf_send.can_dlc = 1;
    390 	cf_send.data[0] = 0xde;
    391 	/* other data[] are expected to be 0 */
    392 
    393 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive, sizeof(cf_send)) == 0,
    394 	    "received packet is not what we sent");
    395 
    396 	rv = rump_sys_write(s, &cf_send, sizeof(cf_send) - 7);
    397 	ATF_CHECK_MSG(rv < 0 && errno == EDESTADDRREQ,
    398 	    "write to unbound socket didn't fail");
    399 }
    400 
    401 ATF_TC(canreadlocal);
    402 ATF_TC_HEAD(canreadlocal, tc)
    403 {
    404 
    405 	atf_tc_set_md_var(tc, "descr", "check all CAN sockets get messages");
    406 	atf_tc_set_md_var(tc, "timeout", "5");
    407 }
    408 
    409 ATF_TC_BODY(canreadlocal, tc)
    410 {
    411 	const char ifname[] = "canlo0";
    412 	int s1, rv1;
    413 	int s2, rv2;
    414 	int v;
    415 	struct can_frame cf_send, cf_receive1, cf_receive2;
    416 
    417 	rump_init();
    418 	cancfg_rump_createif(ifname);
    419 
    420 	memset(&cf_send, 0, sizeof(cf_send));
    421 	cf_send.can_id = 1;
    422 	cf_send.can_dlc = 8;
    423 	cf_send.data[0] = 0xde;
    424 	cf_send.data[1] = 0xad;
    425 	cf_send.data[2] = 0xbe;
    426 	cf_send.data[3] = 0xef;
    427 
    428 
    429 	if ((s1 = rump_sys_socket(AF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
    430 		atf_tc_fail_errno("CAN socket");
    431 	}
    432 
    433 	/* create a second socket */
    434 
    435 	s2 = can_socket_with_own();
    436 
    437 	can_bind(s2, ifname);
    438 
    439 	/*
    440 	 * send a single byte message, but make sure remaining payload is
    441 	 * not 0.
    442 	 */
    443 
    444 	if (rump_sys_write(s2, &cf_send, sizeof(cf_send)) < 0) {
    445 		atf_tc_fail_errno("write");
    446 	}
    447 
    448 	if (can_read(s2, &cf_receive2, &rv2) < 0) {
    449 		atf_tc_fail_errno("can_read");
    450 	}
    451 
    452 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive2, sizeof(cf_send)) == 0,
    453 	    "received (2) packet is not what we sent");
    454 
    455 	/* now check first socket */
    456 	if (can_read(s1, &cf_receive1, &rv1) < 0) {
    457 		atf_tc_fail_errno("can_read");
    458 	}
    459 
    460 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive1, sizeof(cf_send)) == 0,
    461 	    "received (1) packet is not what we sent");
    462 }
    463 
    464 ATF_TC(canrecvfrom);
    465 ATF_TC_HEAD(canrecvfrom, tc)
    466 {
    467 
    468 	atf_tc_set_md_var(tc, "descr", "check that recvfrom gets the CAN interface");
    469 	atf_tc_set_md_var(tc, "timeout", "5");
    470 }
    471 
    472 ATF_TC_BODY(canrecvfrom, tc)
    473 {
    474 	const char ifname[] = "canlo0";
    475 	int s1, rv1;
    476 	int s2, rv2;
    477 	int v;
    478 	struct can_frame cf_send, cf_receive1, cf_receive2;
    479 	socklen_t salen;
    480 	int ifindex;
    481 	struct sockaddr_can sa;
    482 
    483 	rump_init();
    484 	cancfg_rump_createif(ifname);
    485 
    486 	memset(&cf_send, 0, sizeof(cf_send));
    487 	cf_send.can_id = 1;
    488 	cf_send.can_dlc = 8;
    489 	cf_send.data[0] = 0xde;
    490 	cf_send.data[1] = 0xad;
    491 	cf_send.data[2] = 0xbe;
    492 	cf_send.data[3] = 0xef;
    493 
    494 
    495 	s1 = -1;
    496 	if ((s1 = rump_sys_socket(AF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
    497 		atf_tc_fail_errno("CAN socket");
    498 	}
    499 
    500 	/* create a second socket */
    501 
    502 	s2 = can_socket_with_own();
    503 
    504 	ifindex = can_bind(s2, ifname);
    505 
    506 	if (rump_sys_write(s2, &cf_send, sizeof(cf_send)) < 0) {
    507 		atf_tc_fail_errno("write");
    508 	}
    509 
    510 	if (can_read(s2, &cf_receive2, &rv2) < 0) {
    511 		atf_tc_fail_errno("can_read");
    512 	}
    513 
    514 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive2, sizeof(cf_send)) == 0,
    515 	    "received (2) packet is not what we sent");
    516 
    517 	/* now check first socket */
    518 	memset(&sa, 0, sizeof(sa));
    519 	if (can_recvfrom(s1, &cf_receive1, &rv1, &sa) < 0) {
    520 		atf_tc_fail_errno("can_recvfrom");
    521 	}
    522 
    523 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive1, sizeof(cf_send)) == 0,
    524 	    "recvfrom (1) packet is not what we sent");
    525 	ATF_CHECK_MSG(sa.can_ifindex == ifindex,
    526 	   "recvfrom provided wrong ifindex %d (!= %d)",
    527 	    sa.can_ifindex, ifindex);
    528 }
    529 
    530 ATF_TC(canbindfilter);
    531 ATF_TC_HEAD(canbindfilter, tc)
    532 {
    533 
    534 	atf_tc_set_md_var(tc, "descr", "check that socket bound to an interface doens't get other interface's messages");
    535 	atf_tc_set_md_var(tc, "timeout", "5");
    536 }
    537 
    538 ATF_TC_BODY(canbindfilter, tc)
    539 {
    540 	const char ifname[] = "canlo0";
    541 	const char ifname2[] = "canlo1";
    542 	int s1, rv1;
    543 	int s2, rv2;
    544 	int v;
    545 	struct sockaddr_can sa;
    546 	int ifindex2;
    547 	struct ifreq ifr;
    548 	struct can_frame cf_send, cf_receive1, cf_receive2;
    549 	socklen_t salen;
    550 	fd_set rfds;
    551 	struct timeval tmout;
    552 
    553 	rump_init();
    554 	cancfg_rump_createif(ifname);
    555 	cancfg_rump_createif(ifname2);
    556 
    557 	memset(&cf_send, 0, sizeof(cf_send));
    558 	cf_send.can_id = 1;
    559 	cf_send.can_dlc = 8;
    560 	cf_send.data[0] = 0xde;
    561 	cf_send.data[1] = 0xad;
    562 	cf_send.data[2] = 0xbe;
    563 	cf_send.data[3] = 0xef;
    564 
    565 
    566 	s1 = can_socket_with_own();
    567 
    568 	can_bind(s1, ifname);
    569 
    570 	/* create a second socket */
    571 
    572 	s2 = can_socket_with_own();
    573 
    574 	ifindex2 = can_bind(s2, ifname2);
    575 
    576 	if (rump_sys_write(s2, &cf_send, sizeof(cf_send)) < 0) {
    577 		atf_tc_fail_errno("write");
    578 	}
    579 
    580 	if (can_read(s2, &cf_receive2, &rv2) < 0) {
    581 		atf_tc_fail_errno("read");
    582 	}
    583 
    584 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive2, sizeof(cf_send)) == 0,
    585 	    "received (2) packet is not what we sent");
    586 
    587 	/* now check first socket */
    588 	if (can_recvfrom(s1, &cf_receive1, &rv1, &sa) < 0) {
    589 		if (errno == EWOULDBLOCK) {
    590 			/* expected case */
    591 			return;
    592 		}
    593 		atf_tc_fail_errno("can_recvfrom");
    594 	}
    595 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive1, sizeof(cf_send)) == 0,
    596 	    "recvfrom (1) packet is not what we sent");
    597 	ATF_CHECK_MSG(sa.can_ifindex == ifindex2,
    598 	   "recvfrom provided wrong ifindex %d (!= %d)",
    599 	    sa.can_ifindex, ifindex2);
    600 	atf_tc_fail("we got message from other interface");
    601 }
    602 
    603 ATF_TC(cannoloop);
    604 ATF_TC_HEAD(cannoloop, tc)
    605 {
    606 
    607 	atf_tc_set_md_var(tc, "descr", "check that disabling loopback works");
    608 	atf_tc_set_md_var(tc, "timeout", "5");
    609 }
    610 
    611 ATF_TC_BODY(cannoloop, tc)
    612 {
    613 	const char ifname[] = "canlo0";
    614 	int s1, rv1;
    615 	int s2, rv2;
    616 	int v, vlen;
    617 	struct sockaddr_can sa;
    618 	struct ifreq ifr;
    619 	struct can_frame cf_send, cf_receive1, cf_receive2;
    620 	socklen_t salen;
    621 	int ifindex;
    622 	fd_set rfds;
    623 	struct timeval tmout;
    624 
    625 	rump_init();
    626 	cancfg_rump_createif(ifname);
    627 
    628 	memset(&cf_send, 0, sizeof(cf_send));
    629 	cf_send.can_id = 1;
    630 	cf_send.can_dlc = 8;
    631 	cf_send.data[0] = 0xde;
    632 	cf_send.data[1] = 0xad;
    633 	cf_send.data[2] = 0xbe;
    634 	cf_send.data[3] = 0xef;
    635 
    636 
    637 	s1 = can_socket_with_own();
    638 	v = 0;
    639 	if (rump_sys_setsockopt(s1, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
    640 	    &v, sizeof(v)) < 0) {
    641 		atf_tc_fail_errno("setsockopt(LOOPBACK)");
    642 	}
    643 	v = -1;
    644 	vlen = sizeof(v);
    645 	if (rump_sys_getsockopt(s1, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
    646 	    &v, &vlen) < 0) {
    647 		atf_tc_fail_errno("getsockopt(CAN_RAW_LOOPBACK)");
    648 	}
    649 	ATF_CHECK_MSG(vlen == sizeof(v), "getsockopt(CAN_RAW_LOOPBACK) returns wrong len %d", vlen);
    650 	ATF_CHECK_MSG(v == 0, "CAN_RAW_LOOPBACK is not off");
    651 
    652 	ifindex = can_bind(s1, ifname);
    653 
    654 	/* create a second socket */
    655 	s2 = can_socket_with_own();
    656 
    657 	if (rump_sys_write(s1, &cf_send, sizeof(cf_send)) < 0) {
    658 		atf_tc_fail_errno("write");
    659 	}
    660 
    661 
    662 	/* now check the sockets */
    663 	memset(&cf_receive1, 0, sizeof(cf_receive1));
    664 	memset(&cf_receive2, 0, sizeof(cf_receive2));
    665 	FD_ZERO(&rfds);
    666 	FD_SET(s1, &rfds);
    667 	FD_SET(s2, &rfds);
    668 	/* we should receive no message; wait for 1 seconds */
    669 	tmout.tv_sec = 1;
    670 	tmout.tv_usec = 0;
    671 	rv1 = rump_sys_select(MAX(s1,s2) + 1, &rfds, NULL, NULL, &tmout);
    672 	switch(rv1) {
    673 	case -1:
    674 		atf_tc_fail_errno("select");
    675 		break;
    676 	case 0:
    677 		/* timeout: expected case */
    678 		return;
    679 	default: break;
    680 	}
    681 	salen = sizeof(sa);
    682 	ATF_CHECK_MSG(FD_ISSET(s1, &rfds) || FD_ISSET(s2, &rfds),
    683 	   "select returns but s1 nor s2 is in set");
    684 	if (FD_ISSET(s1, &rfds)) {
    685 		if (( rv1 = rump_sys_recvfrom(s1, &cf_receive1,
    686 		    sizeof(cf_receive1), 0,
    687 		    (struct sockaddr *)&sa, &salen)) < 0) {
    688 			atf_tc_fail_errno("recvfrom");
    689 		}
    690 
    691 		ATF_CHECK_MSG(rv1 > 0, "short read on socket");
    692 
    693 		ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive1,
    694 		    sizeof(cf_send)) == 0,
    695 		    "recvfrom (1) packet is not what we sent");
    696 		ATF_CHECK_MSG(sa.can_family == AF_CAN,
    697 		    "recvfrom provided wrong %d family", sa.can_family);
    698 		ATF_CHECK_MSG(salen == sizeof(sa),
    699 		    "recvfrom provided wrong size %d (!= %d)",
    700 		    salen, sizeof(sa));
    701 		ATF_CHECK_MSG(sa.can_ifindex == ifindex,
    702 		   "recvfrom provided wrong ifindex %d (!= %d)",
    703 		    sa.can_ifindex, ifindex);
    704 		atf_tc_fail_nonfatal("we got message on s1");
    705 	}
    706 	if (FD_ISSET(s2, &rfds)) {
    707 		if (( rv2 = rump_sys_recvfrom(s2, &cf_receive2,
    708 		    sizeof(cf_receive2), 0,
    709 		    (struct sockaddr *)&sa, &salen)) < 0) {
    710 			atf_tc_fail_errno("recvfrom");
    711 		}
    712 
    713 		ATF_CHECK_MSG(rv2 > 0, "short read on socket");
    714 
    715 		ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive2,
    716 		    sizeof(cf_send)) == 0,
    717 		    "recvfrom (2) packet is not what we sent");
    718 		ATF_CHECK_MSG(sa.can_family == AF_CAN,
    719 		    "recvfrom provided wrong %d family", sa.can_family);
    720 		ATF_CHECK_MSG(salen == sizeof(sa),
    721 		    "recvfrom provided wrong size %d (!= %d)",
    722 		    salen, sizeof(sa));
    723 		ATF_CHECK_MSG(sa.can_ifindex == ifindex,
    724 		   "recvfrom provided wrong ifindex %d (!= %d)",
    725 		    sa.can_ifindex, ifindex);
    726 		atf_tc_fail_nonfatal("we got message on s2");
    727 	}
    728 }
    729 
    730 ATF_TP_ADD_TCS(tp)
    731 {
    732 
    733         ATF_TP_ADD_TC(tp, canlocreate);
    734         ATF_TP_ADD_TC(tp, cannoown);
    735         ATF_TP_ADD_TC(tp, canwritelo);
    736         ATF_TP_ADD_TC(tp, canwriteunbound);
    737         ATF_TP_ADD_TC(tp, cansendtolo);
    738         ATF_TP_ADD_TC(tp, cansendtowrite);
    739         ATF_TP_ADD_TC(tp, canreadlocal);
    740         ATF_TP_ADD_TC(tp, canrecvfrom);
    741         ATF_TP_ADD_TC(tp, canbindfilter);
    742         ATF_TP_ADD_TC(tp, cannoloop);
    743 	return atf_no_error();
    744 }
    745