fprintf(stderr, " -s <level> (silent mode - %d: off (default) %d: animation %d: silent)\n", SILENT_OFF, SILENT_ANI, SILENT_ON);
fprintf(stderr, " -b <can> (bridge mode - send received frames to <can>)\n");
fprintf(stderr, " -B <can> (bridge mode - like '-b' with disabled loopback)\n");
+ fprintf(stderr, " -u <usecs> (delay bridge forwarding by <usecs> microseconds)\n");
fprintf(stderr, " -l (log CAN-frames into file. Sets '-s %d' by default)\n", SILENT_ON);
fprintf(stderr, " -L (use log file format on stdout)\n");
fprintf(stderr, " -n <count> (terminate after receiption of <count> CAN frames)\n");
fd_set rdfs;
int s[MAXSOCK];
int bridge = 0;
+ useconds_t bridge_delay = 0;
unsigned char timestamp = 0;
unsigned char dropmonitor = 0;
unsigned char silent = SILENT_INI;
last_tv.tv_sec = 0;
last_tv.tv_usec = 0;
- while ((opt = getopt(argc, argv, "t:ciaSs:b:B:ldLn:r:h?")) != -1) {
+ while ((opt = getopt(argc, argv, "t:ciaSs:b:B:u:ldLn:r:h?")) != -1) {
switch (opt) {
case 't':
timestamp = optarg[0];
}
break;
+ case 'u':
+ bridge_delay = (useconds_t)strtoul(optarg, (char **)NULL, 10);
+ break;
+
case 'l':
log = 1;
break;
if (silent == SILENT_INI) {
if (log) {
- fprintf(stderr, "\nDisabled standard output while logging.");
+ fprintf(stderr, "Disabled standard output while logging.\n");
silent = SILENT_ON; /* disable output on stdout */
} else
silent = SILENT_OFF; /* default output */
ptr = nptr+1; /* hop behind the ',' */
nptr = strchr(ptr, ','); /* update exit condition */
- if (sscanf(ptr, "%lx:%lx",
- (long unsigned int *)
+ if (sscanf(ptr, "%x:%x",
&rfilter[numfilter].can_id,
- (long unsigned int *)
&rfilter[numfilter].can_mask) == 2) {
rfilter[numfilter].can_mask &= ~CAN_ERR_FLAG;
numfilter++;
- } else if (sscanf(ptr, "%lx~%lx",
- (long unsigned int *)
+ } else if (sscanf(ptr, "%x~%x",
&rfilter[numfilter].can_id,
- (long unsigned int *)
&rfilter[numfilter].can_mask) == 2) {
rfilter[numfilter].can_id |= CAN_INV_FILTER;
rfilter[numfilter].can_mask &= ~CAN_ERR_FLAG;
numfilter++;
- } else if (sscanf(ptr, "#%lx",
- (long unsigned int *)&err_mask) != 1) {
+ } else if (sscanf(ptr, "#%x", &err_mask) != 1) {
fprintf(stderr, "Error in filter option parsing: '%s'\n", ptr);
return 1;
}
int curr_rcvbuf_size;
socklen_t curr_rcvbuf_size_len = sizeof(curr_rcvbuf_size);
- if (setsockopt(s[i], SOL_SOCKET, SO_RCVBUF,
+ /* try SO_RCVBUFFORCE first, if we run with CAP_NET_ADMIN */
+ if (setsockopt(s[i], SOL_SOCKET, SO_RCVBUFFORCE,
&rcvbuf_size, sizeof(rcvbuf_size)) < 0) {
- perror("setsockopt SO_RCVBUF");
- return 1;
- }
+#ifdef DEBUG
+ printf("SO_RCVBUFFORCE failed so try SO_RCVBUF ...\n");
+#endif
+ if (setsockopt(s[i], SOL_SOCKET, SO_RCVBUF,
+ &rcvbuf_size, sizeof(rcvbuf_size)) < 0) {
+ perror("setsockopt SO_RCVBUF");
+ return 1;
+ }
- if (getsockopt(s[i], SOL_SOCKET, SO_RCVBUF,
- &curr_rcvbuf_size, &curr_rcvbuf_size_len) < 0) {
- perror("getsockopt SO_RCVBUF");
- return 1;
- }
+ if (getsockopt(s[i], SOL_SOCKET, SO_RCVBUF,
+ &curr_rcvbuf_size, &curr_rcvbuf_size_len) < 0) {
+ perror("getsockopt SO_RCVBUF");
+ return 1;
+ }
- /* Only print a warning the first time we detect the adjustment */
- /* n.b.: The wanted size is doubled in Linux in net/sore/sock.c */
- if (!i && curr_rcvbuf_size < rcvbuf_size*2)
- fprintf(stderr, "The socket receive buffer size was "
- "adjusted due to /proc/sys/net/core/rmem_max.\n");
+ /* Only print a warning the first time we detect the adjustment */
+ /* n.b.: The wanted size is doubled in Linux in net/sore/sock.c */
+ if (!i && curr_rcvbuf_size < rcvbuf_size*2)
+ fprintf(stderr, "The socket receive buffer size was "
+ "adjusted due to /proc/sys/net/core/rmem_max.\n");
+ }
}
if (timestamp || log || logfrmt) {
running = 0;
if (bridge) {
+ if (bridge_delay)
+ usleep(bridge_delay);
+
nbytes = write(bridge, &frame, sizeof(struct can_frame));
if (nbytes < 0) {
perror("bridge write");
diff.tv_sec--, diff.tv_usec += 1000000;
if (diff.tv_sec < 0)
diff.tv_sec = diff.tv_usec = 0;
- printf("(%ld.%06ld) ", diff.tv_sec, diff.tv_usec);
+ printf("(%03ld.%06ld) ", diff.tv_sec, diff.tv_usec);
if (timestamp == 'd')
last_tv = tv; /* update for delta calculation */