3387 lines
92 KiB
C
Executable file
3387 lines
92 KiB
C
Executable file
/************************************************************************/
|
|
/* */
|
|
/* ***** ***** */
|
|
/* ***** ***** */
|
|
/* ***** ***** */
|
|
/* ***** ***** */
|
|
/* *************** *************** */
|
|
/* ***************** ***************** */
|
|
/* *************** *************** */
|
|
/* ***** ***** TheNetNode */
|
|
/* ***** ***** Portable */
|
|
/* ***** ***** Network */
|
|
/* ***** ***** Software */
|
|
/* */
|
|
/* File os/linux/ax25ip.c (maintained by: DG9OBU) */
|
|
/* */
|
|
/* This file is part of "TheNetNode" - Software Package */
|
|
/* */
|
|
/* Copyright (C) 1998 - 2008 NORD><LINK e.V. Braunschweig */
|
|
/* */
|
|
/* This program is free software; you can redistribute it and/or modify */
|
|
/* it under the terms of the NORD><LINK ALAS (Allgemeine Lizenz fuer */
|
|
/* Amateurfunk Software) as published by Hans Georg Giese (DF2AU) */
|
|
/* on 13/Oct/1992; either version 1, or (at your option) any later */
|
|
/* version. */
|
|
/* */
|
|
/* This program is distributed WITHOUT ANY WARRANTY only for further */
|
|
/* development and learning purposes. See the ALAS (Allgemeine Lizenz */
|
|
/* fuer Amateurfunk Software). */
|
|
/* */
|
|
/* You should have received a copy of the NORD><LINK ALAS (Allgemeine */
|
|
/* Lizenz fuer Amateurfunk Software) along with this program; if not, */
|
|
/* write to NORD><LINK e.V., Hinter dem Berge 5, D-38108 Braunschweig */
|
|
/* */
|
|
/* Dieses Programm ist PUBLIC DOMAIN, mit den Einschraenkungen durch */
|
|
/* die ALAS (Allgemeine Lizenz fuer Amateurfunk Software), entweder */
|
|
/* Version 1, veroeffentlicht von Hans Georg Giese (DF2AU), */
|
|
/* am 13.Oct.1992, oder (wenn gewuenscht) jede spaetere Version. */
|
|
/* */
|
|
/* Dieses Programm wird unter Haftungsausschluss vertrieben, aus- */
|
|
/* schliesslich fuer Weiterentwicklungs- und Lehrzwecke. Naeheres */
|
|
/* koennen Sie der ALAS (Allgemeine Lizenz fuer Amateurfunk Software) */
|
|
/* entnehmen. */
|
|
/* */
|
|
/* Sollte dieser Software keine ALAS (Allgemeine Lizenz fuer Amateur- */
|
|
/* funk Software) beigelegen haben, wenden Sie sich bitte an */
|
|
/* NORD><LINK e.V., Hinter dem Berge 5, D-38108 Braunschweig */
|
|
/* */
|
|
/************************************************************************/
|
|
|
|
/************************************************************************/
|
|
/* */
|
|
/* AX25IP.C V1.05 01.9.98 by DG1KWA / Andreas */
|
|
/* extended by DG9OBU / Marc */
|
|
/************************************************************************/
|
|
|
|
#include "tnn.h"
|
|
|
|
#ifdef AX25IP
|
|
#include "ax25ip.h"
|
|
|
|
/*************************************************************************/
|
|
/* AX25IP-Hausaufgaben : RX, TX und Routingtabellenpflege */
|
|
/*************************************************************************/
|
|
void ax25ip(void)
|
|
{
|
|
register UBYTE uEntry = 0;
|
|
|
|
/* nur wenn Interface aktiv ist */
|
|
if (!ax25ip_active)
|
|
return;
|
|
|
|
/* empfangene Frames abholen */
|
|
ax25ip_recv();
|
|
|
|
/* IP-Adressen der Routentabelle pflegen */
|
|
if ((uNamesUpdate != 0) && (tic10 % uNamesUpdate == 0))
|
|
{
|
|
for (; uEntry <= TABLE_SIZE; ++uEntry)
|
|
route_update(&route_tbl[uEntry]);
|
|
|
|
route_update(&default_route);
|
|
}
|
|
|
|
/* ausstehende Frames senden wenn vorhanden */
|
|
if (kick[ax25ip_port])
|
|
ax25ip_send();
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/* Einen Eintrag aus der Routingtabelle ausgeben */
|
|
/*************************************************************************/
|
|
void show_rt_entry(struct route_table_entry rp, MBHEAD *bufpoi)
|
|
{
|
|
/* erst mal merken, wo wir sind */
|
|
bufpoi->l4time = bufpoi->mbpc;
|
|
|
|
/* Check auf Eintrag fuer die default-Route */
|
|
if (rp.callsign[0] != 1)
|
|
putprintf(bufpoi, "%s", call_to_a(&rp.callsign[0]));
|
|
else
|
|
putstr("default", bufpoi);
|
|
|
|
putspa(11, bufpoi);
|
|
|
|
/* IP-Adresse ausgeben */
|
|
show_ip_addr(ntohl(rp.ip_addr), bufpoi);
|
|
|
|
putspa(29, bufpoi);
|
|
|
|
/* UDP-Port ausgeben wenn UDP-Port gesetzt */
|
|
if (rp.udp_port != 0)
|
|
{
|
|
/* Eine UDP-Route */
|
|
putstr("UDP", bufpoi);
|
|
putspa(35, bufpoi);
|
|
putnum(ntohs(rp.udp_port), bufpoi);
|
|
}
|
|
else
|
|
/* Eine IP-Route */
|
|
putstr("IP", bufpoi);
|
|
|
|
/* Routen-Timeout anzeigen */
|
|
if (rp.timeout != 0)
|
|
{
|
|
ULONG d = rp.timeout;
|
|
ULONG h, m, s; /* Stunden, Minuten, Sekunden */
|
|
|
|
s = d % 60L;
|
|
d /= 60L;
|
|
m = d % 60L;
|
|
d /= 60L;
|
|
h = d % 24L;
|
|
|
|
putspa(40, bufpoi);
|
|
putprintf(bufpoi, " %02lu:%02lu:%02lu", h, m, s); /* hh:mm:ss */
|
|
}
|
|
|
|
if (rp.hostname[0] != 0)
|
|
{
|
|
putspa(50, bufpoi);
|
|
putprintf(bufpoi, "%s", rp.hostname);
|
|
}
|
|
|
|
putstr("\r", bufpoi);
|
|
}
|
|
|
|
/* Anzahl von IP- oder UDP-Routen in der Routingtabelle feststellen */
|
|
/* (IP-Routen haben keinen UDP-Port gesetzt) */
|
|
/* UDP = FALSE -> IP-Routen zaehlen, UDP = TRUE -> UDP-Routen zaehlen */
|
|
/* Default-Route wird beachtet */
|
|
unsigned int count_routes(BOOLEAN udp)
|
|
{
|
|
register unsigned int i;
|
|
register unsigned int j = 0;
|
|
|
|
/* Gesamte Routingtabelle durchgehen */
|
|
for (i = 0; i < (unsigned int)route_tbl_top; ++i)
|
|
{
|
|
if ( ((udp == TRUE) && (route_tbl[i].udp_port != 0)) /* UDP-Route */
|
|
|| ((udp == FALSE) && (route_tbl[i].udp_port == 0))) /* IP-Route */
|
|
++j;
|
|
}
|
|
|
|
/* Default-Route */
|
|
if (default_route.callsign[0] != 0)
|
|
{
|
|
if ( ((udp == TRUE) && (default_route.udp_port != 0)) /* UDP-Route */
|
|
|| ((udp == FALSE) && (default_route.udp_port == 0))) /* IP-Route */
|
|
++j;
|
|
}
|
|
|
|
/* Anzahl Routen melden */
|
|
return (j);
|
|
}
|
|
|
|
/* Timeout fuer gelernte Routen */
|
|
void route_age(void)
|
|
{
|
|
register unsigned int i = 0;
|
|
|
|
#ifdef AXIPR_HTML
|
|
/* htmlstatistik-timer. */
|
|
h_timer();
|
|
#endif
|
|
|
|
/* Gesamte Routingtabelle durchgehen */
|
|
for (; i < (unsigned int)route_tbl_top; ++i)
|
|
{
|
|
/* Route mit laufendem Timer */
|
|
if (route_tbl[i].timeout != 0)
|
|
{
|
|
/* Timer laeuft jetzt ab */
|
|
if (--route_tbl[i].timeout == 0)
|
|
/* Route loeschen */
|
|
route_del(route_tbl[i].callsign);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Hostname -> IP-Adressen aufloesen */
|
|
void route_update(struct route_table_entry *rtentry)
|
|
{
|
|
struct hostent *hstent;
|
|
|
|
/* Kein Hostname, dann auch keine Umwandlung moeglich */
|
|
if (rtentry->hostname[0] == 0)
|
|
return;
|
|
|
|
/* Hostname im IP-Adresse konvertieren */
|
|
if ((hstent = gethostbyname((char*)&rtentry->hostname[0])) != NULL)
|
|
{
|
|
/* Bei Aenderung uebernehmen */
|
|
if (memcmp(&rtentry->ip_addr, &hstent->h_addr_list[0][0], 4) != 0)
|
|
{
|
|
/* IP-Adresse hat sich geaendert */
|
|
memcpy(&rtentry->ip_addr, &hstent->h_addr_list[0][0], 4);
|
|
LOGL1("IP-adress for %s changed !", rtentry->hostname);
|
|
}
|
|
}
|
|
|
|
#ifdef AXIPR_UDP
|
|
/* Original UDP-Port setzen. */
|
|
rtentry->udp_port = rtentry->org_udp_port;
|
|
#endif /* AXIPR_UDP */
|
|
}
|
|
|
|
/* Partielle Frame-Analyse fuer dyn. Eintraege */
|
|
BOOLEAN route_canlearn(MBHEAD *fbp)
|
|
{
|
|
char *p; /* Zeiger im Header */
|
|
register int n;
|
|
UBYTE ctl;
|
|
|
|
rwndmb(fbp); /* Frame von vorne */
|
|
|
|
for (p = rxfhdr, n = 1; n <= L2INUM + L2VNUM; ++n)
|
|
{
|
|
if (!getfid(p, fbp)) /* naechstes Call lesen */
|
|
return (FALSE);
|
|
|
|
p += L2IDLEN;
|
|
if (*(p - 1) & L2CEOA)
|
|
break; /* Ende des Addressfeldes */
|
|
}
|
|
*(p - 1) &= ~L2CEOA;
|
|
*p = NUL;
|
|
ctl = getchr(fbp); /* Control-Byte extrahieren */
|
|
ctl &= ~L2CPF; /* Poll-Flag loeschen */
|
|
/* Nur UI, UA und SABM/SABME erzeugen einen dynamischen Eintrag */
|
|
if ( ctl == L2CUI /* UI */
|
|
|| ctl == L2CUA /* UA */
|
|
|| ctl == L2CSABM /* SABM */
|
|
#ifdef EAX25
|
|
|| ctl == L2CSABME /* SABME (EAX.25) */
|
|
)
|
|
#endif
|
|
return (TRUE);
|
|
|
|
#ifndef AXIPR_UDP
|
|
/* Alle anderen Kontrollcodes landen hier und bewirken keinen Eintrag */
|
|
return (FALSE);
|
|
#else
|
|
return (TRUE);
|
|
#endif
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/* Kommandointerface fuer Operationen auf die AX25IP-Routentabelle */
|
|
/*************************************************************************/
|
|
|
|
/* Eine Route anhand eines Calls loeschen, liefert TRUE wenn erfolgreich */
|
|
BOOLEAN route_del(unsigned char *call)
|
|
{
|
|
register int i;
|
|
register int j;
|
|
|
|
/* Soll die Default-Route geloescht werden ? */
|
|
if ((call == NULL) || (call[0] == NUL))
|
|
{
|
|
/* Als unbenutzt markieren */
|
|
default_route.callsign[0] = NUL;
|
|
|
|
/* Pruefen, ob Sockets noch notwendig */
|
|
ax25ip_check_down();
|
|
return (TRUE);
|
|
}
|
|
|
|
/* Uebergebenes Call in der Tabelle suchen */
|
|
for (i = 0; i < route_tbl_top; ++i)
|
|
{
|
|
if (addrmatch(call, route_tbl[i].callsign))
|
|
{
|
|
/* BINGO ! */
|
|
/* Problem: die Tabelle hat keinen Merker, ob ein Eintrag gueltig ist, */
|
|
/* die Eintraege haengen einfach hintereinander. Deshalb alle */
|
|
/* Eintraege oberhalb des gefundenen Eintrages einen nach */
|
|
/* unten kopieren und den "table-top" einen herabsetzen. */
|
|
for (j = i; j < route_tbl_top; ++j)
|
|
route_tbl[j] = route_tbl[j + 1];
|
|
|
|
/* Ein Tabelleneintrag weniger */
|
|
route_tbl_top--;
|
|
|
|
/* Pruefen, ob Sockets noch notwendig */
|
|
ax25ip_check_down();
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
static const char inv_mode[] = "Invalid Mode\r";
|
|
static const char inv_call[] = "Invalid Callsign\r";
|
|
static const char inv_ip[] = "Invalid IP adress\r";
|
|
static const char inv_par[] = "Invalid Parameter\r";
|
|
|
|
void
|
|
ccpaxipr(void)
|
|
{
|
|
MBHEAD *mbp;
|
|
int port = 0;
|
|
register int i;
|
|
int tmp_fd = -1;
|
|
int new_udp = 0;
|
|
unsigned char call[L2IDLEN];
|
|
char hostname[HNLEN + 1];
|
|
struct hostent *host = NULL;
|
|
int uNewTimeout;
|
|
#ifdef AXIPR_UDP
|
|
char *Hostname = hostname;
|
|
int NewLogLevel = FALSE;
|
|
#endif
|
|
#ifdef AXIPR_HTML
|
|
char *timeset = set_time();
|
|
int NewHtmlStat = FALSE;
|
|
#endif
|
|
char cBuf[BUFLEN + 1];
|
|
unsigned int uCmd = OP_NONE;
|
|
unsigned int uMode = NO_MODE;
|
|
|
|
#ifdef AXIPR_HTML
|
|
#define OP_HTMLSTAT 10
|
|
#endif
|
|
|
|
memset(hostname, 0, sizeof(hostname));
|
|
|
|
/* AX25IP ueberhaupt aktiv ? */
|
|
if (ax25ip_active == FALSE)
|
|
{
|
|
putmsg("No AX25IP-interface present, nothing to configure or show !\r");
|
|
return;
|
|
}
|
|
|
|
/* neuen Parser verwenden ? */
|
|
if (new_parser == TRUE)
|
|
{
|
|
|
|
/* Sysop will aendern und noch was in der Zeile da ? */
|
|
if (issyso() && skipsp(&clicnt, &clipoi))
|
|
{
|
|
/* Frischer Buffer */
|
|
memset(cBuf, 0, sizeof(cBuf));
|
|
|
|
/* Operation lesen (add, delete) */
|
|
for (i = 0; i < BUFLEN; ++i)
|
|
{
|
|
if ((!clicnt) || (*clipoi == ' '))
|
|
break;
|
|
clicnt--;
|
|
cBuf[i] = toupper(*clipoi++);
|
|
}
|
|
|
|
/* Zum alten Parser zurueckschalten */
|
|
if ( (strcmp(cBuf, "OLD") == 0)
|
|
|| (cBuf[0] == 'O')
|
|
)
|
|
{
|
|
new_parser = FALSE;
|
|
putmsg("Switched to old axipr-parser !!!\r");
|
|
return;
|
|
}
|
|
|
|
/* Hinzufuegen (add oder +) */
|
|
if ( (strcmp(cBuf, "ADD") == 0)
|
|
|| (cBuf[0] == '+')
|
|
)
|
|
uCmd = OP_ADD;
|
|
|
|
/* Loeschen (delete, del oder -) */
|
|
if ( (strcmp(cBuf, "DELETE") == 0)
|
|
|| (strcmp(cBuf, "DEL") == 0)
|
|
|| (cBuf[0] == '-')
|
|
)
|
|
uCmd = OP_DEL;
|
|
|
|
/* eigenen UDP-Port aendern */
|
|
if (strcmp(cBuf, "MYUDP") == 0)
|
|
uCmd = OP_MYUDP;
|
|
|
|
/* Namensaufloesungsintervall einstellen */
|
|
if (strcmp(cBuf, "LOOKUP") == 0)
|
|
uCmd = OP_HNUPD;
|
|
|
|
/* Loglevel */
|
|
if ( (strcmp(cBuf, "LOGLEVEL") == 0)
|
|
|| (strcmp(cBuf, "LOG") == 0)
|
|
)
|
|
uCmd = OP_LOG;
|
|
|
|
/* Timeout fuer dynamische Routen */
|
|
if (strcmp(cBuf, "TIMEOUT") == 0)
|
|
uCmd = OP_TIMEOUT;
|
|
|
|
#ifdef AXIPR_HTML
|
|
/* htmlstatistik */
|
|
if ( (strcmp(cBuf, "HTMLSTAT") == 0)
|
|
|| (strcmp(cBuf, "H") == 0))
|
|
|
|
uCmd = OP_HTMLSTAT;
|
|
#endif
|
|
|
|
/* Fehler bei der Auswertung ? */
|
|
if (uCmd == OP_NONE)
|
|
{
|
|
putmsg(inv_mode);
|
|
return;
|
|
}
|
|
|
|
/* Hier rein, wenn der Timeout fuer dynamische Routen geaendert werden soll */
|
|
if (uCmd == OP_TIMEOUT)
|
|
{
|
|
int uNewTimeout;
|
|
|
|
/* Noch was da in der Kommandozeile ? */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
{
|
|
mbp = getmbp();
|
|
putprintf(mbp, "the actual timeout for dynamic routes is : %u\r", uDynTimeout);
|
|
/* und ab die Post ... */
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
|
|
/* Timeout lesen */
|
|
uNewTimeout = nxtlong(&clicnt, &clipoi);
|
|
|
|
if ( (uNewTimeout < 0)
|
|
||(uNewTimeout > (86400))) /* max. 1 Tag */
|
|
{
|
|
putmsg("error: timeout out of range (0 - 86400) !\r");
|
|
return;
|
|
}
|
|
|
|
/* Wert uebernehmen */
|
|
uDynTimeout = uNewTimeout;
|
|
|
|
/* und ab die Post ... */
|
|
mbp = getmbp();
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
|
|
/* Hier rein, wenn das Intervall der Namensaufloesung geaendert werden soll */
|
|
if (uCmd == OP_HNUPD)
|
|
{
|
|
UWORD uNewInterval;
|
|
|
|
/* Noch was da in der Kommandozeile ? */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
{
|
|
mbp = getmbp();
|
|
|
|
putprintf(mbp, "Hostname-update ");
|
|
|
|
if (uNamesUpdate != 0)
|
|
putprintf(mbp, "occurs every %u seconds.\r", uNamesUpdate / 100);
|
|
else
|
|
putprintf(mbp, "is disabled at the moment.\r");
|
|
|
|
/* und ab die Post ... */
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
|
|
/* Timeout lesen */
|
|
uNewInterval = nxtnum(&clicnt, &clipoi);
|
|
|
|
if (uNewInterval > 3600) /* max. eine Stunde */
|
|
{
|
|
putmsg("error: value out of range (0 - 3600 seconds) !\r");
|
|
return;
|
|
}
|
|
|
|
/* Wert uebernehmen */
|
|
uNamesUpdate = uNewInterval * 100;
|
|
|
|
/* und ab die Post ... */
|
|
mbp = getmbp();
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
|
|
/* Hier rein, wenn der Loglevel geaendert werden soll */
|
|
if (uCmd == OP_LOG)
|
|
{
|
|
int new_loglevel;
|
|
|
|
/* Noch was da in der Kommandozeile ? */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
{
|
|
mbp = getmbp();
|
|
putprintf(mbp, "my actual loglevel is : %u\r", loglevel);
|
|
/* und ab die Post ... */
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
|
|
/* neues Loglevel lesen */
|
|
new_loglevel = nxtnum(&clicnt, &clipoi);
|
|
|
|
if ( (new_loglevel < 0)
|
|
||(new_loglevel > 4))
|
|
{
|
|
putmsg("error: loglevel out of range (0 - 4) !!!\r");
|
|
return;
|
|
}
|
|
|
|
/* Wert uebernehmen */
|
|
loglevel = new_loglevel;
|
|
|
|
/* und ab die Post ... */
|
|
mbp = getmbp();
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
|
|
#ifdef AXIPR_HTML
|
|
if (uCmd == OP_HTMLSTAT)
|
|
{
|
|
/* Noch was da in der Kommandozeile ? */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
{
|
|
mbp = getmbp();
|
|
#ifdef SPEECH
|
|
putprintf(mbp, speech_message(347),HtmlStat);
|
|
#else
|
|
putprintf(mbp, "HTML-Statistic is %d\r", HtmlStat);
|
|
#endif
|
|
/* und ab die Post ... */
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
|
|
/* Timeout lesen */
|
|
NewHtmlStat = nxtnum(&clicnt, &clipoi);
|
|
|
|
if ( (NewHtmlStat < 0)
|
|
||(NewHtmlStat > 1))
|
|
{
|
|
#ifdef SPEECH
|
|
putmsg(speech_message(300));
|
|
#else
|
|
putmsg("errors: Log level worth from 0 to 1!\r");
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
/* Wert uebernehmen */
|
|
HtmlStat = NewHtmlStat;
|
|
|
|
/* und ab die Post ... */
|
|
mbp = getmbp();
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
#endif /* AXIPR_HTML */
|
|
|
|
/* Hier nur rein, wenn wir als naechstes eine UDP-Portnummer erwarten */
|
|
if (uCmd == OP_MYUDP)
|
|
{
|
|
/* Noch was da in der Kommandozeile ? */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
{
|
|
mbp = getmbp();
|
|
putprintf(mbp, "my actual UDP-port is : %u\r", ntohs(my_udp));
|
|
/* und ab die Post ... */
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
|
|
/* neue UDP-Portnummer lesen */
|
|
new_udp = nxtlong(&clicnt, &clipoi);
|
|
|
|
if ( (new_udp <= 0)
|
|
||(new_udp > 65535))
|
|
{
|
|
putmsg("error: UDP-port number not valid (0 - 65535) !!!\r");
|
|
return;
|
|
}
|
|
|
|
#ifdef AXIPR_UDP
|
|
/* Neuer UDP-Port gleich MY-UDP? */
|
|
/* Keine Aenderungen durchfuehren. */
|
|
if (my_udp == htons((unsigned short)new_udp))
|
|
{
|
|
/* und ab die Post ... */
|
|
mbp = getmbp();
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
#endif /* AXIPR_UDP */
|
|
|
|
#ifndef AXIPR_UDP
|
|
/* Laufendes UDP aendern */
|
|
if (fd_udp != -1)
|
|
{
|
|
#endif
|
|
/* Versuchen, neuen UDP-Port anzulegen */
|
|
if ((tmp_fd = setup_udp(htons((unsigned short)new_udp))) != -1)
|
|
{
|
|
#ifndef AXIPR_UDP
|
|
/* Neuen Descriptor eintragen und alten schliessen */
|
|
close(fd_udp);
|
|
#else
|
|
/* Nur wenn alter Socket noch lebt, */
|
|
if (fd_udp != EOF)
|
|
/* dann schliessen wir den Socket. */
|
|
close(fd_udp);
|
|
#endif /* AXIPR_UDP */
|
|
|
|
fd_udp = tmp_fd;
|
|
/* Gibt es einen Eintrag. */
|
|
if (l1pp)
|
|
/* Check, ob neuer Filedescriptor groesser ist */
|
|
l1pp->kisslink = max(fd_ip, fd_udp);
|
|
|
|
/* Neuen UDP-Port merken */
|
|
my_udp = htons((unsigned short)new_udp);
|
|
}
|
|
else
|
|
{
|
|
putmsg("error: changing the UDP-port failed !!!\r");
|
|
return;
|
|
}
|
|
#ifndef AXIPR_UDP
|
|
}
|
|
else
|
|
{
|
|
/* neuen UDP-Port merken */
|
|
my_udp = htons(new_udp);
|
|
}
|
|
#endif
|
|
/* und ab die Post ... */
|
|
mbp = getmbp();
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
|
|
/* Noch was da in der Kommandozeile ? */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
{
|
|
putmsg("syntax error: callsign missing\r");
|
|
return;
|
|
}
|
|
|
|
/* Frischer Buffer */
|
|
memset(cBuf, 0, sizeof(cBuf));
|
|
|
|
/* Call lesen */
|
|
for (i = 0; i < BUFLEN; ++i)
|
|
{
|
|
if ((!clicnt) || (*clipoi == ' '))
|
|
break;
|
|
|
|
clicnt--;
|
|
cBuf[i] = toupper(*clipoi++);
|
|
}
|
|
|
|
/* Operation auf Default-Route ? */
|
|
if (strcmp(cBuf, "DEFAULT") == 0)
|
|
call[0] = NUL; /* Leere Callstring als Indikator fuer Defaultroute */
|
|
else
|
|
{
|
|
/* Call konvertieren und pruefen */
|
|
if (a_to_call(cBuf, call) != 0)
|
|
{
|
|
putmsg(inv_call);
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Wenn wir loeschen wollen, brauchen wir nichts mehr */
|
|
if (uCmd != OP_DEL)
|
|
{
|
|
/* Noch was da in der Kommandozeile ? */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
{
|
|
putmsg("syntax error: IP-adress missing\r");
|
|
return;
|
|
}
|
|
|
|
/* Frische Buffer */
|
|
memset(hostname, 0, sizeof(hostname));
|
|
|
|
/* Hostnamen / IP-Adresse lesen */
|
|
for (i = 0; i < HNLEN; ++i)
|
|
{
|
|
if (!clicnt || *clipoi == ' ')
|
|
break;
|
|
|
|
clicnt--;
|
|
hostname[i] = *clipoi++;
|
|
}
|
|
|
|
/* eventuellen Hostnamen aufloesen */
|
|
if ((host = gethostbyname(hostname)) == NULL)
|
|
{
|
|
mbp = getmbp();
|
|
putprintf(mbp, "Warning: can't resolve IP for host %s ! I keep trying ...\r", hostname);
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
}
|
|
else
|
|
{
|
|
strncpy(hostname, host->h_name, sizeof(hostname));
|
|
}
|
|
} /* if (uCmd != OP_DEL) */
|
|
|
|
/* Optionale UDP-Parameter lesen */
|
|
skipsp(&clicnt, &clipoi);
|
|
|
|
/* Frischer Buffer */
|
|
memset(cBuf, 0, sizeof(cBuf));
|
|
|
|
/* Mode lesen (IP, UDP) */
|
|
for (i = 0; i < BUFLEN; ++i)
|
|
{
|
|
if ((!clicnt) || (*clipoi == ' '))
|
|
break;
|
|
|
|
clicnt--;
|
|
cBuf[i] = toupper(*clipoi++);
|
|
}
|
|
|
|
/* Mode bestimmen (UDP) */
|
|
/* Bei der Initialisierung wurde bereits IP eingestellt */
|
|
if ( (strcmp(cBuf, "UDP") == 0)
|
|
|| (cBuf[0] == 'U')
|
|
)
|
|
uMode = UDP_MODE;
|
|
|
|
/* Noch was da in der Kommandozeile ? */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
port = DEFAULT_UDP_PORT;
|
|
else
|
|
{
|
|
/* neue UDP-Portnummer lesen */
|
|
port = nxtlong(&clicnt, &clipoi);
|
|
|
|
if ( (port <= 0)
|
|
||(port > 65535))
|
|
{
|
|
putmsg("error: UDP-port number not valid\r");
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* Operation ausfuehren */
|
|
switch (uCmd)
|
|
{
|
|
/* Route hinzufuegen */
|
|
case OP_ADD :
|
|
#ifndef AXIPR_UDP
|
|
route_add((unsigned char*)&hostname, host, call, (uMode == UDP_MODE ? port : 0), (call[0] == 0 ? TRUE : FALSE)
|
|
break;
|
|
#else
|
|
if (route_add((unsigned char*)&hostname
|
|
, host
|
|
, call
|
|
, (uMode == UDP_MODE ? (int)port : 0)
|
|
, (call[0] == 0 ? TRUE : FALSE)
|
|
, 0
|
|
, hostname
|
|
#ifdef AXIPR_HTML
|
|
, timeset
|
|
, P_USER
|
|
#endif /* AXIPR_HTML */
|
|
))
|
|
putmsg("Call is registerd.\r");
|
|
|
|
return;
|
|
#endif /* AXIPR_UDP */
|
|
|
|
/* Route loeschen */
|
|
case OP_DEL :
|
|
#ifndef AXIPR_UDP
|
|
route_del(call);
|
|
break;
|
|
#else
|
|
|
|
if (route_del(call))
|
|
putmsg("Call is deleted!\r");
|
|
else
|
|
putmsg("Call no deleted!\r");
|
|
|
|
return;
|
|
#endif /* AXIPR_UDP. */
|
|
|
|
|
|
default : break;
|
|
}
|
|
|
|
mbp = getmbp();
|
|
/* und ab die Post ... */
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
/* ALTE SYNTAX */
|
|
|
|
/* Sysop will aendern und noch was in der Zeile da ? */
|
|
if (issyso() && skipsp(&clicnt, &clipoi))
|
|
{
|
|
clicnt--;
|
|
|
|
switch (toupper(*clipoi++))
|
|
{
|
|
case 'P': /* Parser aendern */
|
|
/* wir koennen nur in den neuen Parser umschalten */
|
|
new_parser = TRUE;
|
|
putmsg("Switched to new axipr-parser !!!\r");
|
|
return;
|
|
break;
|
|
|
|
case 'R': /* Routen-Eintrag */
|
|
/* Kommandozeile pruefen */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
{
|
|
putmsg(inv_par);
|
|
return;
|
|
}
|
|
|
|
clicnt--;
|
|
|
|
switch (*clipoi++)
|
|
{
|
|
case '-': /* Route loeschen */
|
|
/* Call lesen */
|
|
if (getcal(&clicnt, &clipoi, TRUE, (char *)call) != YES)
|
|
{
|
|
invcal();
|
|
return;
|
|
}
|
|
|
|
/* Call konvertieren */
|
|
for (i = 0; i < L2CALEN; ++i)
|
|
call[i] = call[i] << 1;
|
|
|
|
#ifdef AXIPR_UDP
|
|
/* und ab die Post ... */
|
|
mbp = getmbp();
|
|
|
|
if (route_del(call))
|
|
putstr("Call is delete!\r", mbp);
|
|
else
|
|
putstr("Call no delete!\r", mbp);
|
|
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
#else
|
|
/* Route loeschen */
|
|
route_del(call);
|
|
break;
|
|
#endif /* AXIPR_UDP. */
|
|
|
|
case '+': /* Route hinzufuegen */
|
|
/* Call lesen */
|
|
if (getcal(&clicnt, &clipoi, TRUE, (char *)call) != YES)
|
|
{
|
|
invcal();
|
|
return;
|
|
}
|
|
|
|
/* Call linksschieben */
|
|
for (i = 0; i < L2CALEN; ++i)
|
|
call[i] = call[i] << 1;
|
|
|
|
/* Noch was da in der Kommandozeile ? */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
{
|
|
putmsg("IP-Adress/Hostname missing\r");
|
|
return;
|
|
}
|
|
|
|
/* Frische Buffer */
|
|
memset(hostname, 0, sizeof(hostname));
|
|
|
|
/* Hostnamen / IP-Adresse lesen */
|
|
for (i = 0; i < HNLEN; ++i)
|
|
{
|
|
if (!clicnt || *clipoi == ' ')
|
|
break;
|
|
|
|
clicnt--;
|
|
hostname[i] = *clipoi++;
|
|
}
|
|
|
|
/* Hostname / IP-Adresse aufloesen */
|
|
if ((host = gethostbyname(hostname)) == NULL)
|
|
{
|
|
putmsg(inv_ip);
|
|
return;
|
|
}
|
|
|
|
/* Mode-Parameter vorhanden ? */
|
|
if (skipsp(&clicnt, &clipoi))
|
|
{
|
|
--clicnt;
|
|
switch (toupper(*clipoi++))
|
|
{
|
|
case 'I': /* IP: Port steht fest */
|
|
break;
|
|
case 'U': /* UDP: abweichenden Port lesen wenn vorhanden */
|
|
nextspace(&clicnt, &clipoi);
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
port = DEFAULT_UDP_PORT;
|
|
else
|
|
{
|
|
port = nxtlong(&clicnt, &clipoi);
|
|
|
|
if ( (port <= 0)
|
|
||(port > 65535))
|
|
{
|
|
putmsg("error: UDP-port number not valid\r");
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
|
|
default: /* unbekannter Modus */
|
|
putmsg(inv_mode);
|
|
return;
|
|
}
|
|
}
|
|
/* Route hinzufuegen */
|
|
#ifndef AXIPR_UDP
|
|
route_add((unsigned char*)&hostname, host, call, (int) port, FALSE, 0);
|
|
break;
|
|
#else
|
|
if (route_add((unsigned char*)&hostname
|
|
, host
|
|
, call
|
|
, (int) port
|
|
, FALSE
|
|
, 0
|
|
, hostname
|
|
#ifdef AXIPR_HTML
|
|
, timeset
|
|
, P_USER
|
|
#endif /* AXIPR_HTML */
|
|
))
|
|
putmsg("Call is registerd.\r");
|
|
|
|
return;
|
|
#endif /* AXIPR_UDP */
|
|
|
|
}
|
|
break;
|
|
|
|
case 'D': /* Default Route aendern */
|
|
|
|
nextspace(&clicnt, &clipoi);
|
|
|
|
/* Noch Eingaben da ? */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
{
|
|
putmsg(inv_mode);
|
|
return;
|
|
}
|
|
|
|
clicnt--;
|
|
|
|
/* Operation bestimmen */
|
|
switch (*clipoi++)
|
|
{
|
|
case '-': /* Default Route loeschen */
|
|
#ifdef AXIPR_UDP
|
|
/* und ab die Post ... */
|
|
mbp = getmbp();
|
|
|
|
if (route_del((unsigned char *)""))
|
|
putstr("Call is delete!\r", mbp);
|
|
else
|
|
putstr("Call no delete!\r", mbp);
|
|
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
#else
|
|
route_del((unsigned char *)"");
|
|
break;
|
|
#endif /* AXIPR_UDP. */
|
|
|
|
case '+': /* Default Route eingeben */
|
|
|
|
/* IP-Adresse / Hostname lesen */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
{
|
|
putmsg(inv_ip);
|
|
return;
|
|
}
|
|
|
|
/* Frische Buffer */
|
|
memset(hostname, 0, sizeof(hostname));
|
|
|
|
/* IP-Adresse / Hostname kopieren */
|
|
for (i = 0; i < HNLEN; ++i)
|
|
{
|
|
if (!clicnt || *clipoi == ' ')
|
|
break;
|
|
clicnt--;
|
|
hostname[i] = *clipoi++;
|
|
}
|
|
|
|
/* aufloesen */
|
|
if ((host = gethostbyname(hostname)) == NULL)
|
|
{
|
|
putmsg(inv_ip);
|
|
return;
|
|
}
|
|
|
|
/* Modus-Kennzeichner lesen falls vorhanden */
|
|
if (skipsp(&clicnt, &clipoi))
|
|
{
|
|
--clicnt;
|
|
switch (toupper(*clipoi++))
|
|
{
|
|
case 'I': /* IP: Port steht fest */
|
|
break;
|
|
case 'U': /* UDP: eventuell abweichenden Port lesen */
|
|
nextspace(&clicnt, &clipoi);
|
|
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
port = DEFAULT_UDP_PORT;
|
|
else
|
|
{
|
|
port = nxtlong(&clicnt, &clipoi);
|
|
|
|
if ( (port <= 0)
|
|
||(port > 65535))
|
|
{
|
|
putmsg("error: UDP-port number not valid\r");
|
|
return;
|
|
}
|
|
}
|
|
break;
|
|
default: /* unbekannter Modus */
|
|
putmsg(inv_mode);
|
|
return;
|
|
}
|
|
}
|
|
/* Route eintragen */
|
|
#ifndef AXIPR_UDP
|
|
route_add((unsigned char*)&hostname, host, NULL, (int) port, TRUE, 0);
|
|
break;
|
|
#else
|
|
if (route_add((unsigned char*)&hostname
|
|
, host
|
|
, NULL
|
|
, (int) port
|
|
, TRUE
|
|
, 0
|
|
, hostname
|
|
#ifdef AXIPR_HTML
|
|
, timeset
|
|
, P_USER
|
|
#endif /* AXIPR_HTML */
|
|
))
|
|
putmsg("Call is registerd.\r");
|
|
|
|
return;
|
|
#endif /* AXIPR_UDP */
|
|
|
|
default:
|
|
putmsg(inv_mode);
|
|
return;
|
|
}
|
|
break;
|
|
|
|
/* Eigenen UDP-Port aendern */
|
|
case 'U':
|
|
/* neuer Port muss vorhanden sein */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
{
|
|
putmsg(inv_par);
|
|
return;
|
|
}
|
|
|
|
/* Port ermitteln. */
|
|
new_udp = nxtlong(&clicnt, &clipoi);
|
|
|
|
if ( (new_udp <= 0)
|
|
||(new_udp >= 65535))
|
|
{
|
|
putmsg("UDP-Port not valid, not changed !!!\r");
|
|
return;
|
|
}
|
|
|
|
#ifdef AXIPR_UDP
|
|
/* Neuer UDP-Port gleich MY-UDP? */
|
|
/* Keine Aenderungen durchfuehren. */
|
|
if (my_udp == htons((unsigned short)new_udp))
|
|
{
|
|
/* und ab die Post ... */
|
|
mbp = getmbp();
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
#endif /* AXIPR_UDP */
|
|
|
|
#ifndef AXIPR_UDP
|
|
/* Laufendes UDP aendern */
|
|
if (fd_udp != -1)
|
|
{
|
|
#endif
|
|
/* Versuchen, neuen UDP-Port anzulegen */
|
|
if ((tmp_fd = setup_udp(htons((unsigned short)new_udp))) != -1)
|
|
{
|
|
#ifndef AXIPR_UDP
|
|
/* Neuen Descriptor eintragen und alten schliessen */
|
|
close(fd_udp);
|
|
#else
|
|
/* Nur wenn alter Socket noch lebt, */
|
|
if (fd_udp != EOF)
|
|
/* dann schliessen wir den Socket. */
|
|
close(fd_udp);
|
|
#endif /* AXIPR_UDP */
|
|
|
|
fd_udp = tmp_fd;
|
|
/* Gibt es einen Eintrag. */
|
|
if (l1pp)
|
|
/* Check, ob neuer Filedescriptor groesser ist */
|
|
l1pp->kisslink = max(fd_ip, fd_udp);
|
|
|
|
/* Neuen UDP-Port merken */
|
|
my_udp = htons((unsigned short)new_udp);
|
|
}
|
|
else
|
|
{
|
|
putmsg("ERROR: Changing UDP-Port failed, Port not changed !!!\r");
|
|
return;
|
|
}
|
|
#ifndef AXIPR_UDP
|
|
}
|
|
else
|
|
{
|
|
/* neuen UDP-Port merken */
|
|
my_udp = htons(new_udp);
|
|
}
|
|
#endif
|
|
|
|
putmsg("UDP-Port successfully changed\r");
|
|
#ifdef AXIPR_UDP
|
|
return;
|
|
#else
|
|
break;
|
|
#endif /* AXIPR_UDP. */
|
|
|
|
/* Timeout fuer dynamische Routen aendern. */
|
|
case 'T':
|
|
|
|
/* Noch was da in der Kommandozeile ? */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
{
|
|
mbp = getmbp();
|
|
putprintf(mbp, "the actual timeout for dynamic routes is : %u\r", uDynTimeout);
|
|
/* und ab die Post ... */
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
|
|
/* Timeout lesen */
|
|
uNewTimeout = nxtlong(&clicnt, &clipoi);
|
|
|
|
if ( (uNewTimeout < 0)
|
|
||(uNewTimeout > (86400))) /* max. 1 Tag */
|
|
{
|
|
putmsg("error: timeout out of range (0 - 86400) !\r");
|
|
return;
|
|
}
|
|
|
|
/* Wert uebernehmen */
|
|
uDynTimeout = uNewTimeout;
|
|
|
|
/* und ab die Post ... */
|
|
mbp = getmbp();
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
|
|
#ifdef AXIPR_UDP
|
|
/* Loglevel aendern. */
|
|
case 'L':
|
|
|
|
/* Noch was da in der Kommandozeile ? */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
{
|
|
mbp = getmbp();
|
|
#ifdef SPEECH
|
|
putprintf(mbp, speech_message(299),loglevel);
|
|
#else
|
|
putprintf(mbp, "My LogLevel: %d\r",loglevel);
|
|
#endif
|
|
/* und ab die Post ... */
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
|
|
/* Loglevel lesen */
|
|
NewLogLevel = nxtnum(&clicnt, &clipoi);
|
|
|
|
if ( (NewLogLevel < 0)
|
|
||(NewLogLevel > 4))
|
|
{
|
|
#ifdef SPEECH
|
|
putmsg(speech_message(300));
|
|
#else
|
|
putmsg("errors: Log level worth from 0 to 4!\r");
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
/* Wert uebernehmen */
|
|
loglevel = NewLogLevel;
|
|
|
|
/* und ab die Post ... */
|
|
mbp = getmbp();
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
#endif /* AXIPR_UDP */
|
|
|
|
#ifdef AXIPR_HTML
|
|
/* htmlstatistik aendern. */
|
|
case 'H':
|
|
|
|
/* Noch was da in der Kommandozeile ? */
|
|
if (!skipsp(&clicnt, &clipoi))
|
|
{
|
|
mbp = getmbp();
|
|
#ifdef SPEECH
|
|
putprintf(mbp, speech_message(347),HtmlStat);
|
|
#else
|
|
putprintf(mbp, "HTML-Statistic is %d\r", HtmlStat);
|
|
#endif
|
|
/* und ab die Post ... */
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
|
|
/* Loglevel lesen */
|
|
NewHtmlStat = nxtnum(&clicnt, &clipoi);
|
|
|
|
if ( (NewHtmlStat < 0)
|
|
||(NewHtmlStat > 1))
|
|
{
|
|
#ifdef SPEECH
|
|
putmsg(speech_message(348));
|
|
#else
|
|
putmsg("Error: HTML-Statistic worth from 0 to 1!\r\r");
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
/* Wert uebernehmen */
|
|
HtmlStat = NewHtmlStat;
|
|
|
|
/* und ab die Post ... */
|
|
mbp = getmbp();
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
#endif
|
|
|
|
/* Unbekannte Kommandos */
|
|
default:
|
|
putmsg(inv_par);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
mbp = putals("AXIP-Routes:\rCall-------IP----------------Mode--Port--Timeout--IP/Hostname----\r");
|
|
|
|
/* Alle Routingtabelleneintraege durchgehen und ausgeben */
|
|
for (i = 0; i < route_tbl_top; ++i)
|
|
show_rt_entry(route_tbl[i], mbp);
|
|
|
|
/* Default-Route ausgeben wenn vorhanden */
|
|
if (default_route.callsign[0] == 1)
|
|
show_rt_entry(default_route, mbp);
|
|
|
|
putprintf(mbp, "-----------------------------------------------------------------\r");
|
|
|
|
/* Eigenen UDP-Port ausgeben */
|
|
putprintf(mbp, "UDP-port (%u): ", ntohs(my_udp));
|
|
putprintf(mbp, "%s", (fd_udp != -1 ? "active" : "not active"));
|
|
|
|
/* IP-Status ausgeben */
|
|
putprintf(mbp, ", IP-protocol (family %u): ", IPPROTO_AX25);
|
|
putprintf(mbp, "%s", (fd_ip != -1 ? "active" : "not active"));
|
|
|
|
/* Timeout des dynamischen Routenlerners ausgeben */
|
|
putprintf(mbp, "\rTimeout for dynamically learned routes is %u seconds.\r", uDynTimeout);
|
|
|
|
/* Hostname -> IP-Adresse Aktualisierungsintervall ausgeben */
|
|
putprintf(mbp, "Hostname-to-IP-adress conversion ");
|
|
|
|
if (uNamesUpdate != 0)
|
|
putprintf(mbp, "occurs every %u seconds.\r", uNamesUpdate / 100);
|
|
else
|
|
putprintf(mbp, "is disabled.\r");
|
|
|
|
#ifdef AXIPR_UDP
|
|
#ifdef SPEECH
|
|
putprintf(mbp, speech_message(299), loglevel);
|
|
#else
|
|
putprintf(mbp, "My LOGLevel is %u.\r", loglevel);
|
|
#endif /* SPEECH */
|
|
#endif /* AXIPR_UDP */
|
|
|
|
#ifdef AXIPR_HTML
|
|
#ifdef SPEECH
|
|
putprintf(mbp, speech_message(347), HtmlStat);
|
|
#else
|
|
putprintf(mbp, "My HTML-Statistic is %d.\r", HtmlStat);
|
|
#endif /* SPEECH */
|
|
#endif /* AXIPR_HTML */
|
|
|
|
/* und ab die Post ... */
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
}
|
|
|
|
/* Routeneintraege fuer parms.tnb ausgeben */
|
|
void dump_ax25ip(MBHEAD* mbp)
|
|
{
|
|
register int i;
|
|
|
|
putstr(";\r; AX25IP Routes\r;\r", mbp);
|
|
|
|
if (ax25ip_active == FALSE)
|
|
return;
|
|
|
|
if (new_parser == TRUE)
|
|
{
|
|
putstr("; WARNING: this section is written using the new syntax of the AXIPR-command,\r", mbp);
|
|
putstr("; DO NOT USE with older TNNs compiled only for old style syntax !!!\r;\r", mbp);
|
|
|
|
/* Falls wir noch im alten Parser sind, dann umschalten */
|
|
putprintf(mbp, "AXIPR P\r");
|
|
/* eigenen UDP-Port ausgeben */
|
|
putprintf(mbp, "AXIPR MYUDP %u\r", ntohs(my_udp));
|
|
/* Timeout fuer dynamische Routen ausgeben */
|
|
putprintf(mbp, "AXIPR TIMEOUT %u\r", uDynTimeout);
|
|
/* Intervall fuer Hostnamen-Update ausgeben */
|
|
putprintf(mbp, "AXIPR LOOKUP %u\r", uNamesUpdate);
|
|
}
|
|
|
|
#ifdef AXIPR_UDP
|
|
/* eigenen UDP-Port ausgeben */
|
|
putprintf(mbp, "AXIPR U %u\r", ntohs(my_udp));
|
|
/* Timeout fuer dynamische Routen ausgeben */
|
|
putprintf(mbp, "AXIPR T %u\r", uDynTimeout);
|
|
|
|
putprintf(mbp, "AXIPR L %d\r",loglevel);
|
|
|
|
#ifdef AXIPR_HTML
|
|
putprintf(mbp, "AXIPR H %d\r",HtmlStat);
|
|
#endif /* AXIPR_HTML */
|
|
#endif /* AXIPR_UDP */
|
|
|
|
/* alle Routingtabelleneintraege durchgehen und ausgeben */
|
|
for (i = 0; i < route_tbl_top; ++i)
|
|
{
|
|
/* Dynamisch gelernte Routen werden inaktiv zur Information geschrieben ! */
|
|
if (route_tbl[i].timeout != 0)
|
|
continue;
|
|
|
|
/* putprintf(mbp, "; ");*/
|
|
|
|
/* Eintrag einer Route erzeugen */
|
|
putprintf(mbp, (new_parser == FALSE ? "AXIPR R + %s " : "AXIPR ADD %s ")
|
|
, call_to_a(&route_tbl[i].callsign[0]));
|
|
|
|
/* Den Hostnamen ausgeben */
|
|
putprintf(mbp, "%s", route_tbl[i].hostname);
|
|
|
|
/* Mode und ggf. Port ausgeben wenn UDP */
|
|
if (route_tbl[i].udp_port != 0)
|
|
{
|
|
putstr((new_parser == FALSE ? " U " : " UDP "), mbp);
|
|
putnum(ntohs(route_tbl[i].udp_port), mbp);
|
|
}
|
|
|
|
putstr("\r", mbp);
|
|
}
|
|
|
|
/* Die Defaultroute ausgeben wenn gesetzt */
|
|
if (default_route.callsign[0] == 1)
|
|
{
|
|
/* Kommandokopf schreiben */
|
|
putstr((new_parser == FALSE ? "AXIPR D + " : "AXIPR ADD DEFAULT "), mbp);
|
|
|
|
/* Den Hostnamen ausgeben */
|
|
putprintf(mbp, "%s", default_route.hostname);
|
|
|
|
/* Mode und ggf. Port ausgeben wenn UDP */
|
|
if (default_route.udp_port != 0)
|
|
{
|
|
putstr((new_parser == FALSE ? " U " : " UDP "), mbp);
|
|
putnum(ntohs(default_route.udp_port), mbp);
|
|
}
|
|
putstr("\r", mbp);
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* AX25IP Initialisierung */
|
|
/************************************************************************/
|
|
BOOLEAN ax25ip_l1init(int l2port)
|
|
{
|
|
if (ax25ip_active == TRUE)
|
|
return(TRUE);
|
|
|
|
/* Socketstrukturen initialisieren */
|
|
memset((char*)&to, 0, sizeof(to));
|
|
memset((char*)&from, 0, sizeof(from));
|
|
|
|
ax25ip_port = l2port;
|
|
l1pp = &l1port[l1ptab[l2port]];
|
|
l2flp = (LHEAD *) &txl2fl[l2port];
|
|
|
|
/* Routingtabelle initialisieren */
|
|
route_init();
|
|
|
|
/* Konfiguration einlesen */
|
|
if (config_read() == FALSE)
|
|
return(FALSE);
|
|
|
|
/* Notwendige Sockets anlegen */
|
|
#ifndef AXIPR_UDP
|
|
ax25ip_check_up();
|
|
#endif
|
|
|
|
/* Wir sind fertig */
|
|
ax25ip_active = TRUE;
|
|
return(TRUE);
|
|
}
|
|
|
|
/* Einen Filedescriptor fuer IP anlegen */
|
|
int setup_ip(void)
|
|
{
|
|
/* Temporaerer Filedescriptor */
|
|
int tmp_fd = -1;
|
|
|
|
/* Adressstruktur loeschen */
|
|
memset((char*)&ipbind, 0, sizeof(ipbind));
|
|
|
|
/* Rohen IP-Socket anlegen */
|
|
if ((tmp_fd = socket(AF_INET, SOCK_RAW, IPPROTO_AX25)) < 0)
|
|
{
|
|
xprintf("AX25IP : cannot create ip raw-socket: %s\n", strerror(errno));
|
|
LOGL2("AX25IP : cannot create ip raw-socket: %s\n", strerror(errno));
|
|
return(-1);
|
|
}
|
|
|
|
/* Nonblocking-IO */
|
|
if (fcntl(tmp_fd, F_SETFL, FNDELAY) < 0)
|
|
{
|
|
xprintf("AX25IP : cannot set non-blocking I/O on ip raw-socket\n");
|
|
LOGL2("AX25IP : cannot set non-blocking I/O on ip raw-socket\n");
|
|
close(tmp_fd);
|
|
return(-1);
|
|
}
|
|
|
|
/* Adressstruktur mit notwendigen Werten fuellen */
|
|
ipbind.sin_family = AF_INET;
|
|
ipbind.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
return (tmp_fd);
|
|
}
|
|
|
|
/* Einen Filedescriptor fuer UDP anlegen */
|
|
/* Es muss der UDP-Port angegeben werden, auf dem wir hoeren wollen */
|
|
/* (Achtung: UDP-Port in Network-Byteorder) */
|
|
int setup_udp(unsigned short udp_port)
|
|
{
|
|
/* Temporaerer Filedescriptor */
|
|
int tmp_fd = -1;
|
|
|
|
/* Port-Check */
|
|
if (udp_port == 0)
|
|
return(-1);
|
|
|
|
/* Adressstruktur loeschen */
|
|
memset((char*)&udpbind, 0, sizeof(udpbind));
|
|
|
|
/* UDP-Socket anlegen */
|
|
if ((tmp_fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
|
|
{
|
|
xprintf("AX25IP : cannot create socket: %s\n", strerror(errno));
|
|
LOGL2("AX25IP : cannot create socket: %s\n", strerror(errno));
|
|
return(-1);
|
|
}
|
|
|
|
/* Nonblocking-IO */
|
|
if (fcntl(tmp_fd, F_SETFL, FNDELAY) < 0)
|
|
{
|
|
xprintf("AX25IP : cannot set non-blocking I/O on udp socket\n");
|
|
LOGL2("AX25IP : cannot set non-blocking I/O on udp socket\n");
|
|
close(tmp_fd);
|
|
return(-1);
|
|
}
|
|
|
|
/* Socket-Optionen fuer UDP einstellen */
|
|
/* SO_KEEPALIVE einschalten */
|
|
if (sockopt_keepalive == TRUE)
|
|
{
|
|
int iFlag = 1;
|
|
|
|
if (setsockopt(tmp_fd, SOL_SOCKET, SO_KEEPALIVE, (const char *)&iFlag, sizeof(int)) < 0)
|
|
{
|
|
xprintf("AX25IP : cannot set SO_KEEPALIVE for udp : %s\n", strerror(errno));
|
|
LOGL2("AX25IP : cannot set SO_KEEPALIVE for udp : %s\n", strerror(errno));
|
|
}
|
|
}
|
|
|
|
/* Socket auf max. Durchsatz */
|
|
if (sockopt_throughput == TRUE)
|
|
{
|
|
int iFlag = IPTOS_THROUGHPUT;
|
|
|
|
if (setsockopt(tmp_fd, IPPROTO_IP, IP_TOS, (const char *)&iFlag, sizeof(IPTOS_THROUGHPUT)) < 0)
|
|
{
|
|
xprintf("AX25IP : cannot set IPTOS_THROUGHPUT for udp : %s\n", strerror(errno));
|
|
LOGL2("AX25IP : cannot set IPTOS_THROUGHPUT for udp : %s\n", strerror(errno));
|
|
}
|
|
}
|
|
|
|
/* Adressstruktur fuellen */
|
|
udpbind.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
udpbind.sin_port = udp_port;
|
|
udpbind.sin_family = AF_INET;
|
|
|
|
/* Adresse und Port binden */
|
|
if (bind(tmp_fd, (struct sockaddr *)&udpbind, sizeof(udpbind)) < 0)
|
|
{
|
|
xprintf("AX25IP : cannot bind udp socket: %s\n", strerror(errno));
|
|
LOGL2("AX25IP : cannot bind udp socket: %s\n", strerror(errno));
|
|
close(tmp_fd);
|
|
return(-1);
|
|
}
|
|
|
|
return(tmp_fd);
|
|
}
|
|
|
|
/* Pruefen, ob schon Sockets angelegt sind, wenn nicht, dann notwendige */
|
|
/* Sockets oeffnen */
|
|
void ax25ip_check_up(void)
|
|
{
|
|
/* IP notwendig ? */
|
|
if ((count_routes(FALSE) != 0) && (fd_ip == -1))
|
|
fd_ip = setup_ip(); /* IP starten */
|
|
|
|
/* UDP notwendig ? */
|
|
if ((count_routes(TRUE) != 0) && (fd_udp == -1))
|
|
fd_udp = setup_udp(my_udp); /* UDP starten */
|
|
|
|
#ifdef AXIPR_UDP
|
|
if (l1pp != NULL)
|
|
#endif
|
|
/* Markieren, ob IP oder UDP laufen */
|
|
l1pp->kisslink = max(fd_ip, fd_udp);
|
|
}
|
|
|
|
/* Pruefen, ob Sockets angelegt sind und diese noch benoetigt werden. */
|
|
/* Falls nicht, Sockets schliessen */
|
|
void ax25ip_check_down(void)
|
|
{
|
|
/* IP notwendig ? */
|
|
if ((count_routes(FALSE) == 0) && (fd_ip != -1))
|
|
{
|
|
close(fd_ip);
|
|
fd_ip = -1;
|
|
}
|
|
|
|
/* UDP notwendig ? */
|
|
if ((count_routes(TRUE) == 0) && (fd_udp != -1))
|
|
{
|
|
close(fd_udp);
|
|
fd_udp = -1;
|
|
}
|
|
|
|
/* Gibt es einen Eintrag. */
|
|
if (l1pp)
|
|
/* Markieren, ob IP oder UDP laufen */
|
|
l1pp->kisslink = max(fd_ip, fd_udp);
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/* AX25IP Pakete empfangen */
|
|
/*************************************************************************/
|
|
void ax25ip_recv(void)
|
|
{
|
|
struct iphdr *ipptr;
|
|
struct timeval tv;
|
|
int l = 0;
|
|
int iDescriptorsReady = 0;
|
|
register int i = 0;
|
|
register int max_fd = -1;
|
|
socklen_t fromlen = sizeof(from);
|
|
int hdr_len = 0;
|
|
UBYTE buf[MAX_FRAME+1];
|
|
UBYTE *bufptr;
|
|
MBHEAD *rxfhd;
|
|
BOOLEAN UDP_Frame = FALSE;
|
|
fd_set rmask;
|
|
|
|
#ifdef AXIPR_UDP
|
|
if (LookAX25IP)
|
|
return;
|
|
#endif /* AX25IP_UDP */
|
|
|
|
FD_ZERO(&rmask);
|
|
|
|
/* IP-Filedescriptor eintragen */
|
|
if (fd_ip != -1)
|
|
{
|
|
FD_SET((unsigned int)fd_ip, &rmask);
|
|
if (fd_ip > max_fd - 1)
|
|
max_fd = fd_ip + 1;
|
|
}
|
|
|
|
/* UDP-Filedescriptor eintragen */
|
|
if (fd_udp != -1)
|
|
{
|
|
FD_SET((unsigned int)fd_udp, &rmask);
|
|
if (fd_udp > max_fd - 1)
|
|
max_fd = fd_udp + 1;
|
|
}
|
|
|
|
/* ist was aktiv ? */
|
|
if (max_fd == -1)
|
|
return;
|
|
|
|
tv.tv_usec = 0;
|
|
tv.tv_sec = 0;
|
|
|
|
iDescriptorsReady = select(max_fd, &rmask, NULL, NULL, &tv);
|
|
|
|
/* nix da */
|
|
if (iDescriptorsReady == 0)
|
|
return;
|
|
|
|
/* Fehler */
|
|
if (iDescriptorsReady == -1)
|
|
{
|
|
LOGL2("select()-Error %i: %s", errno, strerror(errno));
|
|
return;
|
|
}
|
|
|
|
/* RX fuer IP */
|
|
if ((fd_ip != -1) && (FD_ISSET(fd_ip, &rmask)))
|
|
{
|
|
l = recvfrom(fd_ip, (UBYTE *)(bufptr = buf), MAX_FRAME, 0, (struct sockaddr *) &from, &fromlen);
|
|
|
|
if (l > 0)
|
|
{
|
|
if (l > (signed)sizeof(struct iphdr*))
|
|
{
|
|
ipptr = (struct iphdr*)buf;
|
|
hdr_len = 20;
|
|
|
|
if (!ok_crc(buf + hdr_len, l - hdr_len))
|
|
{ /* stimmt die CRC ? */
|
|
LOGL2("IP-RX: CRC-Error, frame dropped");
|
|
return; /* Fehler */
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LOGL2("IP-RX: frame too short, frame dropped");
|
|
return; /* Fehler */
|
|
}
|
|
}
|
|
i = hdr_len;
|
|
}
|
|
|
|
/* RX fuer UDP, aber nur, wenn nicht schon TCP was empfangen hat */
|
|
if ((fd_udp != -1) && (FD_ISSET(fd_udp, &rmask) && (l == 0)))
|
|
{
|
|
l = recvfrom(fd_udp, (UBYTE *)(bufptr = buf), MAX_FRAME, 0, (struct sockaddr *) &from, &fromlen);
|
|
|
|
if (l > 0)
|
|
{
|
|
if (!ok_crc(buf, l))
|
|
{ /* stimmt die CRC ? */
|
|
LOGL2("UDP-RX: CRC-Error, frame dropped");
|
|
return; /* Fehler */
|
|
}
|
|
}
|
|
UDP_Frame = TRUE;
|
|
}
|
|
|
|
/* Ab hier gemeinsame Behandlung */
|
|
/* Erst mal gucken, ob was gekommen ist */
|
|
if (l == 0)
|
|
return; /* nix da */
|
|
|
|
l -= 2; /* CRC abschneiden */
|
|
|
|
if (l < 15)
|
|
{
|
|
LOGL2("AX25IP: RX frame dropped, length wrong, frame is too short !");
|
|
return;
|
|
}
|
|
|
|
/* Hier angekommen haben wir (hoffentlich) ein gueltiges Frame. Die */
|
|
/* weitere Behandlung ist fuer IP und UDP nahezu identisch. */
|
|
|
|
/* Frame in Buffer umkopieren und Empfangsport eintragen */
|
|
rxfhd = cpyflatmb((char*)&buf[i], l - i);
|
|
rxfhd->l2port = ax25ip_port;
|
|
|
|
/* Frame in die L2-RX-Kette einhaengen */
|
|
relink((LEHEAD *)rxfhd, (LEHEAD *)rxfl.tail);
|
|
|
|
/* Jetzt noch das Frame an den Routenlerner zur Analyse */
|
|
if (route_canlearn(rxfhd))
|
|
{
|
|
/* Frame kann zum Lernen benutzt werden */
|
|
/* Absenderrufzeichen ermitteln und konvertieren */
|
|
/* Wir brauchen hier nicht den eigentlichen Absender, */
|
|
/* sondern den, der als letztes gedigipeated hat. */
|
|
struct in_addr ipaddr;
|
|
#ifndef AXIPR_UDP
|
|
struct route_table_entry* rtptr;
|
|
#endif /* AXIPR_UDP */
|
|
unsigned char srccall[L2IDLEN + 1];
|
|
|
|
cpyid((char *)srccall, dheardcall(rxfhdr));
|
|
|
|
/* Call linksschieben */
|
|
for (i = 0; i < L2CALEN; ++i)
|
|
srccall[i] = srccall[i] << 1;
|
|
|
|
/* Gibt es schon eine IP fuer dieses Call, dann kann sich die IP */
|
|
/* geaendert haben. Falls ja und es sich um einen dynamischen Eintrag */
|
|
/* handelt, dann loeschen und neuen Eintrag anlegen. */
|
|
#ifndef AXIPR_UDP
|
|
if ((rtptr = call_to_ip(srccall)) != NULL)
|
|
{
|
|
if (( (rtptr->ip_addr != from.sin_addr.s_addr)
|
|
|| (rtptr->udp_port != (UDP_Frame == TRUE ? ntohs(from.sin_port) : 0)))
|
|
&& (rtptr->timeout != 0))
|
|
route_del(srccall); /* Route loeschen */
|
|
else
|
|
{
|
|
if (rtptr != &default_route)
|
|
return; /* Adresse unveraendert */
|
|
}
|
|
}
|
|
#endif /* AXIPR_UDP */
|
|
|
|
ipaddr.s_addr = from.sin_addr.s_addr;
|
|
|
|
#ifndef AXIPR_UDP
|
|
/* Route eintragen */
|
|
route_add((unsigned char*)inet_ntoa(ipaddr), NULL, srccall,
|
|
(UDP_Frame == TRUE ? ntohs(from.sin_port) : 0), FALSE, uDynTimeout);
|
|
#else
|
|
route_analyse(ipaddr, srccall,
|
|
(UDP_Frame == TRUE ? ntohs(from.sin_port) : 0));
|
|
}
|
|
#endif /* AXIPR_UDP */
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/* AX25IP Pakete senden */
|
|
/*************************************************************************/
|
|
void ax25ip_send(void)
|
|
{
|
|
unsigned char buf[MAX_FRAME];
|
|
int len = 0;
|
|
int fd = -1;
|
|
MBHEAD *txfhdl;
|
|
|
|
struct route_table_entry *rt;
|
|
struct hostent *hstent;
|
|
|
|
unsigned char *call;
|
|
|
|
if (kick[ax25ip_port]) /* haben wir was zu senden ? */
|
|
{
|
|
/* Sicherheitsabfrage, da kick[] auch manipuliert werden kann */
|
|
if (l2flp->head == l2flp)
|
|
{
|
|
kick[ax25ip_port] = FALSE;
|
|
return;
|
|
}
|
|
|
|
ulink((LEHEAD *)(txfhdl = (MBHEAD *) l2flp->head));/*Zeiger holen*/
|
|
|
|
/* Daten aus den internen Puffern in einen linearen Puffer uebertragen */
|
|
len = cpymbflat((char*)&buf[0], txfhdl);
|
|
|
|
relink((LEHEAD *)txfhdl, /* als gesendet betrachten und in */
|
|
(LEHEAD *)stfl.tail); /* die gesendet Liste umhaengen */
|
|
|
|
kick[ax25ip_port] = ((LHEAD *)l2flp->head != l2flp);
|
|
|
|
/* Naechstes Call der Digipeaterkette holen */
|
|
call = next_addr(buf);
|
|
|
|
/* IP-Adresse des naechsten Digipeaters ermitteln */
|
|
rt = call_to_ip(call);
|
|
|
|
if (rt == NULL) /* wir kennen das Ziel nicht */
|
|
{
|
|
#ifdef AXIPR_UDP
|
|
if ((rt = search_route(call)) == NULL)
|
|
{
|
|
#endif
|
|
LOGL2("no route for %s, can't send", call_to_a(call));
|
|
return;
|
|
}
|
|
#ifdef AXIPR_UDP
|
|
}
|
|
#endif
|
|
|
|
/* Ein Host, zu dem bisher keine IP-Adresse aufgeloest werden konnte */
|
|
if (rt->ip_addr == 0L)
|
|
{
|
|
/* Versuchen, jetzt eine IP-Adresse zu bestimmen */
|
|
if ((hstent = gethostbyname((char*)rt->hostname)) != NULL)
|
|
memcpy((unsigned char*)&rt->hostname, (unsigned char *)&hstent->h_addr_list[0][0], 4);
|
|
}
|
|
|
|
/* Checksumme anhaengen */
|
|
add_ax25crc(buf, len);
|
|
/* CRC-Bytes sind dazugekommen */
|
|
len += 2;
|
|
/* Ziel-IP-Adresse in Sendestruktur eintragen */
|
|
memcpy((char *) &to.sin_addr, (char *)&rt->ip_addr, 4);
|
|
/* Ziel-Port nur bei UDP eintragen */
|
|
if (rt->udp_port != 0)
|
|
memcpy((char *) &to.sin_port, (char *)&rt->udp_port, 2);
|
|
else
|
|
to.sin_port = 0; /* bei IP kein Port */
|
|
|
|
to.sin_family = AF_INET;
|
|
|
|
/* Unterscheidung IP oder UDP */
|
|
if (to.sin_port == 0)
|
|
fd = fd_ip;
|
|
else
|
|
fd = fd_udp;
|
|
|
|
if (fd == -1)
|
|
{
|
|
LOGL2("error: no descriptor, can't send !!!");
|
|
return;
|
|
}
|
|
|
|
if (sendto(fd, (char *)buf, len, 0, (struct sockaddr *)&to, sizeof(to)) < 0)
|
|
LOGL2("error: sendto failed, fd=%u error=%s", fd, strerror(errno));
|
|
}
|
|
}
|
|
|
|
/*************************************************************************/
|
|
/* AX25IP Deinitialisierung, Port und Sockets schliessen */
|
|
/*************************************************************************/
|
|
void ax25ip_l1exit(void)
|
|
{
|
|
/* Nur wenn aktiv */
|
|
if (ax25ip_active == FALSE)
|
|
return;
|
|
|
|
/* IP-Socket schliessen wenn offen */
|
|
if (fd_ip != -1)
|
|
{
|
|
close(fd_ip);
|
|
fd_ip = -1;
|
|
}
|
|
|
|
/* UDP-Socket schliessen wenn offen */
|
|
if (fd_udp != -1)
|
|
{
|
|
close(fd_udp);
|
|
fd_udp = -1;
|
|
}
|
|
|
|
/* AX25IP nicht mehr aktiv */
|
|
ax25ip_active = FALSE;
|
|
|
|
/* Gibt es einen Eintrag. */
|
|
if (l1pp)
|
|
l1pp->kisslink = -1;
|
|
}
|
|
|
|
void ax25ip_l1ctl(int req, int port)
|
|
{
|
|
/* nur eigene Ports bearbeiten */
|
|
if ((ax25ip_active == FALSE) || (kissmode(port) != KISS_AXIP))
|
|
return;
|
|
|
|
switch (req)
|
|
{
|
|
/* Testpattern auf dem Port senden (wird unterdrueckt) */
|
|
case L1CTST : testflag[port] = FALSE;
|
|
kick[port] = FALSE;
|
|
break;
|
|
|
|
default : break;
|
|
}
|
|
}
|
|
|
|
void ax25ip_hwstr(int port, MBHEAD *mbp)
|
|
{
|
|
#ifdef AXIPR_UDP
|
|
putstr(" ", mbp);
|
|
/* My UDP-Port ausgeben. */
|
|
putprintf(mbp,"%u", ntohs(my_udp));
|
|
#endif
|
|
}
|
|
|
|
BOOLEAN ax25ip_dcd(int port)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
|
|
|
|
/* routing.c Routing table manipulation routines
|
|
*
|
|
* Copyright 1991, Michael Westerhof, Sun Microsystems, Inc.
|
|
* This software may be freely used, distributed, or modified, providing
|
|
* this header is not removed.
|
|
*
|
|
|
|
* Modified for use in TNN by DG1KWA & DG9OBU
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* Initialize the routing table */
|
|
void route_init(void)
|
|
{
|
|
/* Defaultroute initialisieren */
|
|
memset(&default_route, 0 , sizeof(struct route_table_entry));
|
|
|
|
/* Routen initialisieren */
|
|
memset(&route_tbl, 0, (TABLE_SIZE * sizeof(struct route_table_entry)));
|
|
}
|
|
|
|
/* Add a new route entry */
|
|
#ifndef AXIPR_UDP
|
|
static void route_add(unsigned char* hostname, struct hostent *hstent, unsigned char *call, int udpport,
|
|
int default_rt, int timeout)
|
|
#else
|
|
static BOOLEAN route_add(unsigned char *host, struct hostent *hstent, unsigned char *call, int udpport,
|
|
int default_rt, int timeout, char *hostname
|
|
#ifdef AXIPR_HTML
|
|
, char *timeset, UWORD protokoll
|
|
#endif /* AXIPR_HTML */
|
|
)
|
|
#endif /* AXIPR_UDP */
|
|
{
|
|
register unsigned int i = 0;
|
|
struct route_table_entry *rtptr;
|
|
struct hostent *hst;
|
|
|
|
/* Eintrag soll Defaultroute sein */
|
|
if (default_rt)
|
|
{
|
|
for (i = 1; i < 7 ;++i)
|
|
default_route.callsign[i] = 0;
|
|
|
|
if (hstent != NULL)
|
|
memcpy(&default_route.ip_addr, (unsigned char *)&hstent->h_addr_list[0][0], 4);
|
|
else
|
|
memset(&default_route.ip_addr, 0, 4);
|
|
|
|
default_route.udp_port = htons((unsigned short)udpport);
|
|
default_route.timeout = 0; /* Defaultroute ohne Timeout */
|
|
|
|
if (hostname != NULL)
|
|
strncpy((char*)&default_route.hostname, (char*)hostname, HNLEN);
|
|
|
|
default_route.callsign[0] = 1; /* mark valid */
|
|
|
|
/* Socket ggf. installieren */
|
|
ax25ip_check_up();
|
|
|
|
#ifndef AXIPR_UDP
|
|
return;
|
|
#else
|
|
return(TRUE);
|
|
#endif /* AXIPR_UDP */
|
|
}
|
|
|
|
/* Normale Routen nur wenn Call vorhanden */
|
|
if (call == NULL)
|
|
#ifndef AXIPR_UDP
|
|
return;
|
|
#else
|
|
return(FALSE);
|
|
#endif /* AXIPR_UDP */
|
|
|
|
/* Check auf doppelte Eintraege, Eintrag wird nur angenommen wenn */
|
|
/* es noch noch keinen Eintrag unter diesem Call gibt. */
|
|
if (((rtptr = call_to_ip(call)) != NULL) && (rtptr->ip_addr != default_route.ip_addr))
|
|
{
|
|
#ifndef AXIPR_UDP
|
|
putmsg("A route to this callsign is already set up, delete it first.\r");
|
|
return;
|
|
#else
|
|
#ifndef AXIPR_HTML
|
|
UpdateRoute(call, udpport, timeout, hostname);
|
|
#else
|
|
UpdateRoute(call, udpport, timeout, hostname, timeset, protokoll);
|
|
#endif /* AXIPR_HTML */
|
|
return(FALSE);
|
|
#endif /* AXIPR_UDP */
|
|
}
|
|
|
|
/* Passt noch ein Eintrag in die Tabelle ? */
|
|
if (route_tbl_top >= TABLE_SIZE)
|
|
{
|
|
xprintf("Routing table is full; entry ignored.\n");
|
|
LOGL2("Routing table is full; entry ignored");
|
|
putmsg("Routing table is full, entry ignored\r");
|
|
#ifndef AXIPR_UDP
|
|
return;
|
|
#else
|
|
return(FALSE);
|
|
#endif /* AXIPR_UDP */
|
|
}
|
|
|
|
/* Call eintragen */
|
|
for (i = 0; i < 6; ++i)
|
|
route_tbl[route_tbl_top].callsign[i] = call[i] & 0xfe;
|
|
|
|
/* SSID eintragen */
|
|
route_tbl[route_tbl_top].callsign[6] = (call[6] & 0x1e) | 0x60;
|
|
|
|
if (hstent != NULL && hstent->h_length != 0)
|
|
{
|
|
memcpy((unsigned char*)&route_tbl[route_tbl_top].ip_addr, (unsigned char *)&hstent->h_addr_list[0][0], 4);
|
|
}
|
|
else
|
|
memset(&route_tbl[route_tbl_top].ip_addr, 0, sizeof(route_tbl[route_tbl_top].ip_addr));
|
|
|
|
route_tbl[route_tbl_top].udp_port = htons((unsigned short)udpport);
|
|
route_tbl[route_tbl_top].timeout = timeout;
|
|
|
|
if (hostname != NULL)
|
|
{
|
|
memcpy(&route_tbl[route_tbl_top].hostname, hostname, strlen((char*)hostname));
|
|
/* Keine Adressaufloesung bisher, dann probieren wir es noch einmal */
|
|
if (hstent == NULL)
|
|
{
|
|
if ((hst = gethostbyname((char*)hostname)) != NULL)
|
|
memcpy((unsigned char*)&route_tbl[route_tbl_top].ip_addr, &hst->h_addr_list[0][0], 4);
|
|
}
|
|
}
|
|
|
|
#ifdef AXIPR_UDP
|
|
/* Original UDP-Port eintragen. */
|
|
route_tbl[route_tbl_top].org_udp_port = htons((UWORD)udpport);
|
|
#endif
|
|
|
|
#ifdef AXIPR_HTML
|
|
/* Hostname eintragen. */
|
|
(void)memcpy(route_tbl[route_tbl_top].timeset, timeset, 17);
|
|
/* Protokoll eintragen. */
|
|
route_tbl[route_tbl_top].protokoll = P_USER;
|
|
/* Route als offline markieren. */
|
|
route_tbl[route_tbl_top].online = FALSE;
|
|
#endif
|
|
|
|
/* Ein Routeneintrag mehr */
|
|
route_tbl_top++;
|
|
|
|
/* Socket ggf. installieren */
|
|
ax25ip_check_up();
|
|
|
|
#ifndef AXIPR_UDP
|
|
return;
|
|
#else
|
|
return(TRUE);
|
|
#endif /* AXIPR_UDP */
|
|
}
|
|
|
|
/*
|
|
* Return an IP address and port number given a callsign.
|
|
* We return a pointer to the route structure for this callsign
|
|
* or a NULL-pointer if no route was found.
|
|
*/
|
|
|
|
struct route_table_entry* call_to_ip(unsigned char *call)
|
|
{
|
|
register int i;
|
|
unsigned char mycall[7];
|
|
|
|
/* Leere Calls koennen nicht verarbeitet werden */
|
|
if (call == NULL)
|
|
return (NULL);
|
|
|
|
/* Call-Bytes kopieren, letztes Bit abschneiden (entspricht >> 1 & 7F) */
|
|
for (i = 0; i < 6; ++i)
|
|
mycall[i] = call[i] & 0xfe;
|
|
|
|
/* SSID kopieren */
|
|
mycall[6] = (call[6] & 0x1e) | 0x60;
|
|
|
|
/* Routingtabelle durchsuchen */
|
|
for (i = 0; i < route_tbl_top; ++i)
|
|
{
|
|
if (addrmatch(mycall , route_tbl[i].callsign))
|
|
{
|
|
/* Aktivitaet auf diesem Eintrag, dann Timeout erneuern */
|
|
if (route_tbl[i].timeout)
|
|
route_tbl[i].timeout = uDynTimeout;
|
|
|
|
return (&route_tbl[i]); /* Eintrag gefunden */
|
|
}
|
|
}
|
|
|
|
/* Kein Routingeintrag vorhanden, Default-Route melden wenn vorhanden */
|
|
if (default_route.callsign[0])
|
|
return (&default_route);
|
|
|
|
/* Kein Routingeintrag gefunden, keine Defaultroute */
|
|
return (NULL);
|
|
}
|
|
|
|
/*
|
|
* tack on the CRC for the frame. Note we assume the buffer is long
|
|
* enough to have the two bytes tacked on.
|
|
*/
|
|
void add_ax25crc(unsigned char *buf, int l)
|
|
{
|
|
unsigned short int u = compute_crc(buf, l);
|
|
|
|
buf[l] = u & 0xff; /* lsb first */
|
|
buf[l + 1] = (u >> 8) & 0xff; /* msb next */
|
|
}
|
|
|
|
|
|
/*
|
|
**********************************************************************
|
|
* The following code was taken from Appendix B of RFC 1171
|
|
* (Point-to-Point Protocol)
|
|
*
|
|
* The RFC credits the following sources for this implementation:
|
|
*
|
|
* Perez, "Byte-wise CRC Calculations", IEEE Micro, June, 1983.
|
|
*
|
|
* Morse, G., "Calculating CRC's by Bits and Bytes", Byte,
|
|
* September 1986.
|
|
*
|
|
* LeVan, J., "A Fast CRC", Byte, November 1987.
|
|
*
|
|
*
|
|
* The HDLC polynomial: x**0 + x**5 + x**12 + x**16
|
|
*/
|
|
|
|
/*
|
|
* u16 represents an unsigned 16-bit number. Adjust the typedef for
|
|
* your hardware.
|
|
*/
|
|
/*typedef unsigned short u16;*/
|
|
|
|
|
|
/*
|
|
* FCS lookup table as calculated by the table generator in section 2.
|
|
*/
|
|
static UWORD fcstab[256] = {
|
|
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
|
|
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
|
|
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
|
|
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
|
|
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
|
|
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
|
|
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
|
|
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
|
|
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
|
|
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
|
|
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
|
|
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
|
|
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
|
|
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
|
|
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
|
|
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
|
|
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
|
|
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
|
|
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
|
|
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
|
|
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
|
|
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
|
|
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
|
|
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
|
|
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
|
|
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
|
|
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
|
|
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
|
|
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
|
|
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
|
|
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
|
|
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
|
|
};
|
|
|
|
#define PPPINITFCS 0xffff /* Initial FCS value */
|
|
#define PPPGOODFCS 0xf0b8 /* Good final FCS value */
|
|
|
|
/*
|
|
* Calculate a new fcs given the current fcs and the new data.
|
|
*/
|
|
UWORD pppfcs(register UWORD fcs, register unsigned char *cp, register int len)
|
|
{
|
|
while (len--)
|
|
fcs = (fcs >> 8) ^ fcstab[(fcs ^ *cp++) & 0xff];
|
|
|
|
return(fcs);
|
|
}
|
|
|
|
/*
|
|
* End code from Appendix B of RFC 1171
|
|
**********************************************************************
|
|
*/
|
|
|
|
/*
|
|
* The following routines are simply convenience routines...
|
|
* I'll merge them into the mainline code when suitably debugged
|
|
*/
|
|
|
|
/* Return the computed CRC */
|
|
UWORD compute_crc(unsigned char *buf, int l)
|
|
{
|
|
UWORD fcs = (pppfcs(PPPINITFCS, buf, l) ^ 0xFFFF);
|
|
|
|
return (fcs);
|
|
}
|
|
|
|
/* Return true if the CRC is correct */
|
|
BOOLEAN ok_crc(unsigned char *buf, int l)
|
|
{
|
|
UWORD fcs = pppfcs(PPPINITFCS, buf, l);
|
|
|
|
return (fcs == PPPGOODFCS);
|
|
}
|
|
|
|
/* return true if the addresses supplied match */
|
|
int addrmatch(unsigned char *a, unsigned char *b)
|
|
{
|
|
if ((*a == '\0') || (*b == '\0')) return(0);
|
|
|
|
if ((*a++ ^ *b++) & 0xfe) return(0); /* "K" */
|
|
if ((*a++ ^ *b++) & 0xfe) return(0); /* "A" */
|
|
if ((*a++ ^ *b++) & 0xfe) return(0); /* "9" */
|
|
if ((*a++ ^ *b++) & 0xfe) return(0); /* "W" */
|
|
if ((*a++ ^ *b++) & 0xfe) return(0); /* "S" */
|
|
if ((*a++ ^ *b++) & 0xfe) return(0); /* "B" */
|
|
if ((*a++ ^ *b++) & 0x1e) return(0); /* ssid */
|
|
return(1);
|
|
}
|
|
|
|
/* return pointer to the next station to get this packet */
|
|
unsigned char *next_addr(unsigned char *f)
|
|
{
|
|
unsigned char *a;
|
|
|
|
/* If no digis, return the destination address */
|
|
if (NO_DIGIS(f)) return(f);
|
|
|
|
/* check each digi field. The first one that hasn't seen it is the one */
|
|
a = f + 7;
|
|
do {
|
|
a += 7;
|
|
if (NOTREPEATED(a)) return(a);
|
|
} while (NOT_LAST(a));
|
|
|
|
/* all the digis have seen it. return the destination address */
|
|
return(f);
|
|
}
|
|
|
|
/* Open and read the config file */
|
|
int config_read(void)
|
|
{
|
|
FILE *cf;
|
|
char buf[256], cbuf[256];
|
|
int errflag = 0;
|
|
int e = 0;
|
|
int lineno = 0;
|
|
char cfgfile[256];
|
|
|
|
strcpy(cfgfile, confpath);
|
|
strcat(cfgfile, CONFIG_FILE);
|
|
|
|
if ((cf = fopen(cfgfile, "r")) == NULL)
|
|
{
|
|
#ifdef INIPATH
|
|
strcpy(cfgfile, INIPATH);
|
|
strcat(cfgfile, CONFIG_FILE);
|
|
|
|
if ((cf = fopen(cfgfile, "r")) == NULL)
|
|
{
|
|
#endif
|
|
#ifdef AXIPR_UDP
|
|
/* AX25IP.CFG ist nicht mehr noetig, */
|
|
/* kann aber weiterhin benutzt werden. */
|
|
return(TRUE);
|
|
#endif
|
|
xprintf("AX25IP: Config file %s not found or could not be opened\n", CONFIG_FILE);
|
|
return(FALSE);
|
|
#ifdef INIPATH
|
|
}
|
|
#endif
|
|
}
|
|
|
|
while (fgets(buf, 255, cf) != NULL)
|
|
{
|
|
(void)strcpy(cbuf, buf);
|
|
++lineno;
|
|
|
|
if ((e = parse_line(buf)) < 0)
|
|
{
|
|
xprintf("Config error at line %d: ", lineno);
|
|
|
|
switch (e)
|
|
{
|
|
case -1 : xprintf("Missing argument\n"); break;
|
|
case -2 : xprintf("Bad callsign format\n"); break;
|
|
case -3 : xprintf("Bad option - on/off\n"); break;
|
|
case -4 : xprintf("Bad option - tnc/digi\n"); break;
|
|
case -5 : xprintf("Host not known\n"); break;
|
|
case -6 : xprintf("Unknown command\n"); break;
|
|
case -7 : xprintf("Text string too long\n"); break;
|
|
case -8 : xprintf("Bad option - every/after\n"); break;
|
|
case -9 : xprintf("Bad option - ip/udp\n"); break;
|
|
|
|
default: xprintf("Unknown error\n"); break;
|
|
}
|
|
xprintf("%s", cbuf);
|
|
++errflag;
|
|
}
|
|
}
|
|
|
|
if (errflag)
|
|
exit(1);
|
|
|
|
if (mode == NO_MODE)
|
|
{
|
|
xprintf("Must specify ip and/or udp sockets\n");
|
|
return(FALSE);
|
|
}
|
|
|
|
fclose(cf);
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
/* Process each line from the config file. The return value is encoded. */
|
|
int parse_line(char *buf)
|
|
{
|
|
char *p;
|
|
char *q;
|
|
char hostname[HNLEN];
|
|
unsigned char tcall[7];
|
|
struct hostent hstent;
|
|
struct hostent *he;
|
|
int i = 0;
|
|
int uport = 0;
|
|
int dfalt = 0;
|
|
#ifdef AXIPR_HTML
|
|
char *timeset = set_time();
|
|
#endif
|
|
|
|
p = strtok(buf, " \t\n\r");
|
|
|
|
memset(&hstent, 0, sizeof(hstent));
|
|
|
|
/* Leere Zeilen */
|
|
if (p == NULL)
|
|
return(0);
|
|
|
|
/* Kommentarzeilen nicht auswerten */
|
|
if (*p == '#')
|
|
return(0);
|
|
|
|
if (strcmp(p, "socket") == 0)
|
|
{
|
|
q = strtok(NULL, " \t\n\r");
|
|
|
|
if (q == NULL)
|
|
return(-1);
|
|
|
|
if (strcmp(q, "ip") == 0)
|
|
mode = IP_MODE;
|
|
else if (strcmp(q, "udp") == 0)
|
|
{
|
|
mode = UDP_MODE;
|
|
my_udp = htons(DEFAULT_UDP_PORT);
|
|
|
|
/* Bei UDP optionale Portnummer lesen */
|
|
q = strtok(NULL, " \t\n\r");
|
|
|
|
/* Nummer war vorhanden, auswerten */
|
|
if (q != NULL)
|
|
{
|
|
i = atoi(q);
|
|
/* Nummer ist gueltig, uebernehmen */
|
|
if (i > 0)
|
|
my_udp = htons((unsigned short)i);
|
|
}
|
|
}
|
|
else
|
|
return(-9);
|
|
|
|
return(0);
|
|
}
|
|
else if (strcmp(p, "socketoption") == 0)
|
|
{
|
|
q = strtok(NULL, " \t\n\r");
|
|
|
|
/* Pruefung auf leere Zeile */
|
|
if (q == NULL)
|
|
return(-1);
|
|
|
|
if (strcmp(q, "SO_KEEPALIVE") == 0)
|
|
{
|
|
sockopt_keepalive = TRUE;
|
|
}
|
|
else if (strcmp(q, "IPTOS_THROUGHPUT") == 0)
|
|
{
|
|
sockopt_throughput = TRUE;
|
|
}
|
|
else return(-9);
|
|
|
|
return(0);
|
|
|
|
} else if (strcmp(p, "loglevel") == 0) {
|
|
q = strtok(NULL, " \t\n\r");
|
|
if (q == NULL) return(-1);
|
|
loglevel = atoi(q);
|
|
return(0);
|
|
|
|
} else if (strcmp(p, "route") == 0) {
|
|
uport = 0;
|
|
dfalt = 0;
|
|
|
|
q = strtok(NULL, " \t\n\r");
|
|
|
|
/* Pruefung auf leere Zeile */
|
|
if (q == NULL)
|
|
return(-1);
|
|
|
|
/* Pruefung auf default-Route */
|
|
if (strcmp(q, "default") == 0)
|
|
dfalt = 1;
|
|
else
|
|
{
|
|
/* Ziel der Route pruefen */
|
|
if (a_to_call(q, tcall) != 0)
|
|
return(-2);
|
|
}
|
|
|
|
/* Hostnamen holen, dies kann auch eine IP-Adresse sein */
|
|
q = strtok(NULL, " \t\n\r");
|
|
if (q == NULL)
|
|
return(-1);
|
|
|
|
he = gethostbyname(q);
|
|
|
|
/* Keine gueltige IP-Adresse ? */
|
|
if (he == NULL)
|
|
{
|
|
/* Da route_add() eine hostent-Struktur braucht, bauen wir ihm eine. */
|
|
/* Den Hostname sichern und den Zeiger auf den Puffer im hostent eintragen. */
|
|
strncpy(hostname, q, HNLEN);
|
|
|
|
he = &hstent;
|
|
he->h_name = hostname;
|
|
}
|
|
|
|
q = strtok(NULL, " \t\n\r");
|
|
|
|
if (q != NULL)
|
|
{
|
|
if (strcmp(q, "udp") == 0)
|
|
{
|
|
uport = DEFAULT_UDP_PORT;
|
|
|
|
q = strtok(NULL, " \t\n\r");
|
|
if (q != NULL)
|
|
{
|
|
i = atoi(q);
|
|
if (i > 0)
|
|
uport = i;
|
|
}
|
|
}
|
|
}
|
|
#ifndef AXIPR_UDP
|
|
route_add((unsigned char*)he->h_name, he, tcall, uport, dfalt, 0);
|
|
#else
|
|
route_add((unsigned char*)he->h_name, he, tcall, uport, dfalt, 0, (char*)he->h_name
|
|
#ifdef AXIPR_HTML
|
|
, timeset, P_USER
|
|
#endif /* AXIPR_HTML */
|
|
);
|
|
#endif /* AXIPR_UDP */
|
|
return(0);
|
|
}
|
|
return(-999);
|
|
}
|
|
|
|
|
|
/* Convert ascii callsign to internal format */
|
|
int a_to_call(char *text, unsigned char *tcall)
|
|
{
|
|
register size_t i = 0;
|
|
int ssid = 0;
|
|
unsigned char c;
|
|
|
|
if (strlen(text) == 0)
|
|
return(-1);
|
|
|
|
for (i = 0; i < 6; ++i)
|
|
tcall[i] = (' ' << 1);
|
|
|
|
tcall[6] = '\0';
|
|
|
|
for (i = 0; i < strlen(text); ++i)
|
|
{
|
|
c = text[i];
|
|
if (c == '-')
|
|
{
|
|
ssid = atoi(&text[i + 1]);
|
|
if (ssid > 15)
|
|
return(-1);
|
|
tcall[6] = (ssid << 1);
|
|
return(0);
|
|
}
|
|
|
|
if (islower(c))
|
|
c = toupper(c);
|
|
|
|
if (i > 5)
|
|
return(-1);
|
|
|
|
tcall[i] = (c << 1);
|
|
}
|
|
return(0);
|
|
}
|
|
|
|
/* Convert internal callsign to printable format */
|
|
char *call_to_a(unsigned char *tcall)
|
|
{
|
|
int i = 0;
|
|
int ssid = 0;
|
|
char *tptr;
|
|
static char t[10];
|
|
|
|
for (i = 0, tptr = t; i < 6; ++i)
|
|
{
|
|
if (tcall[i] == (' ' << 1))
|
|
break;
|
|
*tptr = tcall[i] >> 1;
|
|
tptr++;
|
|
}
|
|
|
|
ssid = (tcall[6] >> 1) & 0x0f;
|
|
if (ssid > 0)
|
|
{
|
|
*tptr = '-';
|
|
tptr++;
|
|
|
|
if (ssid > 9)
|
|
{
|
|
*tptr = '1';
|
|
tptr++;
|
|
ssid -= 10;
|
|
}
|
|
*tptr = '0' + ssid;
|
|
tptr++;
|
|
}
|
|
|
|
*tptr = '\0';
|
|
return(&t[0]);
|
|
}
|
|
|
|
void write_log(const char *format, ...)
|
|
{
|
|
FILE *fp;
|
|
va_list arg_ptr;
|
|
struct tm *lt;
|
|
|
|
fp = fopen("ax25ip.log", "a+");
|
|
|
|
if (fp != NULL)
|
|
{
|
|
lt = localtime(&sys_time);
|
|
fprintf(fp, "%16.16s:", ctime(&sys_time));
|
|
va_start(arg_ptr, format);
|
|
vfprintf(fp, format, arg_ptr);
|
|
va_end(arg_ptr);
|
|
fprintf(fp, "\n");
|
|
fclose(fp);
|
|
}
|
|
else
|
|
loglevel = 0; /* Logging aus da Fehler mit der Logdatei */
|
|
}
|
|
|
|
#ifdef AXIPR_UDP
|
|
/* AX25IP-Frame untersuchen, wenn Aenderungen */
|
|
/* z.B. UDP-Port, IP-Adresse in TBL Aktualisieren.*/
|
|
void route_analyse(struct in_addr ip, unsigned char *call, int uport)
|
|
{
|
|
register int i;
|
|
char mycall[7];
|
|
|
|
#ifdef AXIPR_HTML
|
|
char *timeset = set_time();
|
|
#endif /* AXIPR_HTML */
|
|
|
|
/* Leere Calls koennen nicht verarbeitet werden */
|
|
if (call[0] == FALSE)
|
|
return;
|
|
|
|
/* Call-Bytes kopieren, letztes Bit abschneiden (entspricht >> 1 & 7F) */
|
|
for (i = 0; i < 6; ++i)
|
|
mycall[i] = call[i] & 0xfe;
|
|
|
|
/* SSID kopieren */
|
|
mycall[6] = (call[6] & 0x1e) | 0x60;
|
|
|
|
/* Routingtabelle durchsuchen */
|
|
for (i = 0; i < route_tbl_top; ++i)
|
|
{
|
|
if (addrmatch((unsigned char *)mycall , route_tbl[i].callsign))
|
|
{
|
|
/* Bei Aenderung uebernehmen */
|
|
if (memcmp(&ip, &route_tbl[i].ip_addr, 4) != 0)
|
|
/* IP-Adresse hat sich geaendert */
|
|
memcpy(&route_tbl[i].ip_addr, &ip, 4);
|
|
|
|
/* UDP-Port unterschiedlich? */
|
|
if (route_tbl[i].udp_port != htons((UWORD)uport))
|
|
/* UDP-Port updaten. */
|
|
route_tbl[i].udp_port = htons((UWORD)uport);
|
|
|
|
#ifdef AXIPR_HTML
|
|
/* Route ggf. auf online setzen. */
|
|
if (!route_tbl[i].online)
|
|
route_tbl[i].online = TRUE;
|
|
#endif
|
|
/* Aktivitaet auf diesem Eintrag, dann Timeout erneuern */
|
|
if (route_tbl[i].timeout)
|
|
route_tbl[i].timeout = uDynTimeout;
|
|
|
|
/* Aktualisierung beendet. */
|
|
return;
|
|
}
|
|
}
|
|
|
|
#ifndef AXIPR_HTML
|
|
/* Auto-Route eintragen */
|
|
route_add((unsigned char*)inet_ntoa(ip), NULL, call,uport, FALSE, uDynTimeout, (char*)inet_ntoa(ip));
|
|
#else
|
|
/* Auto-Route eintragen */
|
|
route_add((unsigned char*)inet_ntoa(ip), NULL, call,uport, FALSE, uDynTimeout, (char*)inet_ntoa(ip), timeset, P_USER);
|
|
#endif /* AXIPR_HTML */
|
|
}
|
|
|
|
/* Per Rufzeichen, ohne die SSID zubeachten, einen */
|
|
/* Routeneintrag suchen. Gibt es keinen Eintrag, */
|
|
/* wird sofort abgebrochen, ansonsten werden die */
|
|
/* routeneintraege IP-Adresse und UDP-Port ueber- */
|
|
/* nommen und das neue Rufzeichen wird eingetragen.*/
|
|
struct route_table_entry *search_route(unsigned char *call)
|
|
{
|
|
register int i;
|
|
char srccall[10];
|
|
#ifdef AXIPR_HTML
|
|
char *timeset = set_time();
|
|
#endif /* AXIPR_HTML */
|
|
|
|
/* Konvertiere Rufzeichen. */
|
|
callss2str((char *)srccall, call_to_a(call));
|
|
|
|
/* TB durchgehen. */
|
|
for (i = 0; i < route_tbl_top; ++i)
|
|
{
|
|
/* Suche Rufzeichen. */
|
|
if (cmpcal(srccall, call_to_a(&route_tbl[i].callsign[0])))
|
|
{
|
|
#ifndef AXIPR_HTML
|
|
/* Auto-Route eintragen */
|
|
route_add((unsigned char *)&route_tbl[i].ip_addr, NULL, (unsigned char *)call, htons(route_tbl[i].org_udp_port), FALSE, uDynTimeout, (char *)route_tbl[i].hostname);
|
|
#else
|
|
/* Auto-Route eintragen */
|
|
route_add((unsigned char *)&route_tbl[i].ip_addr, NULL, (unsigned char *)call, htons(route_tbl[i].org_udp_port), FALSE, uDynTimeout, (char *)route_tbl[i].hostname, timeset, P_USER);
|
|
#endif /* AXIPR_HTML */
|
|
/* Aktuellen Eintrag weiterreichen. */
|
|
return (&route_tbl[i]); /* Eintrag gefunden */
|
|
}
|
|
}
|
|
/* Kein Rufzeichen gefunden. */
|
|
return (NULL);
|
|
}
|
|
|
|
/* Eine AX-Route Updaten. */
|
|
void UpdateRoute(unsigned char *srccall,
|
|
int udpport,
|
|
int timeout,
|
|
char *hostname
|
|
#ifdef AXIPR_HTML
|
|
, char *timeset
|
|
, UWORD protokoll
|
|
#endif /* AXIPR_HTML */
|
|
)
|
|
{
|
|
MBHEAD *mbp;
|
|
register int i;
|
|
|
|
/* TB durchgehen. */
|
|
for (i = 0; i < route_tbl_top; ++i)
|
|
{
|
|
/* Suche Rufzeichen. */
|
|
if (addrmatch((unsigned char *)srccall , route_tbl[i].callsign))
|
|
{
|
|
route_tbl[i].org_udp_port = route_tbl[i].udp_port = htons((unsigned short)udpport);
|
|
/* Hostname eintragen. */
|
|
(void)memcpy(route_tbl[i].hostname, hostname, HNLEN);
|
|
/* ggf. Timeout setzen. */
|
|
route_tbl[i].timeout = timeout;
|
|
|
|
#ifdef AXIPR_HTML
|
|
/* Hostname eintragen. */
|
|
(void)memcpy(route_tbl[i].timeset, timeset, 17);
|
|
/* Protokoll eintragen. */
|
|
route_tbl[i].protokoll = P_USER;
|
|
#endif /* AXIPR_HTML */
|
|
|
|
mbp = getmbp();
|
|
|
|
/* und ab die Post ... */
|
|
prompt(mbp);
|
|
seteom(mbp);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef AXIPR_HTML
|
|
|
|
/* Protokoll fuer HTML-Ausgabe setzen. */
|
|
void SetHTML(int port, char *call, PEER *pp, BOOLEAN flag)
|
|
{
|
|
register int i;
|
|
char srccall[10 + 1];
|
|
|
|
call2str(srccall, call);
|
|
|
|
/* Routingtabelle durchsuchen */
|
|
for (i = 0; i < route_tbl_top; ++i)
|
|
{
|
|
if (!strcmp(srccall , call_to_a(&route_tbl[i].callsign[0])))
|
|
{
|
|
/* Protokoll setzen. */
|
|
set_status(i, port, pp);
|
|
|
|
/* Route auf online/offline stellen. */
|
|
route_tbl[i].online = flag;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Aktualisiere Loginzeit fuer TB */
|
|
char *set_time(void)
|
|
{
|
|
time_t go;
|
|
struct tm *zeit;
|
|
static char c[17];
|
|
char *timeset = c;
|
|
|
|
/* aktuelle Kalenderzeit */
|
|
time(&go);
|
|
/* konvertiert Datum und Uhrzeit. */
|
|
zeit = localtime(&go);
|
|
/* Formatiere eine Zeit-/Datumsangabe */
|
|
strftime(c,17,"%d-%b-%H:%M:%S",zeit);
|
|
|
|
/* Aktuelle Login Date/Time */
|
|
return(timeset);
|
|
}
|
|
|
|
/* Protokoll setzen. */
|
|
void set_status(register int a, int port, PEER *pp)
|
|
{
|
|
if (pp == NULL) /* Route wird ausgetragen. */
|
|
{
|
|
route_tbl[a].protokoll = P_OFFLINE; /* Route auf OFFLINE setzen. */
|
|
route_tbl[a].online = FALSE;
|
|
return;
|
|
}
|
|
|
|
switch(pp->typ) /* Protokol-TYP. */
|
|
{
|
|
case INP : /* INP-TYP. */
|
|
route_tbl[a].protokoll = P_INP; /* INP-TYP setzen. */
|
|
break;
|
|
|
|
case TNN : /* TNN-TYP */
|
|
case THENET : /* THENET-TYP. */
|
|
route_tbl[a].protokoll = P_THENET; /* TNN/THENET-TYP setzen. */
|
|
break;
|
|
|
|
case FLEXNET: /* FLEXNET-TYP. */
|
|
route_tbl[a].protokoll = P_FLEXNET; /* FLEXNET-TYP setzen. */
|
|
break;
|
|
|
|
default:
|
|
route_tbl[a].protokoll = P_OFFLINE; /* Route auf OFFLINE setzen. */
|
|
route_tbl[a].online = FALSE;
|
|
return;
|
|
}
|
|
|
|
route_tbl[a].online = TRUE;
|
|
}
|
|
|
|
/* Timer fuer htmlstatistik. */
|
|
void h_timer(void)
|
|
{
|
|
static LONG h_Timer = 0L;
|
|
|
|
/* Timer abgelaufen. */
|
|
if (h_Timer <= 0L)
|
|
{
|
|
/* Timer neu setzen. */
|
|
/* fest auf 60 sec. */
|
|
h_Timer = 60L;
|
|
/* html auf Platte schreiben. */
|
|
w_statistik();
|
|
}
|
|
/* Timer runter zaehlen. */
|
|
h_Timer--;
|
|
}
|
|
|
|
/* Hiermit checken wir ob die rstat.css existiert. */
|
|
/* FALSE = keine rstat.css gefunden */
|
|
/* TRUE = es existiert eine rstat.css */
|
|
static int check_css_file(void)
|
|
{
|
|
char cssfile[255];
|
|
|
|
/* Path kopieren. */
|
|
strcpy(cssfile, htmlpath);
|
|
/* CSS-Dateiname anhaengen. */
|
|
strcat(cssfile, CSS_RFILE);
|
|
|
|
/* Pruefe ob Datei existiert.*/
|
|
if (!access(cssfile,FALSE))
|
|
/* Datei existiert. */
|
|
return(TRUE);
|
|
else
|
|
/* Nix gefunden! */
|
|
return(FALSE);
|
|
}
|
|
|
|
/* Eine default RSTAT.CSS schreiben */
|
|
static void rstat_css_default_file(void)
|
|
{
|
|
FILE *fp;
|
|
char cfgfile[255];
|
|
|
|
if (HtmlStat == FALSE)
|
|
return;
|
|
|
|
strcpy(cfgfile, htmlpath);
|
|
strcat(cfgfile, CSS_RFILE);
|
|
if ((fp = fopen(cfgfile, "w+t")) == NULL)
|
|
return;
|
|
|
|
fprintf(fp,"BODY {\n"
|
|
" BACKGROUND-IMAGE: url('bg.jpg');\n"
|
|
" BACKGROUND-COLOR: #000080;\n"
|
|
" COLOR: #FFFFFF;\n"
|
|
" FONT-FAMILY: Verdana, Arial;\n"
|
|
" FONT-SIZE: 12;\n"
|
|
"}\n");
|
|
|
|
fprintf(fp,"H1 {\n"
|
|
" FONT-SIZE: 18; COLOR: #FFCC00;\n"
|
|
"}\n");
|
|
|
|
fprintf(fp,"H2 {\n"
|
|
" FONT-SIZE: 12; COLOR: #FFFFFF;\n"
|
|
"}\n");
|
|
|
|
fprintf(fp,"a:link, a:visited {\n"
|
|
" COLOR: #FFFFFF;\n"
|
|
" text-weight: bold;\n"
|
|
" text-decoration: none;\n"
|
|
"}\n");
|
|
|
|
fprintf(fp,"a:hover {\n"
|
|
" COLOR: #FF6600;\n"
|
|
" text-weight: bold;\n"
|
|
" text-decoration: none;\n"
|
|
"}\n"
|
|
".info {\n"
|
|
" FONT-SIZE: 12; COLOR: #99CCFF;\n"
|
|
"}\n");
|
|
|
|
fprintf(fp,"table.box {\n"
|
|
" background-color: #ffbb00;\n"
|
|
" backcolor: #220000;\n"
|
|
" backcolorlight: #00ff00;\n"
|
|
" backcolordark: #000000;\n"
|
|
" border-width: 0px;\n"
|
|
" width: 95%%;\n"
|
|
" border-style: outset;\n"
|
|
" border-spacing: 2px;\n"
|
|
" border-padding: 8px;\n"
|
|
"}\n");
|
|
|
|
fprintf(fp,".status {\n"
|
|
" FONT-SIZE: 10; BACKGROUND: #000000; COLOR: #FFCC00; TEXT-ALIGN: center;\n"
|
|
"}\n");
|
|
|
|
fprintf(fp,".off {\n"
|
|
" FONT-SIZE: 10; BACKGROUND: #000000; COLOR: #ffffff;\n"
|
|
"}");
|
|
|
|
fprintf(fp,".offline {\n"
|
|
" FONT-SIZE: 10; BACKGROUND: #9f00FF; COLOR: #ffffff;\n"
|
|
"}");
|
|
|
|
fprintf(fp,".user {\n"
|
|
" FONT-SIZE: 10; BACKGROUND: #E06060; COLOR: #ffffff;\n"
|
|
"}\n");
|
|
|
|
fprintf(fp,".thenet {\n"
|
|
" FONT-SIZE: 10; BACKGROUND: #E00060; COLOR: #ffffff;\n"
|
|
"}\n");
|
|
|
|
fprintf(fp,".inp {\n"
|
|
" FONT-SIZE: 10; BACKGROUND: #0070C0; COLOR: #ffffff;\n"
|
|
"}\n");
|
|
|
|
fprintf(fp,".Flexnet {\n"
|
|
" FONT-SIZE: 10; BACKGROUND: #006060; COLOR: #ffffff;\n"
|
|
"}\n");
|
|
|
|
fprintf(fp,".about {\n"
|
|
" FONT-SIZE: 13; COLOR: #ffffff;\n"
|
|
"}\n");
|
|
|
|
fclose(fp);
|
|
}
|
|
|
|
/* Wie viel Ports sind nich frei ? */
|
|
static int free_ports(void)
|
|
{
|
|
int free = FALSE;
|
|
|
|
return(free = TABLE_SIZE - route_tbl_top);
|
|
}
|
|
|
|
/* Wie viel L2-Links (USER) - sind aktiv ? */
|
|
static int activ_user(void)
|
|
{
|
|
register int a;
|
|
int user = FALSE;
|
|
|
|
/* TB durchgehen */
|
|
for (a = 0; a < route_tbl_top; a++)
|
|
/* nur die als User markiert sind */
|
|
if ( route_tbl[a].protokoll == P_USER
|
|
/* und online sind !!! */
|
|
&& route_tbl[a].online > 0)
|
|
/* Alle USER zaehlen */
|
|
user++;
|
|
|
|
return(user);
|
|
}
|
|
|
|
/* Wie viel L2/L4_links sind aktiv ? */
|
|
static int activ_links(void)
|
|
{
|
|
register int a;
|
|
int links = FALSE;
|
|
|
|
/* TB durchgehen */
|
|
for (a = 0; a < route_tbl_top; a++)
|
|
/* L2/L4-Link online ? */
|
|
if ( route_tbl[a].online > 0
|
|
/* wir zaehlen alle Protokolle, ausser USER */
|
|
&& route_tbl[a].protokoll != 1)
|
|
links++;
|
|
|
|
return(links);
|
|
}
|
|
|
|
/* Die Aktuelle Uhrzeit fuer HTML ausgeben */
|
|
static char *puttim_stat(void)
|
|
{
|
|
struct tm *p;
|
|
static char tim[20];
|
|
time_t timet;
|
|
char *atime = tim;
|
|
|
|
time(&timet);
|
|
|
|
p = localtime(&timet);
|
|
sprintf(tim,"%02i.%02i.%02i %02i:%02i:%02i",
|
|
p->tm_mday, p->tm_mon+1, p->tm_year % 100,
|
|
p->tm_hour, p->tm_min, p->tm_sec);
|
|
|
|
return(atime);
|
|
}
|
|
|
|
static char *set_class(UWORD flag, register int a)
|
|
{
|
|
static char o[8];
|
|
char *protokoll = o;
|
|
|
|
switch(flag)
|
|
{
|
|
case P_OFFLINE :
|
|
if (!route_tbl[a].online)
|
|
strcpy(o, "offline");
|
|
|
|
break;
|
|
|
|
case P_USER :
|
|
if (route_tbl[a].online)
|
|
strcpy(o, "user");
|
|
else
|
|
strcpy(o, "offline");
|
|
break;
|
|
|
|
case P_THENET :
|
|
if (route_tbl[a].online)
|
|
strcpy(o, "thenet");
|
|
else
|
|
strcpy(o, "offline");
|
|
break;
|
|
|
|
case P_INP :
|
|
if (route_tbl[a].online)
|
|
strcpy(o, "inp");
|
|
else
|
|
strcpy(o, "offline");
|
|
|
|
break;
|
|
|
|
case P_FLEXNET :
|
|
if (route_tbl[a].online)
|
|
strcpy(o, "flexnet");
|
|
else
|
|
strcpy(o, "offline");
|
|
|
|
break;
|
|
|
|
default:
|
|
strcpy(o, "unknown");
|
|
break;
|
|
}
|
|
|
|
return(protokoll);
|
|
}
|
|
|
|
static char *set_pname(register int a)
|
|
{
|
|
static char p[8];
|
|
char *protokoll = p;
|
|
|
|
switch(route_tbl[a].protokoll)
|
|
{
|
|
case P_USER :
|
|
strcpy(p, "L2");
|
|
break;
|
|
|
|
case P_THENET :
|
|
strcpy(p, "THENET");
|
|
break;
|
|
|
|
case P_INP :
|
|
strcpy(p, "INP");
|
|
break;
|
|
|
|
case P_FLEXNET :
|
|
strcpy(p, "FLEXNET");
|
|
break;
|
|
|
|
default:
|
|
strcpy(p, "UNKNOWN");
|
|
break;
|
|
}
|
|
|
|
return(protokoll);
|
|
}
|
|
|
|
static void all_route(FILE *fp, UWORD flag, register int a)
|
|
{
|
|
char *pclass = set_class(flag, a);
|
|
char *protokoll = set_pname(a);
|
|
|
|
/* Nummer einer Route. */
|
|
fprintf(fp," <td class=\"%s\"><center>%d</td>\n"
|
|
, pclass, a);
|
|
|
|
/* Rufzeichen. */
|
|
fprintf(fp," <td class=\"%s\">%s</td>\n"
|
|
, pclass
|
|
, call_to_a(&route_tbl[a].callsign[0]));
|
|
|
|
/* IP-Adresse. */
|
|
fprintf(fp," <td class=\"%s\">"
|
|
" <a href=\"http://%s\" target=\"_http\">%s</a></td>\n"
|
|
, pclass
|
|
, route_tbl[a].hostname
|
|
, route_tbl[a].hostname);
|
|
|
|
/* Hostname/IP-Adresse. */
|
|
fprintf(fp," <td class=\"%s\"><center>%s</td>\n"
|
|
, pclass
|
|
, route_tbl[a].hostname);
|
|
|
|
/* UDP-Port */
|
|
fprintf(fp," <td class=\"%s\"><center>%d</td>\n"
|
|
, pclass
|
|
, htons(route_tbl[a].udp_port));
|
|
|
|
/* Loginzeit */
|
|
fprintf(fp," <td class=\"%s\"><center>%s</td>\n"
|
|
, pclass
|
|
, route_tbl[a].timeset);
|
|
|
|
if (route_tbl[a].timeout)
|
|
/* Timeout */
|
|
fprintf(fp," <td class=\"%s\"><center>%d</td>\n"
|
|
, pclass
|
|
, route_tbl[a].timeout);
|
|
else
|
|
/* Statische Route */
|
|
fprintf(fp," <td class=\"%s\"><center>Statisch</td>\n"
|
|
, pclass);
|
|
|
|
/* Protokoll */
|
|
fprintf(fp," <td class=\"%s\"><center>%s</td></tr>\n"
|
|
, pclass
|
|
, protokoll);
|
|
}
|
|
|
|
static void show_route(FILE *fp, UWORD flag, register int a)
|
|
{
|
|
switch(flag)
|
|
{
|
|
case P_OFFLINE :
|
|
if (!route_tbl[a].online)
|
|
fprintf(fp," <tr class=\"offline\">\n");
|
|
|
|
break;
|
|
|
|
case P_USER :
|
|
if ( route_tbl[a].protokoll == flag
|
|
&& route_tbl[a].online)
|
|
fprintf(fp," <tr class=\"user\">\n");
|
|
else
|
|
fprintf(fp," <tr class=\"offline\">\n");
|
|
|
|
break;
|
|
|
|
case P_THENET :
|
|
if ( route_tbl[a].protokoll == flag
|
|
&& route_tbl[a].online)
|
|
fprintf(fp," <tr class=\"thenet\">\n");
|
|
else
|
|
fprintf(fp," <tr class=\"offline\">\n");
|
|
|
|
break;
|
|
|
|
|
|
case P_INP :
|
|
if ( route_tbl[a].protokoll == flag
|
|
&& route_tbl[a].online)
|
|
fprintf(fp," <tr class=\"inp\">\n");
|
|
else
|
|
fprintf(fp," <tr class=\"offline\">\n");
|
|
|
|
break;
|
|
|
|
case P_FLEXNET :
|
|
if ( route_tbl[a].protokoll == flag
|
|
&& route_tbl[a].online)
|
|
fprintf(fp," <tr class=\"flexnet\">\n");
|
|
else
|
|
fprintf(fp," <tr class=\"offline\">\n");
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
if ( route_tbl[a].protokoll == flag
|
|
&& route_tbl[a].online)
|
|
fprintf(fp," <tr class=\"unknow\">\n");
|
|
else
|
|
fprintf(fp," <tr class=\"offline\">\n");
|
|
|
|
break;
|
|
}
|
|
all_route(fp, flag, a);
|
|
}
|
|
|
|
/* Schreibe htmlstatistik auf Platte. */
|
|
void w_statistik(void)
|
|
{
|
|
FILE *fp;
|
|
char cfgfile[255],mycall[10];
|
|
char *atime = puttim_stat();
|
|
register int a;
|
|
char runtime[8 + 1];
|
|
#ifndef CONNECTTIME
|
|
unsigned long upt,
|
|
upd,
|
|
uph;
|
|
#endif /* CONNECTTIME */
|
|
|
|
/* Pruefe, ob htmlstatistik eingeschaltet ist. */
|
|
if (HtmlStat == FALSE)
|
|
/* Ist nicht eingeschaltet, abbruch. */
|
|
return;
|
|
else
|
|
{
|
|
/* Pruefe ob CSS-Datei exisiert. */
|
|
if (!check_css_file())
|
|
/* Nein, dann neuschreiben. */
|
|
rstat_css_default_file();
|
|
|
|
}
|
|
|
|
strcpy(cfgfile,htmlpath );
|
|
strcat(cfgfile, HTML_RFILE);
|
|
if ((fp = fopen(cfgfile,"w+t")) == NULL)
|
|
return;
|
|
|
|
call2str(mycall,myid);
|
|
|
|
#ifndef CONNECTTIME
|
|
upt = sys_time - start_time; /* Uptime in seconds */
|
|
upd = upt / SECONDS_PER_DAY; /* Uptime days */
|
|
upt %= SECONDS_PER_DAY;
|
|
uph = upt / SECONDS_PER_HOUR; /* Uptime hours */
|
|
upt %= SECONDS_PER_HOUR;
|
|
|
|
if (upd > 0)
|
|
sprintf(runtime, "%2lud,%2luh", upd, uph);
|
|
else
|
|
if (uph > 0)
|
|
sprintf(runtime, "%2luh,%2lus", uph, upt);
|
|
else
|
|
if (upt > 0)
|
|
sprintf(runtime, " %2lus", upt);
|
|
else
|
|
sprintf(runtime, " ");
|
|
#else
|
|
sprintf(runtime, "%s", ConnectTime(tic10 / 100));
|
|
#endif /* CONNECTTIME */
|
|
|
|
fprintf(fp,"<html>"
|
|
"<head>\n"
|
|
"<meta http-equiv=\"refresh\" content=\"%d\">\n"
|
|
"<title>AXIPR-Statistik</title>\n"
|
|
"<link rel=stylesheet type=text/css href=rstat.css>\n"
|
|
"</head>\n<body>\n",HTML_INV);
|
|
|
|
fprintf(fp,"<DIV ALIGN=\"CENTER\"><CENTER>\n"
|
|
"<H1><U>%s%s)</U></H1>\n",signon,mycall);
|
|
|
|
fprintf(fp,"<H2>Date/Time: %s Runtime: %s, %d Frei</H2>\n\n",atime, runtime, free_ports());
|
|
fprintf(fp,"<FONT class=\"info\"><B> %d L2/L4-LINKS</b></FONT>\n",activ_links());
|
|
fprintf(fp,"<table class=\"box\" cellspacing=\"2\" cellpadding=\"2\" style=\"border-collapse: collapse\">\n");
|
|
fprintf(fp," <tr class=\"status\">\n"
|
|
" <td class=\"status\">Nr.</td>\n"
|
|
" <td class=\"status\">Rufzeichen</td>\n"
|
|
" <td class=\"status\">IP-Adresse</td>\n"
|
|
" <td class=\"status\">DYNDNS</td>\n"
|
|
" <td class=\"status\">UDP</td>\n"
|
|
" <td class=\"status\">Login</td>\n"
|
|
" <td class=\"status\">Timeout</td>\n"
|
|
" <td class=\"status\">Protokoll</td>\n"
|
|
" </tr>\n");
|
|
|
|
/* TB durchgehen. */
|
|
for (a = 0; a < route_tbl_top; a++)
|
|
{
|
|
/* Nur aktive Routen zeigen. */
|
|
if (route_tbl[a].online == FALSE)
|
|
/* zum naechsten Eintrag. */
|
|
continue;
|
|
|
|
/* Nur INP- oder FLEXNET-Routen bearbeiten */
|
|
if (route_tbl[a].protokoll > P_USER)
|
|
/* und anzeigen. */
|
|
show_route(fp, route_tbl[a].protokoll, a);
|
|
}
|
|
|
|
fprintf(fp,"</table><br><br>\n");
|
|
|
|
fprintf(fp,"<FONT class=\"info\"><B>%d USER</B></FONT>\n",activ_user());
|
|
fprintf(fp,"<table class=\"box\" cellspacing=\"2\" cellpadding=\"2\" style=\"border-collapse: collapse\">\n");
|
|
fprintf(fp," <tr class=\"status\">\n"
|
|
" <td class=\"status\">Nr.</td>\n"
|
|
" <td class=\"status\">Rufzeichen</td>\n"
|
|
" <td class=\"status\">IP-Adresse</td>\n"
|
|
" <td class=\"status\">DYNDNS</td>\n"
|
|
" <td class=\"status\">UDP</td>\n"
|
|
" <td class=\"status\">Login</td>\n"
|
|
" <td class=\"status\">Timeout</td>\n"
|
|
" <td class=\"status\">Protokoll</td>\n"
|
|
" </tr>\n");
|
|
|
|
/* TB durchgehen */
|
|
for (a = 0; a < route_tbl_top; a++)
|
|
{
|
|
/* Nur aktive Routen zeigen. */
|
|
if (route_tbl[a].online == FALSE)
|
|
/* zum naechsten Eintrag. */
|
|
continue;
|
|
|
|
/* Nur USER-Routen bearbeiten */
|
|
if (route_tbl[a].protokoll == P_USER)
|
|
/* und anzeigen. */
|
|
show_route(fp, route_tbl[a].protokoll, a);
|
|
}
|
|
|
|
fprintf(fp,"</table>\n\n");
|
|
fprintf(fp,"<BR><FONT class=\"info\"><B>My UDP-Port: %u</B></FONT>\n",htons(my_udp));
|
|
fprintf(fp,"</body></html>\n");
|
|
fclose(fp);
|
|
}
|
|
|
|
#endif /* AXIPR_HTML */
|
|
#endif /* AXIPR_UDP */
|
|
|
|
#endif
|
|
|
|
/* End of os/win32/ax25ip.c */
|