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