From fbb41991bd530270b0f70a110af507fc029e76b8 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 2 Apr 2008 13:34:05 +0000 Subject: From Matti Aarnio (oh2mqk@sral.fi): * axconfig.c: Find all running network ports, and compare them against the /etc/ax25/axports file. * nrconfig.c: Find all running network ports, and compare them against the /etc/ax25/nrports file. * rsconfig.c: Find all running network ports, and compare them against the /etc/ax25/rsports file. * Update man pages --- axconfig.c | 367 +++++++++++++++++++------------------------------------------ 1 file changed, 113 insertions(+), 254 deletions(-) (limited to 'axconfig.c') diff --git a/axconfig.c b/axconfig.c index 4f64f9a..f6c3e3b 100644 --- a/axconfig.c +++ b/axconfig.c @@ -27,8 +27,6 @@ #include "pathnames.h" #include "axconfig.h" -#define _PATH_PROCNET_DEV "/proc/net/dev" - typedef struct _axport { struct _axport *Next; @@ -44,24 +42,6 @@ typedef struct _axport static AX_Port *ax25_ports = NULL; static AX_Port *ax25_port_tail = NULL; -typedef struct _axiface -{ - struct _axiface *Next; - char *Name; - char *Call; - char *Device; -} AX_Iface; - -static AX_Iface *ax25_ifaces = NULL; - -static int ax25_hw_cmp(char *callsign, char *hw_addr) -{ - ax25_address call; - - ax25_aton_entry(callsign, call.ax25_call); - - return ax25_cmp(&call, (ax25_address *)hw_addr) == 0; -} static AX_Port *ax25_port_ptr(char *name) { @@ -73,6 +53,8 @@ static AX_Port *ax25_port_ptr(char *name) while (p != NULL) { if (strcasecmp(p->Name, name) == 0) return p; + if (strcasecmp(p->Call, name) == 0) + return p; p = p->Next; } @@ -195,171 +177,12 @@ char *ax25_config_get_desc(char *name) return p->Description; } -static void free_ax25_ports() { - AX_Port *axp; - for (axp = ax25_ports; axp; ) { - AX_Port *q = axp->Next; - if (axp->Name) free(axp->Name); - if (axp->Call) free(axp->Call); - if (axp->Device) free(axp->Device); - if (axp->Description) free(axp->Description); - free(axp); - axp = q; - } - ax25_ports = ax25_port_tail = NULL; -} - -static void free_ax25_ifaces() { - AX_Iface *axif; - for (axif = ax25_ifaces; axif; ) { - AX_Iface *q = axif->Next; - if (axif->Name) free(axif->Name); - if (axif->Device) free(axif->Device); - if (axif->Call) free(axif->Call); - free(axif); - axif = q; - } - ax25_ifaces = NULL; -} - -static int test_and_add_ax25_iface(int fd, char *name, struct ifreq *ifr) { - AX_Iface *axif; - - if (fd == -1) - return 0; - if (!name) - return 0; - if (!strcmp(name, "lo")) return 0; - if (!ifr) - return 0; - - strncpy(ifr->ifr_name, name, IFNAMSIZ-1); - ifr->ifr_name[IFNAMSIZ-1] = 0; - - if (ioctl(fd, SIOCGIFFLAGS, ifr) < 0) { - fprintf(stderr, "axconfig: SIOCGIFFLAGS: %s\n", strerror(errno)); - return -1; - } - - if (!(ifr->ifr_flags & IFF_UP)) return 0; - - if (ioctl(fd, SIOCGIFHWADDR, ifr) < 0) { - fprintf(stderr, "axconfig: SIOCGIFHWADDR: %s\n", strerror(errno)); - return -1; - } - - if (ifr->ifr_hwaddr.sa_family != ARPHRD_AX25) return 0; - - if ((axif = (AX_Iface *)malloc(sizeof(AX_Iface))) == NULL) { - fprintf(stderr, "axconfig: out of memory!\n"); - return -1; - } - if (!(axif->Name = strdup(name))) { - fprintf(stderr, "axconfig: out of memory!\n"); - free(axif); - return -1; - } - if (!(axif->Device = strdup(ifr->ifr_name))) { - fprintf(stderr, "axconfig: out of memory!\n"); - free(axif->Name); - free(axif); - return -1; - } - if (!(axif->Call = strdup(ifr->ifr_hwaddr.sa_data))) { - free(axif->Name); - free(axif->Device); - free(axif); - fprintf(stderr, "axconfig: out of memory!\n"); - return -1; - } - axif->Next = ax25_ifaces; - ax25_ifaces = axif; - - return 1; -} - -#ifdef FIND_ALL_INTERFACES -static char *proc_get_iface_name(char *line) { - char *p; - - if (!(p = strchr(line, ':'))) - return 0; - *p = 0; - while (*line && isspace(*line & 0xff)) - line++; - if (!*line) - return 0; - return line; -} -#endif - -static int get_ax25_ifaces(void) { -#ifdef FIND_ALL_INTERFACES - FILE *fp; -#endif - struct ifreq ifr; - int fd = -1; - int ret = -1; - - free_ax25_ifaces(); - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { - fprintf(stderr, "axconfig: unable to open socket (%s)\n", strerror(errno)); - goto out; - } - -#ifdef FIND_ALL_INTERFACES /* will be default soon, after tracing a kernel error */ - if ((fp = fopen(_PATH_PROCNET_DEV, "r"))) { - /* Because ifc.ifc_req does not show interfaces without - * IP-Address assigned, we use the device list via /proc. - * This concept was inspired by net-tools / ifconfig - */ - char buf[512]; - int i = 0; - ret = 0; - while (fgets(buf, sizeof(buf), fp)) { - /* skip proc header */ - if (i < 2) { - i++; - continue; - } - if (test_and_add_ax25_iface(fd, proc_get_iface_name(buf), &ifr) > 0) - ret++; - } - fclose(fp); - } else { -#else - { -#endif - struct ifconf ifc; - struct ifreq *ifrp; - char buffer[1024]; - int n = 0; - ifc.ifc_len = sizeof(buffer); - ifc.ifc_buf = buffer; - - if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) { - fprintf(stderr, "axconfig: SIOCGIFCONF: %s\n", strerror(errno)); - goto out; - } - ret = 0; - - for (ifrp = ifc.ifc_req, n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifrp++) - if (test_and_add_ax25_iface(fd, ifrp->ifr_name, &ifr) > 0) - ret++; - } - -out: - if (fd != -1) - close(fd); - return ret; -} - -static int ax25_config_init_port(int lineno, char *line) +static int ax25_config_init_port(int fd, int lineno, char *line, const char **ifcalls, const char **ifdevs) { AX_Port *p; - AX_Iface *axif = NULL; - char *name, *call, *baud, *paclen, *window, *desc, *dev = NULL; - int found = 0; + char *name, *call, *baud, *paclen, *window, *desc; + const char *dev = NULL; + int found; name = strtok(line, " \t"); call = strtok(NULL, " \t"); @@ -371,93 +194,66 @@ static int ax25_config_init_port(int lineno, char *line) if (name == NULL || call == NULL || baud == NULL || paclen == NULL || window == NULL || desc == NULL) { fprintf(stderr, "axconfig: unable to parse line %d of axports file\n", lineno); - return -1; + return FALSE; } for (p = ax25_ports; p != NULL; p = p->Next) { if (strcasecmp(name, p->Name) == 0) { fprintf(stderr, "axconfig: duplicate port name %s in line %d of axports file\n", name, lineno); - return -1; + return FALSE; } - /* dl9sau: why? */ if (strcasecmp(call, p->Call) == 0) { fprintf(stderr, "axconfig: duplicate callsign %s in line %d of axports file\n", call, lineno); - return -1; + return FALSE; } } if (atoi(baud) < 0) { fprintf(stderr, "axconfig: invalid baud rate setting %s in line %d of axports file\n", baud, lineno); - return -1; + return FALSE; } if (atoi(paclen) <= 0) { fprintf(stderr, "axconfig: invalid packet size setting %s in line %d of axports file\n", paclen, lineno); - return -1; + return FALSE; } if (atoi(window) <= 0) { fprintf(stderr, "axconfig: invalid window size setting %s in line %d of axports file\n", window, lineno); - return -1; + return FALSE; } strupr(call); - for (axif = ax25_ifaces; axif; axif = axif->Next) { - if (ax25_hw_cmp(call, axif->Call)) { - /* associate list of ifaces with the name from axports we just found */ - if (!strcmp(axif->Name, name)) { - free(axif->Name); - if (!(axif->Name = strdup(name))) { - fprintf(stderr, "axconfig: out of memory!\n"); - return -1; - } - } - dev = axif->Device; - found = 1; - break; - } + found = 0; + for (;ifcalls && *ifcalls; ++ifcalls, ++ifdevs) { + if (strcmp(call,*ifcalls) == 0) { + found = 1; + dev = *ifdevs; + break; + } } + if (!found) { - fprintf(stderr, "axconfig: port %s not active\n", name); - return -1; +#if 0 /* None of your business to complain about some port being down... */ + fprintf(stderr, "axconfig: port with call '%s' is not active\n", call); +#endif + return FALSE; } if ((p = (AX_Port *)malloc(sizeof(AX_Port))) == NULL) { fprintf(stderr, "axconfig: out of memory!\n"); - return -1; + return FALSE; } - if (!(p->Name = strdup(name))) { - fprintf(stderr, "axconfig: out of memory!\n"); - free(p); - return -1; - } - if (!(p->Call = strdup(call))) { - fprintf(stderr, "axconfig: out of memory!\n"); - free(p->Name); - free(p); - return -1; - } - if (!(p->Device = strdup(dev))) { - fprintf(stderr, "axconfig: out of memory!\n"); - free(p->Name); - free(p->Call); - free(p); - return -1; - } - if (!(p->Description = strdup(desc))) { - fprintf(stderr, "axconfig: out of memory!\n"); - free(p->Name); - free(p->Call); - free(p->Description); - free(p); - return -1; - } + p->Name = strdup(name); + p->Call = strdup(call); + p->Device = strdup(dev); p->Baud = atoi(baud); p->Window = atoi(window); p->Paclen = atoi(paclen); + p->Description = strdup(desc); if (ax25_ports == NULL) ax25_ports = p; @@ -468,44 +264,107 @@ static int ax25_config_init_port(int lineno, char *line) p->Next = NULL; - return 0; + return TRUE; } int ax25_config_load_ports(void) { - FILE *fp; + FILE *fp = NULL; char buffer[256], *s; - int lineno = 1; - int n = 0; + int fd = -1, lineno = 1, n = 0, i; + const char **calllist = NULL; + const char **devlist = NULL; + int callcount = 0; + struct ifreq ifr; + + /* Reliable listing of all network ports on Linux + is only available via reading /proc/net/dev ... */ + + + if ((fd = socket(PF_FILE, SOCK_DGRAM, 0)) < 0) { + fprintf(stderr, "axconfig: unable to open socket (%s)\n", strerror(errno)); + goto cleanup; + } - /* in case of a "reload" */ - free_ax25_ports(); + if ((fp = fopen("/proc/net/dev", "r"))) { + /* Two header lines.. */ + s = fgets(buffer, sizeof(buffer), fp); + s = fgets(buffer, sizeof(buffer), fp); + /* .. then network interface names */ + while (!feof(fp)) { + if (!fgets(buffer, sizeof(buffer), fp)) + break; + s = strchr(buffer, ':'); + if (s) *s = 0; + s = buffer; + while (*s == ' ') ++s; + + memset(&ifr, 0, sizeof(ifr)); + strcpy(ifr.ifr_name, s); + + if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { + fprintf(stderr, "axconfig: SIOCGIFHWADDR: %s\n", strerror(errno)); + return FALSE; + } + + if (ifr.ifr_hwaddr.sa_family != ARPHRD_AX25) + continue; + + /* store found interface callsigns */ + /* ax25_ntoa() returns pointer to static buffer */ + s = ax25_ntoa((void*)ifr.ifr_hwaddr.sa_data); + + if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { + fprintf(stderr, "axconfig: SIOCGIFFLAGS: %s\n", strerror(errno)); + return FALSE; + } + + if (!(ifr.ifr_flags & IFF_UP)) + continue; + + + calllist = realloc(calllist, sizeof(char *) * (callcount+2)); + devlist = realloc(devlist, sizeof(char *) * (callcount+2)); + calllist[callcount] = strdup(s); + devlist [callcount] = strdup(ifr.ifr_name); + ++callcount; + calllist[callcount] = NULL; + devlist [callcount] = NULL; + } + fclose(fp); + fp = NULL; + } - if (get_ax25_ifaces() <= 0) - goto out; if ((fp = fopen(CONF_AXPORTS_FILE, "r")) == NULL) { - fprintf(stderr, "axconfig: unable to open axports file %s (%s)\n", CONF_AXPORTS_FILE, strerror(errno)); - goto out; + fprintf(stderr, "axconfig: unable to open axports file %s (%s)\n", CONF_AXPORTS_FILE, strerror(errno)); + goto cleanup; } - while (fgets(buffer, 255, fp) != NULL) { - if ((s = strchr(buffer, '\n')) != NULL) - *s = '\0'; + while (fp && fgets(buffer, 255, fp)) { + if ((s = strchr(buffer, '\n'))) + *s = '\0'; - if (strlen(buffer) > 0 && *buffer != '#') - if (!ax25_config_init_port(lineno, buffer)) - n++; + if (strlen(buffer) > 0 && *buffer != '#') + if (ax25_config_init_port(fd, lineno, buffer, calllist, devlist)) + n++; - lineno++; + lineno++; } - fclose(fp); + cleanup:; + if (fd >= 0) close(fd); + if (fp) fclose(fp); + + for(i = 0; calllist && calllist[i]; ++i) { + free((void*)calllist[i]); + free((void*)devlist[i]); + } + if (calllist) free(calllist); + if (devlist) free(devlist); if (ax25_ports == NULL) - n = 0; + return 0; -out: - free_ax25_ifaces(); return n; } -- cgit v1.2.3