summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ax25.399
-rw-r--r--axconfig.c367
-rw-r--r--axports5
-rw-r--r--axports.539
-rw-r--r--nrconfig.c162
-rw-r--r--nrports3
-rw-r--r--rose.341
-rw-r--r--rsconfig.c162
-rw-r--r--rsports3
9 files changed, 432 insertions, 449 deletions
diff --git a/ax25.3 b/ax25.3
index 526c33d..795adf8 100644
--- a/ax25.3
+++ b/ax25.3
@@ -1,57 +1,92 @@
-.TH INET 3 "20 April 1999" "Linux" "Linux Programmer's Manual"
+.TH INET 3 "2008-Feb-04" "Linux" "Linux Programmer's Manual"
.SH NAME
-ax25_aton, ax25_aton_entry, ax25_aton_arglist,
-ax25_ntoa, ax25_cmp, ax25_validate \- AX25 Address manipulation routines
+.B ax25_aton, ax25_aton_entry, ax25_aton_arglist,
+.B ax25_ntoa, ax25_cmp, ax25_validate
+\- AX25 Address manipulation routines
.SH SYNOPSIS
.nf
.B #include <netax25/ax25.h>
-.sp
+.PP
.BI "int ax25_aton(const char *" cp ", struct full_sockaddr_ax25 *" fsap ");"
-.sp
+.PP
.BI "int ax25_aton_arglist(const char **" cp ", struct full_sockaddr_ax25 *" fsap ");"
-.sp
+.PP
.BI "int ax25_aton_entry(const char *" cp ", char *" axp ");"
-.sp
+.PP
.BI "char *ax25_ntoa(ax25_address *" axp ");"
-.sp
+.PP
.BI "int ax25_cmp(ax25_address *" ax1 ", ax25_address *" ax2 ");"
-.sp
+.PP
.BI "int ax25_validate(char *" axp ");"
-.sp
+.PP
.BI "char *ax25_config_file(const char *filename);"
.fi
+
.SH DESCRIPTION
-\fBax25_aton()\fP takes the ASCII string \fIcp\FP that is in the format
-\fIcallsign\fR [[\fIV\fR|\fIVIA\fR] \fIcallsign\fR ...]
-and stores it in \fIfsap\fP in network format.
+.BR ax25_aton ()
+takes the ASCII string
+.I cp
+that is in the format
+.I callsign
+.RI [[ V | VIA ] callsign "...]"
+and stores it in
+.I fsap
+in network format.
.PP
-\fBax25_aton_entry()\fP takes the ASCII string of a callsign \fIcp\fP
-and stores it in network format in \fIaxp\fP.
+.BR ax25_aton_entry ()
+takes the ASCII string of a callsign
+.I cp
+and stores it in network format in
+.I axp.
.PP
-\fBax25_aton_arglist()\fP takes a NULL terminated array of strings \fIcp\fP
-and stores it \fIfsap\fP in network format.
+The
+.BR ax25_aton_arglist ()
+takes a NULL terminated array of strings
+.I cp
+and stores it in
+.I fsap
+in network format.
.PP
-\fBax25_ntoa()\fP takes a network format address \fIaxp\fP and returns the
-ASCII representation. The string is returned in a statically allocated
-buffer, which subsequent calls will overwrite.
+The
+.BR ax25_ntoa ()
+takes a network format address
+.I axp
+and returns the ASCII representation.
+The string is returned in a statically allocated buffer, which
+subsequent calls will overwrite.
.PP
-The \fBax25_cmp()\fP function compares the two ax25 addresses, \fIax1\fP
-and \fIax2\fP, that are in network format and determines wether they
-are identical, differ only by their SSIDs or are different.
+The
+.BR ax25_cmp ()
+function compares the two ax25 addresses,
+.I ax1
+and
+.IR ax2 ,
+that are in network format and determines wether they are identical,
+differ only by their SSIDs or are different.
.PP
-The \fBax25_validate\fP function checks to see if the address \fIaxp\fP
+The
+.BR ax25_validate ()
+function checks to see if the address
+.I axp
in network format is a correctly formatted address.
.SH "RETURN VALUE"
-The \fBax25_aton()\fP and \fBax25_aton_arglist()\fP functions return -1 if
-an error occurs otherwise the length of the returned structure.
+The
+.BR ax25_aton () and
+.BR ax25_aton_arglist ()
+functions return -1 if an error occurs otherwise the length of
+the returned structure.
.PP
-The \fBax25_aton_entry()\fP function returns -1 if an error occurs otherwise
-zero.
+The
+.BR ax25_aton_entry ()
+function returns -1 if an error occurs otherwise zero.
.PP
-The \fBax25_cmp()\fP function returns 0 if the two addresses are identical,
-1 if they are different or 2 is only the SSIDs are different.
+The
+.BR ax25_cmp ()
+function returns 0 if the two addresses are identical, 1 if they are
+different or 2 is only the SSIDs are different.
.PP
-The \fBax25_validate\fP function returns TRUE if the callsign is valid or
-FALSE if it is not.
+The
+.BR ax25_validate ()
+function returns TRUE if the callsign is valid or FALSE if it is not.
.SH "SEE ALSO"
.BR ax25 "(4), " netrom "(4), " rose "(4)"
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;
}
diff --git a/axports b/axports
index 1c53126..6ccef9b 100644
--- a/axports
+++ b/axports
@@ -4,5 +4,6 @@
#
# name callsign speed paclen window description
#
-1 OH2BNS-1 1200 255 2 144.675 MHz (1200 bps)
-2 OH2BNS-9 38400 255 7 TNOS/Linux (38400 bps)
+
+#1 OH2BNS-1 1200 255 2 144.675 MHz (1200 bps)
+#2 OH2BNS-9 38400 255 7 TNOS/Linux (38400 bps)
diff --git a/axports.5 b/axports.5
index fc61a47..e918b96 100644
--- a/axports.5
+++ b/axports.5
@@ -1,27 +1,30 @@
-.TH AXPORTS 5 "15 October 1996" Linux "Linux Programmer's Manual"
+.TH AXPORTS 5 "2008-Feb-04" Linux "Linux Programmer's Manual"
.SH NAME
-axports \- AX.25 port configuration file.
+.I /etc/ax25/axports
+\- AX.25 port configuration file.
.SH DESCRIPTION
.LP
-.B Axports
+.I axports
is an ASCII file that contains information about each of the physical AX.25
-ports that are to be used. When dealing with an AX.25 utility such as
-.B call,
-it takes an optional argument that is the port name. This port name is a
-reference to the line within
+ports that are to be used.
+When dealing with an AX.25 utility such as
+.BR call ,
+it takes an argument that is the port name.
+This port name is a reference to the line within
.B axports,
-which has that name as its first argument. The information on each line
-contains enough information to bind the command to a particular physical AX.25
-interface, this binding is done by matching the callsign on the line in
+which has that name as its first argument.
+The information on each line contains enough information to bind
+the command to a particular physical AX.25 interface, this binding
+is done by matching the callsign on the line in
.B axports
with the callsign of the port set by
.B kissattach.
.LP
The lines within
-.B axports
-must either be a comment line, which starts with a # in the first column, or
-a port description in the following format, each field being delimited by
-white space:
+.I axports
+must either be a comment line, which starts with a # in the first column,
+or a port description in the following format, each field being delimited
+by white space:
.sp
.RS
name callsign speed paclen window description
@@ -32,8 +35,12 @@ The field descriptions are:
.RS
.TP 14
.B name
-is the unique identifier of the port. This is the name given as the port
-argument of many of the AX.25 support programs.
+is the unique identifier of the port.
+This is the name given as the port argument of many of the AX.25 support
+programs.
+This is
+.I not
+in any way related to actual device identities, just unique
.TP 14
.B callsign
the callsign of the physical interface to bind to.
diff --git a/nrconfig.c b/nrconfig.c
index fa64c26..053db68 100644
--- a/nrconfig.c
+++ b/nrconfig.c
@@ -42,15 +42,6 @@ typedef struct _nrport
static NR_Port *nr_ports = NULL;
static NR_Port *nr_port_tail = 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 NR_Port *nr_port_ptr(char *name)
{
NR_Port *p = nr_ports;
@@ -170,15 +161,12 @@ char *nr_config_get_desc(char *name)
return p->Description;
}
-static int nr_config_init_port(int fd, int lineno, char *line)
+static int nr_config_init_port(int fd, int lineno, char *line, const char **ifcalls, const char **ifdevs)
{
NR_Port *p;
- char buffer[1024];
- char *name, *call, *alias, *paclen, *desc, *dev = NULL;
- struct ifconf ifc;
- struct ifreq *ifrp;
- struct ifreq ifr;
- int n, found = 0;
+ char *name, *call, *alias, *paclen, *desc;
+ const char *dev = NULL;
+ int found = 0;
name = strtok(line, " \t");
call = strtok(NULL, " \t");
@@ -215,42 +203,19 @@ static int nr_config_init_port(int fd, int lineno, char *line)
strupr(call);
strupr(alias);
- ifc.ifc_len = sizeof(buffer);
- ifc.ifc_buf = buffer;
-
- if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
- fprintf(stderr, "nrconfig: SIOCGIFCONF: %s\n", strerror(errno));
- return FALSE;
- }
-
- for (ifrp = ifc.ifc_req, n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifrp++) {
- strcpy(ifr.ifr_name, ifrp->ifr_name);
-
- if (strcmp(ifr.ifr_name, "lo") == 0) continue;
-
- if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
- fprintf(stderr, "nrconfig: SIOCGIFFLAGS: %s\n", strerror(errno));
- return FALSE;
- }
-
- if (!(ifr.ifr_flags & IFF_UP)) continue;
-
- if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
- fprintf(stderr, "nrconfig: SIOCGIFHWADDR: %s\n", strerror(errno));
- return FALSE;
- }
-
- if (ifr.ifr_hwaddr.sa_family != ARPHRD_NETROM) continue;
-
- if (ax25_hw_cmp(call, ifr.ifr_hwaddr.sa_data)) {
- dev = ifr.ifr_name;
- found = 1;
- break;
- }
+ found = 0;
+ for (;ifcalls && *ifcalls; ++ifcalls, ++ifdevs) {
+ if (strcmp(call,*ifcalls) == 0) {
+ found = 1;
+ dev = *ifdevs;
+ break;
+ }
}
if (!found) {
+#if 0 /* None of your business to complain about some port being down... */
fprintf(stderr, "nrconfig: port %s not active\n", name);
+#endif
return FALSE;
}
@@ -280,34 +245,99 @@ static int nr_config_init_port(int fd, int lineno, char *line)
int nr_config_load_ports(void)
{
- FILE *fp;
+ FILE *fp = NULL;
char buffer[256], *s;
- int fd, lineno = 1, n = 0;
+ int fd = -1, lineno = 1, n = 0, i;
+ const char **calllist = NULL;
+ const char **devlist = NULL;
+ int callcount = 0;
+ struct ifreq ifr;
- if ((fp = fopen(CONF_NRPORTS_FILE, "r")) == NULL) {
- fprintf(stderr, "nrconfig: unable to open nrports file %s (%s)\n", CONF_NRPORTS_FILE, strerror(errno));
- return 0;
+ /* 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, "nrconfig: unable to open socket (%s)\n", strerror(errno));
+ goto cleanup;
}
- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- fprintf(stderr, "nrconfig: unable to open socket (%s)\n", strerror(errno));
- fclose(fp);
- return 0;
+ 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, "nrconfig: SIOCGIFHWADDR: %s\n", strerror(errno));
+ return FALSE;
+ }
+
+ if (ifr.ifr_hwaddr.sa_family != ARPHRD_NETROM)
+ 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, "nrconfig: 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 ((fp = fopen(CONF_NRPORTS_FILE, "r")) == NULL) {
+ fprintf(stderr, "nrconfig: unable to open nrports file %s (%s)\n", CONF_NRPORTS_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[0] != '#')
- if (nr_config_init_port(fd, lineno, buffer))
- n++;
+ if (strlen(buffer) > 0 && *buffer != '#')
+ if (nr_config_init_port(fd, lineno, buffer, calllist, devlist))
+ n++;
- lineno++;
+ lineno++;
}
- fclose(fp);
- close(fd);
+ 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 (nr_ports == NULL)
return 0;
diff --git a/nrports b/nrports
index 4faa359..41e8999 100644
--- a/nrports
+++ b/nrports
@@ -4,4 +4,5 @@
#
# name callsign alias paclen description
#
-netrom OH2BNS-10 #LNODE 235 Switch Port
+
+#netrom OH2BNS-10 #LNODE 235 Switch Port
diff --git a/rose.3 b/rose.3
index 7b0a33a..98d81d8 100644
--- a/rose.3
+++ b/rose.3
@@ -1,4 +1,4 @@
-.TH INET 3 "20 April 1999" "Linux" "Linux Programmer's Manual"
+.TH INET 3 "2008-Feb-04" "Linux" "Linux Programmer's Manual"
.SH NAME
rose_aton, rose_ntoa, rose_cmp \- ROSE Address manipulation routines
.SH SYNOPSIS
@@ -12,20 +12,39 @@ rose_aton, rose_ntoa, rose_cmp \- ROSE Address manipulation routines
.BI "int rose_cmp(rose_address *" a1 ", rose_address *" a2 ");"
.fi
.SH DESCRIPTION
-\fBrose_aton()\fP converts the ROSE address \fIcp\fP from an ASCII
-representation into network format.
+The
+.BR rose_aton ()
+converts the ROSE address
+.I cp
+from an ASCII representation into network format.
.PP
-\fBrose_ntoa()\fP converts the ROSE address \fIcp\fP that is
-network format to a string that is the ASCII
-representation of the address.
+The
+.BR rose_ntoa ()
+converts the ROSE address
+.I cp
+that is network format to a string that is the ASCII representation
+of the address.
.PP
-\fBrose_cmp()\fP compares the two ROSE address \fIa1\fP and \fIa2\fP
+The
+.BR rose_cmp ()
+compares the two ROSE address
+.I a1
+and
+.I a2
that are in network format.
.SH "RETURN VALUE"
-The \fBrose_ntoa()\fP and \fBrose_aton()\fP functions return zero if all
-went ok, -1 if not.
+The
+.BR rose_ntoa ()
+and
+.BR rose_aton ()
+functions return zero if all went OK, -1 if not.
.PP
-The \fBrose_cmp()\fP returns 0 if address \fIa1\fP and \fIa2\fP are identical,
-1 otherwise.
+The
+.BR rose_cmp ()
+returns 0 if addresses pointer by
+.I a1
+and
+.I a2
+are identical, 1 otherwise.
.SH "SEE ALSO"
.BR ax25 "(4), " netrom "(4), " rose "(4)"
diff --git a/rsconfig.c b/rsconfig.c
index f83e3a0..dae0eb5 100644
--- a/rsconfig.c
+++ b/rsconfig.c
@@ -41,15 +41,6 @@ typedef struct _rsport
static RS_Port *rs_ports = NULL;
static RS_Port *rs_port_tail = NULL;
-static int rose_hw_cmp(char *address, char *hw_addr)
-{
- rose_address addr;
-
- rose_aton(address, addr.rose_addr);
-
- return rose_cmp(&addr, (rose_address *)hw_addr) == 0;
-}
-
static RS_Port *rs_port_ptr(char *name)
{
RS_Port *p = rs_ports;
@@ -154,15 +145,12 @@ int rs_config_get_paclen(char *name)
return 128;
}
-static int rs_config_init_port(int fd, int lineno, char *line)
+static int rs_config_init_port(int fd, int lineno, char *line, const char **ifcalls, const char **ifdevs)
{
RS_Port *p;
- char buffer[1024];
- char *name, *addr, *desc, *dev = NULL;
- struct ifconf ifc;
- struct ifreq *ifrp;
- struct ifreq ifr;
- int n, found = 0;
+ char *name, *addr, *desc;
+ const char *dev = NULL;
+ int found = 0;
name = strtok(line, " \t");
addr = strtok(NULL, " \t");
@@ -184,42 +172,19 @@ static int rs_config_init_port(int fd, int lineno, char *line)
}
}
- ifc.ifc_len = sizeof(buffer);
- ifc.ifc_buf = buffer;
-
- if (ioctl(fd, SIOCGIFCONF, &ifc) < 0) {
- fprintf(stderr, "rsconfig: SIOCGIFCONF: %s\n", strerror(errno));
- return FALSE;
- }
-
- for (ifrp = ifc.ifc_req, n = ifc.ifc_len / sizeof(struct ifreq); --n >= 0; ifrp++) {
- strcpy(ifr.ifr_name, ifrp->ifr_name);
-
- if (strcmp(ifr.ifr_name, "lo") == 0) continue;
-
- if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
- fprintf(stderr, "rsconfig: SIOCGIFFLAGS: %s\n", strerror(errno));
- return FALSE;
- }
-
- if (!(ifr.ifr_flags & IFF_UP)) continue;
-
- if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) {
- fprintf(stderr, "rsconfig: SIOCGIFHWADDR: %s\n", strerror(errno));
- return FALSE;
- }
-
- if (ifr.ifr_hwaddr.sa_family != ARPHRD_ROSE) continue;
-
- if (rose_hw_cmp(addr, ifr.ifr_hwaddr.sa_data)) {
- dev = ifr.ifr_name;
- found = 1;
- break;
- }
+ found = 0;
+ for (;ifcalls && *ifcalls; ++ifcalls, ++ifdevs) {
+ if (strcmp(addr,*ifcalls) == 0) {
+ found = 1;
+ dev = *ifdevs;
+ break;
+ }
}
if (!found) {
+#if 0 /* None of your business to complain about some port being down... */
fprintf(stderr, "rsconfig: port %s not active\n", name);
+#endif
return FALSE;
}
@@ -247,34 +212,99 @@ static int rs_config_init_port(int fd, int lineno, char *line)
int rs_config_load_ports(void)
{
- FILE *fp;
+ FILE *fp = NULL;
char buffer[256], *s;
- int fd, lineno = 1, n = 0;
+ int fd, lineno = 1, n = 0, i;
+ const char **calllist = NULL;
+ const char **devlist = NULL;
+ int callcount = 0;
+ struct ifreq ifr;
- if ((fp = fopen(CONF_RSPORTS_FILE, "r")) == NULL) {
- fprintf(stderr, "rsconfig: unable to open rsports file %s (%s)\n", CONF_RSPORTS_FILE, strerror(errno));
- return 0;
+ /* 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, "rsconfig: unable to open socket (%s)\n", strerror(errno));
+ goto cleanup;
}
- if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- fprintf(stderr, "rsconfig: unable to open socket (%s)\n", strerror(errno));
- fclose(fp);
- return 0;
+ 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, "rsconfig: SIOCGIFHWADDR: %s\n", strerror(errno));
+ return FALSE;
+ }
+
+ if (ifr.ifr_hwaddr.sa_family != ARPHRD_ROSE)
+ continue;
+
+ /* store found interface callsigns */
+ /* rose_ntoa() returns pointer to static buffer */
+ s = rose_ntoa((void*)ifr.ifr_hwaddr.sa_data);
+
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) {
+ fprintf(stderr, "rsconfig: 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 ((fp = fopen(CONF_RSPORTS_FILE, "r")) == NULL) {
+ fprintf(stderr, "rsconfig: unable to open axports file %s (%s)\n", CONF_RSPORTS_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[0] != '#')
- if (rs_config_init_port(fd, lineno, buffer))
- n++;
+ if (strlen(buffer) > 0 && *buffer != '#')
+ if (rs_config_init_port(fd, lineno, buffer, calllist, devlist))
+ n++;
- lineno++;
+ lineno++;
}
- fclose(fp);
- close(fd);
+ 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 (rs_ports == NULL)
return 0;
diff --git a/rsports b/rsports
index 8be51a0..5c18e1e 100644
--- a/rsports
+++ b/rsports
@@ -4,4 +4,5 @@
#
# name address description
#
-rose 2080192203 Rose port
+
+#rose 2080192203 Rose port