Home | History | Annotate | Line # | Download | only in can
t_can.c revision 1.5
      1 /*	$NetBSD: t_can.c,v 1.5 2017/05/28 14:53:13 christos 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.5 2017/05/28 14:53:13 christos 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;
    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);
    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 
    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);
    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 
    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);
    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 
    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);
    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 
    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);
    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 
    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);
    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 
    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);
    526 ATF_TC_HEAD(canbindfilter, tc)
    527 {
    528 
    529 	atf_tc_set_md_var(tc, "descr", "check that socket bound to an interface doens't get other interface's messages");
    530 	atf_tc_set_md_var(tc, "timeout", "5");
    531 }
    532 
    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);
    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 
    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_TP_ADD_TCS(tp)
    721 {
    722 
    723         ATF_TP_ADD_TC(tp, canlocreate);
    724         ATF_TP_ADD_TC(tp, cannoown);
    725         ATF_TP_ADD_TC(tp, canwritelo);
    726         ATF_TP_ADD_TC(tp, canwriteunbound);
    727         ATF_TP_ADD_TC(tp, cansendtolo);
    728         ATF_TP_ADD_TC(tp, cansendtowrite);
    729         ATF_TP_ADD_TC(tp, canreadlocal);
    730         ATF_TP_ADD_TC(tp, canrecvfrom);
    731         ATF_TP_ADD_TC(tp, canbindfilter);
    732         ATF_TP_ADD_TC(tp, cannoloop);
    733 	return atf_no_error();
    734 }
    735