2015-09-03 20:01:45 +01:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <signal.h>
|
|
|
|
|
|
|
|
#include <sys/time.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
|
|
#include <netax25/ax25.h>
|
|
|
|
#include <netrose/rose.h>
|
|
|
|
#include <netinet/ip_icmp.h>
|
|
|
|
#include <netinet/ip.h>
|
|
|
|
|
|
|
|
#include <netax25/axlib.h>
|
|
|
|
#include <netax25/axconfig.h>
|
|
|
|
#include <netax25/nrconfig.h>
|
|
|
|
#include <netax25/rsconfig.h>
|
|
|
|
#include <netax25/procutils.h>
|
|
|
|
#include <netax25/daemon.h>
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
#include "procinfo.h"
|
|
|
|
|
|
|
|
#define DEFAULT_POLL_TIME 600
|
|
|
|
#define MINIMUM_POLL_TIME 300
|
|
|
|
|
|
|
|
int poll_time=DEFAULT_POLL_TIME;
|
|
|
|
char flexgate[10]="\0";
|
|
|
|
char mycall[10]="\0";
|
2016-04-01 16:06:32 +01:00
|
|
|
char prompt1[1]="\0";
|
|
|
|
char prompt2[1]="\0";
|
2015-09-03 20:01:45 +01:00
|
|
|
struct ax_routes *gw;
|
|
|
|
int s;
|
|
|
|
void (*sigterm_defhnd)(int);
|
|
|
|
|
|
|
|
void read_conf(void)
|
|
|
|
{
|
|
|
|
FILE *fp, *fgt;
|
|
|
|
char buf[1024], line[1024], *cp;
|
|
|
|
int i=0,k;
|
|
|
|
char digipath[AX25_MAX_DIGIS*10];
|
|
|
|
|
|
|
|
if ((fp=fopen(FLEXD_CONF_FILE, "r")) == NULL) {
|
|
|
|
fprintf(stderr, "flexd config: Cannot open config file: %s\n", FLEXD_CONF_FILE);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
if ((fgt=fopen(FLEX_GT_FILE, "w")) == NULL) {
|
|
|
|
fprintf(stderr, "flexd config: Cannot open flexnet gateways file: %s\n", FLEX_GT_FILE);
|
|
|
|
fclose(fp);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
fputs("addr callsign dev digipeaters\n", fgt);
|
|
|
|
|
|
|
|
while(fgets(buf, sizeof(buf), fp)) {
|
|
|
|
if(*buf=='#' || *buf==' ') continue; /* comment line/empty line */
|
|
|
|
cp=strchr(buf, '#');
|
|
|
|
if (cp) *cp='\0';
|
|
|
|
cp=strtok(buf, " \t\n\r");
|
|
|
|
if(cp==NULL) continue; /* empty line */
|
|
|
|
|
|
|
|
if(strcasecmp(cp,"pollinterval")==0) { /* set poll interval */
|
|
|
|
cp=strtok(NULL, " \t\n\r");
|
|
|
|
if(cp==NULL) {
|
2016-04-01 16:06:32 +01:00
|
|
|
fprintf(stderr, "flexd config: Poll Interval needs an argument\n");
|
2015-09-03 20:01:45 +01:00
|
|
|
fclose(fp);
|
|
|
|
fclose(fgt);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
poll_time=safe_atoi(cp);
|
|
|
|
if (poll_time<MINIMUM_POLL_TIME) poll_time=MINIMUM_POLL_TIME;
|
|
|
|
}
|
|
|
|
if(strcasecmp(cp,"mycall")==0) { /* set connect call for download */
|
|
|
|
cp=strtok(NULL, " \t\n\r");
|
|
|
|
if(cp==NULL) {
|
|
|
|
fprintf(stderr, "flexd config: MyCall needs an argument\n");
|
|
|
|
fclose(fp);
|
|
|
|
fclose(fgt);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
safe_strncpy(mycall, cp, 9);
|
|
|
|
}
|
|
|
|
if(strcasecmp(cp,"flexgate")==0) { /* set flexnet gateway */
|
|
|
|
cp=strtok(NULL, " \t\n\r");
|
|
|
|
if(cp==NULL) {
|
|
|
|
fprintf(stderr, "flexd config: FlexGate needs an argument\n");
|
|
|
|
fclose(fp);
|
|
|
|
fclose(fgt);
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
safe_strncpy(flexgate, cp, 9);
|
|
|
|
gw=find_route(flexgate, NULL);
|
|
|
|
if (gw==NULL) {
|
|
|
|
fprintf(stderr, "flexd config: FlexGate %s not found in route file: %s\n", flexgate, AX_ROUTES_FILE);
|
|
|
|
fclose(fp);
|
|
|
|
fclose(fgt);
|
|
|
|
exit(1);
|
|
|
|
} else {
|
|
|
|
*digipath='\0';
|
|
|
|
for(k=0;k<AX25_MAX_DIGIS;k++) {
|
|
|
|
if (gw->digis[k]==NULL) break;
|
|
|
|
strcat(digipath," ");
|
|
|
|
strcat(digipath, gw->digis[k]);
|
|
|
|
}
|
|
|
|
sprintf(line, "%05d %-8s %4s %s\n", i++, gw->dest_call, ax25_config_get_dev(gw->dev), digipath);
|
|
|
|
fputs(line, fgt);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-04-01 16:06:32 +01:00
|
|
|
fprintf(stderr,"FlexD started.\n\r");
|
2015-09-03 20:01:45 +01:00
|
|
|
fclose(fgt);
|
|
|
|
fclose(fp);
|
|
|
|
}
|
|
|
|
|
|
|
|
int download_dest(char *gateway, char *fname)
|
|
|
|
{
|
|
|
|
FILE *tmp;
|
2016-04-01 16:06:32 +01:00
|
|
|
char buffer[512], port[14], path[AX25_MAX_DIGIS*10]; /* Increased buffer to 512 from 256 - ve3tok 31 Mar, 2016 */
|
2015-09-03 20:01:45 +01:00
|
|
|
char *addr, *commands[10], *dlist[9]; /* Destination + 8 digipeaters */
|
|
|
|
fd_set read_fd;
|
|
|
|
int n, addrlen, cmd_send=0, cmd_ack=0, c, k;
|
|
|
|
struct full_sockaddr_ax25 axbind, axconnect;
|
|
|
|
struct timeval tv;
|
|
|
|
|
|
|
|
gw=find_route(gateway, NULL);
|
|
|
|
if (gw==NULL) {
|
|
|
|
fprintf(stderr, "flexd connect: FlexGate %s not found in route file: %s\n", gateway, AX_ROUTES_FILE);
|
|
|
|
return 1;
|
|
|
|
} else {
|
|
|
|
*path='\0';
|
|
|
|
for(k=0;k<AX25_MAX_DIGIS;k++) {
|
|
|
|
if (gw->digis[k][0]=='\0') dlist[k+1]=NULL;
|
|
|
|
else dlist[k+1]=gw->digis[k];
|
|
|
|
}
|
|
|
|
dlist[0]=gw->dest_call;
|
|
|
|
strcpy(port,gw->dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((addr = ax25_config_get_addr(port)) == NULL) {
|
|
|
|
sprintf(buffer, "flexd connect: invalid AX.25 port name - %s\r\n", port);
|
|
|
|
write(STDOUT_FILENO, buffer, strlen(buffer));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Open the socket into the kernel.
|
|
|
|
*/
|
|
|
|
if ((s = socket(AF_AX25, SOCK_SEQPACKET, 0)) < 0) {
|
|
|
|
sprintf(buffer, "flexd connect: cannot open AX.25 socket, %s\r\n", strerror(errno));
|
|
|
|
write(STDOUT_FILENO, buffer, strlen(buffer));
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Set our AX.25 callsign and AX.25 port callsign accordingly.
|
|
|
|
*/
|
|
|
|
if (*mycall=='\0') sprintf(buffer, "%s %s", addr, addr);
|
|
|
|
else sprintf(buffer, "%s %s", mycall, addr);
|
|
|
|
ax25_aton(buffer, &axbind);
|
|
|
|
axbind.fsa_ax25.sax25_family = AF_AX25;
|
|
|
|
addrlen=sizeof(struct full_sockaddr_ax25);
|
|
|
|
|
|
|
|
if (bind(s, (struct sockaddr *)&axbind, addrlen) != 0) {
|
|
|
|
sprintf(buffer, "flexd connect: cannot bind AX.25 socket, %s\r\n", strerror(errno));
|
|
|
|
write(STDOUT_FILENO, buffer, strlen(buffer));
|
|
|
|
close(s);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Lets try and connect to the far end.
|
|
|
|
*/
|
|
|
|
addrlen=sizeof(struct full_sockaddr_ax25);
|
|
|
|
axconnect.fsa_ax25.sax25_family = AF_AX25;
|
|
|
|
|
|
|
|
if (fcntl(s, F_SETFL, O_NONBLOCK) == -1) {
|
|
|
|
sprintf(buffer, "flexd connect: fcntl on socket: %s\r\n", strerror(errno));
|
|
|
|
write(STDOUT_FILENO, buffer, strlen(buffer));
|
|
|
|
close(s);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ax25_aton_arglist((const char **)dlist, &axconnect) == -1) {
|
|
|
|
sprintf(buffer, "flexd connect: invalid destination callsign or digipeater\r\n");
|
|
|
|
write(STDOUT_FILENO, buffer, strlen(buffer));
|
|
|
|
close(s);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (connect(s, (struct sockaddr *)&axconnect, addrlen) == -1 && errno != EINPROGRESS) {
|
|
|
|
switch (errno) {
|
|
|
|
case ECONNREFUSED:
|
|
|
|
strcpy(buffer, "*** Connection refused - aborting\r\n");
|
|
|
|
break;
|
|
|
|
case ENETUNREACH:
|
|
|
|
strcpy(buffer, "*** No known route - aborting\r\n");
|
|
|
|
break;
|
|
|
|
case EINTR:
|
|
|
|
strcpy(buffer, "*** Connection timed out - aborting\r\n");
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sprintf(buffer, "*** Cannot connect, %s\r\n", strerror(errno));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
write(STDOUT_FILENO, buffer, strlen(buffer));
|
|
|
|
close(s);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
FD_ZERO(&read_fd);
|
|
|
|
FD_SET(s, &read_fd);
|
|
|
|
|
|
|
|
tv.tv_sec=180;
|
|
|
|
tv.tv_usec=0;
|
|
|
|
|
|
|
|
k=select(s + 3, &read_fd, NULL, 0, &tv);
|
|
|
|
|
|
|
|
if (k<1) { /* error or timeout */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (FD_ISSET(s, &read_fd)) {
|
2016-04-01 16:06:32 +01:00
|
|
|
// int ret, retlen;
|
|
|
|
int ret = 0;
|
|
|
|
int retlen = 0;
|
2015-09-03 20:01:45 +01:00
|
|
|
char *cp;
|
|
|
|
|
|
|
|
/* See if we got connected or if this was an error */
|
|
|
|
getsockopt(s, SOL_SOCKET, SO_ERROR, &ret, &retlen);
|
|
|
|
if (ret != 0) {
|
|
|
|
cp = strdup(strerror(ret));
|
|
|
|
strlwr(cp);
|
2016-04-01 16:06:32 +01:00
|
|
|
sprintf(buffer, "flexd connect: Failure with %s\r\nError: %s\r\n", gateway, cp);
|
2015-09-03 20:01:45 +01:00
|
|
|
write(STDOUT_FILENO, buffer, strlen(buffer));
|
|
|
|
free(cp);
|
|
|
|
close(s);
|
|
|
|
return 1;
|
2016-04-01 16:06:32 +01:00
|
|
|
}
|
2015-09-03 20:01:45 +01:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
commands[0]="d\r\n";
|
|
|
|
commands[1]="q\r\n";
|
|
|
|
commands[2]=NULL;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Loop until one end of the connection goes away.
|
|
|
|
*/
|
|
|
|
|
|
|
|
if ((tmp=fopen(fname, "w")) == NULL) {
|
|
|
|
fprintf(stderr, "flexd connect: Cannot open temporary file: %s\n", fname);
|
|
|
|
close(s);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (;;) {
|
|
|
|
FD_ZERO(&read_fd);
|
|
|
|
FD_SET(s, &read_fd);
|
|
|
|
|
|
|
|
tv.tv_sec=180;
|
|
|
|
tv.tv_usec=0;
|
|
|
|
|
|
|
|
k=select(s + 1, &read_fd, NULL, NULL, &tv);
|
|
|
|
|
|
|
|
if (k<1) { /* error or timeout */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (FD_ISSET(s, &read_fd)) {
|
|
|
|
if ((n = read(s, buffer, 512)) == -1) break;
|
2016-04-01 16:06:32 +01:00
|
|
|
// if ((n = read(s, buffer, 256)) == -1) break;
|
2015-09-03 20:01:45 +01:00
|
|
|
for(c=0;c<n;c++) {
|
|
|
|
if (buffer[c]=='\r') buffer[c]='\n';
|
|
|
|
if (buffer[c]=='=' && c<n-1 && buffer[c+1]=='>') {
|
2016-04-01 16:06:32 +01:00
|
|
|
// if (buffer[c]=='%s' && c<n-1 && buffer [c+1]=='%s', prompt1, prompt2) {
|
|
|
|
// fprintf(stderr, "flex interact: ack[%d]\n", cmd_ack);
|
2015-09-03 20:01:45 +01:00
|
|
|
cmd_ack++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fwrite(buffer, sizeof(char), n, tmp);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cmd_ack!=0) {
|
|
|
|
if (commands[cmd_send]!=NULL) {
|
|
|
|
write(s, commands[cmd_send], 2);
|
2016-04-01 16:06:32 +01:00
|
|
|
// fprintf(stderr, "flexd interact: send[%d]: %s\n", cmd_send, commands[cmd_send]);
|
2015-09-03 20:01:45 +01:00
|
|
|
cmd_send++;
|
|
|
|
}
|
|
|
|
cmd_ack=0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
close(s);
|
|
|
|
|
|
|
|
fputs("\n",tmp);
|
|
|
|
|
|
|
|
fclose(tmp);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int parse_dest(char *gateway, char *fname)
|
|
|
|
{
|
|
|
|
FILE *fdst, *tmp;
|
|
|
|
char *call, *ssid, *rtt, *cp, buf[1024], line[1024], ax[10];
|
|
|
|
int i=0;
|
|
|
|
|
|
|
|
if ((tmp=fopen(fname, "r")) == NULL) {
|
|
|
|
fprintf(stderr, "flexd update: Cannot open temporary file: %s\n", fname);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((fdst=fopen(FLEX_DST_FILE, "w")) == NULL) {
|
|
|
|
fprintf(stderr, "flexd update: Cannot open flexnet destinations file: %s\n", FLEX_DST_FILE);
|
|
|
|
fclose(tmp);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
fputs("callsign ssid rtt gateway\n", fdst);
|
|
|
|
/* fprintf(fdst, "%s %s 0 00000\n", mygate, myrange); */
|
|
|
|
while(fgets(buf, sizeof(buf), tmp)) {
|
|
|
|
cp=strtok(buf, " \t\n\r");
|
|
|
|
if(cp==NULL) continue; /* empty line */
|
|
|
|
if(strstr(cp,"=>")) i++; /* system prompt */
|
|
|
|
if(i==0) continue; /* skip connect text */
|
|
|
|
if(*cp=='#' || *cp=='=' || *cp==' ' || *cp=='*' || *cp=='-' || *cp==':') continue; /* comment line/system prompt */
|
|
|
|
if(strncmp(cp,"73!",3)==0) continue; /* End greeting */
|
|
|
|
|
|
|
|
/* CALL SSID-ESID RTT */
|
|
|
|
do {
|
|
|
|
call=cp;
|
|
|
|
if (call==NULL) break;
|
|
|
|
if (strlen(call)>6) break;
|
|
|
|
if (strchr(call,'-')) break;
|
|
|
|
if (ax25_aton_entry(call,ax)!=0) break;
|
|
|
|
if (!ax25_validate(ax)) break;
|
|
|
|
ssid=strtok(NULL, " \t\n\r");
|
|
|
|
if (ssid==NULL) break;
|
|
|
|
if (!strchr(ssid,'-')) break;
|
|
|
|
rtt=strtok(NULL, " \t\n\r");
|
|
|
|
if (rtt==NULL) break;
|
|
|
|
if (atoi(rtt)==0) break;
|
|
|
|
sprintf(line, "%-8s %-5s %6d %05d\n", call, ssid, safe_atoi(rtt), 0);
|
|
|
|
fputs(line, fdst);
|
|
|
|
cp=strtok(NULL, " \t\n\r");
|
|
|
|
} while(cp!=NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
fclose(fdst);
|
|
|
|
fclose(tmp);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int update_flex(void)
|
|
|
|
{
|
|
|
|
char fname[80];
|
|
|
|
|
|
|
|
sprintf(fname, "%s/.session.%s", FLEXD_TEMP_PATH, flexgate);
|
|
|
|
|
|
|
|
if (download_dest(flexgate, fname)==0) parse_dest(flexgate, fname);
|
|
|
|
remove(fname);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void hup_handler(int sig)
|
|
|
|
{
|
|
|
|
signal(SIGHUP, SIG_IGN);
|
|
|
|
|
2016-04-01 16:06:32 +01:00
|
|
|
fprintf(stderr, "SIGHUP caught by FlexD, restarting... \n\r");
|
2015-09-03 20:01:45 +01:00
|
|
|
read_conf();
|
2016-04-01 16:06:32 +01:00
|
|
|
update_flex();
|
2015-09-03 20:01:45 +01:00
|
|
|
|
|
|
|
signal(SIGHUP, hup_handler); /* Restore hangup handler */
|
|
|
|
}
|
|
|
|
|
|
|
|
void alarm_handler(int sig)
|
|
|
|
{
|
|
|
|
signal(SIGALRM, SIG_IGN);
|
|
|
|
|
|
|
|
update_flex();
|
|
|
|
|
|
|
|
signal(SIGALRM, alarm_handler); /* Restore alarm handler */
|
|
|
|
alarm(poll_time);
|
|
|
|
}
|
|
|
|
|
|
|
|
void quit_handler(int sig)
|
|
|
|
{
|
|
|
|
signal(SIGTERM, SIG_IGN);
|
|
|
|
|
|
|
|
unlink(FLEXD_PID_FILE);
|
2016-04-01 16:06:32 +01:00
|
|
|
fprintf(stderr, "FlexD quitting.\n\r");
|
2015-09-03 20:01:45 +01:00
|
|
|
signal(SIGTERM, sigterm_defhnd);
|
|
|
|
raise(SIGTERM);
|
2015-11-22 14:56:30 +00:00
|
|
|
return;
|
2015-09-03 20:01:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
FILE *pidfile;
|
|
|
|
|
|
|
|
signal(SIGPIPE, SIG_IGN);
|
|
|
|
|
|
|
|
if (ax25_config_load_ports() == 0) {
|
|
|
|
fprintf(stderr, "flexd error: No AX25 port data configured\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
read_conf();
|
|
|
|
|
|
|
|
if (!daemon_start(TRUE)) {
|
|
|
|
fprintf(stderr, "flexd: cannot become a daemon\n");
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
pidfile = fopen(FLEXD_PID_FILE, "w");
|
|
|
|
fprintf(pidfile, "%d\n", (int)getpid());
|
|
|
|
fclose(pidfile);
|
|
|
|
update_flex();
|
|
|
|
|
|
|
|
signal(SIGHUP, hup_handler);
|
|
|
|
signal(SIGALRM, alarm_handler);
|
|
|
|
sigterm_defhnd = signal(SIGTERM, quit_handler);
|
2015-11-22 14:56:30 +00:00
|
|
|
// if (sigterm_defhnd == SIG_ERR)
|
|
|
|
// sigterm_defhnd = SIG_DFL;
|
2015-09-03 20:01:45 +01:00
|
|
|
alarm(poll_time);
|
|
|
|
|
|
|
|
for(;;) pause();
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|