Home | History | Annotate | Line # | Download | only in can
      1 /*	$NetBSD: t_canfilter.c,v 1.2 2017/05/27 21:02:56 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_canfilter.c,v 1.2 2017/05/27 21:02:56 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(canfilter_basic);
     62 ATF_TC_HEAD(canfilter_basic, tc)
     63 {
     64 
     65 	atf_tc_set_md_var(tc, "descr", "check a simple CAN filter");
     66 	atf_tc_set_md_var(tc, "timeout", "5");
     67 }
     68 
     69 ATF_TC_BODY(canfilter_basic, tc)
     70 {
     71 	const char ifname[] = "canlo0";
     72 	int s, rv;
     73 	struct can_frame cf_send, cf_receive;
     74 	struct can_filter cfi;
     75 
     76 	rump_init();
     77 	cancfg_rump_createif(ifname);
     78 
     79 	s = can_socket_with_own();
     80 
     81 	can_bind(s, ifname);
     82 
     83 	/* set filter */
     84 #define MY_ID	1
     85 	cfi.can_id = MY_ID;
     86 	cfi.can_mask = CAN_SFF_MASK | CAN_EFF_FLAG;
     87 	if (rump_sys_setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER,
     88 	    &cfi, sizeof(cfi)) < 0) {
     89 		atf_tc_fail_errno("setsockopt(CAN_RAW_FILTER)");
     90 	}
     91 
     92 	/*
     93 	 * send a single byte message, but make sure remaining payload is
     94 	 * not 0.
     95 	 */
     96 
     97 	memset(&cf_send, 0, sizeof(cf_send));
     98 	cf_send.can_id = MY_ID;
     99 	cf_send.can_dlc = 1;
    100 	cf_send.data[0] = 0xde;
    101 	cf_send.data[1] = 0xad;
    102 	cf_send.data[2] = 0xbe;
    103 	cf_send.data[3] = 0xef;
    104 
    105 	if (rump_sys_write(s, &cf_send, sizeof(cf_send) - 7) < 0) {
    106 		atf_tc_fail_errno("write");
    107 	}
    108 
    109 	if (can_read(s, &cf_receive, &rv) < 0) {
    110 		atf_tc_fail_errno("read");
    111 	}
    112 
    113 	ATF_CHECK_MSG(rv > 0, "short read on socket");
    114 
    115 	memset(&cf_send, 0, sizeof(cf_send));
    116 	cf_send.can_id = MY_ID;
    117 	cf_send.can_dlc = 1;
    118 	cf_send.data[0] = 0xde;
    119 	/* other data[] are expected to be 0 */
    120 
    121 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive, sizeof(cf_send)) == 0,
    122 	    "received packet is not what we sent");
    123 
    124 	/* now send a packet with CAN_RTR_FLAG. Should pass too */
    125 
    126 	memset(&cf_send, 0, sizeof(cf_send));
    127 	cf_send.can_id = MY_ID | CAN_RTR_FLAG;
    128 	cf_send.can_dlc = 1;
    129 	cf_send.data[0] = 0xde;
    130 	cf_send.data[1] = 0xad;
    131 	cf_send.data[2] = 0xbe;
    132 	cf_send.data[3] = 0xef;
    133 
    134 	if (rump_sys_write(s, &cf_send, sizeof(cf_send) - 7) < 0) {
    135 		atf_tc_fail_errno("write");
    136 	}
    137 
    138 	if (can_read(s, &cf_receive, &rv) < 0) {
    139 		atf_tc_fail_errno("read");
    140 	}
    141 
    142 	ATF_CHECK_MSG(rv > 0, "short read on socket");
    143 
    144 	memset(&cf_send, 0, sizeof(cf_send));
    145 	cf_send.can_id = MY_ID | CAN_RTR_FLAG;
    146 	cf_send.can_dlc = 1;
    147 	cf_send.data[0] = 0xde;
    148 	/* other data[] are expected to be 0 */
    149 
    150 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive, sizeof(cf_send)) == 0,
    151 	    "received packet is not what we sent");
    152 
    153 	/* now send a packet for a different id. Should not pass */
    154 
    155 	memset(&cf_send, 0, sizeof(cf_send));
    156 	cf_send.can_id = MY_ID + 1;
    157 	cf_send.can_dlc = 1;
    158 	cf_send.data[0] = 0xde;
    159 	cf_send.data[1] = 0xad;
    160 	cf_send.data[2] = 0xbe;
    161 	cf_send.data[3] = 0xef;
    162 
    163 	if (rump_sys_write(s, &cf_send, sizeof(cf_send) - 7) < 0) {
    164 		atf_tc_fail_errno("write");
    165 	}
    166 
    167 	if (can_read(s, &cf_receive, &rv) < 0) {
    168 		if (errno == EWOULDBLOCK)
    169 			return; /* expected timeout */
    170 		atf_tc_fail_errno("read");
    171 	}
    172 
    173 	ATF_CHECK_MSG(rv > 0, "short read on socket");
    174 
    175 	memset(&cf_send, 0, sizeof(cf_send));
    176 	cf_send.can_id = MY_ID + 1;
    177 	cf_send.can_dlc = 1;
    178 	cf_send.data[0] = 0xde;
    179 	/* other data[] are expected to be 0 */
    180 
    181 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive, sizeof(cf_send)) == 0,
    182 	    "received packet is not what we sent");
    183 	atf_tc_fail("we got our own message");
    184 #undef MY_ID
    185 }
    186 
    187 ATF_TC(canfilter_null);
    188 ATF_TC_HEAD(canfilter_null, tc)
    189 {
    190 
    191 	atf_tc_set_md_var(tc, "descr", "check a NULL CAN filter");
    192 	atf_tc_set_md_var(tc, "timeout", "5");
    193 }
    194 
    195 ATF_TC_BODY(canfilter_null, tc)
    196 {
    197 	const char ifname[] = "canlo0";
    198 	int s, rv;
    199 	struct can_frame cf_send, cf_receive;
    200 	struct can_filter cfi[2];
    201 	socklen_t cfilen;
    202 
    203 	rump_init();
    204 	cancfg_rump_createif(ifname);
    205 
    206 	s = can_socket_with_own();
    207 	can_bind(s, ifname);
    208 
    209 	if (rump_sys_setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER,
    210 	    NULL,  0) < 0) {
    211 		atf_tc_fail_errno("setsockopt(CAN_RAW_FILTER)");
    212 	}
    213 
    214 	/* get filter: should be NULL */
    215 	cfilen = sizeof(cfi);
    216 	if (rump_sys_getsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER,
    217 	    &cfi, &cfilen) < 0) {
    218 		atf_tc_fail_errno("getsockopt(CAN_RAW_FILTER)");
    219 	}
    220 	ATF_CHECK_MSG(cfilen == 0,
    221 	    "CAN_RAW_FILTER returns wrong len (%d)", cfilen);
    222 	/*
    223 	 * send a single byte message, but make sure remaining payload is
    224 	 * not 0.
    225 	 */
    226 #define MY_ID	1
    227 
    228 	memset(&cf_send, 0, sizeof(cf_send));
    229 	cf_send.can_id = MY_ID;
    230 	cf_send.can_dlc = 1;
    231 	cf_send.data[0] = 0xde;
    232 	cf_send.data[1] = 0xad;
    233 	cf_send.data[2] = 0xbe;
    234 	cf_send.data[3] = 0xef;
    235 
    236 	if (rump_sys_write(s, &cf_send, sizeof(cf_send) - 7) < 0) {
    237 		atf_tc_fail_errno("write");
    238 	}
    239 
    240 	if (can_read(s, &cf_receive, &rv) < 0) {
    241 		if (errno == EWOULDBLOCK)
    242 			return; /* expected timeout */
    243 		atf_tc_fail_errno("read");
    244 	}
    245 
    246 	ATF_CHECK_MSG(rv > 0, "short read on socket");
    247 
    248 	memset(&cf_send, 0, sizeof(cf_send));
    249 	cf_send.can_id = MY_ID;
    250 	cf_send.can_dlc = 1;
    251 	cf_send.data[0] = 0xde;
    252 	/* other data[] are expected to be 0 */
    253 
    254 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive, sizeof(cf_send)) == 0,
    255 	    "received packet is not what we sent");
    256 	atf_tc_fail("we got our own message");
    257 #undef MY_ID
    258 }
    259 
    260 ATF_TC(canfilter_multiple);
    261 ATF_TC_HEAD(canfilter_multiple, tc)
    262 {
    263 
    264 	atf_tc_set_md_var(tc, "descr", "check multiple CAN filters");
    265 	atf_tc_set_md_var(tc, "timeout", "5");
    266 }
    267 
    268 ATF_TC_BODY(canfilter_multiple, tc)
    269 {
    270 	const char ifname[] = "canlo0";
    271 	int s, rv;
    272 	struct can_frame cf_send, cf_receive;
    273 	struct can_filter cfi[2];
    274 
    275 	rump_init();
    276 	cancfg_rump_createif(ifname);
    277 
    278 	s = can_socket_with_own();
    279 
    280 	can_bind(s, ifname);
    281 
    282 	/* set filter: accept MY_ID and MY_ID+1 */
    283 #define MY_ID	1
    284 	cfi[0].can_id = MY_ID;
    285 	cfi[0].can_mask = CAN_SFF_MASK | CAN_EFF_FLAG;
    286 	cfi[1].can_id = MY_ID + 1;
    287 	cfi[1].can_mask = CAN_SFF_MASK | CAN_EFF_FLAG;
    288 	if (rump_sys_setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER,
    289 	    &cfi, sizeof(cfi)) < 0) {
    290 		atf_tc_fail_errno("setsockopt(CAN_RAW_FILTER)");
    291 	}
    292 
    293 	/*
    294 	 * send a single byte message, but make sure remaining payload is
    295 	 * not 0.
    296 	 */
    297 
    298 	memset(&cf_send, 0, sizeof(cf_send));
    299 	cf_send.can_id = MY_ID;
    300 	cf_send.can_dlc = 1;
    301 	cf_send.data[0] = 0xde;
    302 	cf_send.data[1] = 0xad;
    303 	cf_send.data[2] = 0xbe;
    304 	cf_send.data[3] = 0xef;
    305 
    306 	if (rump_sys_write(s, &cf_send, sizeof(cf_send) - 7) < 0) {
    307 		atf_tc_fail_errno("write");
    308 	}
    309 
    310 	if (can_read(s, &cf_receive, &rv) < 0) {
    311 		atf_tc_fail_errno("read");
    312 	}
    313 
    314 	ATF_CHECK_MSG(rv > 0, "short read on socket");
    315 
    316 	memset(&cf_send, 0, sizeof(cf_send));
    317 	cf_send.can_id = MY_ID;
    318 	cf_send.can_dlc = 1;
    319 	cf_send.data[0] = 0xde;
    320 	/* other data[] are expected to be 0 */
    321 
    322 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive, sizeof(cf_send)) == 0,
    323 	    "received packet is not what we sent");
    324 
    325 	/* now send a packet with MY_ID+1. Should pass too */
    326 
    327 	memset(&cf_send, 0, sizeof(cf_send));
    328 	cf_send.can_id = MY_ID + 1;
    329 	cf_send.can_dlc = 1;
    330 	cf_send.data[0] = 0xde;
    331 	cf_send.data[1] = 0xad;
    332 	cf_send.data[2] = 0xbe;
    333 	cf_send.data[3] = 0xef;
    334 
    335 	if (rump_sys_write(s, &cf_send, sizeof(cf_send) - 7) < 0) {
    336 		atf_tc_fail_errno("write");
    337 	}
    338 
    339 	if (can_read(s, &cf_receive, &rv) < 0) {
    340 		atf_tc_fail_errno("read");
    341 	}
    342 
    343 	ATF_CHECK_MSG(rv > 0, "short read on socket");
    344 
    345 	memset(&cf_send, 0, sizeof(cf_send));
    346 	cf_send.can_id = MY_ID  + 1;
    347 	cf_send.can_dlc = 1;
    348 	cf_send.data[0] = 0xde;
    349 	/* other data[] are expected to be 0 */
    350 
    351 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive, sizeof(cf_send)) == 0,
    352 	    "received packet is not what we sent");
    353 
    354 	/* now send a packet with MY_ID + 2. Should not pass */
    355 
    356 	memset(&cf_send, 0, sizeof(cf_send));
    357 	cf_send.can_id = MY_ID + 2;
    358 	cf_send.can_dlc = 1;
    359 	cf_send.data[0] = 0xde;
    360 	cf_send.data[1] = 0xad;
    361 	cf_send.data[2] = 0xbe;
    362 	cf_send.data[3] = 0xef;
    363 
    364 	if (rump_sys_write(s, &cf_send, sizeof(cf_send) - 7) < 0) {
    365 		atf_tc_fail_errno("write");
    366 	}
    367 
    368 	if (can_read(s, &cf_receive, &rv) < 0) {
    369 		if (errno == EWOULDBLOCK)
    370 			return; /* expected timeout */
    371 		atf_tc_fail_errno("read");
    372 	}
    373 
    374 	ATF_CHECK_MSG(rv > 0, "short read on socket");
    375 
    376 	memset(&cf_send, 0, sizeof(cf_send));
    377 	cf_send.can_id = MY_ID + 2;
    378 	cf_send.can_dlc = 1;
    379 	cf_send.data[0] = 0xde;
    380 	/* other data[] are expected to be 0 */
    381 
    382 	ATF_CHECK_MSG(memcmp(&cf_send, &cf_receive, sizeof(cf_send)) == 0,
    383 	    "received packet is not what we sent");
    384 	atf_tc_fail("we got our own message");
    385 #undef MY_ID
    386 }
    387 
    388 ATF_TC(canfilter_get);
    389 ATF_TC_HEAD(canfilter_get, tc)
    390 {
    391 
    392 	atf_tc_set_md_var(tc, "descr", "check reading CAN filters");
    393 	atf_tc_set_md_var(tc, "timeout", "5");
    394 }
    395 
    396 ATF_TC_BODY(canfilter_get, tc)
    397 {
    398 	const char ifname[] = "canlo0";
    399 	int s;
    400 	struct can_filter cfi[2];
    401 	socklen_t cfilen;
    402 
    403 	rump_init();
    404 	cancfg_rump_createif(ifname);
    405 
    406 	s = -1;
    407 	if ((s = rump_sys_socket(AF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
    408 		atf_tc_fail_errno("CAN socket");
    409 	}
    410 
    411 	cfilen = sizeof(cfi);
    412 	/* get filter: should be default filter */
    413 	if (rump_sys_getsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER,
    414 	    &cfi, &cfilen) < 0) {
    415 		atf_tc_fail_errno("getsockopt(CAN_RAW_FILTER)");
    416 	}
    417 	ATF_CHECK_MSG(cfilen == sizeof(struct can_filter),
    418 	    "CAN_RAW_FILTER returns wrong len (%d)", cfilen);
    419 	ATF_CHECK_MSG(cfi[0].can_id == 0 && cfi[0].can_mask == 0,
    420 	    "CAN_RAW_FILTER returns wrong filter (%d, %d)",
    421 	    cfi[0].can_id, cfi[0].can_mask);
    422 
    423 	/* set filter: accept MY_ID and MY_ID+1 */
    424 #define MY_ID	1
    425 	cfi[0].can_id = MY_ID;
    426 	cfi[0].can_mask = CAN_SFF_MASK | CAN_EFF_FLAG;
    427 	cfi[1].can_id = MY_ID + 1;
    428 	cfi[1].can_mask = CAN_SFF_MASK;
    429 	if (rump_sys_setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER,
    430 	    &cfi, sizeof(cfi)) < 0) {
    431 		atf_tc_fail_errno("setsockopt(CAN_RAW_FILTER)");
    432 	}
    433 
    434 	/* and read back */
    435 	cfilen = sizeof(cfi);
    436 	memset(cfi, 0, cfilen);
    437 	if (rump_sys_getsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER,
    438 	    &cfi, &cfilen) < 0) {
    439 		atf_tc_fail_errno("getsockopt(CAN_RAW_FILTER)");
    440 	}
    441 	ATF_CHECK_MSG(cfilen == sizeof(struct can_filter) * 2,
    442 	    "CAN_RAW_FILTER returns wrong len (%d)", cfilen);
    443 	ATF_CHECK_MSG(cfi[0].can_id == MY_ID &&
    444 	    cfi[0].can_mask == (CAN_SFF_MASK | CAN_EFF_FLAG),
    445 	    "CAN_RAW_FILTER returns wrong filter 0 (%d, %d)",
    446 	    cfi[0].can_id, cfi[0].can_mask);
    447 	ATF_CHECK_MSG(cfi[1].can_id == MY_ID + 1 &&
    448 	    cfi[1].can_mask == CAN_SFF_MASK,
    449 	    "CAN_RAW_FILTER returns wrong filter 1 (%d, %d)",
    450 	    cfi[1].can_id, cfi[1].can_mask);
    451 
    452 #undef MY_ID
    453 }
    454 
    455 ATF_TP_ADD_TCS(tp)
    456 {
    457 
    458         ATF_TP_ADD_TC(tp, canfilter_basic);
    459         ATF_TP_ADD_TC(tp, canfilter_null);
    460         ATF_TP_ADD_TC(tp, canfilter_multiple);
    461         ATF_TP_ADD_TC(tp, canfilter_get);
    462 	return atf_no_error();
    463 }
    464 
    465