summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2017-01-30 12:26:07 +0100
committerRalf Baechle <ralf@linux-mips.org>2017-02-06 23:43:46 +0100
commitf55a99c6cdf5a9d64ca5a2179649f94435d1260e (patch)
tree86ad9ea4d22eba1c591f4ad7dcdc060cf9ac3ab7
parent8db240507d6fdc417e24b2e3a5edf2123506a5b2 (diff)
ax25d: Reorder code to avoid the need for forward declarations.
And then delete those now useless declarations. Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--ax25/ax25d.c915
1 files changed, 454 insertions, 461 deletions
diff --git a/ax25/ax25d.c b/ax25/ax25d.c
index a172c27..30aa0af 100644
--- a/ax25/ax25d.c
+++ b/ax25/ax25d.c
@@ -191,14 +191,7 @@ static char myAX25Name[10]; /* Room for 'GB9ZZZ-15\0' */
static char *Port;
static int Logging = FALSE;
-static void SignalHUP(int);
-static void SignalTERM(int);
-static void WorkoutArgs(int, char *, int *, char **);
-static void SetupOptions(int, struct axlist *);
static int ReadConfig(void);
-static unsigned long ParseFlags(const char *, int);
-static struct axlist *ClearList(struct axlist *);
-static char *stripssid(const char *);
static fd_set fdread;
static int maxfd = -1;
@@ -256,388 +249,6 @@ static void reload_timer(int sec)
/*--------------------------------------------------------------------------*/
-int main(int argc, char *argv[])
-{
- struct axlist *axltmp, *paxl, *raxl;
- union {
- struct full_sockaddr_ax25 ax25;
- struct sockaddr_rose rose;
- } sockaddr;
- struct sigaction act, oact;
- socklen_t addrlen;
- int cnt;
- char buf[1024];
- char *p;
- char *mesg;
-
- while ((cnt = getopt(argc, argv, "c:lv")) != EOF) {
- switch (cnt) {
- case 'c':
- ConfigFile = optarg;
- break;
-
- case 'l':
- Logging = TRUE;
- break;
-
- case 'v':
- printf("ax25d: %s\n", FULL_VER);
- return 1;
-
- default:
- fprintf(stderr, "Usage: ax25d [-v] [-c altfile] [-l]\n");
- return 1;
- }
- }
-
- if (ax25_config_load_ports() == 0) {
- fprintf(stderr, "ax25d: no AX.25 port data configured\n");
- return 1;
- }
-
- nr_config_load_ports();
-
- rs_config_load_ports();
-
- if (!daemon_start(TRUE)) {
- fprintf(stderr, "ax25d: cannot become a daemon\n");
- return 1;
- }
-
- if (Logging) {
- openlog("ax25d", LOG_PID, LOG_DAEMON);
- syslog(LOG_INFO, "starting");
- }
-
- act.sa_handler = SignalHUP;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- sigaction(SIGHUP, &act, &oact);
-
- act.sa_handler = SignalTERM;
- sigemptyset(&act.sa_mask);
- act.sa_flags = 0;
- sigaction(SIGTERM, &act, &oact);
-
- ReadConfig();
-
- for (;;) {
-
- update_maxfd();
- if (maxfd < 0) {
- sleep(10);
- continue;
- }
-
- if (select(maxfd + 1, &fdread, NULL, NULL, NULL) <= 0)
- continue;
-
- for (paxl = AXL; paxl != NULL; paxl = paxl->next) {
- if (paxl->fd > 0 && FD_ISSET(paxl->fd, &fdread)) {
- pid_t pid;
- gid_t grps[2];
- char *argv[MAX_ARGS];
- int argc;
- int new;
- int i;
-
- /*
- * Setting up a non-blocking accept() so is does not hang up
- * - I am not sure at this time why I didn't/don't assign
- * the socket non-blocking to start with.
- */
- /*
- * We really need to setup the netrom window option here so
- * that it's negotiated correctly on accepting the connection.
- */
- /*
- * It would be very useful if recvmsg/sendmsg were supported
- * then we can move the call checking up here.
- */
- i = TRUE;
- ioctl(paxl->fd, FIONBIO, &i);
-
- addrlen = sizeof(struct full_sockaddr_ax25);
- new = accept(paxl->fd, (struct sockaddr *)&sockaddr, &addrlen);
-
- i = FALSE;
- ioctl(paxl->fd, FIONBIO, &i);
-
- if (new < 0) {
- if (errno == EWOULDBLOCK)
- continue; /* It's gone ??? */
-
- if (Logging)
- syslog(LOG_ERR, "accept error %m, closing socket on port %s", paxl->port);
- close(paxl->fd);
- paxl->fd = -1;
- reload_timer(10);
- continue;
- }
-
- switch (paxl->af_type) {
- case AF_AX25:
- strcpy(User, ax25_ntoa(&sockaddr.ax25.fsa_ax25.sax25_call));
- strcpy(Node, "");
- break;
- case AF_NETROM:
- strcpy(User, ax25_ntoa(&sockaddr.ax25.fsa_ax25.sax25_call));
- strcpy(Node, ax25_ntoa(&sockaddr.ax25.fsa_digipeater[0]));
- break;
- case AF_ROSE:
- strcpy(User, ax25_ntoa(&sockaddr.rose.srose_call));
- strcpy(Node, rose_ntoa(&sockaddr.rose.srose_addr));
- break;
- }
-
- for (raxl = paxl->ents; raxl != NULL; raxl = raxl->ents) {
- if (paxl->af_type == AF_NETROM && raxl->node != NULL && Node[0] != '\0') {
- if (strchr(raxl->node, '-') == NULL) {
- if (strcasecmp(raxl->node, stripssid(Node)) != 0)
- continue; /* Found no match (for any SSID) */
- } else {
- if (strcasecmp(raxl->node, Node) != 0)
- continue; /* Found no match */
- }
- }
-
- if (raxl->call == NULL) /* default */
- break;
-
- if (strchr(raxl->call, '-') == NULL) {
- if (strcasecmp(raxl->call, stripssid(User)) == 0)
- break; /* Found a match (for any SSID) */
- } else {
- if (strcasecmp(raxl->call, User) == 0)
- break; /* Found a match */
- }
- }
-
- addrlen = sizeof(struct full_sockaddr_ax25);
- getsockname(new, (struct sockaddr *)&sockaddr, &addrlen);
-
- switch (paxl->af_type) {
- case AF_AX25:
- Port = ax25_config_get_port(&sockaddr.ax25.fsa_digipeater[0]);
- break;
- case AF_NETROM:
- Port = nr_config_get_port(&sockaddr.ax25.fsa_ax25.sax25_call);
- break;
- case AF_ROSE:
- Port = rs_config_get_port(&sockaddr.rose.srose_addr);
- break;
- default:
- Port = "???";
- break;
- }
-
- if (raxl == NULL) {
- /* No default */
- if (Logging && !(paxl->flags & FLAG_NOLOGGING)) {
- switch (paxl->af_type) {
- case AF_AX25:
- syslog(LOG_INFO, "AX.25 %s (%s) rejected - no default", User, Port);
- break;
- case AF_NETROM:
- syslog(LOG_INFO, "NET/ROM %s@%s (%s) rejected - no default", User, Node, Port);
- break;
- case AF_ROSE:
- syslog(LOG_INFO, "Rose %s@%s (%s) rejected - no default", User, Node, Port);
- break;
- }
- }
- close(new);
- continue;
- }
-
- if (raxl->flags & FLAG_LOCKOUT) {
- /* Not allowed to connect */
- if (Logging && !(paxl->flags & FLAG_NOLOGGING)) {
- switch (raxl->af_type) {
- case AF_AX25:
- syslog(LOG_INFO, "AX.25 %s (%s) rejected - port locked", User, Port);
- break;
- case AF_NETROM:
- syslog(LOG_INFO, "NET/ROM %s@%s (%s) rejected - port locked", User, Node, Port);
- break;
- case AF_ROSE:
- syslog(LOG_INFO, "Rose %s@%s (%s) rejected - port locked", User, Node, Port);
- break;
- }
- }
- close(new);
- continue;
- }
-
- if (raxl->af_type == AF_AX25 && (raxl->flags & FLAG_NODIGIS) && sockaddr.ax25.fsa_ax25.sax25_ndigis != 0) {
- /* Not allowed to uplink via digi's */
- if (Logging && !(paxl->flags & FLAG_NOLOGGING))
- syslog(LOG_INFO, "AX.25 %s (%s) rejected - digipeaters", User, Port);
- close(new);
- continue;
- }
-
- pid = fork();
-
- switch (pid) {
- case -1:
- if (Logging)
- syslog(LOG_ERR, "fork error %m");
- /*
- * I don't think AX25 at the moment will hold the
- * connection open, if the above does not make it
- * through first time.
- */
- close(new);
- break; /* Oh well... */
-
- case 0:
-
- if (raxl->af_type == AF_AX25 && raxl->checkVC) {
- /* to which of my own addresses has the user connected? */
- getsockname(new, (struct sockaddr *)&sockaddr, &addrlen);
- strcpy(myAX25Name, ax25_ntoa(&sockaddr.ax25.fsa_ax25.sax25_call));
-
- sprintf(buf, "/usr/sbin/ax25rtctl -l ip | grep -i ' %s ' | /bin/grep 'v ' >/dev/null", User);
-
- /* he's not a VC user? */
- if (system(buf) != 0)
- goto login;
-
- if (raxl->checkVC > 1) {
- /* setproctitle("ax25d [%d]: rejecting, User); */
- } else {
- /* setproctitle("ax25d [%d]: %s, User, (VCloginEnable ? "waiting" : "discarding")); */
- }
-
- /* is a VC user. checkVC > 0? then reject now, or fork and wait for pid=textdata.. */
- if (raxl->VCsendFailureMsg) {
- sprintf(buf, "*** %s: NO MODE VC with %s\r", myAX25Name, myAX25Name);
- write(new, buf, strlen(buf));
- if (raxl->checkVC > 1)
- sleep(1);
- }
-
- if (raxl->checkVC > 1) {
- if (Logging && (!(paxl->flags & FLAG_NOLOGGING) || raxl->LoggingVC))
- syslog((raxl->LoggingVC ? LOG_NOTICE : LOG_INFO), "AX.25 %s (%s:%s) rejected - AX25.IP-VC entry found", User, Port, myAX25Name);
- goto close_link;
- }
-
- /* checkVC == 1: wait for data */
- if (Logging && (!(paxl->flags & FLAG_NOLOGGING) || raxl->LoggingVC)) {
- syslog((raxl->LoggingVC ? LOG_NOTICE : LOG_INFO), "AX.25 %s (%s:%s) AX25.IP-VC host connected. %s",
- User, Port, myAX25Name,
- (raxl->VCloginEnable ? "waiting for first PID=text packet for triggered login" : "discarding PID=text packets"));
- }
-
- *buf = 0;
- mesg = 0;
- while ((i = read(new, buf, (sizeof(buf)-1))) > 0) {
- buf[i] = 0;
- if (Logging && raxl->LoggingVC > 1) {
- /* debug */
- syslog((LOG_DEBUG), "DEBUG: AX.25 %s (%s:%s) AX25.IP-VC host said: >%s<", User, Port, myAX25Name, buf);
- }
- /* skip leading mess */
- for (p = buf; *p && (isspace(*p & 0xff) || *p == '\r'); p++) ;
- if (raxl->VCdiscOnLinkfailureMsg && !strncmp(p, "***", 3)) {
- /* format received line for debug purposes */
- /* 1. skip "***" */
- for (p += 3; *p && isspace(*p & 0xff); p++ ) ;
- mesg = p;
- /* 2. get rid off EOL delimiters */
- while (*p) {
- if (*p == '\r' || *p == '\n') {
- *p = 0;
- break;
- }
- p++;
- }
- /* end read loop */
- break;
- }
- /* per default, we discard all messages,
- * because there's no useful combination
- * using VC and pidText togegther
- */
- if (raxl->VCloginEnable)
- goto login;
- }
-
- if (Logging && (!(paxl->flags & FLAG_NOLOGGING) || raxl->LoggingVC)) {
- syslog((raxl->LoggingVC ? LOG_NOTICE : LOG_INFO),
- "AX.25 %s (%s:%s) AX25.IP-VC host disconnected%s%s",
- User,
- Port,
- myAX25Name,
- (mesg ? ": " : "."),
- (mesg ? mesg : ""));
- }
- /* point of no return */
-close_link:
- /* close link */
- /* setproctitle("ax25d [%s]: disconnecting", User); */
- close(new);
- exit(0);
- }
-login:
- /* setproctitle("ax25d [%s]: login", User); */
-
- SetupOptions(new, raxl);
- WorkoutArgs(raxl->af_type, raxl->shell, &argc, argv);
-
- if (Logging && !(paxl->flags & FLAG_NOLOGGING)) {
- switch (paxl->af_type) {
- case AF_AX25:
- syslog(LOG_INFO, "AX.25 %s (%s) %s", User, Port, argv[0]);
- break;
- case AF_NETROM:
- syslog(LOG_INFO, "NET/ROM %s@%s (%s) %s", User, Node, Port, argv[0]);
- break;
- case AF_ROSE:
- syslog(LOG_INFO, "Rose %s@%s (%s) %s", User, Node, Port, argv[0]);
- break;
- }
- }
-
- dup2(new, STDIN_FILENO);
- dup2(new, STDOUT_FILENO);
- close(new);
-
- /*
- * Might be more efficient if we just went down AXL,
- * we cleaned up our parents left overs on bootup.
- */
- for (axltmp = AXL; axltmp != NULL; axltmp = axltmp->next)
- close(axltmp->fd);
-
- if (Logging)
- closelog();
-
- /* Make root secure, before we exec() */
- /* Strip any supplementary gid's */
- if (setgroups(0, grps) == -1)
- exit(1);
- if (setgid(raxl->gid) == -1)
- exit(1);
- if (setuid(raxl->uid) == -1)
- exit(1);
- execve(raxl->exec, argv, NULL);
- exit(1);
-
- default:
- close(new);
- break;
- }
- }
- }
- }
-
- /* NOT REACHED */
- return 0;
-}
-
static void SignalHUP(int code)
{
ReadConfig();
@@ -795,6 +406,94 @@ static void SetupOptions(int new, struct axlist *axl)
/**************************** CONFIGURATION STUFF ***************************/
+static unsigned long ParseFlags(const char *kp, int line)
+{
+ unsigned long flags = 0UL;
+
+ for (; *kp != '\0'; kp++) {
+ switch (*kp) {
+ case 'v':
+ case 'V':
+ flags |= FLAG_VALIDCALL;
+ break;
+
+ case 'q':
+ case 'Q':
+ flags |= FLAG_NOLOGGING;
+ break;
+
+ case 'n':
+ case 'N':
+ flags |= FLAG_CHKNRN;
+ break;
+
+ case 'd':
+ case 'D':
+ flags |= FLAG_NODIGIS;
+ break;
+
+ case 'l':
+ case 'L':
+ flags |= FLAG_LOCKOUT;
+ break;
+
+ case '0':
+ case '*':
+ case '-': /* Be compatible and allow markers */
+ break;
+
+ default:
+ fprintf(stderr, "ax25d: config file line %d bad flag option '%c'.\n", line, *kp);
+ break;
+ }
+ }
+
+ return flags;
+}
+
+static struct axlist *ClearList(struct axlist *list)
+{
+ struct axlist *tp1, *tp2, *tmp;
+
+ for (tp1 = list; tp1 != NULL; ) {
+ for (tp2 = tp1->ents; tp2 != NULL; ) {
+ if (tp2->port != NULL)
+ free(tp2->port);
+ if (tp2->call != NULL)
+ free(tp2->call);
+ if (tp2->node != NULL)
+ free(tp2->node);
+ if (tp2->exec != NULL)
+ free(tp2->exec);
+ if (tp2->shell != NULL)
+ free(tp2->shell);
+
+ tmp = tp2->ents;
+ free(tp2);
+ tp2 = tmp;
+ }
+
+ if (tp1->port != NULL)
+ free(tp1->port);
+ if (tp1->call != NULL)
+ free(tp1->call);
+ if (tp1->node != NULL)
+ free(tp1->node);
+ if (tp1->exec != NULL)
+ free(tp1->exec);
+ if (tp1->shell != NULL)
+ free(tp1->shell);
+
+ close(tp1->fd);
+
+ tmp = tp1->next;
+ free(tp1);
+ tp1 = tmp;
+ }
+
+ return NULL;
+}
+
static int ReadConfig(void)
{
struct axlist axl_defaults;
@@ -1284,103 +983,397 @@ Error:
return -1;
}
-static unsigned long ParseFlags(const char *kp, int line)
+static char *stripssid(const char *call)
{
- unsigned long flags = 0UL;
+ static char newcall[10];
+ char *s;
- for (; *kp != '\0'; kp++) {
- switch (*kp) {
- case 'v':
- case 'V':
- flags |= FLAG_VALIDCALL;
- break;
+ strcpy(newcall, call);
- case 'q':
- case 'Q':
- flags |= FLAG_NOLOGGING;
- break;
+ if ((s = strchr(newcall, '-')) != NULL)
+ *s = '\0';
- case 'n':
- case 'N':
- flags |= FLAG_CHKNRN;
- break;
+ return newcall;
+}
- case 'd':
- case 'D':
- flags |= FLAG_NODIGIS;
+int main(int argc, char *argv[])
+{
+ struct axlist *axltmp, *paxl, *raxl;
+ union {
+ struct full_sockaddr_ax25 ax25;
+ struct sockaddr_rose rose;
+ } sockaddr;
+ struct sigaction act, oact;
+ socklen_t addrlen;
+ int cnt;
+ char buf[1024];
+ char *p;
+ char *mesg;
+
+ while ((cnt = getopt(argc, argv, "c:lv")) != EOF) {
+ switch (cnt) {
+ case 'c':
+ ConfigFile = optarg;
break;
case 'l':
- case 'L':
- flags |= FLAG_LOCKOUT;
+ Logging = TRUE;
break;
- case '0':
- case '*':
- case '-': /* Be compatible and allow markers */
- break;
+ case 'v':
+ printf("ax25d: %s\n", FULL_VER);
+ return 1;
default:
- fprintf(stderr, "ax25d: config file line %d bad flag option '%c'.\n", line, *kp);
- break;
+ fprintf(stderr, "Usage: ax25d [-v] [-c altfile] [-l]\n");
+ return 1;
}
}
- return flags;
-}
+ if (ax25_config_load_ports() == 0) {
+ fprintf(stderr, "ax25d: no AX.25 port data configured\n");
+ return 1;
+ }
-static struct axlist *ClearList(struct axlist *list)
-{
- struct axlist *tp1, *tp2, *tmp;
+ nr_config_load_ports();
- for (tp1 = list; tp1 != NULL; ) {
- for (tp2 = tp1->ents; tp2 != NULL; ) {
- if (tp2->port != NULL)
- free(tp2->port);
- if (tp2->call != NULL)
- free(tp2->call);
- if (tp2->node != NULL)
- free(tp2->node);
- if (tp2->exec != NULL)
- free(tp2->exec);
- if (tp2->shell != NULL)
- free(tp2->shell);
+ rs_config_load_ports();
- tmp = tp2->ents;
- free(tp2);
- tp2 = tmp;
+ if (!daemon_start(TRUE)) {
+ fprintf(stderr, "ax25d: cannot become a daemon\n");
+ return 1;
+ }
+
+ if (Logging) {
+ openlog("ax25d", LOG_PID, LOG_DAEMON);
+ syslog(LOG_INFO, "starting");
+ }
+
+ act.sa_handler = SignalHUP;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction(SIGHUP, &act, &oact);
+
+ act.sa_handler = SignalTERM;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction(SIGTERM, &act, &oact);
+
+ ReadConfig();
+
+ for (;;) {
+
+ update_maxfd();
+ if (maxfd < 0) {
+ sleep(10);
+ continue;
}
- if (tp1->port != NULL)
- free(tp1->port);
- if (tp1->call != NULL)
- free(tp1->call);
- if (tp1->node != NULL)
- free(tp1->node);
- if (tp1->exec != NULL)
- free(tp1->exec);
- if (tp1->shell != NULL)
- free(tp1->shell);
+ if (select(maxfd + 1, &fdread, NULL, NULL, NULL) <= 0)
+ continue;
- close(tp1->fd);
+ for (paxl = AXL; paxl != NULL; paxl = paxl->next) {
+ if (paxl->fd > 0 && FD_ISSET(paxl->fd, &fdread)) {
+ pid_t pid;
+ gid_t grps[2];
+ char *argv[MAX_ARGS];
+ int argc;
+ int new;
+ int i;
- tmp = tp1->next;
- free(tp1);
- tp1 = tmp;
- }
+ /*
+ * Setting up a non-blocking accept() so is does not hang up
+ * - I am not sure at this time why I didn't/don't assign
+ * the socket non-blocking to start with.
+ */
+ /*
+ * We really need to setup the netrom window option here so
+ * that it's negotiated correctly on accepting the connection.
+ */
+ /*
+ * It would be very useful if recvmsg/sendmsg were supported
+ * then we can move the call checking up here.
+ */
+ i = TRUE;
+ ioctl(paxl->fd, FIONBIO, &i);
- return NULL;
-}
+ addrlen = sizeof(struct full_sockaddr_ax25);
+ new = accept(paxl->fd, (struct sockaddr *)&sockaddr, &addrlen);
-static char *stripssid(const char *call)
-{
- static char newcall[10];
- char *s;
+ i = FALSE;
+ ioctl(paxl->fd, FIONBIO, &i);
- strcpy(newcall, call);
+ if (new < 0) {
+ if (errno == EWOULDBLOCK)
+ continue; /* It's gone ??? */
- if ((s = strchr(newcall, '-')) != NULL)
- *s = '\0';
+ if (Logging)
+ syslog(LOG_ERR, "accept error %m, closing socket on port %s", paxl->port);
+ close(paxl->fd);
+ paxl->fd = -1;
+ reload_timer(10);
+ continue;
+ }
- return newcall;
+ switch (paxl->af_type) {
+ case AF_AX25:
+ strcpy(User, ax25_ntoa(&sockaddr.ax25.fsa_ax25.sax25_call));
+ strcpy(Node, "");
+ break;
+ case AF_NETROM:
+ strcpy(User, ax25_ntoa(&sockaddr.ax25.fsa_ax25.sax25_call));
+ strcpy(Node, ax25_ntoa(&sockaddr.ax25.fsa_digipeater[0]));
+ break;
+ case AF_ROSE:
+ strcpy(User, ax25_ntoa(&sockaddr.rose.srose_call));
+ strcpy(Node, rose_ntoa(&sockaddr.rose.srose_addr));
+ break;
+ }
+
+ for (raxl = paxl->ents; raxl != NULL; raxl = raxl->ents) {
+ if (paxl->af_type == AF_NETROM && raxl->node != NULL && Node[0] != '\0') {
+ if (strchr(raxl->node, '-') == NULL) {
+ if (strcasecmp(raxl->node, stripssid(Node)) != 0)
+ continue; /* Found no match (for any SSID) */
+ } else {
+ if (strcasecmp(raxl->node, Node) != 0)
+ continue; /* Found no match */
+ }
+ }
+
+ if (raxl->call == NULL) /* default */
+ break;
+
+ if (strchr(raxl->call, '-') == NULL) {
+ if (strcasecmp(raxl->call, stripssid(User)) == 0)
+ break; /* Found a match (for any SSID) */
+ } else {
+ if (strcasecmp(raxl->call, User) == 0)
+ break; /* Found a match */
+ }
+ }
+
+ addrlen = sizeof(struct full_sockaddr_ax25);
+ getsockname(new, (struct sockaddr *)&sockaddr, &addrlen);
+
+ switch (paxl->af_type) {
+ case AF_AX25:
+ Port = ax25_config_get_port(&sockaddr.ax25.fsa_digipeater[0]);
+ break;
+ case AF_NETROM:
+ Port = nr_config_get_port(&sockaddr.ax25.fsa_ax25.sax25_call);
+ break;
+ case AF_ROSE:
+ Port = rs_config_get_port(&sockaddr.rose.srose_addr);
+ break;
+ default:
+ Port = "???";
+ break;
+ }
+
+ if (raxl == NULL) {
+ /* No default */
+ if (Logging && !(paxl->flags & FLAG_NOLOGGING)) {
+ switch (paxl->af_type) {
+ case AF_AX25:
+ syslog(LOG_INFO, "AX.25 %s (%s) rejected - no default", User, Port);
+ break;
+ case AF_NETROM:
+ syslog(LOG_INFO, "NET/ROM %s@%s (%s) rejected - no default", User, Node, Port);
+ break;
+ case AF_ROSE:
+ syslog(LOG_INFO, "Rose %s@%s (%s) rejected - no default", User, Node, Port);
+ break;
+ }
+ }
+ close(new);
+ continue;
+ }
+
+ if (raxl->flags & FLAG_LOCKOUT) {
+ /* Not allowed to connect */
+ if (Logging && !(paxl->flags & FLAG_NOLOGGING)) {
+ switch (raxl->af_type) {
+ case AF_AX25:
+ syslog(LOG_INFO, "AX.25 %s (%s) rejected - port locked", User, Port);
+ break;
+ case AF_NETROM:
+ syslog(LOG_INFO, "NET/ROM %s@%s (%s) rejected - port locked", User, Node, Port);
+ break;
+ case AF_ROSE:
+ syslog(LOG_INFO, "Rose %s@%s (%s) rejected - port locked", User, Node, Port);
+ break;
+ }
+ }
+ close(new);
+ continue;
+ }
+
+ if (raxl->af_type == AF_AX25 && (raxl->flags & FLAG_NODIGIS) && sockaddr.ax25.fsa_ax25.sax25_ndigis != 0) {
+ /* Not allowed to uplink via digi's */
+ if (Logging && !(paxl->flags & FLAG_NOLOGGING))
+ syslog(LOG_INFO, "AX.25 %s (%s) rejected - digipeaters", User, Port);
+ close(new);
+ continue;
+ }
+
+ pid = fork();
+
+ switch (pid) {
+ case -1:
+ if (Logging)
+ syslog(LOG_ERR, "fork error %m");
+ /*
+ * I don't think AX25 at the moment will hold the
+ * connection open, if the above does not make it
+ * through first time.
+ */
+ close(new);
+ break; /* Oh well... */
+
+ case 0:
+
+ if (raxl->af_type == AF_AX25 && raxl->checkVC) {
+ /* to which of my own addresses has the user connected? */
+ getsockname(new, (struct sockaddr *)&sockaddr, &addrlen);
+ strcpy(myAX25Name, ax25_ntoa(&sockaddr.ax25.fsa_ax25.sax25_call));
+
+ sprintf(buf, "/usr/sbin/ax25rtctl -l ip | grep -i ' %s ' | /bin/grep 'v ' >/dev/null", User);
+
+ /* he's not a VC user? */
+ if (system(buf) != 0)
+ goto login;
+
+ if (raxl->checkVC > 1) {
+ /* setproctitle("ax25d [%d]: rejecting, User); */
+ } else {
+ /* setproctitle("ax25d [%d]: %s, User, (VCloginEnable ? "waiting" : "discarding")); */
+ }
+
+ /* is a VC user. checkVC > 0? then reject now, or fork and wait for pid=textdata.. */
+ if (raxl->VCsendFailureMsg) {
+ sprintf(buf, "*** %s: NO MODE VC with %s\r", myAX25Name, myAX25Name);
+ write(new, buf, strlen(buf));
+ if (raxl->checkVC > 1)
+ sleep(1);
+ }
+
+ if (raxl->checkVC > 1) {
+ if (Logging && (!(paxl->flags & FLAG_NOLOGGING) || raxl->LoggingVC))
+ syslog((raxl->LoggingVC ? LOG_NOTICE : LOG_INFO), "AX.25 %s (%s:%s) rejected - AX25.IP-VC entry found", User, Port, myAX25Name);
+ goto close_link;
+ }
+
+ /* checkVC == 1: wait for data */
+ if (Logging && (!(paxl->flags & FLAG_NOLOGGING) || raxl->LoggingVC)) {
+ syslog((raxl->LoggingVC ? LOG_NOTICE : LOG_INFO), "AX.25 %s (%s:%s) AX25.IP-VC host connected. %s",
+ User, Port, myAX25Name,
+ (raxl->VCloginEnable ? "waiting for first PID=text packet for triggered login" : "discarding PID=text packets"));
+ }
+
+ *buf = 0;
+ mesg = 0;
+ while ((i = read(new, buf, (sizeof(buf)-1))) > 0) {
+ buf[i] = 0;
+ if (Logging && raxl->LoggingVC > 1) {
+ /* debug */
+ syslog((LOG_DEBUG), "DEBUG: AX.25 %s (%s:%s) AX25.IP-VC host said: >%s<", User, Port, myAX25Name, buf);
+ }
+ /* skip leading mess */
+ for (p = buf; *p && (isspace(*p & 0xff) || *p == '\r'); p++) ;
+ if (raxl->VCdiscOnLinkfailureMsg && !strncmp(p, "***", 3)) {
+ /* format received line for debug purposes */
+ /* 1. skip "***" */
+ for (p += 3; *p && isspace(*p & 0xff); p++ ) ;
+ mesg = p;
+ /* 2. get rid off EOL delimiters */
+ while (*p) {
+ if (*p == '\r' || *p == '\n') {
+ *p = 0;
+ break;
+ }
+ p++;
+ }
+ /* end read loop */
+ break;
+ }
+ /* per default, we discard all messages,
+ * because there's no useful combination
+ * using VC and pidText togegther
+ */
+ if (raxl->VCloginEnable)
+ goto login;
+ }
+
+ if (Logging && (!(paxl->flags & FLAG_NOLOGGING) || raxl->LoggingVC)) {
+ syslog((raxl->LoggingVC ? LOG_NOTICE : LOG_INFO),
+ "AX.25 %s (%s:%s) AX25.IP-VC host disconnected%s%s",
+ User,
+ Port,
+ myAX25Name,
+ (mesg ? ": " : "."),
+ (mesg ? mesg : ""));
+ }
+ /* point of no return */
+close_link:
+ /* close link */
+ /* setproctitle("ax25d [%s]: disconnecting", User); */
+ close(new);
+ exit(0);
+ }
+login:
+ /* setproctitle("ax25d [%s]: login", User); */
+
+ SetupOptions(new, raxl);
+ WorkoutArgs(raxl->af_type, raxl->shell, &argc, argv);
+
+ if (Logging && !(paxl->flags & FLAG_NOLOGGING)) {
+ switch (paxl->af_type) {
+ case AF_AX25:
+ syslog(LOG_INFO, "AX.25 %s (%s) %s", User, Port, argv[0]);
+ break;
+ case AF_NETROM:
+ syslog(LOG_INFO, "NET/ROM %s@%s (%s) %s", User, Node, Port, argv[0]);
+ break;
+ case AF_ROSE:
+ syslog(LOG_INFO, "Rose %s@%s (%s) %s", User, Node, Port, argv[0]);
+ break;
+ }
+ }
+
+ dup2(new, STDIN_FILENO);
+ dup2(new, STDOUT_FILENO);
+ close(new);
+
+ /*
+ * Might be more efficient if we just went down AXL,
+ * we cleaned up our parents left overs on bootup.
+ */
+ for (axltmp = AXL; axltmp != NULL; axltmp = axltmp->next)
+ close(axltmp->fd);
+
+ if (Logging)
+ closelog();
+
+ /* Make root secure, before we exec() */
+ /* Strip any supplementary gid's */
+ if (setgroups(0, grps) == -1)
+ exit(1);
+ if (setgid(raxl->gid) == -1)
+ exit(1);
+ if (setuid(raxl->uid) == -1)
+ exit(1);
+ execve(raxl->exec, argv, NULL);
+ exit(1);
+
+ default:
+ close(new);
+ break;
+ }
+ }
+ }
+ }
+
+ /* NOT REACHED */
+ return 0;
}