h_canutils.c revision 1.3 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