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