184 lines
4.2 KiB
C
184 lines
4.2 KiB
C
/*
|
|
* isotpterm.c - interactive terminal over isotp
|
|
*/
|
|
|
|
#include <errno.h>
|
|
#include <libgen.h>
|
|
#include <linux/can.h>
|
|
#include <linux/can/isotp.h>
|
|
#include <net/if.h>
|
|
#include <netinet/in.h>
|
|
#include <signal.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/ioctl.h>
|
|
#include <sys/socket.h>
|
|
#include <sys/types.h>
|
|
#include <sys/uio.h>
|
|
#include <sys/wait.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
#define NO_CAN_ID 0xFFFFFFFFU
|
|
#define MAX_PDU_LENGTH 8000
|
|
|
|
void print_usage(char *prg) {
|
|
fprintf(stderr,
|
|
"\nUsage: %s -s <can_id> -d <can_id> [options] <CAN interface>\n",
|
|
prg);
|
|
fprintf(stderr, "Options:\n");
|
|
fprintf(stderr,
|
|
" -s <can_id> * (source can_id. Use 8 digits for extended "
|
|
"IDs)\n");
|
|
fprintf(stderr,
|
|
" -d <can_id> * (destination can_id. Use 8 digits for "
|
|
"extended IDs)\n");
|
|
fprintf(stderr, "\n");
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
extern int optind, opterr, optopt;
|
|
int opt;
|
|
|
|
int sc = 0; /* (C)AN socket */
|
|
struct sockaddr_can caddr;
|
|
static struct can_isotp_options opts;
|
|
|
|
socklen_t caddrlen = sizeof(caddr);
|
|
fd_set readfds;
|
|
|
|
int nbytes;
|
|
int ret = 0;
|
|
char *fgetsret = NULL;
|
|
|
|
char txmsg[MAX_PDU_LENGTH];
|
|
char rxmsg[MAX_PDU_LENGTH];
|
|
|
|
/* mark missing mandatory commandline options as missing */
|
|
caddr.can_addr.tp.tx_id = caddr.can_addr.tp.rx_id = NO_CAN_ID;
|
|
|
|
while ((opt = getopt(argc, argv, "s:d:?")) != -1) {
|
|
switch (opt) {
|
|
case 's':
|
|
caddr.can_addr.tp.tx_id = strtoul(optarg, (char **)NULL, 16);
|
|
if (strlen(optarg) > 7) caddr.can_addr.tp.tx_id |= CAN_EFF_FLAG;
|
|
break;
|
|
|
|
case 'd':
|
|
caddr.can_addr.tp.rx_id = strtoul(optarg, (char **)NULL, 16);
|
|
if (strlen(optarg) > 7) caddr.can_addr.tp.rx_id |= CAN_EFF_FLAG;
|
|
break;
|
|
|
|
case '?':
|
|
print_usage(basename(argv[0]));
|
|
ret = 1; /* no proper operation (for non-interactive users) */
|
|
goto exit;
|
|
|
|
default:
|
|
fprintf(stderr, "Unknown option %c\n", opt);
|
|
print_usage(basename(argv[0]));
|
|
ret = 1;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
if ((argc - optind != 1) || (caddr.can_addr.tp.tx_id == NO_CAN_ID) ||
|
|
(caddr.can_addr.tp.rx_id == NO_CAN_ID)) {
|
|
print_usage(basename(argv[0]));
|
|
ret = -EINVAL;
|
|
goto exit;
|
|
}
|
|
|
|
if ((sc = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
|
|
perror("socket");
|
|
ret = sc;
|
|
goto exit;
|
|
}
|
|
|
|
opts.flags = CAN_ISOTP_WAIT_TX_DONE;
|
|
setsockopt(sc, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts));
|
|
|
|
caddr.can_family = AF_CAN;
|
|
caddr.can_ifindex = if_nametoindex(argv[optind]);
|
|
|
|
ret = bind(sc, (struct sockaddr *)&caddr, caddrlen);
|
|
if (ret < 0) {
|
|
perror("bind");
|
|
goto exit;
|
|
}
|
|
|
|
while (1) {
|
|
FD_ZERO(&readfds);
|
|
FD_SET(STDIN_FILENO, &readfds);
|
|
FD_SET(sc, &readfds);
|
|
|
|
ret = select(sc + 1, &readfds, NULL, NULL, NULL);
|
|
if (ret < 0) {
|
|
perror("select");
|
|
goto exit;
|
|
}
|
|
|
|
if (FD_ISSET(sc, &readfds)) {
|
|
nbytes = read(sc, rxmsg, MAX_PDU_LENGTH - 1);
|
|
|
|
if (nbytes < 1) {
|
|
perror("read from isotp socket");
|
|
ret = nbytes;
|
|
goto exit;
|
|
}
|
|
|
|
rxmsg[nbytes] = 0; /* terminate string */
|
|
printf("%s", rxmsg);
|
|
|
|
if(strncmp(rxmsg, "\nwopr", 4)==0){
|
|
send(sc, "falken\n", 7 , 0);
|
|
}
|
|
if(strncmp(rxmsg, "pass", 4)==0){
|
|
send(sc, "Joshua\n", 7 , 0);
|
|
}
|
|
char *s = strstr(rxmsg, "Test#");
|
|
char c;
|
|
int j = 0;
|
|
if(s){
|
|
printf("detected: %c\n", s[18]);
|
|
c = s[18];
|
|
while(s[0] != '\n')
|
|
s++;
|
|
|
|
s = strstr(rxmsg, "\n'");
|
|
for(int i=0; i<strlen(s); i++)
|
|
if(s[i] == c)
|
|
j++;
|
|
|
|
char msg[10];
|
|
sprintf(msg, "%d\n", j);
|
|
printf("aswering: %d\n", j);
|
|
|
|
send(sc, msg, strlen(msg)+1, 0);
|
|
}
|
|
|
|
fflush(stdout);
|
|
|
|
} else if (FD_ISSET(STDIN_FILENO, &readfds)) {
|
|
fgetsret = fgets(txmsg, MAX_PDU_LENGTH, stdin);
|
|
if (fgetsret == NULL) {
|
|
ret = 0;
|
|
goto exit;
|
|
}
|
|
|
|
nbytes = send(sc, txmsg, strlen(txmsg) + 1, 0);
|
|
if (nbytes != strlen(txmsg) + 1) {
|
|
perror("write to isotp socket");
|
|
ret = nbytes;
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
exit:
|
|
close(sc);
|
|
|
|
return ret;
|
|
}
|