hexagram/bin/convert.c
2019-05-21 11:03:02 -05:00

249 lines
5.8 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <inttypes.h>
#include <unistd.h>
#include <fcntl.h>
#include <endian.h>
#include <hexagram/capture.h>
#include <hexagram/pcapng.h>
char *hexagram_arglist_convert(void) {
return "[infile.pcapng] [outfile.can]";
}
static ssize_t handle_option(hexagram_pcapng_stream *stream,
uint32_t type,
uint16_t code,
uint16_t len,
void *data) {
if (lseek(stream->fd, (size_t)len, SEEK_CUR) < 0) {
goto error_io;
}
stream->error = HEXAGRAM_PCAPNG_ERROR_OK;
return (size_t)len;
error_io:
stream->error = HEXAGRAM_PCAPNG_ERROR_IO;
return -1;
}
static ssize_t handle_block_if(hexagram_pcapng_stream *stream,
uint32_t type,
size_t len,
void *data) {
hexagram_pcapng_if iface;
ssize_t readlen,
total = 0;
size_t remaining = len;
/*
* Read the interface block header.
*/
if ((readlen = read(stream->fd, &iface, sizeof(iface))) < 0) {
stream->error = HEXAGRAM_PCAPNG_ERROR_IO;
goto error_io;
} else {
remaining -= readlen;
total += readlen;
}
if ((readlen = hexagram_pcapng_read_options(stream, handle_option, type, remaining, data)) < 0) {
stream->error = HEXAGRAM_PCAPNG_ERROR_IO;
goto error_io;
} else {
total += readlen;
}
return total;
error_io:
return -1;
}
static ssize_t handle_block_packet(hexagram_pcapng_stream *stream,
uint32_t type,
size_t len,
hexagram_capture *capture) {
hexagram_pcapng_packet header;
uint8_t body[65535];
ssize_t readlen,
total = 0;
size_t remaining = len;
struct timeval timestamp;
uint64_t usec;
/*
* Read the packet block header so that we may determine the size of the
* payload to continue to read.
*/
if ((readlen = read(stream->fd, &header, sizeof(header))) < 0) {
stream->error = HEXAGRAM_PCAPNG_ERROR_IO;
goto error_io;
} else {
remaining -= readlen;
total += readlen;
}
/*
* Read the packet body into our scratchpad.
*/
if ((readlen = read(stream->fd, &body, header.caplen)) < 0) {
stream->error = HEXAGRAM_PCAPNG_ERROR_IO;
goto error_io;
} else {
remaining -= readlen;
total += readlen;
}
usec = ((uint64_t)header.timestamp[0] << 32)
| (uint64_t)header.timestamp[1];
timestamp.tv_sec = usec / 1000000;
timestamp.tv_usec = usec % 1000000;
((struct can_frame *)body)->can_id = be32toh(((struct can_frame *)body)->can_id);
if (hexagram_capture_write(capture, &timestamp, (struct can_frame *)body) < 0) {
goto error_io;
}
if (header.caplen % sizeof(uint32_t)) {
size_t padding = sizeof(uint32_t) - (header.caplen % sizeof(uint32_t));
if (lseek(stream->fd, padding, SEEK_CUR) < 0) {
stream->error = HEXAGRAM_PCAPNG_ERROR_IO;
goto error_io;
} else {
remaining -= padding;
total += padding;
}
}
/*
* The remaining data here should be pcapng option values, and since we do
* not presently require them, we can safely seek past them.
*/
if (lseek(stream->fd, remaining, SEEK_CUR) < 0) {
stream->error = HEXAGRAM_PCAPNG_ERROR_IO;
goto error_io;
} else {
total += remaining;
}
stream->error = HEXAGRAM_PCAPNG_ERROR_OK;
return total;
error_io:
stream->error = HEXAGRAM_PCAPNG_ERROR_IO;
return -1;
}
static ssize_t handle_block(hexagram_pcapng_stream *stream,
uint32_t type,
size_t len,
void *data) {
switch (type) {
case HEXAGRAM_PCAPNG_BLOCK_IF:
return handle_block_if(stream, type, len, data);
case HEXAGRAM_PCAPNG_BLOCK_PACKET:
return handle_block_packet(stream, type, len, (hexagram_capture *)data);
default: break;
}
if (lseek(stream->fd, len, SEEK_CUR) < 0) {
stream->error = HEXAGRAM_PCAPNG_ERROR_IO;
goto error_io;
}
return len;
error_io:
return -1;
}
int hexagram_main_convert(int argc, char **argv) {
int fd;
hexagram_pcapng_stream *stream;
hexagram_capture *capture;
fd = (argc < 2)?
fileno(stdin):
open(argv[1], O_RDONLY);
if (fd < 0) {
perror("open()");
goto error_open_pcapng;
}
if (argc > 2) {
if ((capture = hexagram_capture_open_file(argv[2], O_CREAT | O_WRONLY)) == NULL) {
perror("hexagram_capture_open_file()");
goto error_capture_open;
}
} else {
if ((capture = hexagram_capture_open_fd(fileno(stdout), O_WRONLY)) == NULL) {
perror("hexagram_capture_open_fd()");
goto error_capture_open;
}
}
if ((stream = hexagram_pcapng_stream_open_fd(fd)) < 0) {
perror("hexagram_pcapng_stream_open_fd()");
goto error_pcapng_stream_open_fd;
}
if (hexagram_pcapng_stream_read(stream, handle_block, capture) < 0) {
perror("hexagram_pcapng_stream_read()");
goto error_pcapng_stream_read;
}
hexagram_pcapng_stream_destroy(stream);
hexagram_capture_destroy(capture);
if (argc == 2) {
close(fd);
}
return 0;
error_pcapng_stream_read:
error_pcapng_stream_open_fd:
hexagram_pcapng_stream_destroy(stream);
error_capture_open:
if (argc == 3 || argc == 2) {
close(fd);
}
error_open_pcapng:
return 1;
}