patty/src/sock.c

264 lines
6.4 KiB
C
Raw Normal View History

2020-06-30 23:20:12 -04:00
#define _GNU_SOURCE
2020-06-25 20:37:12 -04:00
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
2020-06-30 23:20:12 -04:00
#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <fcntl.h>
#include <errno.h>
2020-06-25 20:37:12 -04:00
#include <patty/ax25.h>
2020-06-30 23:20:12 -04:00
static int bind_pty(patty_ax25_sock *sock) {
struct termios t;
if ((sock->fd = open("/dev/ptmx", O_RDWR)) < 0) {
goto error_open;
}
if (grantpt(sock->fd) < 0) {
goto error_grantpt;
}
if (unlockpt(sock->fd) < 0) {
goto error_unlockpt;
}
if (ptsname_r(sock->fd, sock->path, sizeof(sock->path)) < 0) {
goto error_ptsname_r;
}
if (tcgetattr(sock->fd, &t) < 0) {
goto error_tcgetattr;
}
cfmakeraw(&t);
if (tcsetattr(sock->fd, TCSANOW, &t) < 0) {
goto error_tcsetattr;
}
return 0;
error_tcsetattr:
error_tcgetattr:
error_ptsname_r:
error_unlockpt:
error_grantpt:
close(sock->fd);
error_open:
return -1;
}
patty_ax25_sock *patty_ax25_sock_new(enum patty_ax25_proto proto,
enum patty_ax25_sock_type type) {
2020-06-25 20:37:12 -04:00
patty_ax25_sock *sock;
if ((sock = malloc(sizeof(*sock))) == NULL) {
goto error_malloc_sock;
}
memset(sock, '\0', sizeof(*sock));
2020-06-30 23:20:12 -04:00
if ((sock->buf = malloc(PATTY_AX25_SOCK_BUFSZ)) == NULL) {
goto error_malloc_buf;
}
if (bind_pty(sock) < 0) {
goto error_bind_pty;
}
sock->bufsz = PATTY_AX25_SOCK_BUFSZ;
sock->proto = proto;
sock->type = type;
2020-06-25 20:37:12 -04:00
sock->status = PATTY_AX25_SOCK_CLOSED;
sock->mode = PATTY_AX25_SOCK_DM;
sock->n_maxlen = PATTY_AX25_FRAME_DEFAULT_MAXLEN;
sock->n_window = PATTY_AX25_FRAME_DEFAULT_WINDOW;
return sock;
2020-06-30 23:20:12 -04:00
error_bind_pty:
free(sock->buf);
error_malloc_buf:
free(sock);
2020-06-25 20:37:12 -04:00
error_malloc_sock:
return NULL;
}
2020-06-30 23:20:12 -04:00
void patty_ax25_sock_reset(patty_ax25_sock *sock) {
sock->status = PATTY_AX25_SOCK_CLOSED;
sock->mode = PATTY_AX25_SOCK_DM;
sock->timer_ack = 0;
sock->timer_response = 0;
sock->timer_keepalive = 0;
sock->n_maxlen = 0;
sock->n_retry = 0;
sock->n_window = 0;
sock->seq_send = 0;
sock->seq_recv = 0;
2020-06-30 23:20:12 -04:00
}
2020-06-25 20:37:12 -04:00
void patty_ax25_sock_destroy(patty_ax25_sock *sock) {
2020-06-30 23:20:12 -04:00
if (sock->fd) {
close(sock->fd);
}
free(sock->buf);
2020-06-25 20:37:12 -04:00
free(sock);
}
char *patty_ax25_sock_pty(patty_ax25_sock *sock) {
return sock->path;
}
void patty_ax25_sock_bind_if(patty_ax25_sock *sock,
patty_ax25_if *iface) {
sock->iface = iface;
}
2020-06-28 18:11:49 -04:00
static size_t copy_addr_to_tx_buf(patty_ax25_sock *sock) {
void *buf = sock->iface->tx_buf;
2020-06-28 18:11:49 -04:00
unsigned int i;
size_t offset = 0;
memcpy((uint8_t *)buf + offset, &sock->remote, sizeof(patty_ax25_addr));
offset += sizeof(patty_ax25_addr);
2020-06-28 18:11:49 -04:00
((uint8_t *)buf)[offset-1] &= ~1;
2020-06-28 18:11:49 -04:00
memcpy((uint8_t *)buf + offset, &sock->local, sizeof(patty_ax25_addr));
offset += sizeof(patty_ax25_addr);
2020-06-28 18:11:49 -04:00
((uint8_t *)buf)[offset-1] &= ~1;
for (i=0; i<sock->hops; i++) {
2020-06-28 22:54:46 -04:00
memcpy((uint8_t *)buf + offset,
&sock->repeaters[i],
sizeof(patty_ax25_addr));
offset += sizeof(patty_ax25_addr);
2020-06-28 22:54:46 -04:00
2020-06-28 18:11:49 -04:00
((uint8_t *)buf)[offset-1] &= ~1;
}
2020-06-28 18:11:49 -04:00
((uint8_t *)buf)[offset-1] |= 1;
2020-06-26 23:03:00 -04:00
return offset;
}
2020-06-28 18:11:49 -04:00
static inline int toobig(patty_ax25_sock *sock,
uint16_t control,
size_t infolen) {
return PATTY_AX25_FRAME_SIZE(sock->mode == PATTY_AX25_SOCK_SABME?
PATTY_AX25_FRAME_EXTENDED:
PATTY_AX25_FRAME_NORMAL,
sock->hops,
control,
infolen) > sock->iface->tx_bufsz? 1: 0;
}
ssize_t patty_ax25_sock_send(patty_ax25_sock *sock,
uint16_t control,
void *info,
size_t infolen) {
2020-06-30 23:20:12 -04:00
size_t offset;
uint8_t *buf = (uint8_t *)sock->iface->tx_buf;
2020-06-28 18:11:49 -04:00
if (toobig(sock, control, infolen)) {
goto error_toobig;
}
2020-06-28 22:54:46 -04:00
offset = copy_addr_to_tx_buf(sock);
2020-06-28 18:11:49 -04:00
if (sock->mode == PATTY_AX25_SOCK_SABME) {
buf[offset++] = (control & 0xff00) >> 8;
buf[offset++] = control & 0x00ff;
2020-06-30 23:20:12 -04:00
sock->seq_send = (sock->seq_send + 1) & 0x07;
2020-06-28 18:11:49 -04:00
} else {
buf[offset++] = control;
2020-06-30 23:20:12 -04:00
sock->seq_send = (sock->seq_send + 1) & 0x7f;
2020-06-28 18:11:49 -04:00
}
if (PATTY_AX25_CONTROL_INFO(control)) {
buf[offset++] = (uint8_t)sock->proto;
2020-06-28 18:11:49 -04:00
memcpy(buf + offset, info, infolen);
2020-06-28 18:11:49 -04:00
offset += infolen;
}
return patty_ax25_if_send(sock->iface, buf, offset);
2020-06-28 18:11:49 -04:00
error_toobig:
return -1;
}
ssize_t patty_ax25_sock_send_sabm(patty_ax25_sock *sock, int poll) {
return patty_ax25_sock_send(sock,
PATTY_AX25_FRAME_U_SABM
| PATTY_AX25_FRAME_POLL,
2020-06-28 18:11:49 -04:00
NULL,
0);
}
2020-06-30 23:20:12 -04:00
ssize_t patty_ax25_sock_send_sabme(patty_ax25_sock *sock, int poll) {
return patty_ax25_sock_send(sock,
PATTY_AX25_FRAME_U_SABME
| PATTY_AX25_FRAME_POLL,
2020-06-30 23:20:12 -04:00
NULL,
0);
}
ssize_t patty_ax25_sock_send_disc(patty_ax25_sock *sock, int poll) {
return patty_ax25_sock_send(sock,
PATTY_AX25_FRAME_U_DISC
| PATTY_AX25_FRAME_POLL,
2020-06-30 23:20:12 -04:00
NULL,
0);
}
2020-06-28 18:11:49 -04:00
ssize_t patty_ax25_sock_write(patty_ax25_sock *sock,
void *buf,
size_t len) {
2020-06-30 23:20:12 -04:00
uint16_t control = 0x0000;
if (sock->type == PATTY_AX25_SOCK_RAW) {
return patty_ax25_if_send(sock->iface, buf, len);
}
2020-06-30 23:20:12 -04:00
switch (sock->mode) {
case PATTY_AX25_SOCK_DM:
errno = EBADF;
goto error_invalid_mode;
case PATTY_AX25_SOCK_SABM:
control = PATTY_AX25_SOCK_CONTROL_SABM(sock, 1);
break;
case PATTY_AX25_SOCK_SABME:
control = PATTY_AX25_SOCK_CONTROL_SABME(sock, 1);
break;
}
2020-06-28 18:11:49 -04:00
if (patty_ax25_sock_send(sock, control, buf, len) < 0) {
2020-06-28 18:11:49 -04:00
goto error_send;
}
2020-06-28 18:11:49 -04:00
return len;
2020-06-28 18:11:49 -04:00
error_send:
2020-06-30 23:20:12 -04:00
error_invalid_mode:
2020-06-28 18:11:49 -04:00
return -1;
}