diff --git a/examples/Makefile b/examples/Makefile index 1cf04b5..507be12 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -7,7 +7,7 @@ INCLUDE_PATH = ../include CFLAGS += -I$(INCLUDE_PATH) LDFLAGS = -L../src -lhexagram -EXAMPLES = convert pcapread replay +EXAMPLES = capture convert pcapread replay RM = /bin/rm diff --git a/examples/capture.c b/examples/capture.c new file mode 100644 index 0000000..16c43a3 --- /dev/null +++ b/examples/capture.c @@ -0,0 +1,91 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +static void usage(int argc, char **argv, const char *message, ...) { + if (message) { + va_list args; + + va_start(args, message); + vfprintf(stderr, message, args); + va_end(args); + } + + fprintf(stderr, "usage: %s canif [file.can]\n", argv[0]); + + exit(1); +} + + + +int main(int argc, char **argv) { + hexagram_can_if *can_if; + hexagram_capture *capture; + struct can_frame frame; + + if (argc == 2) { + if ((capture = hexagram_capture_open_fd(fileno(stdin), O_WRONLY)) == NULL) { + perror("hexagram_capture_open_fd()"); + + goto error_capture_open; + } + } else if (argc == 3) { + if ((capture = hexagram_capture_open_file(argv[2], O_CREAT | O_WRONLY)) == NULL) { + perror("hexagram_capture_open_file()"); + + goto error_capture_open; + } + } else { + usage(argc, argv, NULL); + exit(1); + } + + if ((can_if = hexagram_can_if_open(argv[1])) == NULL) { + perror("hexagram_can_if_open()"); + + goto error_can_if_open; + } + + while (hexagram_can_if_read(can_if, &frame) >= 0) { + if (hexagram_capture_write(capture, &frame, NULL) < 0) { + goto error_capture_write; + } + } + + hexagram_can_if_close(can_if); + + if (argc == 3) { + hexagram_capture_close(capture); + } else { + hexagram_capture_destroy(capture); + } + + return 0; + +error_capture_write: + hexagram_can_if_close(can_if); + +error_can_if_open: + if (argc == 3) { + hexagram_capture_close(capture); + } else { + hexagram_capture_destroy(capture); + } + +error_capture_open: + return 1; +} diff --git a/examples/replay.c b/examples/replay.c index 62e4e07..1f367d4 100644 --- a/examples/replay.c +++ b/examples/replay.c @@ -13,6 +13,7 @@ #include #include +#include #include static void usage(int argc, char **argv, const char *message, ...) { @@ -29,48 +30,14 @@ static void usage(int argc, char **argv, const char *message, ...) { exit(1); } -static int capture_replay(hexagram_capture *capture, int sock) { - ssize_t len; - uint32_t timestamp[2], - usec_last = 0; - struct can_frame frame; - - while (1) { - if ((len = hexagram_capture_read(capture, - ×tamp[0], - ×tamp[1], - &frame)) < 0) { - goto error_io; - } else if (len == 0) { - break; - } - - if (usec_last) { - usleep((useconds_t)(timestamp[1] - usec_last)); - } - - if (write(sock, &frame, sizeof(struct can_frame)) < 0) { - goto error_io; - } - - usec_last = timestamp[1]; - } - - return 0; - -error_io: - return -1; -} - int main(int argc, char **argv) { - struct sockaddr_can addr; - struct ifreq ifr; - int sock; - + hexagram_can_if *can_if; hexagram_capture *capture; if (argc == 2) { if ((capture = hexagram_capture_open_fd(fileno(stdin), O_RDONLY)) == NULL) { + perror("hexagram_capture_open_fd()"); + goto error_capture_open; } } else if (argc == 3) { @@ -84,46 +51,36 @@ int main(int argc, char **argv) { exit(1); } - if ((sock = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { - perror("socket()"); + if ((can_if = hexagram_can_if_open(argv[1])) == NULL) { + perror("hexagram_can_if_open()"); - goto error_socket; + goto error_can_if_open; } - strcpy(ifr.ifr_name, argv[1]); - - ioctl(sock, SIOCGIFINDEX, &ifr); - - addr.can_family = AF_CAN; - addr.can_ifindex = ifr.ifr_ifindex; - - if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - perror("bind()"); - - goto error_bind; - } - - if (capture_replay(capture, sock) < 0) { - perror("capture_replay()"); + if (hexagram_capture_replay(capture, can_if, 1) < 0) { + perror("hexagram_capture_replay()"); goto error_capture_replay; } - close(sock); + hexagram_can_if_close(can_if); if (argc == 3) { hexagram_capture_close(capture); + } else { + hexagram_capture_destroy(capture); } return 0; error_capture_replay: -error_bind: - close(sock); + hexagram_can_if_close(can_if); -error_socket: +error_can_if_open: if (argc == 3) { hexagram_capture_close(capture); + } else { + hexagram_capture_destroy(capture); } error_capture_open: diff --git a/include/hexagram/can.h b/include/hexagram/can.h new file mode 100644 index 0000000..1651ba6 --- /dev/null +++ b/include/hexagram/can.h @@ -0,0 +1,25 @@ +#ifndef _HEXAGRAM_CAN_H +#define _HEXAGRAM_CAN_H + +#include + +#include +#include + +typedef struct _hexagram_can_if { + struct sockaddr_can addr; + struct ifreq ifr; + int sock; +} hexagram_can_if; + +hexagram_can_if *hexagram_can_if_open(const char *name); + +void hexagram_can_if_close(hexagram_can_if *can_if); + +int hexagram_can_if_read(hexagram_can_if *can_if, + struct can_frame *frame); + +int hexagram_can_if_write(hexagram_can_if *can_if, + struct can_frame *frame); + +#endif /* _HEXAGRAM_CAN_H */ diff --git a/include/hexagram/capture.h b/include/hexagram/capture.h index 7bfb4db..6dc5771 100644 --- a/include/hexagram/capture.h +++ b/include/hexagram/capture.h @@ -6,6 +6,8 @@ #include #include +#include + #define HEXAGRAM_CAPTURE_MAGIC "HCAN" #define HEXAGRAM_CAPTURE_ENDIAN 0x0a0b0c0d #define HEXAGRAM_CAPTURE_ENDIAN_SWAPPED 0x0d0c0b0a @@ -40,4 +42,8 @@ ssize_t hexagram_capture_write(hexagram_capture *capture, struct can_frame *frame, struct timeval *timestamp); +int hexagram_capture_replay(hexagram_capture *capture, + hexagram_can_if *can_if, + float speed); + #endif /* _HEXAGRAM_CAPTURE_H */ diff --git a/src/Makefile b/src/Makefile index 36a89db..a9bceec 100644 --- a/src/Makefile +++ b/src/Makefile @@ -7,10 +7,10 @@ CC = $(CROSS)cc CFLAGS += -fPIC -I$(INCLUDE_PATH) LDFLAGS = -HEADERS = capture.h pcapng.h +HEADERS = can.h capture.h pcapng.h HEADERS_LOCAL = util.h -OBJS = capture.o pcapng.o +OBJS = can.o capture.o pcapng.o VERSION_MAJOR = 0 VERSION_MINOR = 0.1 diff --git a/src/can.c b/src/can.c new file mode 100644 index 0000000..63685f7 --- /dev/null +++ b/src/can.c @@ -0,0 +1,67 @@ +#include +#include +#include +#include +#include + +#include + +hexagram_can_if *hexagram_can_if_open(const char *name) { + hexagram_can_if *can_if; + + if (name == NULL) { + errno = EINVAL; + + goto error_no_name; + } + + if ((can_if = malloc(sizeof(*can_if))) == NULL) { + goto error_malloc; + } + + if ((can_if->sock = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) { + goto error_socket; + } + + strcpy(can_if->ifr.ifr_name, name); + + if (ioctl(can_if->sock, SIOCGIFINDEX, &can_if->ifr) < 0) { + goto error_ioctl_siocgifindex; + } + + can_if->addr.can_family = AF_CAN; + can_if->addr.can_ifindex = can_if->ifr.ifr_ifindex; + + if (bind(can_if->sock, (struct sockaddr *)&can_if->addr, sizeof(struct sockaddr)) < 0) { + goto error_bind; + } + + return can_if; + +error_bind: +error_ioctl_siocgifindex: + close(can_if->sock); + +error_socket: + free(can_if); + +error_malloc: +error_no_name: + return NULL; +} + +void hexagram_can_if_close(hexagram_can_if *can_if) { + close(can_if->sock); + + free(can_if); +} + +int hexagram_can_if_read(hexagram_can_if *can_if, + struct can_frame *frame) { + return read(can_if->sock, frame, sizeof(*frame)); +} + +int hexagram_can_if_write(hexagram_can_if *can_if, + struct can_frame *frame) { + return write(can_if->sock, frame, sizeof(*frame)); +} diff --git a/src/capture.c b/src/capture.c index bc44095..2171949 100644 --- a/src/capture.c +++ b/src/capture.c @@ -139,3 +139,40 @@ ssize_t hexagram_capture_write(hexagram_capture *capture, error_gettimeofday: return -1; } + +int hexagram_capture_replay(hexagram_capture *capture, + hexagram_can_if *can_if, + float speed) { + ssize_t len; + + uint32_t timestamp[2], + usec_last = 0; + + struct can_frame frame; + + while (1) { + if ((len = hexagram_capture_read(capture, + ×tamp[0], + ×tamp[1], + &frame)) < 0) { + goto error_io; + } else if (len == 0) { + break; + } + + if (usec_last) { + usleep(speed * (useconds_t)(timestamp[1] - usec_last)); + } + + if (write(can_if->sock, &frame, sizeof(struct can_frame)) < 0) { + goto error_io; + } + + usec_last = timestamp[1]; + } + + return 0; + +error_io: + return -1; +}