summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Osterried <thomas@osterried.de>2009-01-09 17:49:33 +0000
committerThomas Osterried <thomas@osterried.de>2009-01-09 17:49:33 +0000
commit31fe82cdc9b84d7d3ddff5c23e4d56aa1cceb78a (patch)
tree8efca6b013f38e63dd75a13405c268c79255639c
parent5bc46e0558383130785c1c48e703a76aa8fa17b7 (diff)
kissnetd now supports unix98 pty's (new option: -p num).
The num devices are written to stdout and could easily used in startp scripts. Introduced PATH_MAX for the pty name. Kiss header for crc smack and rmnc are now supported. write return code is now honoured. Thanks to dk2crn for contriution.
-rw-r--r--kiss/kissnetd.86
-rw-r--r--kiss/kissnetd.c210
2 files changed, 171 insertions, 45 deletions
diff --git a/kiss/kissnetd.8 b/kiss/kissnetd.8
index d069ac9..3b47bac 100644
--- a/kiss/kissnetd.8
+++ b/kiss/kissnetd.8
@@ -2,7 +2,7 @@
.SH NAME
kissnetd \- Create a virtual network.
.SH SYNOPSIS
-.B kissnetd [-f size] [-v] tty...
+.B kissnetd [-f size] [-v] [-p <num> | tty... ]
.SH DESCRIPTION
.LP
.B Kissnetd
@@ -12,6 +12,10 @@ received on tty is copied to the other ttys. This allows a number of AX.25
systems to share the same packets.
.SH OPTIONS
.TP 10
+.BI "\-p num"
+Automaticaly allocate num Unix98 slave pty's via /dev/ptmx.
+These are written to stdout and could be parsed by your startup scripts.
+.TP 10
.BI "\-f size"
This sets the maximum KISS frame size that the program will handle. The
default is 512 bytes which will be adequate under most circumstances.
diff --git a/kiss/kissnetd.c b/kiss/kissnetd.c
index 62ad4e0..d993e4a 100644
--- a/kiss/kissnetd.c
+++ b/kiss/kissnetd.c
@@ -10,6 +10,7 @@
*/
#include <stdio.h>
+#define __USE_XOPEN
#include <stdlib.h>
#include <sys/time.h>
#include <sys/types.h>
@@ -21,6 +22,7 @@
#include <errno.h>
#include <syslog.h>
#include <time.h>
+#include <limits.h>
static char *Version = "1.5";
static int VerboseMode = 0;
@@ -29,21 +31,26 @@ static int MaxFrameSize = 512;
#define REOPEN_TIMEOUT 30 /* try tio reopen every 10 s */
struct PortDescriptor {
- char Name[80];
+ char Name[PATH_MAX];
int Fd;
unsigned char *FrameBuffer;
int BufferIndex;
time_t TimeLastOpen;
+ char namepts[PATH_MAX]; /* name of the unix98 pts slaves, which
+ * the client has to use */
+ int is_active;
};
static struct PortDescriptor *PortList[FD_SETSIZE];
+
static int NbPort = 0;
static void Usage(void)
{
- fprintf(stderr, "\nUsage : kissnetd [-v] [-f size] /dev/pty?? [/dev/pty??]*\n");
+ fprintf(stderr, "\nUsage : kissnetd [-v] [-f size] [-p num | /dev/pty?? [/dev/pty??]* ]\n");
fprintf(stderr, " -v : Verbose mode, trace on stdout\n");
fprintf(stderr, " -f size : Set max frame size to size bytes (default 512)\n");
+ fprintf(stderr, " -p num : Number of /dev/ptmx-master-devices has to open\n");
exit(1);
}
@@ -83,45 +90,107 @@ static void NewPort(char *Name)
exit(1);
}
- strncpy(MyPort->Name, Name, sizeof(MyPort->Name));
+ strncpy(MyPort->Name, Name, PATH_MAX-1);
+ MyPort->Name[PATH_MAX-1] = '\0';
MyPort->Fd = -1;
MyPort->FrameBuffer[0] = 0xC0;
MyPort->BufferIndex = 1;
+ MyPort->namepts [0] = '\0';
+ MyPort->is_active = 0;
PortList[NbPort++] = MyPort;
}
static void ReopenPort(int PortNumber)
{
char MyString[80];
-
PortList[PortNumber]->TimeLastOpen = time(NULL);
if (VerboseMode) {
printf("Reopening port %d\n", PortNumber);
}
- syslog(LOG_WARNING, "kissnetd : Opening port %s\n", PortList[PortNumber]->Name);
-
- PortList[PortNumber]->Fd = open(PortList[PortNumber]->Name, O_RDWR | O_NONBLOCK);
- if (PortList[PortNumber]->Fd < 0) {
- syslog(LOG_WARNING, "kissnetd : Error opening port %s : %s\n",
- PortList[PortNumber]->Name, strerror(errno));
- if (VerboseMode) {
- sprintf(MyString, "cannot reopen %s", PortList[PortNumber]->Name);
- perror(MyString);
+ if (PortList[PortNumber]->namepts[0] == '\0') {
+
+ syslog(LOG_WARNING, "kissnetd : Opening port %s\n", PortList[PortNumber]->Name);
+ PortList[PortNumber]->Fd = open(PortList[PortNumber]->Name, O_RDWR | O_NONBLOCK);
+ if (PortList[PortNumber]->Fd < 0) {
+ syslog(LOG_WARNING, "kissnetd : Error opening port %s : %s\n",
+ PortList[PortNumber]->Name, strerror(errno));
+ if (VerboseMode) {
+ sprintf(MyString, "cannot reopen %s", PortList[PortNumber]->Name);
+ perror(MyString);
+ }
+ return;
}
+ PortList[PortNumber]->is_active = 1;
+ if (!strcmp(PortList[PortNumber]->Name, "/dev/ptmx")) {
+ char *npts;
+ /* get name of pts-device */
+ if ((npts = ptsname(PortList[PortNumber]->Fd)) == NULL) {
+ sprintf(MyString, "Cannot get name of pts-device.\n");
+ syslog(LOG_WARNING, "kissnetd : Cannot get name of pts-device\n");
+ exit(1);
+ }
+ strncpy(PortList[PortNumber]->namepts, npts, PATH_MAX-1);
+ PortList[PortNumber]->namepts[PATH_MAX-1] = '\0';
+
+ /* unlock pts-device */
+ if (unlockpt(PortList[PortNumber]->Fd) == -1) {
+ sprintf(MyString, "Cannot unlock pts-device %s\n", PortList[PortNumber]->namepts);
+ syslog(LOG_WARNING, "kissnetd : Cannot unlock pts-device %s\n", PortList[PortNumber]->namepts);
+ exit(1);
+ }
+ syslog(LOG_WARNING, "kissnetd : Using /dev/ptmx with slave pty %s\n", PortList[PortNumber]->namepts);
+ }
+ } else {
+ if (PortList[PortNumber]->Fd == -1) {
+ syslog(LOG_WARNING, "kissnetd : Cannot reopen port ptmx (slave %s) : not supported by ptmx-device\n",
+ PortList[PortNumber]->namepts);
+ if (VerboseMode) {
+ sprintf(MyString, "cannot reopen ptmx (slave %s).", PortList[PortNumber]->namepts);
+ perror(MyString);
+ }
+ return;
+ }
+ syslog(LOG_WARNING, "kissnetd : Trying to poll port ptmx (slave %s).\n",
+ PortList[PortNumber]->namepts);
+ PortList[PortNumber]->is_active = 1;
}
}
static void TickReopen(void)
{
int i;
+ static int wrote_info = 0;
time_t CurrentTime = time(NULL);
for (i=0; i<NbPort; i++) {
- if (PortList[i]->Fd >= 0) continue;
+ if (PortList[i]->Fd >= 0 && PortList[i]->is_active == 1) continue;
if ( (CurrentTime - PortList[i]->TimeLastOpen) > REOPEN_TIMEOUT ) ReopenPort(i);
}
+
+ if (!wrote_info) {
+ for (i=0; i<NbPort; i++) {
+ if (PortList[i]->namepts[0] != '\0') {
+ if (wrote_info == 0)
+ printf("\nAwaiting client connects on:\n");
+ else
+ printf(" ");
+ printf("%s", PortList[i]->namepts);
+ wrote_info = 1;
+ }
+ }
+ if (wrote_info > 0) {
+ printf("\n");
+ if (!VerboseMode) {
+ fflush(stdout);
+ fflush(stderr);
+ close(0);
+ close(1);
+ close(2);
+ }
+ }
+ }
}
static void Broadcast(int InputPort)
@@ -131,19 +200,52 @@ static void Broadcast(int InputPort)
/* Broadcast only info frames */
- if (PortList[InputPort]->FrameBuffer[1] != 0x00) return;
+ if (PortList[InputPort]->FrameBuffer[1] != 0x00 && \
+ PortList[InputPort]->FrameBuffer[1] != 0x20 && \
+ PortList[InputPort]->FrameBuffer[1] != 0x80)
+ return;
for (i=0; i<NbPort; i++) {
+ int offset = 0;
if (i == InputPort) continue;
- if (PortList[i]->Fd < 0) continue;
+ if (PortList[i]->Fd < 0 || PortList[i]->is_active == 0) continue;
+again:
rc = write(PortList[i]->Fd,
- PortList[InputPort]->FrameBuffer,
- PortList[InputPort]->BufferIndex);
+ PortList[InputPort]->FrameBuffer+offset,
+ PortList[InputPort]->BufferIndex-offset);
+ if (rc < 0) {
+ if (errno == EAGAIN) {
+ if (PortList[i]->namepts[0] == '\0')
+ syslog(LOG_WARNING, "kissnetd : write buffer full on port %s. dropping frame. %s",
+ PortList[i]->Name, strerror(errno));
+ else
+ syslog(LOG_WARNING, "kissnetd : write buffer full on ptmx port %s. dropping frame. %s",
+ PortList[i]->namepts, strerror(errno));
+ continue;
+ }
+ if (PortList[i]->namepts[0] == '\0')
+ syslog(LOG_WARNING, "kissnetd : Error writing to port %s : %s\n",
+ PortList[i]->Name, strerror(errno));
+ else
+ syslog(LOG_WARNING, "kissnetd : Error writing to port ptmx (slave %s) : %s\n",
+ PortList[i]->namepts, strerror(errno));
+ if (VerboseMode) perror("write");
+ PortList[i]->is_active = 0;
+ if (PortList[i]->namepts[0] == '\0') {
+ close(PortList[i]->Fd);
+ PortList[i]->Fd = -1;
+ }
+ continue;
+ }
if (VerboseMode) {
printf("Sending %d bytes on port %d : rc=%d\n",
PortList[InputPort]->BufferIndex,
i, rc);
}
+ if (rc < PortList[InputPort]->BufferIndex-offset) {
+ offset += rc;
+ goto again;
+ }
}
}
@@ -160,11 +262,20 @@ static void ProcessInput(int PortNumber)
}
if (!Length) return;
if (Length < 0) {
- syslog(LOG_WARNING, "kissnetd : Error reading port %s : %s\n",
- PortList[PortNumber]->Name, strerror(errno));
+ if (errno == EAGAIN)
+ return;
+ if (MyPort->namepts[0] == '\0')
+ syslog(LOG_WARNING, "kissnetd : Error reading from port %s : %s\n",
+ PortList[PortNumber]->Name, strerror(errno));
+ else
+ syslog(LOG_WARNING, "kissnetd : Error reading from port ptmx (slave %s) : %s\n",
+ PortList[PortNumber]->namepts, strerror(errno));
if (VerboseMode) perror("read");
- close(MyPort->Fd);
- MyPort->Fd = -1;
+ MyPort->is_active = 0;
+ if (MyPort->namepts[0] == '\0') {
+ close(MyPort->Fd);
+ MyPort->Fd = -1;
+ }
return;
}
for (i=0; i<Length; i++) {
@@ -195,7 +306,7 @@ static void ProcessPortList(void)
FD_ZERO(&MyFdSet);
for (i=0; i<NbPort; i++) {
- if (PortList[i]->Fd >= 0) FD_SET(PortList[i]->Fd, &MyFdSet);
+ if (PortList[i]->Fd >= 0 && PortList[i]->is_active) FD_SET(PortList[i]->Fd, &MyFdSet);
}
rc = select(FD_SETSIZE, &MyFdSet, NULL, NULL, &Timeout);
@@ -213,31 +324,42 @@ static void ProcessPortList(void)
}
}
-static void ProcessArgv(char *argv[])
+static void ProcessArgv(int argc, char *argv[])
{
- char *Opt;
- int ArgvIndex = 0;
+ int opt;
+ int i=0;
+ int ptmxdevices = 0;
- while (argv[ArgvIndex]) {
- if (argv[ArgvIndex][0] != '-') {
- NewPort(argv[ArgvIndex++]);
- continue;
- }
- for (Opt = &argv[ArgvIndex++][1]; *Opt; Opt++) {
- switch (*Opt) {
- case 'v':
- VerboseMode = 1;
- break;
- case 'f':
- MaxFrameSize = atoi(argv[ArgvIndex++]);
- break;
- default:
- fprintf(stderr, "Invalid option %c\n", *Opt);
- Usage();
- break;
+ while ((opt = getopt(argc, argv, "vf:p:")) != -1) {
+ switch (opt) {
+ case 'v':
+ VerboseMode = 1;
+ break;
+ case 'f':
+ MaxFrameSize = atoi(argv[optind]);
+ break;
+ case 'p':
+ ptmxdevices = atoi(optarg);
+ if (ptmxdevices < 1) {
+ fprintf(stderr, "error: too many devices\n");
+ exit(1);
}
+ for (i=0; i < ptmxdevices; i++)
+ NewPort("/dev/ptmx");
+ break;
+ default:
+ fprintf(stderr, "Invalid option %s\n", argv[optind]);
+ Usage();
+ exit(1);
}
+ }
+ while (optind < argc)
+ NewPort(argv[optind++]);
+
+ if (NbPort < 2) {
+ fprintf(stderr, "This multiplexer needs at least two pty's\n");
+ exit(1);
}
}
@@ -252,7 +374,7 @@ int main(int argc, char *argv[])
Banner(1);
}
- ProcessArgv(argv+1);
+ ProcessArgv(argc, argv);
while (1) ProcessPortList();
return 0;
}