diff options
-rw-r--r-- | ax25.3 | 99 | ||||
-rw-r--r-- | axconfig.c | 367 | ||||
-rw-r--r-- | axports | 5 | ||||
-rw-r--r-- | axports.5 | 39 | ||||
-rw-r--r-- | nrconfig.c | 162 | ||||
-rw-r--r-- | nrports | 3 | ||||
-rw-r--r-- | rose.3 | 41 | ||||
-rw-r--r-- | rsconfig.c | 162 | ||||
-rw-r--r-- | rsports | 3 |
9 files changed, 432 insertions, 449 deletions
@@ -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)" @@ -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; } @@ -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) @@ -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. @@ -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; @@ -4,4 +4,5 @@ # # name callsign alias paclen description # -netrom OH2BNS-10 #LNODE 235 Switch Port + +#netrom OH2BNS-10 #LNODE 235 Switch Port @@ -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)" @@ -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; @@ -4,4 +4,5 @@ # # name address description # -rose 2080192203 Rose port + +#rose 2080192203 Rose port |