1 /* $NetBSD: h_canutils.c,v 1.3 2017/05/28 13:55:07 kre 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: h_canutils.c,v 1.3 2017/05/28 13:55:07 kre 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 void 62 cancfg_rump_createif(const char *ifname) 63 { 64 int s, rv; 65 struct ifreq ifr; 66 67 s = -1; 68 if ((s = rump_sys_socket(AF_CAN, SOCK_RAW, CAN_RAW)) < 0) { 69 atf_tc_fail_errno("if config socket"); 70 } 71 72 memset(&ifr, 0, sizeof(ifr)); 73 strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 74 75 if ((rv = rump_sys_ioctl(s, SIOCIFCREATE, &ifr)) < 0) { 76 atf_tc_fail_errno("if config create"); 77 } 78 79 memset(&ifr, 0, sizeof(ifr)); 80 strncpy(ifr.ifr_name, ifname, IFNAMSIZ); 81 82 if ((rv = rump_sys_ioctl(s, SIOCGIFFLAGS, &ifr)) < 0) { 83 atf_tc_fail_errno("if config get flags"); 84 } 85 86 ifr.ifr_flags |= IFF_UP; 87 if ((rv = rump_sys_ioctl(s, SIOCSIFFLAGS, &ifr)) < 0) { 88 atf_tc_fail_errno("if config set flags"); 89 } 90 } 91 92 int 93 can_recvfrom(int s, struct can_frame *cf, int *len, struct sockaddr_can *sa) 94 { 95 socklen_t salen; 96 fd_set rfds; 97 struct timeval tmout; 98 int rv; 99 100 memset(cf, 0, sizeof(struct can_frame)); 101 FD_ZERO(&rfds); 102 FD_SET(s, &rfds); 103 /* wait 1 second for the message (in some tests we expect no message) */ 104 tmout.tv_sec = 1; 105 tmout.tv_usec = 0; 106 rv = rump_sys_select(s + 1, &rfds, NULL, NULL, &tmout); 107 switch(rv) { 108 case -1: 109 atf_tc_fail_errno("select"); 110 /* NOTREACHED */ 111 case 0: 112 /* timeout */ 113 errno = EWOULDBLOCK; 114 return -1; 115 default: break; 116 } 117 ATF_CHECK_MSG(FD_ISSET(s, &rfds), "select returns but s not in set"); 118 salen = sizeof(struct sockaddr_can); 119 if (( *len = rump_sys_recvfrom(s, cf, sizeof(struct can_frame), 120 0, (struct sockaddr *)sa, &salen)) < 0) { 121 atf_tc_fail_errno("recvfrom"); 122 } 123 ATF_CHECK_MSG(rv > 0, "short read on socket"); 124 ATF_CHECK_MSG(sa->can_family == AF_CAN, 125 "recvfrom provided wrong %d family", sa->can_family); 126 ATF_CHECK_MSG(salen == sizeof(struct sockaddr_can), 127 "recvfrom provided wrong size %d (!= %zu)", salen, sizeof(sa)); 128 return 0; 129 } 130 131 int 132 can_read(int s, struct can_frame *cf, int *len) 133 { 134 fd_set rfds; 135 struct timeval tmout; 136 int rv; 137 138 memset(cf, 0, sizeof(struct can_frame)); 139 FD_ZERO(&rfds); 140 FD_SET(s, &rfds); 141 /* wait 1 second for the message (in some tests we expect no message) */ 142 tmout.tv_sec = 1; 143 tmout.tv_usec = 0; 144 rv = rump_sys_select(s + 1, &rfds, NULL, NULL, &tmout); 145 switch(rv) { 146 case -1: 147 atf_tc_fail_errno("select"); 148 /* NOTREACHED */ 149 case 0: 150 /* timeout */ 151 errno = EWOULDBLOCK; 152 return -1; 153 default: break; 154 } 155 ATF_CHECK_MSG(FD_ISSET(s, &rfds), "select returns but s not in set"); 156 if (( *len = rump_sys_read(s, cf, sizeof(struct can_frame))) < 0) { 157 atf_tc_fail_errno("read"); 158 } 159 ATF_CHECK_MSG(rv > 0, "short read on socket"); 160 return 0; 161 } 162 163 int 164 can_bind(int s, const char *ifname) 165 { 166 struct ifreq ifr; 167 struct sockaddr_can sa; 168 169 strcpy(ifr.ifr_name, ifname ); 170 if (rump_sys_ioctl(s, SIOCGIFINDEX, &ifr) < 0) { 171 atf_tc_fail_errno("SIOCGIFINDEX"); 172 } 173 ATF_CHECK_MSG(ifr.ifr_ifindex > 0, "%s index is %d (not > 0)", 174 ifname, ifr.ifr_ifindex); 175 176 sa.can_family = AF_CAN; 177 sa.can_ifindex = ifr.ifr_ifindex; 178 179 if (rump_sys_bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 180 atf_tc_fail_errno("bind"); 181 } 182 return ifr.ifr_ifindex; 183 } 184 185 int 186 can_socket_with_own(void) 187 { 188 int s; 189 int v; 190 191 if ((s = rump_sys_socket(AF_CAN, SOCK_RAW, CAN_RAW)) < 0) { 192 atf_tc_fail_errno("CAN socket"); 193 } 194 v = 1; 195 if (rump_sys_setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, 196 &v, sizeof(v)) < 0) { 197 atf_tc_fail_errno("setsockopt(CAN_RAW_RECV_OWN_MSGS)"); 198 } 199 return s; 200 } 201