Whitespace fixes. Indented the code following Linux styleguide to fix
the mess between tabs and spaces.pull/7/head
parent
8a5c0365e6
commit
adbe6f9bee
424
asc2log.c
424
asc2log.c
|
|
@ -65,272 +65,272 @@ extern int optind, opterr, optopt;
|
|||
|
||||
void print_usage(char *prg)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s\n", prg);
|
||||
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
|
||||
fprintf(stderr, " -O <outfile> (default stdout)\n");
|
||||
fprintf(stderr, "Usage: %s\n", prg);
|
||||
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
|
||||
fprintf(stderr, " -O <outfile> (default stdout)\n");
|
||||
}
|
||||
|
||||
void prframe(FILE *file, struct timeval *tv, int dev, struct can_frame *cf) {
|
||||
|
||||
fprintf(file, "(%ld.%06ld) ", tv->tv_sec, tv->tv_usec);
|
||||
if (dev > 0)
|
||||
fprintf(file, "can%d ", dev-1);
|
||||
else
|
||||
fprintf(file, "canX ");
|
||||
fprint_canframe(file, cf, "\n", 0);
|
||||
fprintf(file, "(%ld.%06ld) ", tv->tv_sec, tv->tv_usec);
|
||||
if (dev > 0)
|
||||
fprintf(file, "can%d ", dev-1);
|
||||
else
|
||||
fprintf(file, "canX ");
|
||||
fprint_canframe(file, cf, "\n", 0);
|
||||
}
|
||||
|
||||
void get_can_id(struct can_frame *cf, char *idstring, int base) {
|
||||
|
||||
if (idstring[strlen(idstring)-1] == 'x') {
|
||||
cf->can_id = CAN_EFF_FLAG;
|
||||
idstring[strlen(idstring)-1] = 0;
|
||||
} else
|
||||
cf->can_id = 0;
|
||||
if (idstring[strlen(idstring)-1] == 'x') {
|
||||
cf->can_id = CAN_EFF_FLAG;
|
||||
idstring[strlen(idstring)-1] = 0;
|
||||
} else
|
||||
cf->can_id = 0;
|
||||
|
||||
cf->can_id |= strtoul(idstring, NULL, base);
|
||||
cf->can_id |= strtoul(idstring, NULL, base);
|
||||
}
|
||||
|
||||
void calc_tv(struct timeval *tv, struct timeval *read_tv,
|
||||
struct timeval *date_tv, char timestamps, int dplace) {
|
||||
|
||||
if (dplace == 4) /* shift values having only 4 decimal places */
|
||||
read_tv->tv_usec *= 100; /* and need for 6 */
|
||||
if (dplace == 4) /* shift values having only 4 decimal places */
|
||||
read_tv->tv_usec *= 100; /* and need for 6 */
|
||||
|
||||
if (timestamps == 'a') { /* absolute */
|
||||
if (timestamps == 'a') { /* absolute */
|
||||
|
||||
tv->tv_sec = date_tv->tv_sec + read_tv->tv_sec;
|
||||
tv->tv_usec = date_tv->tv_usec + read_tv->tv_usec;
|
||||
tv->tv_sec = date_tv->tv_sec + read_tv->tv_sec;
|
||||
tv->tv_usec = date_tv->tv_usec + read_tv->tv_usec;
|
||||
|
||||
} else { /* relative */
|
||||
} else { /* relative */
|
||||
|
||||
if (((!tv->tv_sec) && (!tv->tv_usec)) &&
|
||||
(date_tv->tv_sec || date_tv->tv_usec)) {
|
||||
tv->tv_sec = date_tv->tv_sec; /* initial date/time */
|
||||
tv->tv_usec = date_tv->tv_usec;
|
||||
if (((!tv->tv_sec) && (!tv->tv_usec)) &&
|
||||
(date_tv->tv_sec || date_tv->tv_usec)) {
|
||||
tv->tv_sec = date_tv->tv_sec; /* initial date/time */
|
||||
tv->tv_usec = date_tv->tv_usec;
|
||||
}
|
||||
|
||||
tv->tv_sec += read_tv->tv_sec;
|
||||
tv->tv_usec += read_tv->tv_usec;
|
||||
}
|
||||
|
||||
tv->tv_sec += read_tv->tv_sec;
|
||||
tv->tv_usec += read_tv->tv_usec;
|
||||
}
|
||||
|
||||
if (tv->tv_usec > 1000000) {
|
||||
tv->tv_usec -= 1000000;
|
||||
tv->tv_sec++;
|
||||
}
|
||||
if (tv->tv_usec > 1000000) {
|
||||
tv->tv_usec -= 1000000;
|
||||
tv->tv_sec++;
|
||||
}
|
||||
}
|
||||
|
||||
int get_date(struct timeval *tv, char *date) {
|
||||
|
||||
char ctmp[10];
|
||||
int itmp;
|
||||
char ctmp[10];
|
||||
int itmp;
|
||||
|
||||
struct tm tms;
|
||||
struct tm tms;
|
||||
|
||||
if (sscanf(date, "%9s %d %9s %9s %d", ctmp, &itmp, ctmp, ctmp, &itmp) == 5) {
|
||||
/* assume EN/US date due to existing am/pm field */
|
||||
if (sscanf(date, "%9s %d %9s %9s %d", ctmp, &itmp, ctmp, ctmp, &itmp) == 5) {
|
||||
/* assume EN/US date due to existing am/pm field */
|
||||
|
||||
if (!setlocale(LC_TIME, "en_US"))
|
||||
return 1;
|
||||
if (!setlocale(LC_TIME, "en_US"))
|
||||
return 1;
|
||||
|
||||
if (!strptime(date, "%B %d %r %Y", &tms))
|
||||
return 1;
|
||||
if (!strptime(date, "%B %d %r %Y", &tms))
|
||||
return 1;
|
||||
|
||||
} else {
|
||||
/* assume DE date due to non existing am/pm field */
|
||||
} else {
|
||||
/* assume DE date due to non existing am/pm field */
|
||||
|
||||
if (sscanf(date, "%9s %d %9s %d", ctmp, &itmp, ctmp, &itmp) != 4)
|
||||
return 1;
|
||||
if (sscanf(date, "%9s %d %9s %d", ctmp, &itmp, ctmp, &itmp) != 4)
|
||||
return 1;
|
||||
|
||||
if (!setlocale(LC_TIME, "de_DE"))
|
||||
return 1;
|
||||
if (!setlocale(LC_TIME, "de_DE"))
|
||||
return 1;
|
||||
|
||||
if (!strptime(date, "%B %d %T %Y", &tms))
|
||||
return 1;
|
||||
}
|
||||
if (!strptime(date, "%B %d %T %Y", &tms))
|
||||
return 1;
|
||||
}
|
||||
|
||||
//printf("h %d m %d s %d d %d m %d y %d\n",
|
||||
//tms.tm_hour, tms.tm_min, tms.tm_sec,
|
||||
//tms.tm_mday, tms.tm_mon+1, tms.tm_year+1900);
|
||||
//printf("h %d m %d s %d d %d m %d y %d\n",
|
||||
//tms.tm_hour, tms.tm_min, tms.tm_sec,
|
||||
//tms.tm_mday, tms.tm_mon+1, tms.tm_year+1900);
|
||||
|
||||
tv->tv_sec = mktime(&tms);
|
||||
tv->tv_sec = mktime(&tms);
|
||||
|
||||
if (tv->tv_sec < 0)
|
||||
return 1;
|
||||
if (tv->tv_sec < 0)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char buf[100], tmp1[100], tmp2[100];
|
||||
char buf[100], tmp1[100], tmp2[100];
|
||||
|
||||
FILE *infile = stdin;
|
||||
FILE *outfile = stdout;
|
||||
static int verbose;
|
||||
struct can_frame cf;
|
||||
static struct timeval tv; /* current frame timestamp */
|
||||
static struct timeval read_tv; /* frame timestamp from ASC file */
|
||||
static struct timeval date_tv; /* date of the ASC file */
|
||||
static int dplace; /* decimal place 4 or 6 or uninitialized */
|
||||
static char base; /* 'd'ec or 'h'ex */
|
||||
static char timestamps; /* 'a'bsolute or 'r'elative */
|
||||
FILE *infile = stdin;
|
||||
FILE *outfile = stdout;
|
||||
static int verbose;
|
||||
struct can_frame cf;
|
||||
static struct timeval tv; /* current frame timestamp */
|
||||
static struct timeval read_tv; /* frame timestamp from ASC file */
|
||||
static struct timeval date_tv; /* date of the ASC file */
|
||||
static int dplace; /* decimal place 4 or 6 or uninitialized */
|
||||
static char base; /* 'd'ec or 'h'ex */
|
||||
static char timestamps; /* 'a'bsolute or 'r'elative */
|
||||
|
||||
int interface;
|
||||
char rtr;
|
||||
int dlc = 0;
|
||||
int data[8];
|
||||
int i, found, opt;
|
||||
int interface;
|
||||
char rtr;
|
||||
int dlc = 0;
|
||||
int data[8];
|
||||
int i, found, opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "I:O:v")) != -1) {
|
||||
switch (opt) {
|
||||
case 'I':
|
||||
infile = fopen(optarg, "r");
|
||||
if (!infile) {
|
||||
perror("infile");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
while ((opt = getopt(argc, argv, "I:O:v")) != -1) {
|
||||
switch (opt) {
|
||||
case 'I':
|
||||
infile = fopen(optarg, "r");
|
||||
if (!infile) {
|
||||
perror("infile");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
outfile = fopen(optarg, "w");
|
||||
if (!outfile) {
|
||||
perror("outfile");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
outfile = fopen(optarg, "w");
|
||||
if (!outfile) {
|
||||
perror("outfile");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unknown option %c\n", opt);
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
while (fgets(buf, 99, infile)) {
|
||||
|
||||
if (!dplace) { /* the representation of a valid CAN frame not known */
|
||||
|
||||
/* check for base and timestamp entries in the header */
|
||||
if ((!base) &&
|
||||
(sscanf(buf, "base %s timestamps %s", tmp1, tmp2) == 2)) {
|
||||
base = tmp1[0];
|
||||
timestamps = tmp2[0];
|
||||
if (verbose)
|
||||
printf("base %c timestamps %c\n", base, timestamps);
|
||||
if ((base != 'h') && (base != 'd')) {
|
||||
printf("invalid base %s (must be 'hex' or 'dez')!\n",
|
||||
tmp1);
|
||||
return 1;
|
||||
default:
|
||||
fprintf(stderr, "Unknown option %c\n", opt);
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
if ((timestamps != 'a') && (timestamps != 'r')) {
|
||||
printf("invalid timestamps %s (must be 'absolute'"
|
||||
" or 'relative')!\n", tmp2);
|
||||
return 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check for the original logging date in the header */
|
||||
if ((!date_tv.tv_sec) &&
|
||||
(!strncmp(buf, "date", 4))) {
|
||||
|
||||
if (get_date(&date_tv, &buf[9])) { /* skip 'date day ' */
|
||||
fprintf(stderr, "Not able to determine original log "
|
||||
"file date. Using current time.\n");
|
||||
/* use current date as default */
|
||||
gettimeofday(&date_tv, NULL);
|
||||
}
|
||||
if (verbose)
|
||||
printf("date %ld => %s", date_tv.tv_sec, ctime(&date_tv.tv_sec));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check for decimal places length in valid CAN frames */
|
||||
if (sscanf(buf, "%ld.%s %d ", &tv.tv_sec, tmp2, &i) == 3){
|
||||
dplace = strlen(tmp2);
|
||||
if (verbose)
|
||||
printf("decimal place %d, e.g. '%s'\n", dplace, tmp2);
|
||||
if ((dplace != 4) && (dplace != 6)) {
|
||||
printf("invalid dplace %d (must be 4 or 6)!\n", dplace);
|
||||
return 1;
|
||||
}
|
||||
} else
|
||||
continue; /* dplace remains zero until first found CAN frame */
|
||||
}
|
||||
|
||||
/* the representation of a valid CAN frame is known here */
|
||||
/* so try to get CAN frames and ErrorFrames and convert them */
|
||||
|
||||
/* 0.002367 1 390x Rx d 8 17 00 14 00 C0 00 08 00 */
|
||||
|
||||
found = 0; /* found valid CAN frame ? */
|
||||
|
||||
if (base == 'h') { /* check for CAN frames with hexadecimal values */
|
||||
|
||||
if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %x %x %x %x %x %x %x %x",
|
||||
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
|
||||
tmp1, &rtr, &dlc,
|
||||
&data[0], &data[1], &data[2], &data[3],
|
||||
&data[4], &data[5], &data[6], &data[7]
|
||||
) == dlc + 6 ) {
|
||||
|
||||
found = 1;
|
||||
get_can_id(&cf, tmp1, 16);
|
||||
}
|
||||
|
||||
} else { /* check for CAN frames with decimal values */
|
||||
|
||||
if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %d %d %d %d %d %d %d %d",
|
||||
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
|
||||
tmp1, &rtr, &dlc,
|
||||
&data[0], &data[1], &data[2], &data[3],
|
||||
&data[4], &data[5], &data[6], &data[7]
|
||||
) == dlc + 6 ) {
|
||||
|
||||
found = 1;
|
||||
get_can_id(&cf, tmp1, 10);
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
if (rtr == 'r')
|
||||
cf.can_id |= CAN_RTR_FLAG;
|
||||
|
||||
while (fgets(buf, 99, infile)) {
|
||||
|
||||
if (!dplace) { /* the representation of a valid CAN frame not known */
|
||||
|
||||
/* check for base and timestamp entries in the header */
|
||||
if ((!base) &&
|
||||
(sscanf(buf, "base %s timestamps %s", tmp1, tmp2) == 2)) {
|
||||
base = tmp1[0];
|
||||
timestamps = tmp2[0];
|
||||
if (verbose)
|
||||
printf("base %c timestamps %c\n", base, timestamps);
|
||||
if ((base != 'h') && (base != 'd')) {
|
||||
printf("invalid base %s (must be 'hex' or 'dez')!\n",
|
||||
tmp1);
|
||||
return 1;
|
||||
}
|
||||
if ((timestamps != 'a') && (timestamps != 'r')) {
|
||||
printf("invalid timestamps %s (must be 'absolute'"
|
||||
" or 'relative')!\n", tmp2);
|
||||
return 1;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check for the original logging date in the header */
|
||||
if ((!date_tv.tv_sec) &&
|
||||
(!strncmp(buf, "date", 4))) {
|
||||
|
||||
if (get_date(&date_tv, &buf[9])) { /* skip 'date day ' */
|
||||
fprintf(stderr, "Not able to determine original log "
|
||||
"file date. Using current time.\n");
|
||||
/* use current date as default */
|
||||
gettimeofday(&date_tv, NULL);
|
||||
}
|
||||
if (verbose)
|
||||
printf("date %ld => %s", date_tv.tv_sec, ctime(&date_tv.tv_sec));
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check for decimal places length in valid CAN frames */
|
||||
if (sscanf(buf, "%ld.%s %d ", &tv.tv_sec, tmp2, &i) == 3){
|
||||
dplace = strlen(tmp2);
|
||||
if (verbose)
|
||||
printf("decimal place %d, e.g. '%s'\n", dplace, tmp2);
|
||||
if ((dplace != 4) && (dplace != 6)) {
|
||||
printf("invalid dplace %d (must be 4 or 6)!\n", dplace);
|
||||
return 1;
|
||||
}
|
||||
} else
|
||||
continue; /* dplace remains zero until first found CAN frame */
|
||||
}
|
||||
|
||||
/* the representation of a valid CAN frame is known here */
|
||||
/* so try to get CAN frames and ErrorFrames and convert them */
|
||||
|
||||
/* 0.002367 1 390x Rx d 8 17 00 14 00 C0 00 08 00 */
|
||||
|
||||
found = 0; /* found valid CAN frame ? */
|
||||
|
||||
if (base == 'h') { /* check for CAN frames with hexadecimal values */
|
||||
|
||||
if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %x %x %x %x %x %x %x %x",
|
||||
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
|
||||
tmp1, &rtr, &dlc,
|
||||
&data[0], &data[1], &data[2], &data[3],
|
||||
&data[4], &data[5], &data[6], &data[7]
|
||||
) == dlc + 6 ) {
|
||||
|
||||
found = 1;
|
||||
get_can_id(&cf, tmp1, 16);
|
||||
}
|
||||
|
||||
} else { /* check for CAN frames with decimal values */
|
||||
|
||||
if (sscanf(buf, "%ld.%ld %d %s %*s %c %d %d %d %d %d %d %d %d %d",
|
||||
&read_tv.tv_sec, &read_tv.tv_usec, &interface,
|
||||
tmp1, &rtr, &dlc,
|
||||
&data[0], &data[1], &data[2], &data[3],
|
||||
&data[4], &data[5], &data[6], &data[7]
|
||||
) == dlc + 6 ) {
|
||||
|
||||
found = 1;
|
||||
get_can_id(&cf, tmp1, 10);
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
if (rtr == 'r')
|
||||
cf.can_id |= CAN_RTR_FLAG;
|
||||
|
||||
cf.can_dlc = dlc & 0x0FU;
|
||||
for (i=0; i<dlc; i++)
|
||||
cf.data[i] = data[i] & 0xFFU;
|
||||
cf.can_dlc = dlc & 0x0FU;
|
||||
for (i=0; i<dlc; i++)
|
||||
cf.data[i] = data[i] & 0xFFU;
|
||||
|
||||
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
|
||||
prframe(outfile, &tv, interface, &cf);
|
||||
fflush(outfile);
|
||||
continue;
|
||||
}
|
||||
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
|
||||
prframe(outfile, &tv, interface, &cf);
|
||||
fflush(outfile);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* check for ErrorFrames */
|
||||
if (sscanf(buf, "%ld.%ld %d %s",
|
||||
&read_tv.tv_sec, &read_tv.tv_usec,
|
||||
&interface, tmp1) == 4) {
|
||||
/* check for ErrorFrames */
|
||||
if (sscanf(buf, "%ld.%ld %d %s",
|
||||
&read_tv.tv_sec, &read_tv.tv_usec,
|
||||
&interface, tmp1) == 4) {
|
||||
|
||||
if (!strncmp(tmp1, "ErrorFrame", strlen("ErrorFrame"))) {
|
||||
if (!strncmp(tmp1, "ErrorFrame", strlen("ErrorFrame"))) {
|
||||
|
||||
memset(&cf, 0, sizeof(cf));
|
||||
/* do not know more than 'Error' */
|
||||
cf.can_id = (CAN_ERR_FLAG | CAN_ERR_BUSERROR);
|
||||
cf.can_dlc = CAN_ERR_DLC;
|
||||
memset(&cf, 0, sizeof(cf));
|
||||
/* do not know more than 'Error' */
|
||||
cf.can_id = (CAN_ERR_FLAG | CAN_ERR_BUSERROR);
|
||||
cf.can_dlc = CAN_ERR_DLC;
|
||||
|
||||
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
|
||||
prframe(outfile, &tv, interface, &cf);
|
||||
fflush(outfile);
|
||||
}
|
||||
calc_tv(&tv, &read_tv, &date_tv, timestamps, dplace);
|
||||
prframe(outfile, &tv, interface, &cf);
|
||||
fflush(outfile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(outfile);
|
||||
return 0;
|
||||
fclose(outfile);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
452
canbusload.c
452
canbusload.c
|
|
@ -74,11 +74,11 @@
|
|||
extern int optind, opterr, optopt;
|
||||
|
||||
static struct {
|
||||
char devname[IFNAMSIZ+1];
|
||||
unsigned int bitrate;
|
||||
unsigned int recv_frames;
|
||||
unsigned int recv_bits_total;
|
||||
unsigned int recv_bits_payload;
|
||||
char devname[IFNAMSIZ+1];
|
||||
unsigned int bitrate;
|
||||
unsigned int recv_frames;
|
||||
unsigned int recv_bits_total;
|
||||
unsigned int recv_bits_payload;
|
||||
} stat[MAXSOCK+1];
|
||||
|
||||
static int max_devname_len; /* to prevent frazzled device name output */
|
||||
|
|
@ -92,289 +92,289 @@ static char *prg;
|
|||
|
||||
void print_usage(char *prg)
|
||||
{
|
||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
||||
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
||||
fprintf(stderr, "Options: -t (show current time on the first line)\n");
|
||||
fprintf(stderr, " -c (colorize lines)\n");
|
||||
fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES);
|
||||
fprintf(stderr, " -r (redraw the terminal - similar to top)\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Up to %d CAN interfaces with mandatory bitrate can be specified on the \n", MAXSOCK);
|
||||
fprintf(stderr, "commandline in the form: <ifname>@<bitrate>\n\n");
|
||||
fprintf(stderr, "The bitrate is mandatory as it is needed to know the CAN bus bitrate to\n");
|
||||
fprintf(stderr, "calcultate the bus load percentage based on the received CAN frames.\n");
|
||||
fprintf(stderr, "For each given interface the data is presented in one line which contains:\n\n");
|
||||
fprintf(stderr, "(interface) (received CAN frames) (used bits total) (used bits for payload)\n");
|
||||
fprintf(stderr, "\nExample:\n");
|
||||
fprintf(stderr, "\nuser$> canbusload can0@100000 can1@500000 can2@500000 can3@500000 -r -t -b -c\n\n");
|
||||
fprintf(stderr, "%s 2008-05-27 15:18:49\n", prg);
|
||||
fprintf(stderr, " can0@100000 805 74491 36656 74%% |XXXXXXXXXXXXXX......|\n");
|
||||
fprintf(stderr, " can1@500000 796 75140 37728 15%% |XXX.................|\n");
|
||||
fprintf(stderr, " can2@500000 0 0 0 0%% |....................|\n");
|
||||
fprintf(stderr, " can3@500000 47 4633 2424 0%% |....................|\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
||||
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
||||
fprintf(stderr, "Options: -t (show current time on the first line)\n");
|
||||
fprintf(stderr, " -c (colorize lines)\n");
|
||||
fprintf(stderr, " -b (show bargraph in %d%% resolution)\n", PERCENTRES);
|
||||
fprintf(stderr, " -r (redraw the terminal - similar to top)\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Up to %d CAN interfaces with mandatory bitrate can be specified on the \n", MAXSOCK);
|
||||
fprintf(stderr, "commandline in the form: <ifname>@<bitrate>\n\n");
|
||||
fprintf(stderr, "The bitrate is mandatory as it is needed to know the CAN bus bitrate to\n");
|
||||
fprintf(stderr, "calcultate the bus load percentage based on the received CAN frames.\n");
|
||||
fprintf(stderr, "For each given interface the data is presented in one line which contains:\n\n");
|
||||
fprintf(stderr, "(interface) (received CAN frames) (used bits total) (used bits for payload)\n");
|
||||
fprintf(stderr, "\nExample:\n");
|
||||
fprintf(stderr, "\nuser$> canbusload can0@100000 can1@500000 can2@500000 can3@500000 -r -t -b -c\n\n");
|
||||
fprintf(stderr, "%s 2008-05-27 15:18:49\n", prg);
|
||||
fprintf(stderr, " can0@100000 805 74491 36656 74%% |XXXXXXXXXXXXXX......|\n");
|
||||
fprintf(stderr, " can1@500000 796 75140 37728 15%% |XXX.................|\n");
|
||||
fprintf(stderr, " can2@500000 0 0 0 0%% |....................|\n");
|
||||
fprintf(stderr, " can3@500000 47 4633 2424 0%% |....................|\n");
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void sigterm(int signo)
|
||||
{
|
||||
exit(0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void printstats(int signo)
|
||||
{
|
||||
int i, j, percent;
|
||||
int i, j, percent;
|
||||
|
||||
if (redraw)
|
||||
printf("%s", CSR_HOME);
|
||||
if (redraw)
|
||||
printf("%s", CSR_HOME);
|
||||
|
||||
if (timestamp) {
|
||||
time_t currtime;
|
||||
struct tm now;
|
||||
if (timestamp) {
|
||||
time_t currtime;
|
||||
struct tm now;
|
||||
|
||||
if (time(&currtime) == (time_t)-1) {
|
||||
perror("time");
|
||||
exit(1);
|
||||
if (time(&currtime) == (time_t)-1) {
|
||||
perror("time");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
localtime_r(&currtime, &now);
|
||||
|
||||
printf("%s %04d-%02d-%02d %02d:%02d:%02d\n",
|
||||
prg,
|
||||
now.tm_year + 1900,
|
||||
now.tm_mon + 1,
|
||||
now.tm_mday,
|
||||
now.tm_hour,
|
||||
now.tm_min,
|
||||
now.tm_sec);
|
||||
}
|
||||
|
||||
localtime_r(&currtime, &now);
|
||||
for (i=0; i<currmax; i++) {
|
||||
|
||||
printf("%s %04d-%02d-%02d %02d:%02d:%02d\n",
|
||||
prg,
|
||||
now.tm_year + 1900,
|
||||
now.tm_mon + 1,
|
||||
now.tm_mday,
|
||||
now.tm_hour,
|
||||
now.tm_min,
|
||||
now.tm_sec);
|
||||
}
|
||||
if (color)
|
||||
if (i%2)
|
||||
printf("%s", FGRED);
|
||||
else
|
||||
printf("%s", FGBLUE);
|
||||
|
||||
for (i=0; i<currmax; i++) {
|
||||
|
||||
if (color)
|
||||
if (i%2)
|
||||
printf("%s", FGRED);
|
||||
else
|
||||
printf("%s", FGBLUE);
|
||||
|
||||
if (stat[i].bitrate)
|
||||
percent = (stat[i].recv_bits_total*100)/stat[i].bitrate;
|
||||
else
|
||||
percent = 0;
|
||||
|
||||
printf(" %*s@%-*d %4d %6d %6d %3d%%",
|
||||
max_devname_len, stat[i].devname,
|
||||
max_bitrate_len, stat[i].bitrate,
|
||||
stat[i].recv_frames,
|
||||
stat[i].recv_bits_total,
|
||||
stat[i].recv_bits_payload,
|
||||
percent);
|
||||
|
||||
if (bargraph) {
|
||||
|
||||
printf(" |");
|
||||
|
||||
for (j=0; j < NUMBAR; j++){
|
||||
if (j < percent/PERCENTRES)
|
||||
printf("X");
|
||||
if (stat[i].bitrate)
|
||||
percent = (stat[i].recv_bits_total*100)/stat[i].bitrate;
|
||||
else
|
||||
printf(".");
|
||||
}
|
||||
percent = 0;
|
||||
|
||||
printf(" %*s@%-*d %4d %6d %6d %3d%%",
|
||||
max_devname_len, stat[i].devname,
|
||||
max_bitrate_len, stat[i].bitrate,
|
||||
stat[i].recv_frames,
|
||||
stat[i].recv_bits_total,
|
||||
stat[i].recv_bits_payload,
|
||||
percent);
|
||||
|
||||
if (bargraph) {
|
||||
|
||||
printf(" |");
|
||||
|
||||
for (j=0; j < NUMBAR; j++){
|
||||
if (j < percent/PERCENTRES)
|
||||
printf("X");
|
||||
else
|
||||
printf(".");
|
||||
}
|
||||
|
||||
printf("|");
|
||||
}
|
||||
printf("|");
|
||||
}
|
||||
|
||||
if (color)
|
||||
printf("%s", ATTRESET);
|
||||
if (color)
|
||||
printf("%s", ATTRESET);
|
||||
|
||||
printf("\n");
|
||||
|
||||
stat[i].recv_frames = 0;
|
||||
stat[i].recv_bits_total = 0;
|
||||
stat[i].recv_bits_payload = 0;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
stat[i].recv_frames = 0;
|
||||
stat[i].recv_bits_total = 0;
|
||||
stat[i].recv_bits_payload = 0;
|
||||
}
|
||||
|
||||
printf("\n");
|
||||
|
||||
alarm(1);
|
||||
alarm(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
fd_set rdfs;
|
||||
int s[MAXSOCK];
|
||||
fd_set rdfs;
|
||||
int s[MAXSOCK];
|
||||
|
||||
int opt;
|
||||
char *ptr, *nptr;
|
||||
struct sockaddr_can addr;
|
||||
struct can_frame frame;
|
||||
int nbytes, i;
|
||||
struct ifreq ifr;
|
||||
sigset_t sigmask, savesigmask;
|
||||
int opt;
|
||||
char *ptr, *nptr;
|
||||
struct sockaddr_can addr;
|
||||
struct can_frame frame;
|
||||
int nbytes, i;
|
||||
struct ifreq ifr;
|
||||
sigset_t sigmask, savesigmask;
|
||||
|
||||
signal(SIGTERM, sigterm);
|
||||
signal(SIGHUP, sigterm);
|
||||
signal(SIGINT, sigterm);
|
||||
signal(SIGTERM, sigterm);
|
||||
signal(SIGHUP, sigterm);
|
||||
signal(SIGINT, sigterm);
|
||||
|
||||
signal(SIGALRM, printstats);
|
||||
signal(SIGALRM, printstats);
|
||||
|
||||
prg = basename(argv[0]);
|
||||
prg = basename(argv[0]);
|
||||
|
||||
while ((opt = getopt(argc, argv, "rtbch?")) != -1) {
|
||||
switch (opt) {
|
||||
case 'r':
|
||||
redraw = 1;
|
||||
break;
|
||||
while ((opt = getopt(argc, argv, "rtbch?")) != -1) {
|
||||
switch (opt) {
|
||||
case 'r':
|
||||
redraw = 1;
|
||||
break;
|
||||
|
||||
case 't':
|
||||
timestamp = 1;
|
||||
break;
|
||||
case 't':
|
||||
timestamp = 1;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
bargraph = 1;
|
||||
break;
|
||||
case 'b':
|
||||
bargraph = 1;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
color = 1;
|
||||
break;
|
||||
case 'c':
|
||||
color = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
print_usage(prg);
|
||||
exit(1);
|
||||
break;
|
||||
default:
|
||||
print_usage(prg);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (optind == argc) {
|
||||
print_usage(prg);
|
||||
exit(0);
|
||||
}
|
||||
if (optind == argc) {
|
||||
print_usage(prg);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
currmax = argc - optind; /* find real number of CAN devices */
|
||||
currmax = argc - optind; /* find real number of CAN devices */
|
||||
|
||||
if (currmax > MAXSOCK) {
|
||||
printf("More than %d CAN devices given on commandline!\n", MAXSOCK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i=0; i < currmax; i++) {
|
||||
|
||||
ptr = argv[optind+i];
|
||||
|
||||
nbytes = strlen(ptr);
|
||||
if (nbytes >= IFNAMSIZ+sizeof("@1000000")+1) {
|
||||
printf("name of CAN device '%s' is too long!\n", ptr);
|
||||
return 1;
|
||||
if (currmax > MAXSOCK) {
|
||||
printf("More than %d CAN devices given on commandline!\n", MAXSOCK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i=0; i < currmax; i++) {
|
||||
|
||||
ptr = argv[optind+i];
|
||||
|
||||
nbytes = strlen(ptr);
|
||||
if (nbytes >= IFNAMSIZ+sizeof("@1000000")+1) {
|
||||
printf("name of CAN device '%s' is too long!\n", ptr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("open %d '%s'.\n", i, ptr);
|
||||
printf("open %d '%s'.\n", i, ptr);
|
||||
#endif
|
||||
|
||||
s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||
if (s[i] < 0) {
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||
if (s[i] < 0) {
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
nptr = strchr(ptr, '@');
|
||||
nptr = strchr(ptr, '@');
|
||||
|
||||
if (!nptr) {
|
||||
print_usage(prg);
|
||||
return 1;
|
||||
}
|
||||
if (!nptr) {
|
||||
print_usage(prg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
nbytes = nptr - ptr; /* interface name is up the first '@' */
|
||||
nbytes = nptr - ptr; /* interface name is up the first '@' */
|
||||
|
||||
if (nbytes >= IFNAMSIZ) {
|
||||
printf("name of CAN device '%s' is too long!\n", ptr);
|
||||
return 1;
|
||||
}
|
||||
if (nbytes >= IFNAMSIZ) {
|
||||
printf("name of CAN device '%s' is too long!\n", ptr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
strncpy(stat[i].devname, ptr, nbytes);
|
||||
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
|
||||
strncpy(ifr.ifr_name, ptr, nbytes);
|
||||
strncpy(stat[i].devname, ptr, nbytes);
|
||||
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
|
||||
strncpy(ifr.ifr_name, ptr, nbytes);
|
||||
|
||||
if (nbytes > max_devname_len)
|
||||
max_devname_len = nbytes; /* for nice printing */
|
||||
if (nbytes > max_devname_len)
|
||||
max_devname_len = nbytes; /* for nice printing */
|
||||
|
||||
stat[i].bitrate = atoi(nptr+1); /* bitrate is placed behind the '@' */
|
||||
stat[i].bitrate = atoi(nptr+1); /* bitrate is placed behind the '@' */
|
||||
|
||||
if (!stat[i].bitrate || stat[i].bitrate > 1000000) {
|
||||
printf("invalid bitrate for CAN device '%s'!\n", ptr);
|
||||
return 1;
|
||||
}
|
||||
if (!stat[i].bitrate || stat[i].bitrate > 1000000) {
|
||||
printf("invalid bitrate for CAN device '%s'!\n", ptr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
nbytes = strlen(nptr+1);
|
||||
if (nbytes > max_bitrate_len)
|
||||
max_bitrate_len = nbytes; /* for nice printing */
|
||||
nbytes = strlen(nptr+1);
|
||||
if (nbytes > max_bitrate_len)
|
||||
max_bitrate_len = nbytes; /* for nice printing */
|
||||
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("using interface name '%s'.\n", ifr.ifr_name);
|
||||
printf("using interface name '%s'.\n", ifr.ifr_name);
|
||||
#endif
|
||||
|
||||
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
|
||||
perror("SIOCGIFINDEX");
|
||||
exit(1);
|
||||
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
|
||||
perror("SIOCGIFINDEX");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
|
||||
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
alarm(1);
|
||||
|
||||
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
return 1;
|
||||
if (redraw)
|
||||
printf("%s", CLR_SCREEN);
|
||||
|
||||
while (1) {
|
||||
|
||||
FD_ZERO(&rdfs);
|
||||
for (i=0; i<currmax; i++)
|
||||
FD_SET(s[i], &rdfs);
|
||||
|
||||
savesigmask = sigmask;
|
||||
|
||||
if (pselect(s[currmax-1]+1, &rdfs, NULL, NULL, NULL, &sigmask) < 0) {
|
||||
//perror("pselect");
|
||||
sigmask = savesigmask;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
|
||||
|
||||
if (FD_ISSET(s[i], &rdfs)) {
|
||||
|
||||
nbytes = read(s[i], &frame, sizeof(struct can_frame));
|
||||
|
||||
if (nbytes < 0) {
|
||||
perror("read");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nbytes < sizeof(struct can_frame)) {
|
||||
fprintf(stderr, "read: incomplete CAN frame\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
stat[i].recv_frames++;
|
||||
stat[i].recv_bits_payload += frame.can_dlc*8;
|
||||
stat[i].recv_bits_total += frame.can_dlc*8;
|
||||
if (frame.can_id & CAN_EFF_FLAG)
|
||||
stat[i].recv_bits_total += 67;
|
||||
else
|
||||
stat[i].recv_bits_total += 47;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
alarm(1);
|
||||
|
||||
if (redraw)
|
||||
printf("%s", CLR_SCREEN);
|
||||
|
||||
while (1) {
|
||||
|
||||
FD_ZERO(&rdfs);
|
||||
for (i=0; i<currmax; i++)
|
||||
FD_SET(s[i], &rdfs);
|
||||
close(s[i]);
|
||||
|
||||
savesigmask = sigmask;
|
||||
|
||||
if (pselect(s[currmax-1]+1, &rdfs, NULL, NULL, NULL, &sigmask) < 0) {
|
||||
//perror("pselect");
|
||||
sigmask = savesigmask;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
|
||||
|
||||
if (FD_ISSET(s[i], &rdfs)) {
|
||||
|
||||
nbytes = read(s[i], &frame, sizeof(struct can_frame));
|
||||
|
||||
if (nbytes < 0) {
|
||||
perror("read");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nbytes < sizeof(struct can_frame)) {
|
||||
fprintf(stderr, "read: incomplete CAN frame\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
stat[i].recv_frames++;
|
||||
stat[i].recv_bits_payload += frame.can_dlc*8;
|
||||
stat[i].recv_bits_total += frame.can_dlc*8;
|
||||
if (frame.can_id & CAN_EFF_FLAG)
|
||||
stat[i].recv_bits_total += 67;
|
||||
else
|
||||
stat[i].recv_bits_total += 47;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<currmax; i++)
|
||||
close(s[i]);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
762
candump.c
762
candump.c
|
|
@ -98,476 +98,476 @@ static volatile int running = 1;
|
|||
|
||||
void print_usage(char *prg)
|
||||
{
|
||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
||||
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
||||
fprintf(stderr, "Options: -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
|
||||
fprintf(stderr, " -c (increment color mode level)\n");
|
||||
fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n");
|
||||
fprintf(stderr, " -a (enable additional ASCII output)\n");
|
||||
fprintf(stderr, " -s <level> (silent mode - 1: animation 2: completely silent)\n");
|
||||
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, " -l (log CAN-frames into file)\n");
|
||||
fprintf(stderr, " -L (use log file format on stdout)\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Up to %d CAN interfaces with optional filter sets can be specified\n", MAXSOCK);
|
||||
fprintf(stderr, "on the commandline in the form: <ifname>[,filter]*\n");
|
||||
fprintf(stderr, "\nUp to %d comma separated filters can be specified for each given CAN interface:\n", MAXFILTER);
|
||||
fprintf(stderr, " <can_id>:<can_mask> (matches when <received_can_id> & mask == can_id & mask)\n");
|
||||
fprintf(stderr, " <can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)\n");
|
||||
fprintf(stderr, " #<error_mask> (set error frame filter, see include/linux/can/error.h)\n");
|
||||
fprintf(stderr, "\nUse interface name '%s' to receive from all CAN interfaces.\n", ANYDEV);
|
||||
fprintf(stderr, "CAN IDs, masks and data content are given and expected in hexadecimal values.\n");
|
||||
fprintf(stderr, "\nExamples:\n");
|
||||
fprintf(stderr, "%s -c -c -ta can0,123:7FF,400:700,#000000FF can2,400~7F0 can3 can8\n", prg);
|
||||
fprintf(stderr, "%s -l any,0~0,#FFFFFFFF (log only error frames but no(!) data frames)\n", prg);
|
||||
fprintf(stderr, "%s vcan2,92345678:9FFFFFFF (match only for extended CAN ID 12345678)\n", prg);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
||||
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
||||
fprintf(stderr, "Options: -t <type> (timestamp: (a)bsolute/(d)elta/(z)ero/(A)bsolute w date)\n");
|
||||
fprintf(stderr, " -c (increment color mode level)\n");
|
||||
fprintf(stderr, " -i (binary output - may exceed 80 chars/line)\n");
|
||||
fprintf(stderr, " -a (enable additional ASCII output)\n");
|
||||
fprintf(stderr, " -s <level> (silent mode - 1: animation 2: completely silent)\n");
|
||||
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, " -l (log CAN-frames into file)\n");
|
||||
fprintf(stderr, " -L (use log file format on stdout)\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "Up to %d CAN interfaces with optional filter sets can be specified\n", MAXSOCK);
|
||||
fprintf(stderr, "on the commandline in the form: <ifname>[,filter]*\n");
|
||||
fprintf(stderr, "\nUp to %d comma separated filters can be specified for each given CAN interface:\n", MAXFILTER);
|
||||
fprintf(stderr, " <can_id>:<can_mask> (matches when <received_can_id> & mask == can_id & mask)\n");
|
||||
fprintf(stderr, " <can_id>~<can_mask> (matches when <received_can_id> & mask != can_id & mask)\n");
|
||||
fprintf(stderr, " #<error_mask> (set error frame filter, see include/linux/can/error.h)\n");
|
||||
fprintf(stderr, "\nUse interface name '%s' to receive from all CAN interfaces.\n", ANYDEV);
|
||||
fprintf(stderr, "CAN IDs, masks and data content are given and expected in hexadecimal values.\n");
|
||||
fprintf(stderr, "\nExamples:\n");
|
||||
fprintf(stderr, "%s -c -c -ta can0,123:7FF,400:700,#000000FF can2,400~7F0 can3 can8\n", prg);
|
||||
fprintf(stderr, "%s -l any,0~0,#FFFFFFFF (log only error frames but no(!) data frames)\n", prg);
|
||||
fprintf(stderr, "%s vcan2,92345678:9FFFFFFF (match only for extended CAN ID 12345678)\n", prg);
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
void sigterm(int signo)
|
||||
{
|
||||
running = 0;
|
||||
running = 0;
|
||||
}
|
||||
|
||||
int idx2dindex(int ifidx, int socket) {
|
||||
|
||||
int i;
|
||||
struct ifreq ifr;
|
||||
int i;
|
||||
struct ifreq ifr;
|
||||
|
||||
for (i=0; i < MAXIFNAMES; i++) {
|
||||
if (dindex[i] == ifidx)
|
||||
return i;
|
||||
}
|
||||
|
||||
/* create new interface index cache entry */
|
||||
|
||||
/* remove index cache zombies first */
|
||||
for (i=0; i < MAXIFNAMES; i++) {
|
||||
if (dindex[i]) {
|
||||
ifr.ifr_ifindex = dindex[i];
|
||||
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
||||
dindex[i] = 0;
|
||||
for (i=0; i < MAXIFNAMES; i++) {
|
||||
if (dindex[i] == ifidx)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i < MAXIFNAMES; i++)
|
||||
if (!dindex[i]) /* free entry */
|
||||
break;
|
||||
/* create new interface index cache entry */
|
||||
|
||||
if (i == MAXIFNAMES) {
|
||||
printf("Interface index cache only supports %d interfaces.\n",
|
||||
MAXIFNAMES);
|
||||
exit(1);
|
||||
}
|
||||
/* remove index cache zombies first */
|
||||
for (i=0; i < MAXIFNAMES; i++) {
|
||||
if (dindex[i]) {
|
||||
ifr.ifr_ifindex = dindex[i];
|
||||
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
||||
dindex[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
dindex[i] = ifidx;
|
||||
for (i=0; i < MAXIFNAMES; i++)
|
||||
if (!dindex[i]) /* free entry */
|
||||
break;
|
||||
|
||||
ifr.ifr_ifindex = ifidx;
|
||||
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
||||
perror("SIOCGIFNAME");
|
||||
if (i == MAXIFNAMES) {
|
||||
printf("Interface index cache only supports %d interfaces.\n",
|
||||
MAXIFNAMES);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (max_devname_len < strlen(ifr.ifr_name))
|
||||
max_devname_len = strlen(ifr.ifr_name);
|
||||
dindex[i] = ifidx;
|
||||
|
||||
strcpy(devname[i], ifr.ifr_name);
|
||||
ifr.ifr_ifindex = ifidx;
|
||||
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
||||
perror("SIOCGIFNAME");
|
||||
|
||||
if (max_devname_len < strlen(ifr.ifr_name))
|
||||
max_devname_len = strlen(ifr.ifr_name);
|
||||
|
||||
strcpy(devname[i], ifr.ifr_name);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("new index %d (%s)\n", i, devname[i]);
|
||||
printf("new index %d (%s)\n", i, devname[i]);
|
||||
#endif
|
||||
|
||||
return i;
|
||||
return i;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
fd_set rdfs;
|
||||
int s[MAXSOCK];
|
||||
int bridge = 0;
|
||||
unsigned char timestamp = 0;
|
||||
unsigned char silent = 0;
|
||||
unsigned char silentani = 0;
|
||||
unsigned char color = 0;
|
||||
unsigned char view = 0;
|
||||
unsigned char log = 0;
|
||||
unsigned char logfrmt = 0;
|
||||
int opt, ret;
|
||||
int currmax, numfilter;
|
||||
char *ptr, *nptr;
|
||||
struct sockaddr_can addr;
|
||||
struct can_filter rfilter[MAXFILTER];
|
||||
can_err_mask_t err_mask;
|
||||
struct can_frame frame;
|
||||
int nbytes, i;
|
||||
struct ifreq ifr;
|
||||
struct timeval tv, last_tv;
|
||||
FILE *logfile = NULL;
|
||||
fd_set rdfs;
|
||||
int s[MAXSOCK];
|
||||
int bridge = 0;
|
||||
unsigned char timestamp = 0;
|
||||
unsigned char silent = 0;
|
||||
unsigned char silentani = 0;
|
||||
unsigned char color = 0;
|
||||
unsigned char view = 0;
|
||||
unsigned char log = 0;
|
||||
unsigned char logfrmt = 0;
|
||||
int opt, ret;
|
||||
int currmax, numfilter;
|
||||
char *ptr, *nptr;
|
||||
struct sockaddr_can addr;
|
||||
struct can_filter rfilter[MAXFILTER];
|
||||
can_err_mask_t err_mask;
|
||||
struct can_frame frame;
|
||||
int nbytes, i;
|
||||
struct ifreq ifr;
|
||||
struct timeval tv, last_tv;
|
||||
FILE *logfile = NULL;
|
||||
|
||||
signal(SIGTERM, sigterm);
|
||||
signal(SIGHUP, sigterm);
|
||||
signal(SIGINT, sigterm);
|
||||
signal(SIGTERM, sigterm);
|
||||
signal(SIGHUP, sigterm);
|
||||
signal(SIGINT, sigterm);
|
||||
|
||||
last_tv.tv_sec = 0;
|
||||
last_tv.tv_usec = 0;
|
||||
last_tv.tv_sec = 0;
|
||||
last_tv.tv_usec = 0;
|
||||
|
||||
while ((opt = getopt(argc, argv, "t:cias:b:B:lLh?")) != -1) {
|
||||
switch (opt) {
|
||||
case 't':
|
||||
timestamp = optarg[0];
|
||||
if ((timestamp != 'a') && (timestamp != 'A') &&
|
||||
(timestamp != 'd') && (timestamp != 'z')) {
|
||||
printf("%s: unknown timestamp mode '%c' - ignored\n",
|
||||
basename(argv[0]), optarg[0]);
|
||||
timestamp = 0;
|
||||
}
|
||||
break;
|
||||
while ((opt = getopt(argc, argv, "t:cias:b:B:lLh?")) != -1) {
|
||||
switch (opt) {
|
||||
case 't':
|
||||
timestamp = optarg[0];
|
||||
if ((timestamp != 'a') && (timestamp != 'A') &&
|
||||
(timestamp != 'd') && (timestamp != 'z')) {
|
||||
printf("%s: unknown timestamp mode '%c' - ignored\n",
|
||||
basename(argv[0]), optarg[0]);
|
||||
timestamp = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
color++;
|
||||
break;
|
||||
case 'c':
|
||||
color++;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
view |= CANLIB_VIEW_BINARY;
|
||||
break;
|
||||
case 'i':
|
||||
view |= CANLIB_VIEW_BINARY;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
view |= CANLIB_VIEW_ASCII;
|
||||
break;
|
||||
case 'a':
|
||||
view |= CANLIB_VIEW_ASCII;
|
||||
break;
|
||||
|
||||
case 's':
|
||||
silent = atoi(optarg);
|
||||
break;
|
||||
case 's':
|
||||
silent = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
case 'B':
|
||||
if (strlen(optarg) >= IFNAMSIZ) {
|
||||
printf("Name of CAN device '%s' is too long!\n\n", optarg);
|
||||
return 1;
|
||||
} else {
|
||||
bridge = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||
if (bridge < 0) {
|
||||
perror("bridge socket");
|
||||
return 1;
|
||||
}
|
||||
addr.can_family = AF_CAN;
|
||||
strcpy(ifr.ifr_name, optarg);
|
||||
if (ioctl(bridge, SIOCGIFINDEX, &ifr) < 0)
|
||||
perror("SIOCGIFINDEX");
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
case 'b':
|
||||
case 'B':
|
||||
if (strlen(optarg) >= IFNAMSIZ) {
|
||||
printf("Name of CAN device '%s' is too long!\n\n", optarg);
|
||||
return 1;
|
||||
} else {
|
||||
bridge = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||
if (bridge < 0) {
|
||||
perror("bridge socket");
|
||||
return 1;
|
||||
}
|
||||
addr.can_family = AF_CAN;
|
||||
strcpy(ifr.ifr_name, optarg);
|
||||
if (ioctl(bridge, SIOCGIFINDEX, &ifr) < 0)
|
||||
perror("SIOCGIFINDEX");
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
|
||||
if (!addr.can_ifindex) {
|
||||
perror("invalid bridge interface");
|
||||
return 1;
|
||||
}
|
||||
if (!addr.can_ifindex) {
|
||||
perror("invalid bridge interface");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (opt == 'B') {
|
||||
int loopback = 0;
|
||||
if (opt == 'B') {
|
||||
int loopback = 0;
|
||||
|
||||
setsockopt(bridge, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
|
||||
&loopback, sizeof(loopback));
|
||||
}
|
||||
setsockopt(bridge, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
|
||||
&loopback, sizeof(loopback));
|
||||
}
|
||||
|
||||
if (bind(bridge, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bridge bind");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
if (bind(bridge, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bridge bind");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
log = 1;
|
||||
break;
|
||||
case 'l':
|
||||
log = 1;
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
logfrmt = 1;
|
||||
break;
|
||||
case 'L':
|
||||
logfrmt = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
print_usage(basename(argv[0]));
|
||||
exit(1);
|
||||
break;
|
||||
default:
|
||||
print_usage(basename(argv[0]));
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (optind == argc) {
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
if (optind == argc) {
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
currmax = argc - optind; /* find real number of CAN devices */
|
||||
currmax = argc - optind; /* find real number of CAN devices */
|
||||
|
||||
if (currmax > MAXSOCK) {
|
||||
printf("More than %d CAN devices given on commandline!\n", MAXSOCK);
|
||||
return 1;
|
||||
}
|
||||
if (currmax > MAXSOCK) {
|
||||
printf("More than %d CAN devices given on commandline!\n", MAXSOCK);
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (i=0; i < currmax; i++) {
|
||||
for (i=0; i < currmax; i++) {
|
||||
|
||||
ptr = argv[optind+i];
|
||||
nptr = strchr(ptr, ',');
|
||||
ptr = argv[optind+i];
|
||||
nptr = strchr(ptr, ',');
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("open %d '%s'.\n", i, ptr);
|
||||
printf("open %d '%s'.\n", i, ptr);
|
||||
#endif
|
||||
|
||||
s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||
if (s[i] < 0) {
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW);
|
||||
if (s[i] < 0) {
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nptr)
|
||||
nbytes = nptr - ptr; /* interface name is up the first ',' */
|
||||
else
|
||||
nbytes = strlen(ptr); /* no ',' found => no filter definitions */
|
||||
if (nptr)
|
||||
nbytes = nptr - ptr; /* interface name is up the first ',' */
|
||||
else
|
||||
nbytes = strlen(ptr); /* no ',' found => no filter definitions */
|
||||
|
||||
if (nbytes >= IFNAMSIZ) {
|
||||
printf("name of CAN device '%s' is too long!\n", ptr);
|
||||
return 1;
|
||||
}
|
||||
if (nbytes >= IFNAMSIZ) {
|
||||
printf("name of CAN device '%s' is too long!\n", ptr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nbytes > max_devname_len)
|
||||
max_devname_len = nbytes; /* for nice printing */
|
||||
if (nbytes > max_devname_len)
|
||||
max_devname_len = nbytes; /* for nice printing */
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_family = AF_CAN;
|
||||
|
||||
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
|
||||
strncpy(ifr.ifr_name, ptr, nbytes);
|
||||
memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
|
||||
strncpy(ifr.ifr_name, ptr, nbytes);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("using interface name '%s'.\n", ifr.ifr_name);
|
||||
printf("using interface name '%s'.\n", ifr.ifr_name);
|
||||
#endif
|
||||
|
||||
if (strcmp(ANYDEV, ifr.ifr_name)) {
|
||||
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
|
||||
perror("SIOCGIFINDEX");
|
||||
exit(1);
|
||||
}
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
} else
|
||||
addr.can_ifindex = 0; /* any can interface */
|
||||
if (strcmp(ANYDEV, ifr.ifr_name)) {
|
||||
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
|
||||
perror("SIOCGIFINDEX");
|
||||
exit(1);
|
||||
}
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
} else
|
||||
addr.can_ifindex = 0; /* any can interface */
|
||||
|
||||
if (nptr) {
|
||||
if (nptr) {
|
||||
|
||||
/* found a ',' after the interface name => check for filters */
|
||||
/* found a ',' after the interface name => check for filters */
|
||||
|
||||
numfilter = 0;
|
||||
err_mask = 0;
|
||||
numfilter = 0;
|
||||
err_mask = 0;
|
||||
|
||||
while (nptr) {
|
||||
while (nptr) {
|
||||
|
||||
ptr = nptr+1; /* hop behind the ',' */
|
||||
nptr = strchr(ptr, ','); /* update exit condition */
|
||||
ptr = nptr+1; /* hop behind the ',' */
|
||||
nptr = strchr(ptr, ','); /* update exit condition */
|
||||
|
||||
if (sscanf(ptr, "%lx:%lx",
|
||||
(long unsigned int *)
|
||||
&rfilter[numfilter].can_id,
|
||||
(long unsigned int *)
|
||||
&rfilter[numfilter].can_mask) == 2) {
|
||||
numfilter++;
|
||||
} else if (sscanf(ptr, "%lx~%lx",
|
||||
(long unsigned int *)
|
||||
&rfilter[numfilter].can_id,
|
||||
(long unsigned int *)
|
||||
&rfilter[numfilter].can_mask) == 2) {
|
||||
rfilter[numfilter].can_id |= CAN_INV_FILTER;
|
||||
numfilter++;
|
||||
} else if (sscanf(ptr, "#%lx",
|
||||
(long unsigned int *)&err_mask) != 1) {
|
||||
printf("Error in filter option parsing: '%s'\n", ptr);
|
||||
exit(1);
|
||||
}
|
||||
if (sscanf(ptr, "%lx:%lx",
|
||||
(long unsigned int *)
|
||||
&rfilter[numfilter].can_id,
|
||||
(long unsigned int *)
|
||||
&rfilter[numfilter].can_mask) == 2) {
|
||||
numfilter++;
|
||||
} else if (sscanf(ptr, "%lx~%lx",
|
||||
(long unsigned int *)
|
||||
&rfilter[numfilter].can_id,
|
||||
(long unsigned int *)
|
||||
&rfilter[numfilter].can_mask) == 2) {
|
||||
rfilter[numfilter].can_id |= CAN_INV_FILTER;
|
||||
numfilter++;
|
||||
} else if (sscanf(ptr, "#%lx",
|
||||
(long unsigned int *)&err_mask) != 1) {
|
||||
printf("Error in filter option parsing: '%s'\n", ptr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (numfilter > MAXFILTER) {
|
||||
printf("Too many filters specified for '%s'.\n",
|
||||
ifr.ifr_name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (numfilter > MAXFILTER) {
|
||||
printf("Too many filters specified for '%s'.\n",
|
||||
ifr.ifr_name);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (err_mask)
|
||||
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
|
||||
&err_mask, sizeof(err_mask));
|
||||
if (err_mask)
|
||||
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
|
||||
&err_mask, sizeof(err_mask));
|
||||
|
||||
if (numfilter)
|
||||
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
|
||||
&rfilter, numfilter * sizeof(struct can_filter));
|
||||
} /* if (nptr) */
|
||||
if (numfilter)
|
||||
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
|
||||
&rfilter, numfilter * sizeof(struct can_filter));
|
||||
} /* if (nptr) */
|
||||
|
||||
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (log) {
|
||||
time_t currtime;
|
||||
struct tm now;
|
||||
char fname[sizeof("candump-2006-11-20_202026.log")+1];
|
||||
|
||||
if (time(&currtime) == (time_t)-1) {
|
||||
perror("time");
|
||||
return 1;
|
||||
}
|
||||
|
||||
localtime_r(&currtime, &now);
|
||||
|
||||
sprintf(fname, "candump-%04d-%02d-%02d_%02d%02d%02d.log",
|
||||
now.tm_year + 1900,
|
||||
now.tm_mon + 1,
|
||||
now.tm_mday,
|
||||
now.tm_hour,
|
||||
now.tm_min,
|
||||
now.tm_sec);
|
||||
|
||||
printf("\nEnabling Logfile '%s'\n\n", fname);
|
||||
|
||||
logfile = fopen(fname, "w");
|
||||
if (!logfile) {
|
||||
perror("logfile");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (running) {
|
||||
|
||||
FD_ZERO(&rdfs);
|
||||
for (i=0; i<currmax; i++)
|
||||
FD_SET(s[i], &rdfs);
|
||||
|
||||
if ((ret = select(s[currmax-1]+1, &rdfs, NULL, NULL, NULL)) < 0) {
|
||||
//perror("select");
|
||||
running = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
|
||||
|
||||
if (FD_ISSET(s[i], &rdfs)) {
|
||||
|
||||
socklen_t len = sizeof(addr);
|
||||
int idx;
|
||||
|
||||
nbytes = recvfrom(s[i], &frame, sizeof(struct can_frame), 0,
|
||||
(struct sockaddr*)&addr, &len);
|
||||
if (nbytes < 0) {
|
||||
perror("read");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nbytes < sizeof(struct can_frame)) {
|
||||
fprintf(stderr, "read: incomplete CAN frame\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bridge) {
|
||||
nbytes = write(bridge, &frame, sizeof(struct can_frame));
|
||||
if (nbytes < 0) {
|
||||
perror("bridge write");
|
||||
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
return 1;
|
||||
} else if (nbytes < sizeof(struct can_frame)) {
|
||||
fprintf(stderr,"bridge write: incomplete CAN frame\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (log) {
|
||||
time_t currtime;
|
||||
struct tm now;
|
||||
char fname[sizeof("candump-2006-11-20_202026.log")+1];
|
||||
|
||||
if (time(&currtime) == (time_t)-1) {
|
||||
perror("time");
|
||||
return 1;
|
||||
}
|
||||
|
||||
localtime_r(&currtime, &now);
|
||||
|
||||
sprintf(fname, "candump-%04d-%02d-%02d_%02d%02d%02d.log",
|
||||
now.tm_year + 1900,
|
||||
now.tm_mon + 1,
|
||||
now.tm_mday,
|
||||
now.tm_hour,
|
||||
now.tm_min,
|
||||
now.tm_sec);
|
||||
|
||||
printf("\nEnabling Logfile '%s'\n\n", fname);
|
||||
|
||||
logfile = fopen(fname, "w");
|
||||
if (!logfile) {
|
||||
perror("logfile");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (running) {
|
||||
|
||||
FD_ZERO(&rdfs);
|
||||
for (i=0; i<currmax; i++)
|
||||
FD_SET(s[i], &rdfs);
|
||||
|
||||
if ((ret = select(s[currmax-1]+1, &rdfs, NULL, NULL, NULL)) < 0) {
|
||||
//perror("select");
|
||||
running = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
|
||||
|
||||
if (FD_ISSET(s[i], &rdfs)) {
|
||||
|
||||
socklen_t len = sizeof(addr);
|
||||
int idx;
|
||||
|
||||
nbytes = recvfrom(s[i], &frame, sizeof(struct can_frame), 0,
|
||||
(struct sockaddr*)&addr, &len);
|
||||
if (nbytes < 0) {
|
||||
perror("read");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nbytes < sizeof(struct can_frame)) {
|
||||
fprintf(stderr, "read: incomplete CAN frame\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (bridge) {
|
||||
nbytes = write(bridge, &frame, sizeof(struct can_frame));
|
||||
if (nbytes < 0) {
|
||||
perror("bridge write");
|
||||
return 1;
|
||||
} else if (nbytes < sizeof(struct can_frame)) {
|
||||
fprintf(stderr,"bridge write: incomplete CAN frame\n");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (timestamp || log || logfrmt)
|
||||
if (ioctl(s[i], SIOCGSTAMP, &tv) < 0)
|
||||
perror("SIOCGSTAMP");
|
||||
if (timestamp || log || logfrmt)
|
||||
if (ioctl(s[i], SIOCGSTAMP, &tv) < 0)
|
||||
perror("SIOCGSTAMP");
|
||||
|
||||
|
||||
idx = idx2dindex(addr.can_ifindex, s[i]);
|
||||
idx = idx2dindex(addr.can_ifindex, s[i]);
|
||||
|
||||
if (log) {
|
||||
/* log CAN frame with absolute timestamp & device */
|
||||
fprintf(logfile, "(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
||||
fprintf(logfile, "%*s ", max_devname_len, devname[idx]);
|
||||
/* without seperator as logfile use-case is parsing */
|
||||
fprint_canframe(logfile, &frame, "\n", 0);
|
||||
}
|
||||
if (log) {
|
||||
/* log CAN frame with absolute timestamp & device */
|
||||
fprintf(logfile, "(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
||||
fprintf(logfile, "%*s ", max_devname_len, devname[idx]);
|
||||
/* without seperator as logfile use-case is parsing */
|
||||
fprint_canframe(logfile, &frame, "\n", 0);
|
||||
}
|
||||
|
||||
if (logfrmt) {
|
||||
/* print CAN frame in log file style to stdout */
|
||||
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
||||
printf("%*s ", max_devname_len, devname[idx]);
|
||||
fprint_canframe(stdout, &frame, "\n", 0);
|
||||
goto out_fflush; /* no other output to stdout */
|
||||
}
|
||||
if (logfrmt) {
|
||||
/* print CAN frame in log file style to stdout */
|
||||
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
||||
printf("%*s ", max_devname_len, devname[idx]);
|
||||
fprint_canframe(stdout, &frame, "\n", 0);
|
||||
goto out_fflush; /* no other output to stdout */
|
||||
}
|
||||
|
||||
if (silent){
|
||||
if (silent == 1) {
|
||||
printf("%c\b", anichar[silentani%=MAXANI]);
|
||||
silentani++;
|
||||
}
|
||||
goto out_fflush; /* no other output to stdout */
|
||||
}
|
||||
if (silent){
|
||||
if (silent == 1) {
|
||||
printf("%c\b", anichar[silentani%=MAXANI]);
|
||||
silentani++;
|
||||
}
|
||||
goto out_fflush; /* no other output to stdout */
|
||||
}
|
||||
|
||||
printf(" %s", (color>2)?col_on[idx%MAXCOL]:"");
|
||||
printf(" %s", (color>2)?col_on[idx%MAXCOL]:"");
|
||||
|
||||
switch (timestamp) {
|
||||
switch (timestamp) {
|
||||
|
||||
case 'a': /* absolute with timestamp */
|
||||
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
||||
break;
|
||||
case 'a': /* absolute with timestamp */
|
||||
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
||||
break;
|
||||
|
||||
case 'A': /* absolute with date */
|
||||
{
|
||||
struct tm tm;
|
||||
char timestring[25];
|
||||
case 'A': /* absolute with date */
|
||||
{
|
||||
struct tm tm;
|
||||
char timestring[25];
|
||||
|
||||
tm = *localtime(&tv.tv_sec);
|
||||
strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", &tm);
|
||||
printf("(%s.%06ld) ", timestring, tv.tv_usec);
|
||||
}
|
||||
break;
|
||||
tm = *localtime(&tv.tv_sec);
|
||||
strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", &tm);
|
||||
printf("(%s.%06ld) ", timestring, tv.tv_usec);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd': /* delta */
|
||||
case 'z': /* starting with zero */
|
||||
{
|
||||
struct timeval diff;
|
||||
case 'd': /* delta */
|
||||
case 'z': /* starting with zero */
|
||||
{
|
||||
struct timeval diff;
|
||||
|
||||
if (last_tv.tv_sec == 0) /* first init */
|
||||
last_tv = tv;
|
||||
diff.tv_sec = tv.tv_sec - last_tv.tv_sec;
|
||||
diff.tv_usec = tv.tv_usec - last_tv.tv_usec;
|
||||
if (diff.tv_usec < 0)
|
||||
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);
|
||||
if (last_tv.tv_sec == 0) /* first init */
|
||||
last_tv = tv;
|
||||
diff.tv_sec = tv.tv_sec - last_tv.tv_sec;
|
||||
diff.tv_usec = tv.tv_usec - last_tv.tv_usec;
|
||||
if (diff.tv_usec < 0)
|
||||
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);
|
||||
|
||||
if (timestamp == 'd')
|
||||
last_tv = tv; /* update for delta calculation */
|
||||
}
|
||||
break;
|
||||
if (timestamp == 'd')
|
||||
last_tv = tv; /* update for delta calculation */
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* no timestamp output */
|
||||
break;
|
||||
default: /* no timestamp output */
|
||||
break;
|
||||
}
|
||||
|
||||
printf(" %s", (color && (color<3))?col_on[idx%MAXCOL]:"");
|
||||
printf("%*s", max_devname_len, devname[idx]);
|
||||
printf("%s ", (color==1)?col_off:"");
|
||||
|
||||
fprint_long_canframe(stdout, &frame, NULL, view);
|
||||
|
||||
printf("%s", (color>1)?col_off:"");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
out_fflush:
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
printf(" %s", (color && (color<3))?col_on[idx%MAXCOL]:"");
|
||||
printf("%*s", max_devname_len, devname[idx]);
|
||||
printf("%s ", (color==1)?col_off:"");
|
||||
|
||||
fprint_long_canframe(stdout, &frame, NULL, view);
|
||||
|
||||
printf("%s", (color>1)?col_off:"");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
out_fflush:
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<currmax; i++)
|
||||
close(s[i]);
|
||||
for (i=0; i<currmax; i++)
|
||||
close(s[i]);
|
||||
|
||||
if (bridge)
|
||||
close(bridge);
|
||||
if (bridge)
|
||||
close(bridge);
|
||||
|
||||
if (log)
|
||||
fclose(logfile);
|
||||
if (log)
|
||||
fclose(logfile);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
514
cangen.c
514
cangen.c
|
|
@ -80,306 +80,306 @@ static unsigned long long enobufs_count;
|
|||
|
||||
void print_usage(char *prg)
|
||||
{
|
||||
fprintf(stderr, "\n%s: generate CAN frames\n\n", prg);
|
||||
fprintf(stderr, "Usage: %s [options] <CAN interface>\n", prg);
|
||||
fprintf(stderr, "Options: -g <ms> (gap in milli seconds "
|
||||
"- default: %d ms)\n", DEFAULT_GAP);
|
||||
fprintf(stderr, " -e (generate extended frame mode "
|
||||
"(EFF) CAN frames)\n");
|
||||
fprintf(stderr, " -I <mode> (CAN ID"
|
||||
" generation mode - see below)\n");
|
||||
fprintf(stderr, " -L <mode> (CAN data length code (dlc)"
|
||||
" generation mode - see below)\n");
|
||||
fprintf(stderr, " -D <mode> (CAN data (payload)"
|
||||
" generation mode - see below)\n");
|
||||
fprintf(stderr, " -i (ignore -ENOBUFS return values on"
|
||||
" write() syscalls)\n");
|
||||
fprintf(stderr, " -x (disable local loopback of "
|
||||
"generated CAN frames)\n");
|
||||
fprintf(stderr, " -v (increment verbose level for "
|
||||
"printing sent CAN frames)\n\n");
|
||||
fprintf(stderr, "Generation modes:\n");
|
||||
fprintf(stderr, "'r' => random values (default)\n");
|
||||
fprintf(stderr, "'i' => increment values\n");
|
||||
fprintf(stderr, "<hexvalue> => fix value using <hexvalue>\n\n");
|
||||
fprintf(stderr, "When incrementing the CAN data the data length code "
|
||||
"minimum is set to 1.\n");
|
||||
fprintf(stderr, "CAN IDs and data content are given and expected in hexadecimal values.\n\n");
|
||||
fprintf(stderr, "Examples:\n");
|
||||
fprintf(stderr, "%s vcan0 -g 4 -I 42A -L 1 -D i -v -v ", prg);
|
||||
fprintf(stderr, "(fixed CAN ID and length, inc. data)\n");
|
||||
fprintf(stderr, "%s vcan0 -e -L i -v -v -v ", prg);
|
||||
fprintf(stderr, "(generate EFF frames, incr. length)\n");
|
||||
fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8 ", prg);
|
||||
fprintf(stderr, "(fixed CAN data payload and length)\n");
|
||||
fprintf(stderr, "%s vcan0 -g 0 -i -x ", prg);
|
||||
fprintf(stderr, "(full load test ignoring -ENOBUFS)\n");
|
||||
fprintf(stderr, "%s vcan0 ", prg);
|
||||
fprintf(stderr, "(my favourite default :)\n\n");
|
||||
fprintf(stderr, "\n%s: generate CAN frames\n\n", prg);
|
||||
fprintf(stderr, "Usage: %s [options] <CAN interface>\n", prg);
|
||||
fprintf(stderr, "Options: -g <ms> (gap in milli seconds "
|
||||
"- default: %d ms)\n", DEFAULT_GAP);
|
||||
fprintf(stderr, " -e (generate extended frame mode "
|
||||
"(EFF) CAN frames)\n");
|
||||
fprintf(stderr, " -I <mode> (CAN ID"
|
||||
" generation mode - see below)\n");
|
||||
fprintf(stderr, " -L <mode> (CAN data length code (dlc)"
|
||||
" generation mode - see below)\n");
|
||||
fprintf(stderr, " -D <mode> (CAN data (payload)"
|
||||
" generation mode - see below)\n");
|
||||
fprintf(stderr, " -i (ignore -ENOBUFS return values on"
|
||||
" write() syscalls)\n");
|
||||
fprintf(stderr, " -x (disable local loopback of "
|
||||
"generated CAN frames)\n");
|
||||
fprintf(stderr, " -v (increment verbose level for "
|
||||
"printing sent CAN frames)\n\n");
|
||||
fprintf(stderr, "Generation modes:\n");
|
||||
fprintf(stderr, "'r' => random values (default)\n");
|
||||
fprintf(stderr, "'i' => increment values\n");
|
||||
fprintf(stderr, "<hexvalue> => fix value using <hexvalue>\n\n");
|
||||
fprintf(stderr, "When incrementing the CAN data the data length code "
|
||||
"minimum is set to 1.\n");
|
||||
fprintf(stderr, "CAN IDs and data content are given and expected in hexadecimal values.\n\n");
|
||||
fprintf(stderr, "Examples:\n");
|
||||
fprintf(stderr, "%s vcan0 -g 4 -I 42A -L 1 -D i -v -v ", prg);
|
||||
fprintf(stderr, "(fixed CAN ID and length, inc. data)\n");
|
||||
fprintf(stderr, "%s vcan0 -e -L i -v -v -v ", prg);
|
||||
fprintf(stderr, "(generate EFF frames, incr. length)\n");
|
||||
fprintf(stderr, "%s vcan0 -D 11223344DEADBEEF -L 8 ", prg);
|
||||
fprintf(stderr, "(fixed CAN data payload and length)\n");
|
||||
fprintf(stderr, "%s vcan0 -g 0 -i -x ", prg);
|
||||
fprintf(stderr, "(full load test ignoring -ENOBUFS)\n");
|
||||
fprintf(stderr, "%s vcan0 ", prg);
|
||||
fprintf(stderr, "(my favourite default :)\n\n");
|
||||
}
|
||||
|
||||
void sigterm(int signo)
|
||||
{
|
||||
running = 0;
|
||||
running = 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
unsigned long gap = DEFAULT_GAP;
|
||||
unsigned char ignore_enobufs = 0;
|
||||
unsigned char extended = 0;
|
||||
unsigned char id_mode = MODE_RANDOM;
|
||||
unsigned char data_mode = MODE_RANDOM;
|
||||
unsigned char dlc_mode = MODE_RANDOM;
|
||||
unsigned char loopback_disable = 0;
|
||||
unsigned char verbose = 0;
|
||||
uint64_t incdata = 0;
|
||||
unsigned long gap = DEFAULT_GAP;
|
||||
unsigned char ignore_enobufs = 0;
|
||||
unsigned char extended = 0;
|
||||
unsigned char id_mode = MODE_RANDOM;
|
||||
unsigned char data_mode = MODE_RANDOM;
|
||||
unsigned char dlc_mode = MODE_RANDOM;
|
||||
unsigned char loopback_disable = 0;
|
||||
unsigned char verbose = 0;
|
||||
uint64_t incdata = 0;
|
||||
|
||||
int opt;
|
||||
int s; /* socket */
|
||||
int opt;
|
||||
int s; /* socket */
|
||||
|
||||
struct sockaddr_can addr;
|
||||
static struct can_frame frame;
|
||||
int nbytes;
|
||||
int i;
|
||||
struct ifreq ifr;
|
||||
struct sockaddr_can addr;
|
||||
static struct can_frame frame;
|
||||
int nbytes;
|
||||
int i;
|
||||
struct ifreq ifr;
|
||||
|
||||
struct timespec ts;
|
||||
struct timespec ts;
|
||||
|
||||
signal(SIGTERM, sigterm);
|
||||
signal(SIGHUP, sigterm);
|
||||
signal(SIGINT, sigterm);
|
||||
signal(SIGTERM, sigterm);
|
||||
signal(SIGHUP, sigterm);
|
||||
signal(SIGINT, sigterm);
|
||||
|
||||
while ((opt = getopt(argc, argv, "ig:eI:L:D:xvh?")) != -1) {
|
||||
switch (opt) {
|
||||
while ((opt = getopt(argc, argv, "ig:eI:L:D:xvh?")) != -1) {
|
||||
switch (opt) {
|
||||
|
||||
case 'i':
|
||||
ignore_enobufs = 1;
|
||||
break;
|
||||
case 'i':
|
||||
ignore_enobufs = 1;
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
gap = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
case 'g':
|
||||
gap = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
extended = 1;
|
||||
break;
|
||||
case 'e':
|
||||
extended = 1;
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
if (optarg[0] == 'r') {
|
||||
id_mode = MODE_RANDOM;
|
||||
} else if (optarg[0] == 'i') {
|
||||
id_mode = MODE_INCREMENT;
|
||||
} else {
|
||||
id_mode = MODE_FIX;
|
||||
frame.can_id = strtoul(optarg, NULL, 16);
|
||||
}
|
||||
break;
|
||||
case 'I':
|
||||
if (optarg[0] == 'r') {
|
||||
id_mode = MODE_RANDOM;
|
||||
} else if (optarg[0] == 'i') {
|
||||
id_mode = MODE_INCREMENT;
|
||||
} else {
|
||||
id_mode = MODE_FIX;
|
||||
frame.can_id = strtoul(optarg, NULL, 16);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
if (optarg[0] == 'r') {
|
||||
dlc_mode = MODE_RANDOM;
|
||||
} else if (optarg[0] == 'i') {
|
||||
dlc_mode = MODE_INCREMENT;
|
||||
} else {
|
||||
dlc_mode = MODE_FIX;
|
||||
frame.can_dlc = atoi(optarg)%9;
|
||||
}
|
||||
break;
|
||||
case 'L':
|
||||
if (optarg[0] == 'r') {
|
||||
dlc_mode = MODE_RANDOM;
|
||||
} else if (optarg[0] == 'i') {
|
||||
dlc_mode = MODE_INCREMENT;
|
||||
} else {
|
||||
dlc_mode = MODE_FIX;
|
||||
frame.can_dlc = atoi(optarg)%9;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
if (optarg[0] == 'r') {
|
||||
data_mode = MODE_RANDOM;
|
||||
} else if (optarg[0] == 'i') {
|
||||
data_mode = MODE_INCREMENT;
|
||||
} else {
|
||||
data_mode = MODE_FIX;
|
||||
incdata = strtoull(optarg, NULL, 16);
|
||||
for (i=0; i<8 ;i++)
|
||||
frame.data[i] = (incdata >> (7-i)*8) & 0xFFULL;
|
||||
}
|
||||
break;
|
||||
case 'D':
|
||||
if (optarg[0] == 'r') {
|
||||
data_mode = MODE_RANDOM;
|
||||
} else if (optarg[0] == 'i') {
|
||||
data_mode = MODE_INCREMENT;
|
||||
} else {
|
||||
data_mode = MODE_FIX;
|
||||
incdata = strtoull(optarg, NULL, 16);
|
||||
for (i=0; i<8 ;i++)
|
||||
frame.data[i] = (incdata >> (7-i)*8) & 0xFFULL;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
loopback_disable = 1;
|
||||
break;
|
||||
case 'x':
|
||||
loopback_disable = 1;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
case 'h':
|
||||
default:
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
break;
|
||||
case '?':
|
||||
case 'h':
|
||||
default:
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (optind == argc) {
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
}
|
||||
if (optind == argc) {
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
}
|
||||
|
||||
ts.tv_sec = gap / 1000;
|
||||
ts.tv_nsec = (gap % 1000) * 1000000;
|
||||
ts.tv_sec = gap / 1000;
|
||||
ts.tv_nsec = (gap % 1000) * 1000000;
|
||||
|
||||
|
||||
if (id_mode == MODE_FIX) {
|
||||
if (id_mode == MODE_FIX) {
|
||||
|
||||
/* recognize obviously missing commandline option */
|
||||
if ((frame.can_id > 0x7FF) && !extended) {
|
||||
printf("The given CAN-ID is greater than 0x7FF and "
|
||||
"the '-e' option is not set.\n");
|
||||
return 1;
|
||||
/* recognize obviously missing commandline option */
|
||||
if ((frame.can_id > 0x7FF) && !extended) {
|
||||
printf("The given CAN-ID is greater than 0x7FF and "
|
||||
"the '-e' option is not set.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (extended)
|
||||
frame.can_id &= CAN_EFF_MASK;
|
||||
else
|
||||
frame.can_id &= CAN_SFF_MASK;
|
||||
}
|
||||
|
||||
if (extended)
|
||||
frame.can_id &= CAN_EFF_MASK;
|
||||
else
|
||||
frame.can_id &= CAN_SFF_MASK;
|
||||
}
|
||||
frame.can_id |= CAN_EFF_FLAG;
|
||||
|
||||
if (extended)
|
||||
frame.can_id |= CAN_EFF_FLAG;
|
||||
|
||||
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
|
||||
frame.can_dlc = 1; /* min dlc value for incr. data */
|
||||
|
||||
if (strlen(argv[optind]) >= IFNAMSIZ) {
|
||||
printf("Name of CAN device '%s' is too long!\n\n", argv[optind]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
|
||||
strcpy(ifr.ifr_name, argv[optind]);
|
||||
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
|
||||
perror("SIOCGIFINDEX");
|
||||
return 1;
|
||||
}
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
|
||||
/* disable default receive filter on this RAW socket */
|
||||
/* This is obsolete as we do not read from the socket at all, but for */
|
||||
/* this reason we can remove the receive list in the Kernel to save a */
|
||||
/* little (really a very little!) CPU usage. */
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
||||
|
||||
if (loopback_disable) {
|
||||
int loopback = 0;
|
||||
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
|
||||
&loopback, sizeof(loopback));
|
||||
}
|
||||
|
||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (running) {
|
||||
|
||||
if (id_mode == MODE_RANDOM) {
|
||||
|
||||
frame.can_id = random();
|
||||
|
||||
if (extended) {
|
||||
frame.can_id &= CAN_EFF_MASK;
|
||||
frame.can_id |= CAN_EFF_FLAG;
|
||||
} else
|
||||
frame.can_id &= CAN_SFF_MASK;
|
||||
}
|
||||
|
||||
if (dlc_mode == MODE_RANDOM) {
|
||||
|
||||
frame.can_dlc = random() & 0xF;
|
||||
|
||||
if (frame.can_dlc & 8)
|
||||
frame.can_dlc = 8; /* for about 50% of the frames */
|
||||
|
||||
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
|
||||
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
|
||||
frame.can_dlc = 1; /* min dlc value for incr. data */
|
||||
}
|
||||
|
||||
if (data_mode == MODE_RANDOM) {
|
||||
|
||||
/* that's what the 64 bit alignment of data[] is for ... :) */
|
||||
*(unsigned long*)(&frame.data[0]) = random();
|
||||
*(unsigned long*)(&frame.data[4]) = random();
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
|
||||
printf(" %s ", argv[optind]);
|
||||
|
||||
if (verbose > 1)
|
||||
fprint_long_canframe(stdout, &frame, "\n", (verbose > 2)?1:0);
|
||||
else
|
||||
fprint_canframe(stdout, &frame, "\n", 1);
|
||||
}
|
||||
|
||||
nbytes = write(s, &frame, sizeof(struct can_frame));
|
||||
if (nbytes < 0) {
|
||||
if (errno != ENOBUFS) {
|
||||
perror("write");
|
||||
if (strlen(argv[optind]) >= IFNAMSIZ) {
|
||||
printf("Name of CAN device '%s' is too long!\n\n", argv[optind]);
|
||||
return 1;
|
||||
}
|
||||
if (!ignore_enobufs) {
|
||||
perror("write");
|
||||
return 1;
|
||||
}
|
||||
enobufs_count++;
|
||||
|
||||
} else if (nbytes < sizeof(struct can_frame)) {
|
||||
fprintf(stderr, "write: incomplete CAN frame\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (gap) /* gap == 0 => performance test :-] */
|
||||
if (nanosleep(&ts, NULL))
|
||||
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
|
||||
strcpy(ifr.ifr_name, argv[optind]);
|
||||
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
|
||||
perror("SIOCGIFINDEX");
|
||||
return 1;
|
||||
}
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
|
||||
/* disable default receive filter on this RAW socket */
|
||||
/* This is obsolete as we do not read from the socket at all, but for */
|
||||
/* this reason we can remove the receive list in the Kernel to save a */
|
||||
/* little (really a very little!) CPU usage. */
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
||||
|
||||
if (loopback_disable) {
|
||||
int loopback = 0;
|
||||
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
|
||||
&loopback, sizeof(loopback));
|
||||
}
|
||||
|
||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (running) {
|
||||
|
||||
if (id_mode == MODE_RANDOM) {
|
||||
|
||||
frame.can_id = random();
|
||||
|
||||
if (extended) {
|
||||
frame.can_id &= CAN_EFF_MASK;
|
||||
frame.can_id |= CAN_EFF_FLAG;
|
||||
} else
|
||||
frame.can_id &= CAN_SFF_MASK;
|
||||
}
|
||||
|
||||
if (dlc_mode == MODE_RANDOM) {
|
||||
|
||||
frame.can_dlc = random() & 0xF;
|
||||
|
||||
if (frame.can_dlc & 8)
|
||||
frame.can_dlc = 8; /* for about 50% of the frames */
|
||||
|
||||
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
|
||||
frame.can_dlc = 1; /* min dlc value for incr. data */
|
||||
}
|
||||
|
||||
if (data_mode == MODE_RANDOM) {
|
||||
|
||||
/* that's what the 64 bit alignment of data[] is for ... :) */
|
||||
*(unsigned long*)(&frame.data[0]) = random();
|
||||
*(unsigned long*)(&frame.data[4]) = random();
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
|
||||
printf(" %s ", argv[optind]);
|
||||
|
||||
if (verbose > 1)
|
||||
fprint_long_canframe(stdout, &frame, "\n", (verbose > 2)?1:0);
|
||||
else
|
||||
fprint_canframe(stdout, &frame, "\n", 1);
|
||||
}
|
||||
|
||||
nbytes = write(s, &frame, sizeof(struct can_frame));
|
||||
if (nbytes < 0) {
|
||||
if (errno != ENOBUFS) {
|
||||
perror("write");
|
||||
return 1;
|
||||
}
|
||||
if (!ignore_enobufs) {
|
||||
perror("write");
|
||||
return 1;
|
||||
}
|
||||
enobufs_count++;
|
||||
|
||||
} else if (nbytes < sizeof(struct can_frame)) {
|
||||
fprintf(stderr, "write: incomplete CAN frame\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (gap) /* gap == 0 => performance test :-] */
|
||||
if (nanosleep(&ts, NULL))
|
||||
return 1;
|
||||
|
||||
if (id_mode == MODE_INCREMENT) {
|
||||
if (id_mode == MODE_INCREMENT) {
|
||||
|
||||
frame.can_id++;
|
||||
frame.can_id++;
|
||||
|
||||
if (extended) {
|
||||
frame.can_id &= CAN_EFF_MASK;
|
||||
frame.can_id |= CAN_EFF_FLAG;
|
||||
} else
|
||||
frame.can_id &= CAN_SFF_MASK;
|
||||
if (extended) {
|
||||
frame.can_id &= CAN_EFF_MASK;
|
||||
frame.can_id |= CAN_EFF_FLAG;
|
||||
} else
|
||||
frame.can_id &= CAN_SFF_MASK;
|
||||
}
|
||||
|
||||
if (dlc_mode == MODE_INCREMENT) {
|
||||
|
||||
frame.can_dlc++;
|
||||
frame.can_dlc %= 9;
|
||||
|
||||
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
|
||||
frame.can_dlc = 1; /* min dlc value for incr. data */
|
||||
}
|
||||
|
||||
if (data_mode == MODE_INCREMENT) {
|
||||
|
||||
incdata++;
|
||||
|
||||
for (i=0; i<8 ;i++)
|
||||
frame.data[i] = (incdata >> i*8) & 0xFFULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (dlc_mode == MODE_INCREMENT) {
|
||||
if (enobufs_count)
|
||||
printf("\nCounted %llu ENOBUFS return values on write().\n\n",
|
||||
enobufs_count);
|
||||
|
||||
frame.can_dlc++;
|
||||
frame.can_dlc %= 9;
|
||||
close(s);
|
||||
|
||||
if ((data_mode == MODE_INCREMENT) && !frame.can_dlc)
|
||||
frame.can_dlc = 1; /* min dlc value for incr. data */
|
||||
}
|
||||
|
||||
if (data_mode == MODE_INCREMENT) {
|
||||
|
||||
incdata++;
|
||||
|
||||
for (i=0; i<8 ;i++)
|
||||
frame.data[i] = (incdata >> i*8) & 0xFFULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (enobufs_count)
|
||||
printf("\nCounted %llu ENOBUFS return values on write().\n\n",
|
||||
enobufs_count);
|
||||
|
||||
close(s);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
558
canlogserver.c
558
canlogserver.c
|
|
@ -86,68 +86,68 @@ static volatile int running = 1;
|
|||
|
||||
void print_usage(char *prg)
|
||||
{
|
||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
||||
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
||||
fprintf(stderr, "Options: -m <mask> (ID filter mask. Default 0x00000000) *\n");
|
||||
fprintf(stderr, " -v <value> (ID filter value. Default 0x00000000) *\n");
|
||||
fprintf(stderr, " -i <0|1> (invert the specified ID filter) *\n");
|
||||
fprintf(stderr, " -e <emask> (mask for error frames)\n");
|
||||
fprintf(stderr, " -p <port> (listen on port <port>. Default: %d)\n", DEFPORT);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "* The CAN ID filter matches, when ...\n");
|
||||
fprintf(stderr, " <received_can_id> & mask == value & mask\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "When using more than one CAN interface the options\n");
|
||||
fprintf(stderr, "m/v/i/e have comma seperated values e.g. '-m 0,7FF,0'\n");
|
||||
fprintf(stderr, "\nUse interface name '%s' to receive from all CAN interfaces.\n\n", ANYDEV);
|
||||
fprintf(stderr, "\nUsage: %s [options] <CAN interface>+\n", prg);
|
||||
fprintf(stderr, " (use CTRL-C to terminate %s)\n\n", prg);
|
||||
fprintf(stderr, "Options: -m <mask> (ID filter mask. Default 0x00000000) *\n");
|
||||
fprintf(stderr, " -v <value> (ID filter value. Default 0x00000000) *\n");
|
||||
fprintf(stderr, " -i <0|1> (invert the specified ID filter) *\n");
|
||||
fprintf(stderr, " -e <emask> (mask for error frames)\n");
|
||||
fprintf(stderr, " -p <port> (listen on port <port>. Default: %d)\n", DEFPORT);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "* The CAN ID filter matches, when ...\n");
|
||||
fprintf(stderr, " <received_can_id> & mask == value & mask\n");
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "When using more than one CAN interface the options\n");
|
||||
fprintf(stderr, "m/v/i/e have comma seperated values e.g. '-m 0,7FF,0'\n");
|
||||
fprintf(stderr, "\nUse interface name '%s' to receive from all CAN interfaces.\n\n", ANYDEV);
|
||||
}
|
||||
|
||||
int idx2dindex(int ifidx, int socket)
|
||||
{
|
||||
int i;
|
||||
struct ifreq ifr;
|
||||
int i;
|
||||
struct ifreq ifr;
|
||||
|
||||
for (i=0; i<MAXDEV; i++) {
|
||||
if (dindex[i] == ifidx)
|
||||
return i;
|
||||
}
|
||||
|
||||
/* create new interface index cache entry */
|
||||
|
||||
/* remove index cache zombies first */
|
||||
for (i=0; i < MAXDEV; i++) {
|
||||
if (dindex[i]) {
|
||||
ifr.ifr_ifindex = dindex[i];
|
||||
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
||||
dindex[i] = 0;
|
||||
for (i=0; i<MAXDEV; i++) {
|
||||
if (dindex[i] == ifidx)
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i < MAXDEV; i++)
|
||||
if (!dindex[i]) /* free entry */
|
||||
break;
|
||||
/* create new interface index cache entry */
|
||||
|
||||
if (i == MAXDEV) {
|
||||
printf("Interface index cache only supports %d interfaces.\n", MAXDEV);
|
||||
exit(1);
|
||||
}
|
||||
/* remove index cache zombies first */
|
||||
for (i=0; i < MAXDEV; i++) {
|
||||
if (dindex[i]) {
|
||||
ifr.ifr_ifindex = dindex[i];
|
||||
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
||||
dindex[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
dindex[i] = ifidx;
|
||||
for (i=0; i < MAXDEV; i++)
|
||||
if (!dindex[i]) /* free entry */
|
||||
break;
|
||||
|
||||
ifr.ifr_ifindex = ifidx;
|
||||
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
||||
perror("SIOCGIFNAME");
|
||||
if (i == MAXDEV) {
|
||||
printf("Interface index cache only supports %d interfaces.\n", MAXDEV);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (max_devname_len < strlen(ifr.ifr_name))
|
||||
max_devname_len = strlen(ifr.ifr_name);
|
||||
dindex[i] = ifidx;
|
||||
|
||||
strcpy(devname[i], ifr.ifr_name);
|
||||
ifr.ifr_ifindex = ifidx;
|
||||
if (ioctl(socket, SIOCGIFNAME, &ifr) < 0)
|
||||
perror("SIOCGIFNAME");
|
||||
|
||||
if (max_devname_len < strlen(ifr.ifr_name))
|
||||
max_devname_len = strlen(ifr.ifr_name);
|
||||
|
||||
strcpy(devname[i], ifr.ifr_name);
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("new index %d (%s)\n", i, devname[i]);
|
||||
printf("new index %d (%s)\n", i, devname[i]);
|
||||
#endif
|
||||
|
||||
return i;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -156,7 +156,7 @@ int idx2dindex(int ifidx, int socket)
|
|||
*/
|
||||
void childdied(int i)
|
||||
{
|
||||
wait(NULL);
|
||||
wait(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -164,273 +164,273 @@ void childdied(int i)
|
|||
*/
|
||||
void shutdown_gra(int i)
|
||||
{
|
||||
exit(0);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct sigaction signalaction;
|
||||
sigset_t sigset;
|
||||
fd_set rdfs;
|
||||
int s[MAXDEV];
|
||||
int socki, accsocket;
|
||||
canid_t mask[MAXDEV] = {0};
|
||||
canid_t value[MAXDEV] = {0};
|
||||
int inv_filter[MAXDEV] = {0};
|
||||
can_err_mask_t err_mask[MAXDEV] = {0};
|
||||
int opt, ret;
|
||||
int currmax = 1; /* we assume at least one can bus ;-) */
|
||||
struct sockaddr_can addr;
|
||||
struct can_filter rfilter;
|
||||
struct can_frame frame;
|
||||
int nbytes, i, j;
|
||||
struct ifreq ifr;
|
||||
struct timeval tv, last_tv;
|
||||
int port = DEFPORT;
|
||||
struct sockaddr_in inaddr;
|
||||
struct sockaddr_in clientaddr;
|
||||
socklen_t sin_size = sizeof(clientaddr);
|
||||
char temp[128];
|
||||
struct sigaction signalaction;
|
||||
sigset_t sigset;
|
||||
fd_set rdfs;
|
||||
int s[MAXDEV];
|
||||
int socki, accsocket;
|
||||
canid_t mask[MAXDEV] = {0};
|
||||
canid_t value[MAXDEV] = {0};
|
||||
int inv_filter[MAXDEV] = {0};
|
||||
can_err_mask_t err_mask[MAXDEV] = {0};
|
||||
int opt, ret;
|
||||
int currmax = 1; /* we assume at least one can bus ;-) */
|
||||
struct sockaddr_can addr;
|
||||
struct can_filter rfilter;
|
||||
struct can_frame frame;
|
||||
int nbytes, i, j;
|
||||
struct ifreq ifr;
|
||||
struct timeval tv, last_tv;
|
||||
int port = DEFPORT;
|
||||
struct sockaddr_in inaddr;
|
||||
struct sockaddr_in clientaddr;
|
||||
socklen_t sin_size = sizeof(clientaddr);
|
||||
char temp[128];
|
||||
|
||||
sigemptyset(&sigset);
|
||||
signalaction.sa_handler = &childdied;
|
||||
signalaction.sa_mask = sigset;
|
||||
signalaction.sa_flags = 0;
|
||||
sigaction(SIGCHLD, &signalaction, NULL); /* install signal for dying child */
|
||||
signalaction.sa_handler = &shutdown_gra;
|
||||
signalaction.sa_mask = sigset;
|
||||
signalaction.sa_flags = 0;
|
||||
sigaction(SIGTERM, &signalaction, NULL); /* install Signal for termination */
|
||||
sigaction(SIGINT, &signalaction, NULL); /* install Signal for termination */
|
||||
sigemptyset(&sigset);
|
||||
signalaction.sa_handler = &childdied;
|
||||
signalaction.sa_mask = sigset;
|
||||
signalaction.sa_flags = 0;
|
||||
sigaction(SIGCHLD, &signalaction, NULL); /* install signal for dying child */
|
||||
signalaction.sa_handler = &shutdown_gra;
|
||||
signalaction.sa_mask = sigset;
|
||||
signalaction.sa_flags = 0;
|
||||
sigaction(SIGTERM, &signalaction, NULL); /* install Signal for termination */
|
||||
sigaction(SIGINT, &signalaction, NULL); /* install Signal for termination */
|
||||
|
||||
|
||||
last_tv.tv_sec = 0;
|
||||
last_tv.tv_usec = 0;
|
||||
last_tv.tv_sec = 0;
|
||||
last_tv.tv_usec = 0;
|
||||
|
||||
while ((opt = getopt(argc, argv, "m:v:i:e:p:?")) != -1) {
|
||||
while ((opt = getopt(argc, argv, "m:v:i:e:p:?")) != -1) {
|
||||
|
||||
switch (opt) {
|
||||
case 'm':
|
||||
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
|
||||
&mask[0], &mask[1], &mask[2],
|
||||
&mask[3], &mask[4], &mask[5]);
|
||||
if (i > currmax)
|
||||
currmax = i;
|
||||
break;
|
||||
switch (opt) {
|
||||
case 'm':
|
||||
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
|
||||
&mask[0], &mask[1], &mask[2],
|
||||
&mask[3], &mask[4], &mask[5]);
|
||||
if (i > currmax)
|
||||
currmax = i;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
|
||||
&value[0], &value[1], &value[2],
|
||||
&value[3], &value[4], &value[5]);
|
||||
if (i > currmax)
|
||||
currmax = i;
|
||||
break;
|
||||
case 'v':
|
||||
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
|
||||
&value[0], &value[1], &value[2],
|
||||
&value[3], &value[4], &value[5]);
|
||||
if (i > currmax)
|
||||
currmax = i;
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
i = sscanf(optarg, "%d,%d,%d,%d,%d,%d",
|
||||
&inv_filter[0], &inv_filter[1], &inv_filter[2],
|
||||
&inv_filter[3], &inv_filter[4], &inv_filter[5]);
|
||||
if (i > currmax)
|
||||
currmax = i;
|
||||
break;
|
||||
case 'i':
|
||||
i = sscanf(optarg, "%d,%d,%d,%d,%d,%d",
|
||||
&inv_filter[0], &inv_filter[1], &inv_filter[2],
|
||||
&inv_filter[3], &inv_filter[4], &inv_filter[5]);
|
||||
if (i > currmax)
|
||||
currmax = i;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
|
||||
&err_mask[0], &err_mask[1], &err_mask[2],
|
||||
&err_mask[3], &err_mask[4], &err_mask[5]);
|
||||
if (i > currmax)
|
||||
currmax = i;
|
||||
break;
|
||||
case 'p':
|
||||
port = atoi(optarg);
|
||||
break;
|
||||
default:
|
||||
print_usage(basename(argv[0]));
|
||||
exit(1);
|
||||
break;
|
||||
case 'e':
|
||||
i = sscanf(optarg, "%x,%x,%x,%x,%x,%x",
|
||||
&err_mask[0], &err_mask[1], &err_mask[2],
|
||||
&err_mask[3], &err_mask[4], &err_mask[5]);
|
||||
if (i > currmax)
|
||||
currmax = i;
|
||||
break;
|
||||
case 'p':
|
||||
port = atoi(optarg);
|
||||
break;
|
||||
default:
|
||||
print_usage(basename(argv[0]));
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (optind == argc) {
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* count in options higher than device count ? */
|
||||
if (optind + currmax > argc) {
|
||||
printf("low count of CAN devices!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
currmax = argc - optind; /* find real number of CAN devices */
|
||||
|
||||
if (currmax > MAXDEV) {
|
||||
printf("More than %d CAN devices!\n", MAXDEV);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
socki = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (socki < 0) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
inaddr.sin_family = AF_INET;
|
||||
inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
inaddr.sin_port = htons(port);
|
||||
|
||||
while(bind(socki, (struct sockaddr*)&inaddr, sizeof(inaddr)) < 0) {
|
||||
printf(".");fflush(NULL);
|
||||
usleep(100000);
|
||||
}
|
||||
|
||||
if (listen(socki, 3) != 0) {
|
||||
perror("listen");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
accsocket = accept(socki, (struct sockaddr*)&clientaddr, &sin_size);
|
||||
if (accsocket > 0) {
|
||||
//printf("accepted\n");
|
||||
if (!fork())
|
||||
break;
|
||||
else
|
||||
close(accsocket);
|
||||
if (optind == argc) {
|
||||
print_usage(basename(argv[0]));
|
||||
exit(0);
|
||||
}
|
||||
else if (errno != EINTR) {
|
||||
perror("accept");
|
||||
exit(1);
|
||||
|
||||
/* count in options higher than device count ? */
|
||||
if (optind + currmax > argc) {
|
||||
printf("low count of CAN devices!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
currmax = argc - optind; /* find real number of CAN devices */
|
||||
|
||||
if (currmax > MAXDEV) {
|
||||
printf("More than %d CAN devices!\n", MAXDEV);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
socki = socket(PF_INET, SOCK_STREAM, 0);
|
||||
if (socki < 0) {
|
||||
perror("socket");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
inaddr.sin_family = AF_INET;
|
||||
inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
inaddr.sin_port = htons(port);
|
||||
|
||||
while(bind(socki, (struct sockaddr*)&inaddr, sizeof(inaddr)) < 0) {
|
||||
printf(".");fflush(NULL);
|
||||
usleep(100000);
|
||||
}
|
||||
|
||||
if (listen(socki, 3) != 0) {
|
||||
perror("listen");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while(1) {
|
||||
accsocket = accept(socki, (struct sockaddr*)&clientaddr, &sin_size);
|
||||
if (accsocket > 0) {
|
||||
//printf("accepted\n");
|
||||
if (!fork())
|
||||
break;
|
||||
else
|
||||
close(accsocket);
|
||||
}
|
||||
else if (errno != EINTR) {
|
||||
perror("accept");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<currmax; i++) {
|
||||
for (i=0; i<currmax; i++) {
|
||||
|
||||
#ifdef DEBUG
|
||||
printf("open %d '%s' m%08X v%08X i%d e%d.\n",
|
||||
i, argv[optind+i], mask[i], value[i],
|
||||
inv_filter[i], err_mask[i]);
|
||||
printf("open %d '%s' m%08X v%08X i%d e%d.\n",
|
||||
i, argv[optind+i], mask[i], value[i],
|
||||
inv_filter[i], err_mask[i]);
|
||||
#endif
|
||||
|
||||
if ((s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (mask[i] || value[i]) {
|
||||
|
||||
printf("CAN ID filter[%d] for %s set to "
|
||||
"mask = %08X, value = %08X %s\n",
|
||||
i, argv[optind+i], mask[i], value[i],
|
||||
(inv_filter[i]) ? "(inv_filter)" : "");
|
||||
|
||||
rfilter.can_id = value[i];
|
||||
rfilter.can_mask = mask[i];
|
||||
if (inv_filter[i])
|
||||
rfilter.can_id |= CAN_INV_FILTER;
|
||||
|
||||
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
|
||||
&rfilter, sizeof(rfilter));
|
||||
}
|
||||
|
||||
if (err_mask[i])
|
||||
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
|
||||
&err_mask[i], sizeof(err_mask[i]));
|
||||
|
||||
j = strlen(argv[optind+i]);
|
||||
|
||||
if (!(j < IFNAMSIZ)) {
|
||||
printf("name of CAN device '%s' is too long!\n", argv[optind+i]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (j > max_devname_len)
|
||||
max_devname_len = j; /* for nice printing */
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
|
||||
if (strcmp(ANYDEV, argv[optind+i])) {
|
||||
strcpy(ifr.ifr_name, argv[optind+i]);
|
||||
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
|
||||
perror("SIOCGIFINDEX");
|
||||
exit(1);
|
||||
}
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
}
|
||||
else
|
||||
addr.can_ifindex = 0; /* any can interface */
|
||||
|
||||
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bindcan");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (running) {
|
||||
|
||||
FD_ZERO(&rdfs);
|
||||
for (i=0; i<currmax; i++)
|
||||
FD_SET(s[i], &rdfs);
|
||||
|
||||
if ((ret = select(s[currmax-1]+1, &rdfs, NULL, NULL, NULL)) < 0) {
|
||||
//perror("select");
|
||||
running = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
|
||||
|
||||
if (FD_ISSET(s[i], &rdfs)) {
|
||||
|
||||
socklen_t len = sizeof(addr);
|
||||
int idx;
|
||||
|
||||
if ((nbytes = recvfrom(s[i], &frame,
|
||||
sizeof(struct can_frame), 0,
|
||||
(struct sockaddr*)&addr, &len)) < 0) {
|
||||
perror("read");
|
||||
return 1;
|
||||
if ((s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nbytes < sizeof(struct can_frame)) {
|
||||
fprintf(stderr, "read: incomplete CAN frame\n");
|
||||
return 1;
|
||||
if (mask[i] || value[i]) {
|
||||
|
||||
printf("CAN ID filter[%d] for %s set to "
|
||||
"mask = %08X, value = %08X %s\n",
|
||||
i, argv[optind+i], mask[i], value[i],
|
||||
(inv_filter[i]) ? "(inv_filter)" : "");
|
||||
|
||||
rfilter.can_id = value[i];
|
||||
rfilter.can_mask = mask[i];
|
||||
if (inv_filter[i])
|
||||
rfilter.can_id |= CAN_INV_FILTER;
|
||||
|
||||
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_FILTER,
|
||||
&rfilter, sizeof(rfilter));
|
||||
}
|
||||
|
||||
if (ioctl(s[i], SIOCGSTAMP, &tv) < 0)
|
||||
perror("SIOCGSTAMP");
|
||||
if (err_mask[i])
|
||||
setsockopt(s[i], SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
|
||||
&err_mask[i], sizeof(err_mask[i]));
|
||||
|
||||
j = strlen(argv[optind+i]);
|
||||
|
||||
idx = idx2dindex(addr.can_ifindex, s[i]);
|
||||
|
||||
sprintf(temp, "(%ld.%06ld) %*s ",
|
||||
tv.tv_sec, tv.tv_usec, max_devname_len, devname[idx]);
|
||||
sprint_canframe(temp+strlen(temp), &frame, 0);
|
||||
strcat(temp, "\n");
|
||||
|
||||
if (write(accsocket, temp, strlen(temp)) < 0) {
|
||||
perror("writeaccsock");
|
||||
return 1;
|
||||
if (!(j < IFNAMSIZ)) {
|
||||
printf("name of CAN device '%s' is too long!\n", argv[optind+i]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (j > max_devname_len)
|
||||
max_devname_len = j; /* for nice printing */
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
|
||||
if (strcmp(ANYDEV, argv[optind+i])) {
|
||||
strcpy(ifr.ifr_name, argv[optind+i]);
|
||||
if (ioctl(s[i], SIOCGIFINDEX, &ifr) < 0) {
|
||||
perror("SIOCGIFINDEX");
|
||||
exit(1);
|
||||
}
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
}
|
||||
else
|
||||
addr.can_ifindex = 0; /* any can interface */
|
||||
|
||||
if (bind(s[i], (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bindcan");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (running) {
|
||||
|
||||
FD_ZERO(&rdfs);
|
||||
for (i=0; i<currmax; i++)
|
||||
FD_SET(s[i], &rdfs);
|
||||
|
||||
if ((ret = select(s[currmax-1]+1, &rdfs, NULL, NULL, NULL)) < 0) {
|
||||
//perror("select");
|
||||
running = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i=0; i<currmax; i++) { /* check all CAN RAW sockets */
|
||||
|
||||
if (FD_ISSET(s[i], &rdfs)) {
|
||||
|
||||
socklen_t len = sizeof(addr);
|
||||
int idx;
|
||||
|
||||
if ((nbytes = recvfrom(s[i], &frame,
|
||||
sizeof(struct can_frame), 0,
|
||||
(struct sockaddr*)&addr, &len)) < 0) {
|
||||
perror("read");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (nbytes < sizeof(struct can_frame)) {
|
||||
fprintf(stderr, "read: incomplete CAN frame\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (ioctl(s[i], SIOCGSTAMP, &tv) < 0)
|
||||
perror("SIOCGSTAMP");
|
||||
|
||||
|
||||
idx = idx2dindex(addr.can_ifindex, s[i]);
|
||||
|
||||
sprintf(temp, "(%ld.%06ld) %*s ",
|
||||
tv.tv_sec, tv.tv_usec, max_devname_len, devname[idx]);
|
||||
sprint_canframe(temp+strlen(temp), &frame, 0);
|
||||
strcat(temp, "\n");
|
||||
|
||||
if (write(accsocket, temp, strlen(temp)) < 0) {
|
||||
perror("writeaccsock");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* printf("%s\n",temp2); */
|
||||
/* printf("%s\n",temp2); */
|
||||
|
||||
#if 0
|
||||
/* print CAN frame in log file style to stdout */
|
||||
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
||||
printf("%*s ", max_devname_len, devname[idx]);
|
||||
fprint_canframe(stdout, &frame, "\n", 0);
|
||||
/* print CAN frame in log file style to stdout */
|
||||
printf("(%ld.%06ld) ", tv.tv_sec, tv.tv_usec);
|
||||
printf("%*s ", max_devname_len, devname[idx]);
|
||||
fprint_canframe(stdout, &frame, "\n", 0);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i=0; i<currmax; i++)
|
||||
close(s[i]);
|
||||
for (i=0; i<currmax; i++)
|
||||
close(s[i]);
|
||||
|
||||
close(accsocket);
|
||||
return 0;
|
||||
close(accsocket);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
610
canplayer.c
610
canplayer.c
|
|
@ -66,9 +66,9 @@
|
|||
#define BUFSZ 100 /* for one line in the logfile */
|
||||
|
||||
struct assignment {
|
||||
char txif[IFNAMSIZ];
|
||||
int txifidx;
|
||||
char rxif[IFNAMSIZ];
|
||||
char txif[IFNAMSIZ];
|
||||
int txifidx;
|
||||
char rxif[IFNAMSIZ];
|
||||
};
|
||||
static struct assignment asgn[CHANNELS];
|
||||
|
||||
|
|
@ -76,28 +76,28 @@ extern int optind, opterr, optopt;
|
|||
|
||||
void print_usage(char *prg)
|
||||
{
|
||||
fprintf(stderr, "\nUsage: %s <options> [interface assignment]*\n\n", prg);
|
||||
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
|
||||
fprintf(stderr, " -l <num> "
|
||||
"(process input file <num> times)\n"
|
||||
" "
|
||||
"(Use 'i' for infinite loop - default: %d)\n", DEFAULT_LOOPS);
|
||||
fprintf(stderr, " -t (ignore timestamps: "
|
||||
"send frames immediately)\n");
|
||||
fprintf(stderr, " -g <ms> (gap in milli "
|
||||
"seconds - default: %d ms)\n", DEFAULT_GAP);
|
||||
fprintf(stderr, " -s <s> (skip gaps in "
|
||||
"timestamps > 's' seconds)\n");
|
||||
fprintf(stderr, " -x (disable local "
|
||||
"loopback of sent CAN frames)\n");
|
||||
fprintf(stderr, " -v (verbose: print "
|
||||
"sent CAN frames)\n\n");
|
||||
fprintf(stderr, "Interface assignment: 0..n assignments like "
|
||||
"<write-if>=<log-if>\n");
|
||||
fprintf(stderr, "e.g. vcan2=can0 ( send frames received from can0 on "
|
||||
"vcan2 )\n");
|
||||
fprintf(stderr, "No assignments => send frames to the interface(s) they "
|
||||
"had been received from.\n\n");
|
||||
fprintf(stderr, "\nUsage: %s <options> [interface assignment]*\n\n", prg);
|
||||
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
|
||||
fprintf(stderr, " -l <num> "
|
||||
"(process input file <num> times)\n"
|
||||
" "
|
||||
"(Use 'i' for infinite loop - default: %d)\n", DEFAULT_LOOPS);
|
||||
fprintf(stderr, " -t (ignore timestamps: "
|
||||
"send frames immediately)\n");
|
||||
fprintf(stderr, " -g <ms> (gap in milli "
|
||||
"seconds - default: %d ms)\n", DEFAULT_GAP);
|
||||
fprintf(stderr, " -s <s> (skip gaps in "
|
||||
"timestamps > 's' seconds)\n");
|
||||
fprintf(stderr, " -x (disable local "
|
||||
"loopback of sent CAN frames)\n");
|
||||
fprintf(stderr, " -v (verbose: print "
|
||||
"sent CAN frames)\n\n");
|
||||
fprintf(stderr, "Interface assignment: 0..n assignments like "
|
||||
"<write-if>=<log-if>\n");
|
||||
fprintf(stderr, "e.g. vcan2=can0 ( send frames received from can0 on "
|
||||
"vcan2 )\n");
|
||||
fprintf(stderr, "No assignments => send frames to the interface(s) they "
|
||||
"had been received from.\n\n");
|
||||
}
|
||||
|
||||
/* copied from /usr/src/linux/include/linux/time.h ...
|
||||
|
|
@ -107,367 +107,367 @@ void print_usage(char *prg)
|
|||
*/
|
||||
static inline int timeval_compare(struct timeval *lhs, struct timeval *rhs)
|
||||
{
|
||||
if (lhs->tv_sec < rhs->tv_sec)
|
||||
return -1;
|
||||
if (lhs->tv_sec > rhs->tv_sec)
|
||||
return 1;
|
||||
return lhs->tv_usec - rhs->tv_usec;
|
||||
if (lhs->tv_sec < rhs->tv_sec)
|
||||
return -1;
|
||||
if (lhs->tv_sec > rhs->tv_sec)
|
||||
return 1;
|
||||
return lhs->tv_usec - rhs->tv_usec;
|
||||
}
|
||||
|
||||
static inline void create_diff_tv(struct timeval *today, struct timeval *diff,
|
||||
struct timeval *log) {
|
||||
|
||||
/* create diff_tv so that log_tv + diff_tv = today_tv */
|
||||
diff->tv_sec = today->tv_sec - log->tv_sec;
|
||||
diff->tv_usec = today->tv_usec - log->tv_usec;
|
||||
/* create diff_tv so that log_tv + diff_tv = today_tv */
|
||||
diff->tv_sec = today->tv_sec - log->tv_sec;
|
||||
diff->tv_usec = today->tv_usec - log->tv_usec;
|
||||
}
|
||||
|
||||
static inline int frames_to_send(struct timeval *today, struct timeval *diff,
|
||||
struct timeval *log)
|
||||
{
|
||||
/* return value <0 when log + diff < today */
|
||||
/* return value <0 when log + diff < today */
|
||||
|
||||
struct timeval cmp;
|
||||
struct timeval cmp;
|
||||
|
||||
cmp.tv_sec = log->tv_sec + diff->tv_sec;
|
||||
cmp.tv_usec = log->tv_usec + diff->tv_usec;
|
||||
cmp.tv_sec = log->tv_sec + diff->tv_sec;
|
||||
cmp.tv_usec = log->tv_usec + diff->tv_usec;
|
||||
|
||||
if (cmp.tv_usec > 1000000) {
|
||||
cmp.tv_usec -= 1000000;
|
||||
cmp.tv_sec++;
|
||||
}
|
||||
if (cmp.tv_usec > 1000000) {
|
||||
cmp.tv_usec -= 1000000;
|
||||
cmp.tv_sec++;
|
||||
}
|
||||
|
||||
if (cmp.tv_usec < 0) {
|
||||
cmp.tv_usec += 1000000;
|
||||
cmp.tv_sec--;
|
||||
}
|
||||
if (cmp.tv_usec < 0) {
|
||||
cmp.tv_usec += 1000000;
|
||||
cmp.tv_sec--;
|
||||
}
|
||||
|
||||
return timeval_compare(&cmp, today);
|
||||
return timeval_compare(&cmp, today);
|
||||
}
|
||||
|
||||
int get_txidx(char *logif_name) {
|
||||
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for (i=0; i<CHANNELS; i++) {
|
||||
if (asgn[i].rxif[0] == 0) /* end of table content */
|
||||
break;
|
||||
if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */
|
||||
break;
|
||||
}
|
||||
for (i=0; i<CHANNELS; i++) {
|
||||
if (asgn[i].rxif[0] == 0) /* end of table content */
|
||||
break;
|
||||
if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */
|
||||
break;
|
||||
}
|
||||
|
||||
if ((i == CHANNELS) || (asgn[i].rxif[0] == 0))
|
||||
return 0; /* not found */
|
||||
if ((i == CHANNELS) || (asgn[i].rxif[0] == 0))
|
||||
return 0; /* not found */
|
||||
|
||||
return asgn[i].txifidx; /* return interface index */
|
||||
return asgn[i].txifidx; /* return interface index */
|
||||
}
|
||||
|
||||
char *get_txname(char *logif_name) {
|
||||
|
||||
int i;
|
||||
int i;
|
||||
|
||||
for (i=0; i<CHANNELS; i++) {
|
||||
if (asgn[i].rxif[0] == 0) /* end of table content */
|
||||
break;
|
||||
if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */
|
||||
break;
|
||||
}
|
||||
for (i=0; i<CHANNELS; i++) {
|
||||
if (asgn[i].rxif[0] == 0) /* end of table content */
|
||||
break;
|
||||
if (strcmp(asgn[i].rxif, logif_name) == 0) /* found device name */
|
||||
break;
|
||||
}
|
||||
|
||||
if ((i == CHANNELS) || (asgn[i].rxif[0] == 0))
|
||||
return 0; /* not found */
|
||||
if ((i == CHANNELS) || (asgn[i].rxif[0] == 0))
|
||||
return 0; /* not found */
|
||||
|
||||
return asgn[i].txif; /* return interface name */
|
||||
return asgn[i].txif; /* return interface name */
|
||||
}
|
||||
|
||||
int add_assignment(char *mode, int socket, char *txname, char *rxname,
|
||||
int verbose) {
|
||||
|
||||
struct ifreq ifr;
|
||||
int i;
|
||||
struct ifreq ifr;
|
||||
int i;
|
||||
|
||||
/* find free entry */
|
||||
for (i=0; i<CHANNELS; i++) {
|
||||
if (asgn[i].txif[0] == 0)
|
||||
break;
|
||||
}
|
||||
/* find free entry */
|
||||
for (i=0; i<CHANNELS; i++) {
|
||||
if (asgn[i].txif[0] == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i == CHANNELS) {
|
||||
fprintf(stderr, "Assignment table exceeded!\n");
|
||||
return 1;
|
||||
}
|
||||
if (i == CHANNELS) {
|
||||
fprintf(stderr, "Assignment table exceeded!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (strlen(txname) >= IFNAMSIZ) {
|
||||
fprintf(stderr, "write-if interface name '%s' too long!", txname);
|
||||
return 1;
|
||||
}
|
||||
strcpy(asgn[i].txif, txname);
|
||||
if (strlen(txname) >= IFNAMSIZ) {
|
||||
fprintf(stderr, "write-if interface name '%s' too long!", txname);
|
||||
return 1;
|
||||
}
|
||||
strcpy(asgn[i].txif, txname);
|
||||
|
||||
if (strlen(rxname) >= IFNAMSIZ) {
|
||||
fprintf(stderr, "log-if interface name '%s' too long!", rxname);
|
||||
return 1;
|
||||
}
|
||||
strcpy(asgn[i].rxif, rxname);
|
||||
if (strlen(rxname) >= IFNAMSIZ) {
|
||||
fprintf(stderr, "log-if interface name '%s' too long!", rxname);
|
||||
return 1;
|
||||
}
|
||||
strcpy(asgn[i].rxif, rxname);
|
||||
|
||||
strcpy(ifr.ifr_name, txname);
|
||||
if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0) {
|
||||
perror("SIOCGIFINDEX");
|
||||
fprintf(stderr, "write-if interface name '%s' is wrong!\n", txname);
|
||||
return 1;
|
||||
}
|
||||
asgn[i].txifidx = ifr.ifr_ifindex;
|
||||
strcpy(ifr.ifr_name, txname);
|
||||
if (ioctl(socket, SIOCGIFINDEX, &ifr) < 0) {
|
||||
perror("SIOCGIFINDEX");
|
||||
fprintf(stderr, "write-if interface name '%s' is wrong!\n", txname);
|
||||
return 1;
|
||||
}
|
||||
asgn[i].txifidx = ifr.ifr_ifindex;
|
||||
|
||||
if (verbose > 1) /* use -v -v to see this */
|
||||
printf("added %s assignment: log-if=%s write-if=%s write-if-idx=%d\n",
|
||||
mode, asgn[i].rxif, asgn[i].txif, asgn[i].txifidx);
|
||||
if (verbose > 1) /* use -v -v to see this */
|
||||
printf("added %s assignment: log-if=%s write-if=%s write-if-idx=%d\n",
|
||||
mode, asgn[i].rxif, asgn[i].txif, asgn[i].txifidx);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ];
|
||||
struct sockaddr_can addr;
|
||||
static struct can_frame frame;
|
||||
static struct timeval today_tv, log_tv, last_log_tv, diff_tv;
|
||||
struct timespec sleep_ts;
|
||||
int s; /* CAN_RAW socket */
|
||||
FILE *infile = stdin;
|
||||
unsigned long gap = DEFAULT_GAP;
|
||||
int use_timestamps = 1;
|
||||
static int verbose, opt, delay_loops, skipgap;
|
||||
static int loopback_disable = 0;
|
||||
static int infinite_loops = 0;
|
||||
static int loops = DEFAULT_LOOPS;
|
||||
int assignments; /* assignments defined on the commandline */
|
||||
int txidx; /* sendto() interface index */
|
||||
int eof, nbytes, i, j;
|
||||
static char buf[BUFSZ], device[BUFSZ], ascframe[BUFSZ];
|
||||
struct sockaddr_can addr;
|
||||
static struct can_frame frame;
|
||||
static struct timeval today_tv, log_tv, last_log_tv, diff_tv;
|
||||
struct timespec sleep_ts;
|
||||
int s; /* CAN_RAW socket */
|
||||
FILE *infile = stdin;
|
||||
unsigned long gap = DEFAULT_GAP;
|
||||
int use_timestamps = 1;
|
||||
static int verbose, opt, delay_loops, skipgap;
|
||||
static int loopback_disable = 0;
|
||||
static int infinite_loops = 0;
|
||||
static int loops = DEFAULT_LOOPS;
|
||||
int assignments; /* assignments defined on the commandline */
|
||||
int txidx; /* sendto() interface index */
|
||||
int eof, nbytes, i, j;
|
||||
|
||||
while ((opt = getopt(argc, argv, "I:l:tg:s:xv")) != -1) {
|
||||
switch (opt) {
|
||||
case 'I':
|
||||
infile = fopen(optarg, "r");
|
||||
if (!infile) {
|
||||
perror("infile");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
while ((opt = getopt(argc, argv, "I:l:tg:s:xv")) != -1) {
|
||||
switch (opt) {
|
||||
case 'I':
|
||||
infile = fopen(optarg, "r");
|
||||
if (!infile) {
|
||||
perror("infile");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
if (optarg[0] == 'i')
|
||||
infinite_loops = 1;
|
||||
else
|
||||
if (!(loops = atoi(optarg))) {
|
||||
fprintf(stderr, "Invalid argument for option -l !\n");
|
||||
return 1;
|
||||
case 'l':
|
||||
if (optarg[0] == 'i')
|
||||
infinite_loops = 1;
|
||||
else
|
||||
if (!(loops = atoi(optarg))) {
|
||||
fprintf(stderr, "Invalid argument for option -l !\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
use_timestamps = 0;
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
gap = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
skipgap = strtoul(optarg, NULL, 10);
|
||||
if (skipgap < 1) {
|
||||
fprintf(stderr, "Invalid argument for option -s !\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
loopback_disable = 1;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
|
||||
default:
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
use_timestamps = 0;
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
gap = strtoul(optarg, NULL, 10);
|
||||
break;
|
||||
|
||||
case 's':
|
||||
skipgap = strtoul(optarg, NULL, 10);
|
||||
if (skipgap < 1) {
|
||||
fprintf(stderr, "Invalid argument for option -s !\n");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
loopback_disable = 1;
|
||||
break;
|
||||
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
|
||||
default:
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assignments = argc - optind; /* find real number of user assignments */
|
||||
assignments = argc - optind; /* find real number of user assignments */
|
||||
|
||||
if (infile == stdin) { /* no jokes with stdin */
|
||||
infinite_loops = 0;
|
||||
loops = 1;
|
||||
}
|
||||
|
||||
if (verbose > 1) /* use -v -v to see this */
|
||||
if (infinite_loops)
|
||||
printf("infinite_loops\n");
|
||||
else
|
||||
printf("%d loops\n", loops);
|
||||
|
||||
sleep_ts.tv_sec = gap / 1000;
|
||||
sleep_ts.tv_nsec = (gap % 1000) * 1000000;
|
||||
|
||||
/* open socket */
|
||||
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = 0;
|
||||
|
||||
/* disable unneeded default receive filter on this RAW socket */
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
||||
|
||||
if (loopback_disable) {
|
||||
int loopback = 0;
|
||||
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
|
||||
&loopback, sizeof(loopback));
|
||||
}
|
||||
|
||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (assignments) {
|
||||
/* add & check user assginments from commandline */
|
||||
for (i=0; i<assignments; i++) {
|
||||
if (strlen(argv[optind+i]) >= BUFSZ) {
|
||||
fprintf(stderr, "Assignment too long!\n");
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
}
|
||||
strcpy(buf, argv[optind+i]);
|
||||
for (j=0; j<BUFSZ; j++) { /* find '=' in assignment */
|
||||
if (buf[j] == '=')
|
||||
break;
|
||||
}
|
||||
if (buf[j] != '=') {
|
||||
fprintf(stderr, "'=' missing in assignment!\n");
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
}
|
||||
buf[j] = 0; /* cut string in two pieces */
|
||||
if (add_assignment("user", s, &buf[0], &buf[j+1], verbose))
|
||||
return 1;
|
||||
if (infile == stdin) { /* no jokes with stdin */
|
||||
infinite_loops = 0;
|
||||
loops = 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (infinite_loops || loops--) {
|
||||
|
||||
if (infile != stdin)
|
||||
rewind(infile); /* for each loop */
|
||||
|
||||
if (verbose > 1) /* use -v -v to see this */
|
||||
printf (">>>>>>>>> start reading file. remaining loops = %d\n", loops);
|
||||
if (infinite_loops)
|
||||
printf("infinite_loops\n");
|
||||
else
|
||||
printf("%d loops\n", loops);
|
||||
|
||||
if (!fgets(buf, BUFSZ-1, infile)) /* read first frame from logfile */
|
||||
goto out; /* nothing to read */
|
||||
sleep_ts.tv_sec = gap / 1000;
|
||||
sleep_ts.tv_nsec = (gap % 1000) * 1000000;
|
||||
|
||||
eof = 0;
|
||||
|
||||
if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec,
|
||||
device, ascframe) != 4)
|
||||
return 1;
|
||||
|
||||
if (use_timestamps) { /* throttle sending due to logfile timestamps */
|
||||
|
||||
gettimeofday(&today_tv, NULL);
|
||||
create_diff_tv(&today_tv, &diff_tv, &log_tv);
|
||||
last_log_tv = log_tv;
|
||||
/* open socket */
|
||||
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
while (!eof) {
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = 0;
|
||||
|
||||
while ((!use_timestamps) ||
|
||||
(frames_to_send(&today_tv, &diff_tv, &log_tv) < 0)) {
|
||||
/* disable unneeded default receive filter on this RAW socket */
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
||||
|
||||
/* log_tv/device/ascframe are valid here */
|
||||
if (loopback_disable) {
|
||||
int loopback = 0;
|
||||
|
||||
if (strlen(device) >= IFNAMSIZ) {
|
||||
fprintf(stderr, "log interface name '%s' too long!", device);
|
||||
return 1;
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK,
|
||||
&loopback, sizeof(loopback));
|
||||
}
|
||||
|
||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (assignments) {
|
||||
/* add & check user assginments from commandline */
|
||||
for (i=0; i<assignments; i++) {
|
||||
if (strlen(argv[optind+i]) >= BUFSZ) {
|
||||
fprintf(stderr, "Assignment too long!\n");
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
}
|
||||
strcpy(buf, argv[optind+i]);
|
||||
for (j=0; j<BUFSZ; j++) { /* find '=' in assignment */
|
||||
if (buf[j] == '=')
|
||||
break;
|
||||
}
|
||||
if (buf[j] != '=') {
|
||||
fprintf(stderr, "'=' missing in assignment!\n");
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
}
|
||||
buf[j] = 0; /* cut string in two pieces */
|
||||
if (add_assignment("user", s, &buf[0], &buf[j+1], verbose))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
txidx = get_txidx(device); /* get ifindex for sending the frame */
|
||||
|
||||
if ((!txidx) && (!assignments)) {
|
||||
/* ifindex not found and no user assignments */
|
||||
/* => assign this device automatically */
|
||||
if (add_assignment("auto", s, device, device, verbose))
|
||||
return 1;
|
||||
txidx = get_txidx(device);
|
||||
}
|
||||
while (infinite_loops || loops--) {
|
||||
|
||||
if (txidx) { /* only send to valid CAN devices */
|
||||
if (infile != stdin)
|
||||
rewind(infile); /* for each loop */
|
||||
|
||||
if (parse_canframe(ascframe, &frame)) {
|
||||
fprintf(stderr, "wrong CAN frame format: '%s'!", ascframe);
|
||||
return 1;
|
||||
}
|
||||
if (verbose > 1) /* use -v -v to see this */
|
||||
printf (">>>>>>>>> start reading file. remaining loops = %d\n", loops);
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = txidx; /* send via this interface */
|
||||
|
||||
nbytes = sendto(s, &frame, sizeof(struct can_frame), 0,
|
||||
(struct sockaddr*)&addr, sizeof(addr));
|
||||
if (!fgets(buf, BUFSZ-1, infile)) /* read first frame from logfile */
|
||||
goto out; /* nothing to read */
|
||||
|
||||
if (nbytes != sizeof(struct can_frame)) {
|
||||
perror("sendto");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
printf("%s (%s) ", get_txname(device), device);
|
||||
fprint_long_canframe(stdout, &frame, "\n", 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* read next frame from logfile */
|
||||
if (!fgets(buf, BUFSZ-1, infile)) {
|
||||
eof = 1; /* this file is completely processed */
|
||||
break;
|
||||
}
|
||||
eof = 0;
|
||||
|
||||
if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec,
|
||||
device, ascframe) != 4)
|
||||
return 1;
|
||||
return 1;
|
||||
|
||||
if (use_timestamps) {
|
||||
gettimeofday(&today_tv, NULL);
|
||||
if (use_timestamps) { /* throttle sending due to logfile timestamps */
|
||||
|
||||
/* test for logfile timestamps jumping backwards OR */
|
||||
/* if the user likes to skip long gaps in the timestamps */
|
||||
if ((last_log_tv.tv_sec > log_tv.tv_sec) ||
|
||||
(skipgap && abs(last_log_tv.tv_sec - log_tv.tv_sec) > skipgap))
|
||||
gettimeofday(&today_tv, NULL);
|
||||
create_diff_tv(&today_tv, &diff_tv, &log_tv);
|
||||
|
||||
last_log_tv = log_tv;
|
||||
last_log_tv = log_tv;
|
||||
}
|
||||
|
||||
} /* while frames_to_send ... */
|
||||
while (!eof) {
|
||||
|
||||
if (nanosleep(&sleep_ts, NULL))
|
||||
return 1;
|
||||
while ((!use_timestamps) ||
|
||||
(frames_to_send(&today_tv, &diff_tv, &log_tv) < 0)) {
|
||||
|
||||
delay_loops++; /* private statistics */
|
||||
gettimeofday(&today_tv, NULL);
|
||||
/* log_tv/device/ascframe are valid here */
|
||||
|
||||
} /* while (!eof) */
|
||||
if (strlen(device) >= IFNAMSIZ) {
|
||||
fprintf(stderr, "log interface name '%s' too long!", device);
|
||||
return 1;
|
||||
}
|
||||
|
||||
} /* while (infinite_loops || loops--) */
|
||||
txidx = get_txidx(device); /* get ifindex for sending the frame */
|
||||
|
||||
if ((!txidx) && (!assignments)) {
|
||||
/* ifindex not found and no user assignments */
|
||||
/* => assign this device automatically */
|
||||
if (add_assignment("auto", s, device, device, verbose))
|
||||
return 1;
|
||||
txidx = get_txidx(device);
|
||||
}
|
||||
|
||||
out:
|
||||
if (txidx) { /* only send to valid CAN devices */
|
||||
|
||||
close(s);
|
||||
fclose(infile);
|
||||
if (parse_canframe(ascframe, &frame)) {
|
||||
fprintf(stderr, "wrong CAN frame format: '%s'!", ascframe);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (verbose > 1) /* use -v -v to see this */
|
||||
printf("%d delay_loops\n", delay_loops);
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_ifindex = txidx; /* send via this interface */
|
||||
|
||||
nbytes = sendto(s, &frame, sizeof(struct can_frame), 0,
|
||||
(struct sockaddr*)&addr, sizeof(addr));
|
||||
|
||||
return 0;
|
||||
if (nbytes != sizeof(struct can_frame)) {
|
||||
perror("sendto");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
printf("%s (%s) ", get_txname(device), device);
|
||||
fprint_long_canframe(stdout, &frame, "\n", 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* read next frame from logfile */
|
||||
if (!fgets(buf, BUFSZ-1, infile)) {
|
||||
eof = 1; /* this file is completely processed */
|
||||
break;
|
||||
}
|
||||
|
||||
if (sscanf(buf, "(%ld.%ld) %s %s", &log_tv.tv_sec, &log_tv.tv_usec,
|
||||
device, ascframe) != 4)
|
||||
return 1;
|
||||
|
||||
if (use_timestamps) {
|
||||
gettimeofday(&today_tv, NULL);
|
||||
|
||||
/* test for logfile timestamps jumping backwards OR */
|
||||
/* if the user likes to skip long gaps in the timestamps */
|
||||
if ((last_log_tv.tv_sec > log_tv.tv_sec) ||
|
||||
(skipgap && abs(last_log_tv.tv_sec - log_tv.tv_sec) > skipgap))
|
||||
create_diff_tv(&today_tv, &diff_tv, &log_tv);
|
||||
|
||||
last_log_tv = log_tv;
|
||||
}
|
||||
|
||||
} /* while frames_to_send ... */
|
||||
|
||||
if (nanosleep(&sleep_ts, NULL))
|
||||
return 1;
|
||||
|
||||
delay_loops++; /* private statistics */
|
||||
gettimeofday(&today_tv, NULL);
|
||||
|
||||
} /* while (!eof) */
|
||||
|
||||
} /* while (infinite_loops || loops--) */
|
||||
|
||||
out:
|
||||
|
||||
close(s);
|
||||
fclose(infile);
|
||||
|
||||
if (verbose > 1) /* use -v -v to see this */
|
||||
printf("%d delay_loops\n", delay_loops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
102
cansend.c
102
cansend.c
|
|
@ -60,66 +60,66 @@
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int s; /* can raw socket */
|
||||
int nbytes;
|
||||
struct sockaddr_can addr;
|
||||
struct can_frame frame;
|
||||
struct ifreq ifr;
|
||||
int s; /* can raw socket */
|
||||
int nbytes;
|
||||
struct sockaddr_can addr;
|
||||
struct can_frame frame;
|
||||
struct ifreq ifr;
|
||||
|
||||
/* check command line options */
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: %s <device> <can_frame>.\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
/* check command line options */
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: %s <device> <can_frame>.\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* parse CAN frame */
|
||||
if (parse_canframe(argv[2], &frame)){
|
||||
fprintf(stderr, "\nWrong CAN-frame format!\n\n");
|
||||
fprintf(stderr, "Try: <can_id>#{R|data}\n");
|
||||
fprintf(stderr, "can_id can have 3 (SFF) or 8 (EFF) hex chars\n");
|
||||
fprintf(stderr, "data has 0 to 8 hex-values that can (optionally)");
|
||||
fprintf(stderr, " be seperated by '.'\n\n");
|
||||
fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / ");
|
||||
fprintf(stderr, "5AA# /\n 1F334455#1122334455667788 / 123#R ");
|
||||
fprintf(stderr, "for remote transmission request.\n\n");
|
||||
return 1;
|
||||
}
|
||||
/* parse CAN frame */
|
||||
if (parse_canframe(argv[2], &frame)){
|
||||
fprintf(stderr, "\nWrong CAN-frame format!\n\n");
|
||||
fprintf(stderr, "Try: <can_id>#{R|data}\n");
|
||||
fprintf(stderr, "can_id can have 3 (SFF) or 8 (EFF) hex chars\n");
|
||||
fprintf(stderr, "data has 0 to 8 hex-values that can (optionally)");
|
||||
fprintf(stderr, " be seperated by '.'\n\n");
|
||||
fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / ");
|
||||
fprintf(stderr, "5AA# /\n 1F334455#1122334455667788 / 123#R ");
|
||||
fprintf(stderr, "for remote transmission request.\n\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* open socket */
|
||||
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
/* open socket */
|
||||
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
||||
perror("socket");
|
||||
return 1;
|
||||
}
|
||||
|
||||
addr.can_family = AF_CAN;
|
||||
addr.can_family = AF_CAN;
|
||||
|
||||
strcpy(ifr.ifr_name, argv[1]);
|
||||
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
|
||||
perror("SIOCGIFINDEX");
|
||||
return 1;
|
||||
}
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
strcpy(ifr.ifr_name, argv[1]);
|
||||
if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
|
||||
perror("SIOCGIFINDEX");
|
||||
return 1;
|
||||
}
|
||||
addr.can_ifindex = ifr.ifr_ifindex;
|
||||
|
||||
/* disable default receive filter on this RAW socket */
|
||||
/* This is obsolete as we do not read from the socket at all, but for */
|
||||
/* this reason we can remove the receive list in the Kernel to save a */
|
||||
/* little (really a very little!) CPU usage. */
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
||||
/* disable default receive filter on this RAW socket */
|
||||
/* This is obsolete as we do not read from the socket at all, but for */
|
||||
/* this reason we can remove the receive list in the Kernel to save a */
|
||||
/* little (really a very little!) CPU usage. */
|
||||
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
|
||||
|
||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
return 1;
|
||||
}
|
||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||
perror("bind");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* send frame */
|
||||
if ((nbytes = write(s, &frame, sizeof(frame))) != sizeof(frame)) {
|
||||
perror("write");
|
||||
return 1;
|
||||
}
|
||||
/* send frame */
|
||||
if ((nbytes = write(s, &frame, sizeof(frame))) != sizeof(frame)) {
|
||||
perror("write");
|
||||
return 1;
|
||||
}
|
||||
|
||||
//fprint_long_canframe(stdout, &frame, "\n", 0);
|
||||
//fprint_long_canframe(stdout, &frame, "\n", 0);
|
||||
|
||||
close(s);
|
||||
close(s);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
1020
cansniffer.c
1020
cansniffer.c
File diff suppressed because it is too large
Load Diff
278
lib.c
278
lib.c
|
|
@ -61,187 +61,187 @@
|
|||
|
||||
static int asc2nibble(char c) {
|
||||
|
||||
if ((c >= '0') && (c <= '9'))
|
||||
return c - '0';
|
||||
if ((c >= '0') && (c <= '9'))
|
||||
return c - '0';
|
||||
|
||||
if ((c >= 'A') && (c <= 'F'))
|
||||
return c - 'A' + 10;
|
||||
if ((c >= 'A') && (c <= 'F'))
|
||||
return c - 'A' + 10;
|
||||
|
||||
if ((c >= 'a') && (c <= 'f'))
|
||||
return c - 'a' + 10;
|
||||
if ((c >= 'a') && (c <= 'f'))
|
||||
return c - 'a' + 10;
|
||||
|
||||
return 16; /* error */
|
||||
return 16; /* error */
|
||||
}
|
||||
|
||||
int parse_canframe(char *cs, struct can_frame *cf) {
|
||||
/* documentation see lib.h */
|
||||
/* documentation see lib.h */
|
||||
|
||||
int i, idx, dlc, len, tmp;
|
||||
int i, idx, dlc, len, tmp;
|
||||
|
||||
len = strlen(cs);
|
||||
//printf("'%s' len %d\n", cs, len);
|
||||
len = strlen(cs);
|
||||
//printf("'%s' len %d\n", cs, len);
|
||||
|
||||
memset(cf, 0, sizeof(*cf)); /* init CAN frame, e.g. DLC = 0 */
|
||||
memset(cf, 0, sizeof(*cf)); /* init CAN frame, e.g. DLC = 0 */
|
||||
|
||||
if (len < 4)
|
||||
return 1;
|
||||
|
||||
if (!((cs[3] == CANID_DELIM) || (cs[8] == CANID_DELIM)))
|
||||
return 1;
|
||||
|
||||
if (cs[8] == CANID_DELIM) { /* 8 digits */
|
||||
|
||||
idx = 9;
|
||||
for (i=0; i<8; i++){
|
||||
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
||||
if (len < 4)
|
||||
return 1;
|
||||
cf->can_id |= (tmp << (7-i)*4);
|
||||
}
|
||||
if (!(cf->can_id & CAN_ERR_FLAG)) /* 8 digits but no errorframe? */
|
||||
cf->can_id |= CAN_EFF_FLAG; /* then it is an extended frame */
|
||||
|
||||
} else { /* 3 digits */
|
||||
|
||||
idx = 4;
|
||||
for (i=0; i<3; i++){
|
||||
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
||||
if (!((cs[3] == CANID_DELIM) || (cs[8] == CANID_DELIM)))
|
||||
return 1;
|
||||
cf->can_id |= (tmp << (2-i)*4);
|
||||
}
|
||||
}
|
||||
|
||||
if((cs[idx] == 'R') || (cs[idx] == 'r')){ /* RTR frame */
|
||||
cf->can_id |= CAN_RTR_FLAG;
|
||||
if (cs[8] == CANID_DELIM) { /* 8 digits */
|
||||
|
||||
idx = 9;
|
||||
for (i=0; i<8; i++){
|
||||
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
||||
return 1;
|
||||
cf->can_id |= (tmp << (7-i)*4);
|
||||
}
|
||||
if (!(cf->can_id & CAN_ERR_FLAG)) /* 8 digits but no errorframe? */
|
||||
cf->can_id |= CAN_EFF_FLAG; /* then it is an extended frame */
|
||||
|
||||
} else { /* 3 digits */
|
||||
|
||||
idx = 4;
|
||||
for (i=0; i<3; i++){
|
||||
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
||||
return 1;
|
||||
cf->can_id |= (tmp << (2-i)*4);
|
||||
}
|
||||
}
|
||||
|
||||
if((cs[idx] == 'R') || (cs[idx] == 'r')){ /* RTR frame */
|
||||
cf->can_id |= CAN_RTR_FLAG;
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i=0, dlc=0; i<8; i++){
|
||||
|
||||
if(cs[idx] == DATA_SEPERATOR) /* skip (optional) seperator */
|
||||
idx++;
|
||||
|
||||
if(idx >= len) /* end of string => end of data */
|
||||
break;
|
||||
|
||||
if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
|
||||
return 1;
|
||||
cf->data[i] = (tmp << 4);
|
||||
if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
|
||||
return 1;
|
||||
cf->data[i] |= tmp;
|
||||
dlc++;
|
||||
}
|
||||
|
||||
cf->can_dlc = dlc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i=0, dlc=0; i<8; i++){
|
||||
|
||||
if(cs[idx] == DATA_SEPERATOR) /* skip (optional) seperator */
|
||||
idx++;
|
||||
|
||||
if(idx >= len) /* end of string => end of data */
|
||||
break;
|
||||
|
||||
if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
|
||||
return 1;
|
||||
cf->data[i] = (tmp << 4);
|
||||
if ((tmp = asc2nibble(cs[idx++])) > 0x0F)
|
||||
return 1;
|
||||
cf->data[i] |= tmp;
|
||||
dlc++;
|
||||
}
|
||||
|
||||
cf->can_dlc = dlc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void fprint_canframe(FILE *stream , struct can_frame *cf, char *eol, int sep) {
|
||||
/* documentation see lib.h */
|
||||
/* documentation see lib.h */
|
||||
|
||||
char buf[sizeof(MAX_CANFRAME)+1]; /* max length */
|
||||
char buf[sizeof(MAX_CANFRAME)+1]; /* max length */
|
||||
|
||||
sprint_canframe(buf, cf, sep);
|
||||
fprintf(stream, "%s", buf);
|
||||
if (eol)
|
||||
fprintf(stream, "%s", eol);
|
||||
sprint_canframe(buf, cf, sep);
|
||||
fprintf(stream, "%s", buf);
|
||||
if (eol)
|
||||
fprintf(stream, "%s", eol);
|
||||
}
|
||||
|
||||
void sprint_canframe(char *buf , struct can_frame *cf, int sep) {
|
||||
/* documentation see lib.h */
|
||||
/* documentation see lib.h */
|
||||
|
||||
int i,offset;
|
||||
int i,offset;
|
||||
|
||||
if (cf->can_id & CAN_ERR_FLAG) {
|
||||
sprintf(buf, "%08X#", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
|
||||
offset = 9;
|
||||
} else if (cf->can_id & CAN_EFF_FLAG) {
|
||||
sprintf(buf, "%08X#", cf->can_id & CAN_EFF_MASK);
|
||||
offset = 9;
|
||||
} else {
|
||||
sprintf(buf, "%03X#", cf->can_id & CAN_SFF_MASK);
|
||||
offset = 4;
|
||||
}
|
||||
|
||||
if (cf->can_id & CAN_RTR_FLAG) /* there are no ERR frames with RTR */
|
||||
sprintf(buf+offset, "R");
|
||||
else
|
||||
for (i = 0; i < cf->can_dlc; i++) {
|
||||
sprintf(buf+offset, "%02X", cf->data[i]);
|
||||
offset += 2;
|
||||
if (sep && (i+1 < cf->can_dlc))
|
||||
sprintf(buf+offset++, ".");
|
||||
if (cf->can_id & CAN_ERR_FLAG) {
|
||||
sprintf(buf, "%08X#", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
|
||||
offset = 9;
|
||||
} else if (cf->can_id & CAN_EFF_FLAG) {
|
||||
sprintf(buf, "%08X#", cf->can_id & CAN_EFF_MASK);
|
||||
offset = 9;
|
||||
} else {
|
||||
sprintf(buf, "%03X#", cf->can_id & CAN_SFF_MASK);
|
||||
offset = 4;
|
||||
}
|
||||
|
||||
if (cf->can_id & CAN_RTR_FLAG) /* there are no ERR frames with RTR */
|
||||
sprintf(buf+offset, "R");
|
||||
else
|
||||
for (i = 0; i < cf->can_dlc; i++) {
|
||||
sprintf(buf+offset, "%02X", cf->data[i]);
|
||||
offset += 2;
|
||||
if (sep && (i+1 < cf->can_dlc))
|
||||
sprintf(buf+offset++, ".");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void fprint_long_canframe(FILE *stream , struct can_frame *cf, char *eol, int view) {
|
||||
/* documentation see lib.h */
|
||||
/* documentation see lib.h */
|
||||
|
||||
char buf[sizeof(MAX_LONG_CANFRAME)+1]; /* max length */
|
||||
char buf[sizeof(MAX_LONG_CANFRAME)+1]; /* max length */
|
||||
|
||||
sprint_long_canframe(buf, cf, view);
|
||||
fprintf(stream, "%s", buf);
|
||||
if (eol)
|
||||
fprintf(stream, "%s", eol);
|
||||
sprint_long_canframe(buf, cf, view);
|
||||
fprintf(stream, "%s", buf);
|
||||
if (eol)
|
||||
fprintf(stream, "%s", eol);
|
||||
}
|
||||
|
||||
void sprint_long_canframe(char *buf , struct can_frame *cf, int view) {
|
||||
/* documentation see lib.h */
|
||||
/* documentation see lib.h */
|
||||
|
||||
int i, j, dlen, offset;
|
||||
int i, j, dlen, offset;
|
||||
|
||||
if (cf->can_id & CAN_ERR_FLAG) {
|
||||
sprintf(buf, "%8X ", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
|
||||
offset = 10;
|
||||
} else if (cf->can_id & CAN_EFF_FLAG) {
|
||||
sprintf(buf, "%8X ", cf->can_id & CAN_EFF_MASK);
|
||||
offset = 10;
|
||||
} else {
|
||||
sprintf(buf, "%3X ", cf->can_id & CAN_SFF_MASK);
|
||||
offset = 5;
|
||||
}
|
||||
|
||||
sprintf(buf+offset, "[%d]", cf->can_dlc);
|
||||
offset += 3;
|
||||
|
||||
if (cf->can_id & CAN_RTR_FLAG) { /* there are no ERR frames with RTR */
|
||||
sprintf(buf+offset, " remote request");
|
||||
return;
|
||||
}
|
||||
|
||||
if (view & CANLIB_VIEW_BINARY) {
|
||||
dlen = 9; /* _10101010 */
|
||||
for (i = 0; i < cf->can_dlc; i++) {
|
||||
buf[offset++] = ' ';
|
||||
for (j = 7; j >= 0; j--)
|
||||
buf[offset++] = (1<<j & cf->data[i])?'1':'0';
|
||||
if (cf->can_id & CAN_ERR_FLAG) {
|
||||
sprintf(buf, "%8X ", cf->can_id & (CAN_ERR_MASK|CAN_ERR_FLAG));
|
||||
offset = 10;
|
||||
} else if (cf->can_id & CAN_EFF_FLAG) {
|
||||
sprintf(buf, "%8X ", cf->can_id & CAN_EFF_MASK);
|
||||
offset = 10;
|
||||
} else {
|
||||
sprintf(buf, "%3X ", cf->can_id & CAN_SFF_MASK);
|
||||
offset = 5;
|
||||
}
|
||||
buf[offset] = 0; /* terminate string */
|
||||
} else {
|
||||
dlen = 3; /* _AA */
|
||||
for (i = 0; i < cf->can_dlc; i++) {
|
||||
sprintf(buf+offset, " %02X", cf->data[i]);
|
||||
offset += dlen;
|
||||
|
||||
sprintf(buf+offset, "[%d]", cf->can_dlc);
|
||||
offset += 3;
|
||||
|
||||
if (cf->can_id & CAN_RTR_FLAG) { /* there are no ERR frames with RTR */
|
||||
sprintf(buf+offset, " remote request");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (cf->can_id & CAN_ERR_FLAG)
|
||||
sprintf(buf+offset, "%*s", dlen*(8-cf->can_dlc)+13, "ERRORFRAME");
|
||||
else if (view & CANLIB_VIEW_ASCII) {
|
||||
j = dlen*(8-cf->can_dlc)+4;
|
||||
sprintf(buf+offset, "%*s", j, "'");
|
||||
offset += j;
|
||||
if (view & CANLIB_VIEW_BINARY) {
|
||||
dlen = 9; /* _10101010 */
|
||||
for (i = 0; i < cf->can_dlc; i++) {
|
||||
buf[offset++] = ' ';
|
||||
for (j = 7; j >= 0; j--)
|
||||
buf[offset++] = (1<<j & cf->data[i])?'1':'0';
|
||||
}
|
||||
buf[offset] = 0; /* terminate string */
|
||||
} else {
|
||||
dlen = 3; /* _AA */
|
||||
for (i = 0; i < cf->can_dlc; i++) {
|
||||
sprintf(buf+offset, " %02X", cf->data[i]);
|
||||
offset += dlen;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < cf->can_dlc; i++)
|
||||
if ((cf->data[i] > 0x1F) && (cf->data[i] < 0x7F))
|
||||
buf[offset++] = cf->data[i];
|
||||
else
|
||||
buf[offset++] = '.';
|
||||
if (cf->can_id & CAN_ERR_FLAG)
|
||||
sprintf(buf+offset, "%*s", dlen*(8-cf->can_dlc)+13, "ERRORFRAME");
|
||||
else if (view & CANLIB_VIEW_ASCII) {
|
||||
j = dlen*(8-cf->can_dlc)+4;
|
||||
sprintf(buf+offset, "%*s", j, "'");
|
||||
offset += j;
|
||||
|
||||
sprintf(buf+offset, "'");
|
||||
}
|
||||
for (i = 0; i < cf->can_dlc; i++)
|
||||
if ((cf->data[i] > 0x1F) && (cf->data[i] < 0x7F))
|
||||
buf[offset++] = cf->data[i];
|
||||
else
|
||||
buf[offset++] = '.';
|
||||
|
||||
sprintf(buf+offset, "'");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
224
log2asc.c
224
log2asc.c
|
|
@ -60,129 +60,129 @@ extern int optind, opterr, optopt;
|
|||
|
||||
void print_usage(char *prg)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [can-interfaces]\n", prg);
|
||||
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
|
||||
fprintf(stderr, " -O <outfile> (default stdout)\n");
|
||||
fprintf(stderr, " -4 (reduce decimal place to 4 digits)\n");
|
||||
fprintf(stderr, " -n (set newline to cr/lf - default lf)\n");
|
||||
fprintf(stderr, "Usage: %s [can-interfaces]\n", prg);
|
||||
fprintf(stderr, "Options: -I <infile> (default stdin)\n");
|
||||
fprintf(stderr, " -O <outfile> (default stdout)\n");
|
||||
fprintf(stderr, " -4 (reduce decimal place to 4 digits)\n");
|
||||
fprintf(stderr, " -n (set newline to cr/lf - default lf)\n");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char buf[100], device[100], ascframe[100], id[10];
|
||||
char buf[100], device[100], ascframe[100], id[10];
|
||||
|
||||
struct can_frame cf;
|
||||
static struct timeval tv, start_tv;
|
||||
FILE *infile = stdin;
|
||||
FILE *outfile = stdout;
|
||||
static int maxdev, devno, i, crlf, d4, opt;
|
||||
struct can_frame cf;
|
||||
static struct timeval tv, start_tv;
|
||||
FILE *infile = stdin;
|
||||
FILE *outfile = stdout;
|
||||
static int maxdev, devno, i, crlf, d4, opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "I:O:4n")) != -1) {
|
||||
switch (opt) {
|
||||
case 'I':
|
||||
infile = fopen(optarg, "r");
|
||||
if (!infile) {
|
||||
perror("infile");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
while ((opt = getopt(argc, argv, "I:O:4n")) != -1) {
|
||||
switch (opt) {
|
||||
case 'I':
|
||||
infile = fopen(optarg, "r");
|
||||
if (!infile) {
|
||||
perror("infile");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'O':
|
||||
outfile = fopen(optarg, "w");
|
||||
if (!outfile) {
|
||||
perror("outfile");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case 'O':
|
||||
outfile = fopen(optarg, "w");
|
||||
if (!outfile) {
|
||||
perror("outfile");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'n':
|
||||
crlf = 1;
|
||||
break;
|
||||
case 'n':
|
||||
crlf = 1;
|
||||
break;
|
||||
|
||||
case '4':
|
||||
d4 = 1;
|
||||
break;
|
||||
case '4':
|
||||
d4 = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
fprintf(stderr, "Unknown option %c\n", opt);
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
maxdev = argc - optind; /* find real number of CAN devices */
|
||||
|
||||
if (!maxdev) {
|
||||
fprintf(stderr, "no CAN interfaces defined!\n");
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
}
|
||||
|
||||
//printf("Found %d CAN devices!\n", maxdev);
|
||||
|
||||
while (fgets(buf, 99, infile)) {
|
||||
if (sscanf(buf, "(%ld.%ld) %s %s", &tv.tv_sec, &tv.tv_usec,
|
||||
device, ascframe) != 4)
|
||||
return 1;
|
||||
|
||||
if (!start_tv.tv_sec) { /* print banner */
|
||||
start_tv = tv;
|
||||
fprintf(outfile, "date %s", ctime(&start_tv.tv_sec));
|
||||
fprintf(outfile, "base hex timestamps absolute%s",
|
||||
(crlf)?"\r\n":"\n");
|
||||
fprintf(outfile, "no internal events logged%s",
|
||||
(crlf)?"\r\n":"\n");
|
||||
}
|
||||
|
||||
for (i=0, devno=0; i<maxdev; i++) {
|
||||
if (!strcmp(device, argv[optind+i])) {
|
||||
devno = i+1; /* start with channel '1' */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (devno) { /* only convert for selected CAN devices */
|
||||
if (parse_canframe(ascframe, &cf))
|
||||
return 1;
|
||||
|
||||
tv.tv_sec = tv.tv_sec - start_tv.tv_sec;
|
||||
tv.tv_usec = tv.tv_usec - start_tv.tv_usec;
|
||||
if (tv.tv_usec < 0)
|
||||
tv.tv_sec--, tv.tv_usec += 1000000;
|
||||
if (tv.tv_sec < 0)
|
||||
tv.tv_sec = tv.tv_usec = 0;
|
||||
|
||||
if (d4)
|
||||
fprintf(outfile, "%4ld.%04ld ", tv.tv_sec, tv.tv_usec/100);
|
||||
else
|
||||
fprintf(outfile, "%4ld.%06ld ", tv.tv_sec, tv.tv_usec);
|
||||
|
||||
fprintf(outfile, "%-2d ", devno); /* channel number left aligned */
|
||||
|
||||
if (cf.can_id & CAN_ERR_FLAG)
|
||||
fprintf(outfile, "ErrorFrame");
|
||||
else {
|
||||
sprintf(id, "%X%c", cf.can_id & CAN_EFF_MASK,
|
||||
(cf.can_id & CAN_EFF_FLAG)?'x':' ');
|
||||
fprintf(outfile, "%-15s Rx ", id);
|
||||
|
||||
if (cf.can_id & CAN_RTR_FLAG)
|
||||
fprintf(outfile, "r"); /* RTR frame */
|
||||
else {
|
||||
fprintf(outfile, "d %d", cf.can_dlc); /* data frame */
|
||||
|
||||
for (i = 0; i < cf.can_dlc; i++) {
|
||||
fprintf(outfile, " %02X", cf.data[i]);
|
||||
}
|
||||
default:
|
||||
fprintf(stderr, "Unknown option %c\n", opt);
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (crlf)
|
||||
fprintf(outfile, "\r");
|
||||
fprintf(outfile, "\n");
|
||||
}
|
||||
}
|
||||
fflush(outfile);
|
||||
|
||||
return 0;
|
||||
maxdev = argc - optind; /* find real number of CAN devices */
|
||||
|
||||
if (!maxdev) {
|
||||
fprintf(stderr, "no CAN interfaces defined!\n");
|
||||
print_usage(basename(argv[0]));
|
||||
return 1;
|
||||
}
|
||||
|
||||
//printf("Found %d CAN devices!\n", maxdev);
|
||||
|
||||
while (fgets(buf, 99, infile)) {
|
||||
if (sscanf(buf, "(%ld.%ld) %s %s", &tv.tv_sec, &tv.tv_usec,
|
||||
device, ascframe) != 4)
|
||||
return 1;
|
||||
|
||||
if (!start_tv.tv_sec) { /* print banner */
|
||||
start_tv = tv;
|
||||
fprintf(outfile, "date %s", ctime(&start_tv.tv_sec));
|
||||
fprintf(outfile, "base hex timestamps absolute%s",
|
||||
(crlf)?"\r\n":"\n");
|
||||
fprintf(outfile, "no internal events logged%s",
|
||||
(crlf)?"\r\n":"\n");
|
||||
}
|
||||
|
||||
for (i=0, devno=0; i<maxdev; i++) {
|
||||
if (!strcmp(device, argv[optind+i])) {
|
||||
devno = i+1; /* start with channel '1' */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (devno) { /* only convert for selected CAN devices */
|
||||
if (parse_canframe(ascframe, &cf))
|
||||
return 1;
|
||||
|
||||
tv.tv_sec = tv.tv_sec - start_tv.tv_sec;
|
||||
tv.tv_usec = tv.tv_usec - start_tv.tv_usec;
|
||||
if (tv.tv_usec < 0)
|
||||
tv.tv_sec--, tv.tv_usec += 1000000;
|
||||
if (tv.tv_sec < 0)
|
||||
tv.tv_sec = tv.tv_usec = 0;
|
||||
|
||||
if (d4)
|
||||
fprintf(outfile, "%4ld.%04ld ", tv.tv_sec, tv.tv_usec/100);
|
||||
else
|
||||
fprintf(outfile, "%4ld.%06ld ", tv.tv_sec, tv.tv_usec);
|
||||
|
||||
fprintf(outfile, "%-2d ", devno); /* channel number left aligned */
|
||||
|
||||
if (cf.can_id & CAN_ERR_FLAG)
|
||||
fprintf(outfile, "ErrorFrame");
|
||||
else {
|
||||
sprintf(id, "%X%c", cf.can_id & CAN_EFF_MASK,
|
||||
(cf.can_id & CAN_EFF_FLAG)?'x':' ');
|
||||
fprintf(outfile, "%-15s Rx ", id);
|
||||
|
||||
if (cf.can_id & CAN_RTR_FLAG)
|
||||
fprintf(outfile, "r"); /* RTR frame */
|
||||
else {
|
||||
fprintf(outfile, "d %d", cf.can_dlc); /* data frame */
|
||||
|
||||
for (i = 0; i < cf.can_dlc; i++) {
|
||||
fprintf(outfile, " %02X", cf.data[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (crlf)
|
||||
fprintf(outfile, "\r");
|
||||
fprintf(outfile, "\n");
|
||||
}
|
||||
}
|
||||
fflush(outfile);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
22
log2long.c
22
log2long.c
|
|
@ -54,17 +54,17 @@
|
|||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char buf[100], timestamp[100], device[100], ascframe[100];
|
||||
struct can_frame cf;
|
||||
char buf[100], timestamp[100], device[100], ascframe[100];
|
||||
struct can_frame cf;
|
||||
|
||||
while (fgets(buf, 99, stdin)) {
|
||||
if (sscanf(buf, "%s %s %s", timestamp, device, ascframe) != 3)
|
||||
return 1;
|
||||
if (parse_canframe(ascframe, &cf))
|
||||
return 1;
|
||||
sprint_long_canframe(ascframe, &cf, 1); /* with ASCII output */
|
||||
printf("%s %s %s\n", timestamp, device, ascframe);
|
||||
}
|
||||
while (fgets(buf, 99, stdin)) {
|
||||
if (sscanf(buf, "%s %s %s", timestamp, device, ascframe) != 3)
|
||||
return 1;
|
||||
if (parse_canframe(ascframe, &cf))
|
||||
return 1;
|
||||
sprint_long_canframe(ascframe, &cf, 1); /* with ASCII output */
|
||||
printf("%s %s %s\n", timestamp, device, ascframe);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
154
vcan.c
154
vcan.c
|
|
@ -33,15 +33,15 @@
|
|||
|
||||
enum
|
||||
{
|
||||
IFLA_INFO_UNSPEC,
|
||||
IFLA_INFO_NAME,
|
||||
IFLA_INFO_DATA,
|
||||
IFLA_INFO_XSTATS,
|
||||
__IFLA_INFO_MAX,
|
||||
IFLA_INFO_UNSPEC,
|
||||
IFLA_INFO_NAME,
|
||||
IFLA_INFO_DATA,
|
||||
IFLA_INFO_XSTATS,
|
||||
__IFLA_INFO_MAX,
|
||||
};
|
||||
#endif
|
||||
|
||||
#define NLMSG_TAIL(nmsg) \
|
||||
#define NLMSG_TAIL(nmsg) \
|
||||
((struct rtattr *)(((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
|
||||
|
||||
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
|
||||
|
|
@ -49,101 +49,101 @@ int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
|
|||
|
||||
void usage()
|
||||
{
|
||||
fprintf(stderr, "Usage: vcan create\n"
|
||||
" vcan delete iface\n");
|
||||
exit(1);
|
||||
fprintf(stderr, "Usage: vcan create\n"
|
||||
" vcan delete iface\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int s;
|
||||
char *cmd, *dev;
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct ifinfomsg i;
|
||||
char buf[1024];
|
||||
} req;
|
||||
struct sockaddr_nl nladdr;
|
||||
struct rtattr *linkinfo;
|
||||
int s;
|
||||
char *cmd, *dev;
|
||||
struct {
|
||||
struct nlmsghdr n;
|
||||
struct ifinfomsg i;
|
||||
char buf[1024];
|
||||
} req;
|
||||
struct sockaddr_nl nladdr;
|
||||
struct rtattr *linkinfo;
|
||||
|
||||
#ifdef OBSOLETE
|
||||
fprintf(stderr, "This program is a temporary hack and is now obsolete.\n"
|
||||
"Please use ip(8) instead, i.e.\n"
|
||||
" ip link add type vcan or\n"
|
||||
" ip link delete iface\n");
|
||||
exit(1);
|
||||
fprintf(stderr, "This program is a temporary hack and is now obsolete.\n"
|
||||
"Please use ip(8) instead, i.e.\n"
|
||||
" ip link add type vcan or\n"
|
||||
" ip link delete iface\n");
|
||||
exit(1);
|
||||
#endif
|
||||
if (argc < 2)
|
||||
usage();
|
||||
cmd = argv[1];
|
||||
if (argc < 2)
|
||||
usage();
|
||||
cmd = argv[1];
|
||||
|
||||
s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
s = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
|
||||
|
||||
memset(&req, 0, sizeof(req));
|
||||
memset(&req, 0, sizeof(req));
|
||||
|
||||
if (strcmp(cmd, "create") == 0) {
|
||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
|
||||
req.n.nlmsg_type = RTM_NEWLINK;
|
||||
req.n.nlmsg_seq = 0;
|
||||
req.i.ifi_family = AF_UNSPEC;
|
||||
if (strcmp(cmd, "create") == 0) {
|
||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||
req.n.nlmsg_flags = NLM_F_REQUEST | NLM_F_CREATE | NLM_F_EXCL;
|
||||
req.n.nlmsg_type = RTM_NEWLINK;
|
||||
req.n.nlmsg_seq = 0;
|
||||
req.i.ifi_family = AF_UNSPEC;
|
||||
|
||||
linkinfo = NLMSG_TAIL(&req.n);
|
||||
addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
|
||||
addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "vcan", strlen("vcan"));
|
||||
linkinfo->rta_len = (void*)NLMSG_TAIL(&req.n) - (void*)linkinfo;
|
||||
linkinfo = NLMSG_TAIL(&req.n);
|
||||
addattr_l(&req.n, sizeof(req), IFLA_LINKINFO, NULL, 0);
|
||||
addattr_l(&req.n, sizeof(req), IFLA_INFO_KIND, "vcan", strlen("vcan"));
|
||||
linkinfo->rta_len = (void*)NLMSG_TAIL(&req.n) - (void*)linkinfo;
|
||||
|
||||
} else if (strcmp(cmd, "delete") == 0) {
|
||||
if (argc < 3)
|
||||
usage();
|
||||
dev = argv[2];
|
||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||
req.n.nlmsg_flags = NLM_F_REQUEST;
|
||||
req.n.nlmsg_type = RTM_DELLINK;
|
||||
req.i.ifi_family = AF_UNSPEC;
|
||||
req.i.ifi_index = if_nametoindex(dev);
|
||||
} else
|
||||
usage();
|
||||
} else if (strcmp(cmd, "delete") == 0) {
|
||||
if (argc < 3)
|
||||
usage();
|
||||
dev = argv[2];
|
||||
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||
req.n.nlmsg_flags = NLM_F_REQUEST;
|
||||
req.n.nlmsg_type = RTM_DELLINK;
|
||||
req.i.ifi_family = AF_UNSPEC;
|
||||
req.i.ifi_index = if_nametoindex(dev);
|
||||
} else
|
||||
usage();
|
||||
|
||||
memset(&nladdr, 0, sizeof(nladdr));
|
||||
nladdr.nl_family = AF_NETLINK;
|
||||
nladdr.nl_pid = 0;
|
||||
nladdr.nl_groups = 0;
|
||||
memset(&nladdr, 0, sizeof(nladdr));
|
||||
nladdr.nl_family = AF_NETLINK;
|
||||
nladdr.nl_pid = 0;
|
||||
nladdr.nl_groups = 0;
|
||||
#if 1
|
||||
sendto(s, &req, req.n.nlmsg_len, 0,
|
||||
(struct sockaddr*)&nladdr, sizeof(nladdr));
|
||||
sendto(s, &req, req.n.nlmsg_len, 0,
|
||||
(struct sockaddr*)&nladdr, sizeof(nladdr));
|
||||
#else
|
||||
{
|
||||
int i;
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < req.n.nlmsg_len; i++) {
|
||||
printf(" %02x", ((unsigned char*)&req)[i]);
|
||||
if (i % 16 == 15)
|
||||
for (i = 0; i < req.n.nlmsg_len; i++) {
|
||||
printf(" %02x", ((unsigned char*)&req)[i]);
|
||||
if (i % 16 == 15)
|
||||
putchar('\n');
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
putchar('\n');
|
||||
}
|
||||
#endif
|
||||
close(s);
|
||||
close(s);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int addattr_l(struct nlmsghdr *n, int maxlen, int type, const void *data,
|
||||
int alen)
|
||||
{
|
||||
int len = RTA_LENGTH(alen);
|
||||
struct rtattr *rta;
|
||||
int len = RTA_LENGTH(alen);
|
||||
struct rtattr *rta;
|
||||
|
||||
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
|
||||
fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",
|
||||
maxlen);
|
||||
return -1;
|
||||
}
|
||||
rta = NLMSG_TAIL(n);
|
||||
rta->rta_type = type;
|
||||
rta->rta_len = len;
|
||||
memcpy(RTA_DATA(rta), data, alen);
|
||||
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
|
||||
return 0;
|
||||
if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
|
||||
fprintf(stderr, "addattr_l ERROR: message exceeded bound of %d\n",
|
||||
maxlen);
|
||||
return -1;
|
||||
}
|
||||
rta = NLMSG_TAIL(n);
|
||||
rta->rta_type = type;
|
||||
rta->rta_len = len;
|
||||
memcpy(RTA_DATA(rta), data, alen);
|
||||
n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue