patty/examples/ax25dump.c
XANTRONIX Development ebbfb50b1c Use KISS framing for raw sockets
Use KISS framing for raw sockets to avoid multiple write() calls from
being buffered, which caused read() on the other end of a file
descriptor to read more than frame at once
2024-03-01 00:20:46 -05:00

130 lines
3.1 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
#include <errno.h>
#include <patty/ax25.h>
#include <patty/print.h>
static void usage(int argc, char **argv, const char *message, ...) {
if (message != NULL) {
va_list args;
va_start(args, message);
vfprintf(stderr, message, args);
fprintf(stderr, "\n");
va_end(args);
}
fprintf(stderr, "usage: %s /var/run/patty/patty.sock\n", argv[0]);
exit(1);
}
int main(int argc, char **argv) {
struct sockaddr_un addr;
patty_ax25_call_setsockopt_if ifreq;
int fd,
sock;
patty_ax25_addr peer;
char path[PATTY_AX25_SOCK_PATH_SIZE];
uint8_t buf[4096];
ssize_t readlen;
patty_kiss_tnc *raw;
if (argc != 2) {
usage(argc, argv, "No patty socket provided");
}
patty_ax25_pton("KZ3ROX", 0, &peer);
if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], "socket()", argv[1], strerror(errno));
goto error_socket;
}
memset(&addr, '\0', sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, argv[1], sizeof(addr.sun_path));
if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
goto error_connect;
}
if ((sock = patty_ax25_call_socket(fd, PATTY_AX25_PROTO_NONE, PATTY_AX25_SOCK_RAW, path, sizeof(path))) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_socket()", strerror(errno));
goto error_call_socket;
}
strncpy(ifreq.name, "kiss0", sizeof(ifreq.name));
if (patty_ax25_call_setsockopt(fd, sock, PATTY_AX25_SOCK_IF, &ifreq, sizeof(ifreq)) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_call_setsockopt()", strerror(errno));
goto error_call_setsockopt;
}
if ((raw = patty_kiss_tnc_new(path)) == NULL) {
fprintf(stderr, "%s: %s: %s: %s\n",
argv[0], path, "patty_kiss_tnc_new()", strerror(errno));
goto error_kiss_tnc_new;
}
while ((readlen = patty_kiss_tnc_recv(raw, buf, sizeof(buf), NULL)) > 0) {
patty_ax25_frame frame;
if (patty_ax25_frame_decode(&frame, PATTY_AX25_FRAME_NORMAL, buf, readlen) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_ax25_frame_decode()", strerror(errno));
goto error_ax25_frame_decode;
}
if (patty_print_frame(stdout, &frame, buf, readlen) < 0) {
fprintf(stderr, "%s: %s: %s\n",
argv[0], "patty_print_frame()", strerror(errno));
goto error_print_frame;
}
}
patty_kiss_tnc_destroy(raw);
patty_ax25_call_close(fd, sock);
close(fd);
return 0;
error_print_frame:
error_ax25_frame_decode:
patty_kiss_tnc_destroy(raw);
error_kiss_tnc_new:
patty_ax25_call_close(fd, sock);
error_call_setsockopt:
error_call_socket:
close(fd);
error_connect:
error_socket:
return 1;
}