Home | History | Annotate | Download | only in filter-tests
      1 /*
      2  * tst-rcv-own-msgs.c
      3  *
      4  * Copyright (c) 2010 Volkswagen Group Electronic Research
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of Volkswagen nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * Alternatively, provided that this notice is retained in full, this
     20  * software may be distributed under the terms of the GNU General
     21  * Public License ("GPL") version 2, in which case the provisions of the
     22  * GPL apply INSTEAD OF those given above.
     23  *
     24  * The provided data structures and external interfaces from this code
     25  * are not restricted to be used by modules with a GPL compatible license.
     26  *
     27  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     28  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     29  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     30  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     31  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     32  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     33  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     34  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     35  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     36  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     37  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
     38  * DAMAGE.
     39  *
     40  * Send feedback to <socketcan-users (at) lists.berlios.de>
     41  *
     42  */
     43 
     44 #include <stdio.h>
     45 #include <stdlib.h>
     46 #include <unistd.h>
     47 #include <string.h>
     48 
     49 #include <sys/types.h>
     50 #include <sys/socket.h>
     51 #include <sys/ioctl.h>
     52 #include <sys/time.h>
     53 #include <net/if.h>
     54 #include "config.h"
     55 #include "tst_res_flags.h"
     56 #include "tst_minmax.h"
     57 
     58 #ifdef HAVE_LINUX_CAN_H
     59 
     60 #include <linux/can.h>
     61 #include <linux/can/raw.h>
     62 
     63 struct rxs {
     64 	int s;
     65 	int t;
     66 };
     67 
     68 struct rxs test_sockets(int s, int t, canid_t can_id)
     69 {
     70 	fd_set rdfs;
     71 	struct timeval tv;
     72 	int m = MAX(s, t) + 1;
     73 	int have_rx = 1;
     74 	struct can_frame frame;
     75 	struct rxs rx;
     76 	int ret;
     77 
     78 	frame.can_id = can_id;
     79 	frame.can_dlc = 0;
     80 	if (write(s, &frame, sizeof(frame)) < 0) {
     81 		perror("write");
     82 		exit(1);
     83 	}
     84 
     85 	rx.s = rx.t = 0;
     86 
     87 	while (have_rx) {
     88 
     89 		FD_ZERO(&rdfs);
     90 		FD_SET(s, &rdfs);
     91 		FD_SET(t, &rdfs);
     92 		tv.tv_sec = 0;
     93 		tv.tv_usec = 50000;	/* 50ms timeout */
     94 		have_rx = 0;
     95 
     96 		ret = select(m, &rdfs, NULL, NULL, &tv);
     97 		if (ret < 0) {
     98 			perror("select");
     99 			exit(1);
    100 		}
    101 
    102 		if (FD_ISSET(s, &rdfs)) {
    103 
    104 			have_rx = 1;
    105 			ret = read(s, &frame, sizeof(struct can_frame));
    106 			if (ret < 0) {
    107 				perror("read");
    108 				exit(1);
    109 			}
    110 			if (frame.can_id != can_id) {
    111 				fprintf(stderr, "received wrong can_id!\n");
    112 				exit(1);
    113 			}
    114 			rx.s++;
    115 		}
    116 
    117 		if (FD_ISSET(t, &rdfs)) {
    118 
    119 			have_rx = 1;
    120 			ret = read(t, &frame, sizeof(struct can_frame));
    121 			if (ret < 0) {
    122 				perror("read");
    123 				exit(1);
    124 			}
    125 			if (frame.can_id != can_id) {
    126 				fprintf(stderr, "received wrong can_id!\n");
    127 				exit(1);
    128 			}
    129 			rx.t++;
    130 		}
    131 	}
    132 
    133 	/* timeout */
    134 
    135 	return rx;
    136 }
    137 
    138 void setopts(int s, int loopback, int recv_own_msgs)
    139 {
    140 	setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback,
    141 		   sizeof(loopback));
    142 	setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs,
    143 		   sizeof(recv_own_msgs));
    144 
    145 	printf("check loopback %d recv_own_msgs %d ... ", loopback,
    146 	       recv_own_msgs);
    147 }
    148 
    149 int main(int argc, char **argv)
    150 {
    151 	int s, t;
    152 	struct sockaddr_can addr;
    153 	struct ifreq ifr;
    154 	struct rxs rx;
    155 
    156 	/* check command line options */
    157 	if (argc != 2) {
    158 		fprintf(stderr, "Usage: %s <device>\n", argv[0]);
    159 		return TFAIL;
    160 	}
    161 
    162 	s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    163 	if (s < 0) {
    164 		perror("socket");
    165 		return TFAIL;
    166 	}
    167 	t = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    168 	if (t < 0) {
    169 		perror("socket");
    170 		return TFAIL;
    171 	}
    172 
    173 	strcpy(ifr.ifr_name, argv[1]);
    174 	if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
    175 		perror("SIOCGIFINDEX");
    176 		return TFAIL;
    177 	}
    178 	addr.can_ifindex = ifr.ifr_ifindex;
    179 	addr.can_family = AF_CAN;
    180 
    181 	if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
    182 		perror("bind");
    183 		return TFAIL;
    184 	}
    185 	if (bind(t, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
    186 		perror("bind");
    187 		return TFAIL;
    188 	}
    189 
    190 	printf("Starting PF_CAN frame flow test.\n");
    191 	printf("checking socket default settings ... ");
    192 	rx = test_sockets(s, t, 0x340);
    193 	if (rx.s == 0 && rx.t == 1)
    194 		printf("ok.\n");
    195 	else {
    196 		printf("failure!\n");
    197 		return TFAIL;
    198 	}
    199 
    200 	/* check loopback 0 recv_own_msgs 0 */
    201 	setopts(s, 0, 0);
    202 	rx = test_sockets(s, t, 0x341);
    203 	if (rx.s == 0 && rx.t == 0)
    204 		printf("ok.\n");
    205 	else {
    206 		printf("failure!\n");
    207 		return TFAIL;
    208 	}
    209 
    210 	/* check loopback 0 recv_own_msgs 1 */
    211 	setopts(s, 0, 1);
    212 	rx = test_sockets(s, t, 0x342);
    213 	if (rx.s == 0 && rx.t == 0)
    214 		printf("ok.\n");
    215 	else {
    216 		printf("failure!\n");
    217 		return TFAIL;
    218 	}
    219 
    220 	/* check loopback 1 recv_own_msgs 0 */
    221 	setopts(s, 1, 0);
    222 	rx = test_sockets(s, t, 0x343);
    223 	if (rx.s == 0 && rx.t == 1)
    224 		printf("ok.\n");
    225 	else {
    226 		printf("failure!\n");
    227 		return TFAIL;
    228 	}
    229 
    230 	/* check loopback 1 recv_own_msgs 1 */
    231 	setopts(s, 1, 1);
    232 	rx = test_sockets(s, t, 0x344);
    233 	if (rx.s == 1 && rx.t == 1)
    234 		printf("ok.\n");
    235 	else {
    236 		printf("failure!\n");
    237 		return TFAIL;
    238 	}
    239 
    240 	printf("PF_CAN frame flow test was successful.\n");
    241 
    242 	close(s);
    243 	close(t);
    244 
    245 	return TPASS;
    246 }
    247 
    248 #else
    249 
    250 int main(void)
    251 {
    252 	printf("The linux/can.h was missing upon compilation.\n");
    253 	return TCONF;
    254 }
    255 
    256 #endif /* HAVE_LINUX_CAN_H */
    257