patty/bin/if.c
XANTRONIX Development 188d43f98d Improve error reporting, CLI code reuse
Changes:

    * Move network interface configuration logic from bin/pattyd.c to
      bin/if.c; implement a more robust state machine

    * Move KISS TNC configuration code from bin/pattyd.c to bin/kiss.c

    * Ensure configuration file name, line number, and erroneous part
      of an expression are clearly indicated upon failure

Other changes:

    * Improve bin/Makefile to rebuild objects when accompanying header
      files change

    * Refer to HEADERS_SUBDIR, not HEADER_SUBDIR, in Makefiles
2024-03-01 00:20:47 -05:00

134 lines
3.3 KiB
C

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <patty/bin/if.h>
enum mode {
MODE_NONE,
MODE_IFNAME,
MODE_IFOPTS,
MODE_IFADDR,
MODE_KISS,
MODE_BAUD,
MODE_FLOW
};
static int eprintf(patty_bin_if_data *data, const char *format, ...) {
int ret;
va_list args;
va_start(args, format);
ret = vsnprintf(data->err, sizeof(data->err)-1, format, args);
va_end(args);
return ret;
}
int patty_bin_if_config(patty_bin_if_data *data, int argc, char **argv) {
enum mode mode = MODE_NONE;
patty_kiss_tnc_info *info = &data->info;
int i;
for (i=0; i<argc; i++) {
switch (mode) {
case MODE_NONE:
if (strcmp(argv[i], "if") != 0) {
eprintf(data, "Unexpected start of expression '%s'",
argv[i]);
goto error_invalid;
} else {
mode = MODE_IFNAME;
}
break;
case MODE_IFNAME:
data->name = argv[i];
mode = MODE_IFOPTS;
break;
case MODE_IFOPTS:
if (strcmp(argv[i], "ax25") == 0) {
mode = MODE_IFADDR;
} else if (strcmp(argv[i], "kiss") == 0) {
mode = MODE_KISS;
} else if (strcmp(argv[i], "baud") == 0) {
mode = MODE_BAUD;
} else if (strcmp(argv[i], "flow") == 0) {
mode = MODE_FLOW;
} else {
eprintf(data, "Invalid parameter '%s'", argv[i]);
goto error_invalid;
}
break;
case MODE_IFADDR:
if (patty_ax25_pton(argv[i], &data->addr) < 0) {
eprintf(data, "Invalid AX.25 address '%s': %s",
argv[i], strerror(errno));
goto error_invalid;
}
mode = MODE_IFOPTS;
break;
case MODE_KISS:
data->type = PATTY_AX25_IF_KISS_TNC;
info->flags |= PATTY_KISS_TNC_DEVICE;
info->device = argv[i];
mode = MODE_IFOPTS;
break;
case MODE_BAUD:
if (!(argv[i][0] >= '0' && argv[i][0] <= '9')) {
eprintf(data, "Invalid baud rate '%s'", argv[i]);
goto error_invalid;
}
info->flags |= PATTY_KISS_TNC_BAUD;
info->baud = atoi(argv[i]);
mode = MODE_IFOPTS;
break;
case MODE_FLOW:
if (strcmp(argv[i], "crtscts") == 0) {
info->flags |= PATTY_KISS_TNC_FLOW;
info->flow = PATTY_KISS_TNC_FLOW_CRTSCTS;
} else if (strcmp(argv[i], "xonxoff") == 0) {
info->flags |= PATTY_KISS_TNC_FLOW;
info->flow = PATTY_KISS_TNC_FLOW_XONXOFF;
} else {
eprintf(data, "Invalid flow control '%s'", argv[i]);
goto error_invalid;
}
mode = MODE_IFOPTS;
break;
}
}
return 0;
error_invalid:
return -1;
}