TheNetNode-CB/src/l7showl3.c

1101 lines
35 KiB
C
Executable File

/************************************************************************/
/* */
/* ***** ***** */
/* ***** ***** */
/* ***** ***** */
/* ***** ***** */
/* *************** *************** */
/* ***************** ***************** */
/* *************** *************** */
/* ***** ***** TheNetNode */
/* ***** ***** Portable */
/* ***** ***** Network */
/* ***** ***** Software */
/* */
/* File src/l7showl3.c (maintained by: ???) */
/* */
/* 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 */
/* */
/************************************************************************/
#include "tnn.h"
static void putnod(NODE *, int, MBHEAD *);
static void show_nodes(const char *, int);
static WORD nodprm(char *, WORD, char *, UWORD *, char *);
static void dump_options(NODE *, MBHEAD *);
static void putquality(MBHEAD *, ULONG, int);
static void putrou(PEER *, MBHEAD *, BOOLEAN);
static void
dump_options(NODE *np, MBHEAD *mbp)
{
MBHEAD *op;
int len,
i;
UBYTE tag;
char buf[256];
if (np->options == NULL)
return;
op = np->options;
rwndmb(op);
putstr("\rINP-Options:", mbp);
while (op->mbpc > op->mbgc)
{
len = getchr(op);
tag = getchr(op);
for (i = 0; i < len - 2; i++)
buf[i] = getchr(op);
buf[i] = NUL;
putprintf(mbp, "\rlen = %d, tag = 0x%02x\r", len, tag);
for (i = 0; i < len - 2; i++)
putprintf(mbp, "%02x%c", buf[i], ((i % 16) == 0) ? CR : ' ');
}
putchr(CR, mbp);
}
/* Rufzeichen eines Node ausgeben, wahlweise Alias und SSID-Bereich */
static void
putnod(NODE *np, int options, MBHEAD *mbp)
{
char id[L2IDLEN];
int i;
cpyid(id, np->id);
if (np->options != NULL)
{
for(i = 0; i < L2CALEN; i++)
id[i] = tolower(id[i]);
}
if (!(options & OPT_SSID_RANGE)) /* Anzeige als Node */
{
if (*np->alias != ' ') /* Alias ist vorhanden, dann */
options |= OPT_ALIAS; /* auch anzeigen */
}
if (options & OPT_ALIAS)
{
putide(np->alias, mbp);
putchr(':', mbp); /* ":" als Trennung zum Rufzeichen */
}
if (options & OPT_SSID_RANGE)
{
putprintf(mbp, "%6.6s %2d-%-2d", id, SSID(np->id), np->ssid_high);
}
else
putid(id, mbp);
}
/*----------------------------------------------------------------------*/
/* NODES */
/* ----------- */
/* clipoi zeigt auf das naechste Zeichen der Komandozeile. */
/* Wenn clicnt == 0 ist diese zu ende. */
/* nodprm() operiert nur auf einer KOPIE von clicnt/clipoi ! */
/*----------------------------------------------------------------------*/
static void
show_nodes(const char *name, /* Name (Nodes,Destinations,Locals) */
int options) /* Optionen fuer die Ausgabe */
{
char newcal[L2IDLEN]; /* neues Call */
char niden[L2CALEN]; /* neuer Alias */
char *cpoisa; /* temp fuer clipoi */
BOOLEAN alles; /* versteckte Nodes auch zeigen */
BOOLEAN plus_quality; /* mit Qualitaet etc. zeigen */
TRILLIAN callok; /* Ergebnis Test auf gueltiges Call */
TRILLIAN isnode; /* Ergebnis Test auf gueltigen Alias */
WORD ccntsa; /* temp fuer clicnt */
MBHEAD *mbp; /* Buffer fuer Meldung an User */
WORD is_mask_or_qual; /* Qualitaet / Wildcards angegeben */
char mask[MAXMASK];
UWORD qual;
char nbrcal[L2IDLEN];
int j;
INDEX index;
int max_peers = netp->max_peers;
unsigned route_quality;
unsigned quality = 0;
PEER *pp;
PEER *bestpp;
NODE *np;
ROUTE *rp;
int width;
int len;
BOOLEAN all_routes;
char buf[40];
char call1[15];
char call2[15];
int maske = OPTIONS_MASK;
if (!ismemr()) /* Nicht genuegend Buffer !!! */
return;
alles = /* default: keine versteckten Nodes */
plus_quality = FALSE; /* default: ohne Qualitaet etc. */
/* Wenn Befehlszeile leer, Qualitaet nicht beruecksichtigen; bei Aufruf */
/* mit Parametern, pruefen, ob Qualitaet / Wildcards angegeben */
is_mask_or_qual = clicnt ? nodprm(clipoi, clicnt, mask, &qual, nbrcal) : 0;
if ((!is_mask_or_qual) && clicnt) /* nur 1 Node gefragt */
{
cpoisa = clipoi; /* Befehlszeile merken */
ccntsa = clicnt;
if (options & OPT_ALIAS)
{
isnode = getide(&clicnt, &clipoi, niden); /* Test auf gueltigen */
/* Alias */
clipoi = cpoisa; /* Befehlszeile zurueck */
clicnt = ccntsa;
}
else
isnode = NO;
callok = getcal(&clicnt, &clipoi, TRUE, newcal); /* Rufzeichen? */
if (callok == YES || isnode != ERRORS) /* einzelner Eintrag gefragt */
{
if ( !(options & OPT_ALIAS)
|| !(isnode)
|| ((index = find_alias(niden)) == NO_INDEX))
{
/* Bei Nodes gibt es nur eine SSID. Nur Flex kann mehrere haben. Darum */
/* erstmal auf genaues Ziel testen. */
/* Wenn das genaue Ziel nicht gefunden wurde, koennen wir noch nach dem */
/* SSID-Bereich ueber Flexnet-Nachbarn suchen */
if (callok == YES)
{
if ((index = find_node_this_ssid(newcal)) == NO_INDEX)
{
/* Da das genaue Ziel nicht gefunden wurde, koennen wir noch nach dem */
/* SSID-Bereich ueber Flexnet-Nachbarn suchen */
if ((index = find_node_ssid_range(newcal)) != NO_INDEX)
{
/* Wir haben einen Flexnet-Weg gefunden - dann duerfen wir nachher auch */
/* nur einen Flexnet-Weg anzeigen */
maske = VC | VC_FAR;
}
}
}
else
index = NO_INDEX;
}
if (index != NO_INDEX)
{
np = netp->nodetab + index;
find_best_qual(index, &bestpp, options & maske);
#ifdef NONODESFIX
if (bestpp == NULL)
{
mbp = putals("No entry for: ");
putid(newcal, mbp);
putstr("\r", mbp);
prompt(mbp);
seteom(mbp);
return;
}
#endif /* NONODESFIX */
mbp = getmbp(); /* Buffer holen fuer Antwort */
putstr("Routes to ", mbp);
if (!(maske & DG)) /* Flex-Ziel ueber SSID-Bereich */
putid(newcal, mbp);
else
{
putnod(np, (options & ~OPT_ALIAS), mbp);
/* bei "n alias" wird kein Call uebergeben */
cpyid(newcal,np->id);
if (np->ipa != 0L)
putprintf(mbp, " (%u.%u.%u.%u/%u)",
(unsigned)(np->ipa >> 24),
(unsigned)((np->ipa >> 16) & 0xff),
(unsigned)((np->ipa >> 8) & 0xff),
(unsigned)(np->ipa & 0xff),
(unsigned)np->bits);
}
putstr("\r---T[ms]----RxT----TxT--LT-Mode-Obc-----"
"RTT-Po-Route------------------------", mbp);
all_routes = (strchr((char *)clipoi, '*') != NULL);
for (pp = netp->peertab, j = 0; /* alle Wege anzeigen */
j < max_peers; j++, pp++)
{
if (!pp->used)
continue;
if (!(pp->options & (options & OPTIONS_MASK)))
continue;
if (!(maske & DG))
if (pp->typ != FLEXNET)
continue;
mbp->l4time = mbp->mbpc;
rp = pp->routes + index;
route_quality = rp->quality;
quality = getquality(route_quality, pp);
if (!quality && !all_routes)
continue;
if (pp->typ == FLEXNET)
putstr(rp->reported_quality ? "\r- " : "\r> ", mbp);
else
putstr(quality ? pp == bestpp ? "\r> " : "\r " : "\r- ", mbp);
putspa(2, mbp);
putprintf(mbp, "%6lu %6lu ",
((ULONG)quality) * 10L,
((ULONG)route_quality) * 10L);
if (rp->reported_quality != DIRTY)
putprintf(mbp, "%6lu ",
((ULONG)rp->reported_quality) * 10L);
else
putstr("UPDATE ", mbp);
putprintf(mbp, "%3u %4s %3u %7lu %2u",
(int)rp->lt,
pp->typ <= NETROM ? "DG" : "VC",
rp->timeout,
((ULONG)pp->quality * 10),
pp->l2link->port);
putspa(48, mbp);
putid(pp->l2link->call, mbp); /* Nachbarcall fuer Weg */
putdil(pp->l2link->digil, mbp); /* Digiweg zum Nachbarn */
}
putchr('\r', mbp); /* Antwort abschliessen */
dump_options(np, mbp);
call2str(call1, myid);
if (quality && bestpp->typ >= LOCAL)
{
putchr('\r', mbp);
putalt(alias, mbp);
putid(myid, mbp);
putprintf(mbp, "> %s <local>\r\r", call1);
}
prompt(mbp);
seteom(mbp); /* Antwort abschicken */
/* Routentest abhaengig vom Typ des besten Weges (LOCAL / LOCAL_M wurde */
/* schon vorher behandelt) */
if (bestpp->typ <= NETROM)
request_nrr(np->id, userpo->uid);
else
if (bestpp->typ == FLEXNET)
{
call2str(call2, newcal); /* das gesuchte Call */
sprintf(buf, "6!%5u%s %s", userpo->uid, call1, call2);
if (clipoi[clicnt-1] == '>')/* Routentest um Laufzeitangabe */
buf[2] = buf[2] | 0x60; /* der Einzellinks erweitert */
flex_route_query(buf);
}
return; /* fertig */
}
else
{
mbp = putals("No entry for: ");
strupr((char *)cpoisa);
putstr((char *)cpoisa, mbp);
putchr('\r', mbp);
prompt(mbp);
seteom(mbp);
return;
}
}
}
/* ========================== Nodestabelle anzeigen =================== */
mbp = putals(name); /* Kopfzeile */
putnum(netp->num_nodes, mbp); /* Zahl Nodeseintraege anzeigen */
putchr('/', mbp); /* Maximalanzahl ausgeben */
putnum(num_nodes_max, mbp);
putstr("):\r", mbp); /* Zeile abschliessen */
width = 0;
if (is_mask_or_qual) /* wenn Wildcards, alle untersuchen */
alles = plus_quality = TRUE;
for (np = (NODE *)netp->nodelis.head;
np != (NODE *)&netp->nodelis;/* sortierte Nodes-Liste durchgehen */
np = np->next)
{
index = (INDEX)(np - netp->nodetab); /* Index berechnen */
if ((np->alias[0] != '#') || (alles == TRUE))
{ /* Eintrag kein #-Node oder alles anzeigen */
quality = find_best_qual(index, &bestpp, options & OPTIONS_MASK);
if (bestpp == NULL)
continue;
rp = bestpp->routes + index;
if (is_mask_or_qual) /* nur eine Auswahl bitte ... */
{
/* wird nach Routes eines bestimmten Nachbarn gesucht? */
if ( (is_mask_or_qual & ISNBRCALL)
&& (!cmpid(bestpp->l2link->call, nbrcal)))
continue;
if (is_mask_or_qual & ISCALLMASK) /* Call mit Wildcards? */
{
/* wenn Call mit Wildcards nicht passt und nicht Alias mit Wildcards */
/* gefragt wurde oder auch nicht passt, naechsten Eintrag testen */
if ( !c6mtch(np->id, mask)
&& ( !(is_mask_or_qual & ISIDENTMASK)
|| !c6mtch(np->alias, mask)))
continue;
}
/* wenn Alias mit Wildcards gefragt, aber nicht passt, naechsten */
/* Eintrag */
else if ( (is_mask_or_qual & ISIDENTMASK)
&& !c6mtch(np->alias, mask))
continue;
if (quality > 0)
{ /* aktiver Weg zum Node? */
/* wenn untere Qualitaetsgrenze angegeben, aber die Qualitaet fuer den */
/* aktiven Weg zu gering ist, naechsten Eintrag testen */
if ( (is_mask_or_qual & ISMINQUAL)
&& (quality < qual))
continue;
/* wenn obere Qualitaetsgrenze angegeben, aber die Qualitaet fuer den */
/* aktiven Weg zu hoch ist, naechsten Eintrag testen */
if ( (is_mask_or_qual & ISMAXQUAL)
&& (quality > qual))
continue;
}
}
else if (quality == 0)
continue;
}
#ifdef LINKSMOD_LOCALMOD
if (CheckLocalLink(np->id) == TRUE) /* Ist ein LOCAL-Link. */
continue; /* Zum naechsten Eintrag. */
#endif /* LINKSMOD_LOCALMOD */
mbp->l4time = mbp->mbpc; /* Zaehler merken fuer putspa() */
putnod(np, options, mbp);
if (options & OPT_SSID_RANGE)
putspa(12, mbp);
else
{
if (options & OPT_ALIAS)
putspa(16, mbp);
else
putspa(9, mbp);
}
if (plus_quality == TRUE) /* Qualitaet etc. auch anzeigen? */
{
if (quality > 0)
{ /* wenn aktiver, diesen anzeigen */
if (quality > 6000) /* mehr als eine Minute? */
putprintf(mbp, " %2umin", quality / 6000);
else
putprintf(mbp, " %5lu", ((ULONG)quality) * 10L);
if (bestpp)
{
putchr('/', mbp);
putprintf(mbp, "%2d ", bestpp->l2link->port);
}
else
putstr(" ", mbp);
}
else /* kein aktiver Weg */
putstr(" -/ - ", mbp);
}
len = (mbp->mbpc - mbp->l4time); /* Laenge eines Eintrages */
width += len;
if (width + len < 79)
{ /* einer passt noch in die Zeile */
len = (79 % len) / (79 / len);
while (len--)
putchr(' ', mbp);
}
else
{
putchr('\r', mbp);
width = 0;
}
}
putchr('\r', mbp); /* Antwort abschliessen */
prompt(mbp);
seteom(mbp); /* und abschicken */
}
/*----------------------------------------------------------------------*/
/* nodprm() - Parameter des erweiterten NODE Befehls auswerten */
/* testet ob p ein Wort mit Wildcard enthaelt, kopiert dieses nach mp */
/* Case-Conversion! Nod*E wird NOD*E */
/* n MUSS > 0 sein */
/*----------------------------------------------------------------------*/
static WORD
nodprm(char *p, /* parameter des node befehls */
WORD n, /* restlaenge der parameterzeile */
char *mp, /* nimmt die maske auf */
UWORD *qp, /* nimmt die quality auf */
char *nc) /* nimmt das nachbarcall auf */
{
WORD i;
WORD ret = ISMINQUAL;
WORD matchok;
WORD c;
if (*p == '-')
{
n--;
p++;
ret = ISMAXQUAL;
}
if ((*qp = (UWORD)(nxtlong(&n, &p) / 10L)) == 0)
{
ret = 0;
}
if (*p == '<')
{
n--;
p++;
if (getcal(&n, &p, TRUE, nc) == YES)
ret |= ISNBRCALL;
}
if (skipsp(&n, &p))
{
matchok = FALSE;
for (i = 0; i < (MAXMASK - 1);)
{
if (!n || ((c = *p++) == ' '))
break;
n--;
if (c == ':')
{
if (i == 0)
{
ret |= ISCALLMASK;
continue;
}
else
{
ret &= ~ISCALLMASK;
ret |= ISIDENTMASK;
break;
}
}
if ((c == MATCHMANY) || (c == MATCHONE))
{
matchok = TRUE;
}
mp[i++] = isascii(c) ? toupper(c) : MATCHONE;
}
mp[i] = MATCHEND;
if (matchok)
{
if (!(ret & (ISCALLMASK | ISIDENTMASK)))
{
ret |= (ISCALLMASK | ISIDENTMASK);
}
}
else
{
ret &= ~(ISCALLMASK | ISIDENTMASK);
}
}
return (ret);
}
/*----------------------------------------------------------------------*/
void
ccpnod(void) /* Nodes ausgeben */
{
#ifndef SHOW_DESTNODES
show_nodes("Nodes (", OPT_ALIAS | OPT_DGTEST | VC | VC_FAR | DG);
#else
show_nodes("Nodes (", OPT_ALIAS | OPT_DGTEST | VC | DG);
#endif /* SHOW_DESTNODES */
}
/*----------------------------------------------------------------------*/
void
ccpdest(void) /* Destinations ausgeben */
{
#ifndef SHOW_DESTNODES
show_nodes("Destinations (", OPT_SSID_RANGE | OPT_VCTEST | VC | VC_FAR | DG);
#else
show_nodes("Destinations (", OPT_SSID_RANGE | OPT_VCTEST | VC | VC_FAR);
#endif /* SHOW_DESTNODES */
}
/* Die Antwort wird hier etwas leserlicher gemacht und an den User */
/* geschickt */
static const char *reason[] =
{"no route", "local", "flexgate", "", "loop"};
void
nrr2usr(NRRLIST *l, char time_to_live)
{
char buffer[512],
*bp,
call[10];
int llt,
lt,
err;
UID uid;
USRBLK *up;
bp = buffer;
llt = l->lt & LT_MASK;
while (*l->id)
{ /* Liste abarbeiten */
*bp++ = ' ';
lt = l->lt & LT_MASK;
while (llt > lt)
{ /* fehlende Digis markieren */
*bp++ = '?';
*bp++ = ' ';
llt--;
}
call2str(call, l->id);
bp += sprintf(bp, "%s", call);
if (l->lt & ECHO_FLAG)
{ /* Echoflag anzeigen */
*bp++ = '*';
err = l->id[L2CALEN] >> 5; /* Fehlercode extrahieren */
if (err < 5 && err != 3) /* und anzeigen */
bp += sprintf(bp, "<%s>", reason[err]);
}
llt--;
l++;
}
*bp++ = ' ';
time_to_live++;
while (llt > time_to_live)
{
*bp++ = '?';
*bp++ = ' ';
llt--;
}
call2str(call, myid);
bp += sprintf(bp, "%s", call);
uid = (l4hdr2 << 8) | l4hdr3; /* User suchen */
if (uid > 0 && uid < NUMPAT)
if ((up = ptctab[uid].ublk) != NULL)
#ifndef SEND_ASYNC_RESFIX
send_async_response(up, "Route (DG):", buffer);
#else
{
/* Sicher ist sicher. */
buffer[256] = 0;
send_async_response(up, "Route (DG):", buffer);
}
#endif /* SEND_ASYNC_RESFIX. */
}
/*
* Qualitaet links oder rechtsbuendig ausgeben
*/
static void putquality(MBHEAD *mbp, ULONG qual, int align)
{
#define QA_LEFT 0
#define QA_RIGHT 1
if (align == QA_LEFT) {
#ifndef ROUTESMOD_L3RTTSHOW
if (qual) putprintf(mbp, "%-6ld ", qual*10L);
#else
if (qual) putprintf(mbp, "%-6ld ", qual/10L);
#endif /* ROUTESMOD_L3RTTSHOW */
else putstr("---- ", mbp);
} else {
#ifndef ROUTESMOD_L3RTTSHOW
if (qual) putprintf(mbp, " %6ld", qual*10L);
#else
if (qual) putprintf(mbp, " %6ld", qual/10L);
#endif /* ROUTESMOD_L3RTTSHOW */
else putstr(" ----", mbp);
}
}
/**************************************************************************/
/* Anzeigen des Routing und der Links */
/*------------------------------------------------------------------------*/
static void putrou(PEER *pp, MBHEAD *mbp, BOOLEAN printver)
{
const char *c_state[] = {" ", "setup ", "conn. ", "active"};
int state;
#define S_UNUSED 0
#define S_SETUP 1
#define S_CONN 2
#define S_ACTIVE 3
int typ = pp->typ;
char *c;
const char *cp;
NODE *np;
PEER *bestpp;
INDEX index;
unsigned int numroutes = 0;
unsigned int qual;
#ifdef LINKSMOD_LOCALMOD
if ( (pp->typ == LOCAL_V) /* Segment ist eine versteckte LOCAL-Route. */
&&(!issyso())) /* Kein Sysop. */
return; /* Eintrag geheim halten. */
#endif /* LINKSMOD_LOCALMOD */
mbp->l4time = mbp->mbpc;
putid(pp->l2link->call, mbp); /* Node Call ausgeben */
if (pp->primary != pp)
putchr('*', mbp);
putspa(10, mbp); /* Qua-Po-Dst Werte ausgeben */
for (np = (NODE *)netp->nodelis.head;
np != (NODE *)&netp->nodelis;/* sortierte Nodes-Liste durchgehen */
np = np->next)
{
if (np->id[0]) /* nur benutzte Eintraege interessieren */
{
index = (INDEX)(np - netp->nodetab); /* Index berechnen */
qual = find_best_qual(index, &bestpp, OPTIONS_MASK); /* suche besten Weg */
if ((bestpp == NULL) || (qual == 0)) /* geloeschte Nodes abfangen */
continue;
if (cmpid(bestpp->l2link->call, pp->l2link->call)) /* Callvergleich */
++numroutes;
}
}
/* TEST DG9OBU */
/* SSID bzw. SSID-Bereich ausgeben */
if (pp->typ == FLEXNET)
{
putprintf(mbp, "%2d-%-2d", SSID(pp->l2link->call), pp->l2link->ssid_high);
}
else
{
putspa(11, mbp);
putprintf(mbp, "%2d", SSID(pp->l2link->call));
}
putspa(17, mbp);
putprintf(mbp, "%2.2s %2d %4d/%-4d", typtbl + pp->typ*2,
pp->l2link->port,
pp->num_routes,
numroutes);
if (pp->nbrl2l != NULL) {
if (pp->nbrl2l->state < L2SIXFER)
state = S_SETUP; /* setup */
else
state = S_CONN; /* connected */
} else {
if (pp->typ == LOCAL_M) {
if (pp->quality > 0)
state = S_ACTIVE; /* active */
else
state = S_UNUSED; /* unused */
} else
state = S_UNUSED; /* nicht connected */
}
#ifndef LINKSMOD_LOCALMOD
if (typ != LOCAL)
#else
if (typ < LOCAL)
#endif /* LINKSMOD_LOCALMOD */
{
if (typ == THENET && pp->quality != 0)
putprintf(mbp," Qual:%d",pp->quality);
else {
putquality(mbp, pp->my_quality, QA_RIGHT);
putchr('/', mbp);
if (pp->my_quality)
putquality(mbp, pp->his_quality, QA_LEFT);
else
putquality(mbp, 0, QA_LEFT);
}
}
putspa(40, mbp);
if (typ == INP || typ == FLEXNET)
putprintf(mbp, "%8lu ", (ULONG)pp->maxtime * 10L);
else
putstr(" ", mbp);
putspa(52,mbp);
putstr(c_state[state], mbp);
putchr(' ', mbp);
if (typ == LOCAL)
putstr(" ", mbp);
if (!printver) {
if (*(c = pp->l2link->digil))
{
while (*c)
{
putid(c, mbp);
putchr(' ', mbp);
c += L2IDLEN;
}
}
}
else
{
switch (pp->typ)
{
case NETROM :
cp = "NET/ROM (UI)";
break;
case THENET :
cp = "THENET (UI)";
break;
case TNN :
putprintf(mbp, "TNN V%d.%d (I) ", (pp->version/100),
(pp->version%100));
cp = "";
break;
case INP :
cp = "INP Node";
break;
case FLEXNET :
switch (pp->version & 0x07)
{
case 0 : cp = "FlexNet"; break;
case 1 : cp = "BayCom"; break;
case 2 : cp = "Digiware"; break;
case 3 : cp = "TheNetNode"; break;
case 4 : cp = "SNet"; break;
case 5 : cp = "(X)Net"; break;
default: cp = "unknown"; return;
}
putspa(58,mbp);
putstr(cp, mbp);
if (pp->version)
putprintf (mbp, " V%d.%d", ((pp->version>>8) / 10),
((pp->version>>8) % 10));
default :
cp = "";
break;
}
putspa(65,mbp);
putstr(cp, mbp);
}
#ifdef CONNECTTIME
if (!printver) /* Nur wenn keine erweiterte Ausgabe */
{ /* Connectzeit ausgeben. */
putspa(72, mbp);
putprintf(mbp, "%s", ConnectTime(pp->contime));
}
#endif /* CONNECTTIME */
putchr('\r', mbp);
}
#ifdef ROUTESMODVIANODES
/**************************************************************************/
/* */
/* Segment suchen und bereitstellen. */
/* */
/**************************************************************************/
static PEER *isSegment(const char *call)
{
PEER *pp;
int max_peers = netp->max_peers;
int i;
if (call[0] == FALSE)
return(NULL);
/* durchsuche alle Segmente. */
for (i = 0, pp = netp->peertab; i < max_peers; i++, pp++)
{
/* Nur benutzte Eintraege. */
if ( (pp->used)
/* Callvergleich (SSID beachten). */
&&(cmpid(call, pp->l2link->call)))
/* Segment gefunden. */
return(pp);
}
/* Kein Eintrag gefunden. */
return(NULL);
}
/**************************************************************************/
/* */
/* Ausgabe vorbereiten. */
/* */
/**************************************************************************/
static MBHEAD *RoutesMBP(void)
{
MBHEAD *mbp;
mbp = getmbp(); /* frischen Puffer besorgen */
putstr("Routes of ", mbp); /* Konfiguration zeigen */
putalt(alias, mbp);
putid(myid, mbp);
putprintf(mbp, " (%d/%d)\r", netp->num_peers, netp->max_peers);
#ifndef CONNECTTIME
putstr("Node------SSID--Typ-Po--Dst/Rou---L3SRTT[ms]---MaxT[ms]-State--Route-\r", mbp);
#else
putstr("Node------SSID--Typ-Po--Dst/Rou---L3SRTT[ms]---MaxT[ms]-State--Route----Contime\r", mbp);
#endif /* CONNECTTIME */
return(mbp);
}
/**************************************************************************/
/* */
/* ROUTES COMMAND mit Erweiterung. */
/* Ein Routes-Eintrag ausgeben und dazu alle Noden */
/* die ueber diesen Routes-Eintrag geroutet werden. */
/* */
/* THENETMOD */
/* Qualitaet einer Route (nur THENET-Typ) setzen/aendern. */
/**************************************************************************/
void putnodes(PEER *pp, MBHEAD *mbp)
{
PEER *bestpp;
NODE *np;
INDEX index;
char call[10];
int len;
int width = 0;
unsigned int numroutes = 0;
unsigned int qual;
call2str(call, pp->l2link->call);
#ifdef SPEECH
putprintf(mbp,speech_message(273), call);
#else
putprintf(mbp, "\rAll Nodes over %s to be geroutet to show:\r", call);
#endif
for (np = (NODE *)netp->nodelis.head;
np != (NODE *)&netp->nodelis;/* sortierte Nodes-Liste durchgehen */
np = np->next)
{
if (np->id[0]) /* nur benutzte Eintraege interessieren */
{
index = (INDEX)(np - netp->nodetab); /* Index berechnen */
qual = find_best_qual(index, &bestpp, OPTIONS_MASK); /* suche besten Weg */
if ((bestpp == NULL) || (qual == 0)) /* geloeschte Nodes abfangen */
continue;
if (cmpid(bestpp->l2link->call, pp->l2link->call)) /* Callvergleich */
{
++numroutes;
/* Rufzeichen ausgeben. */
putid(np->id,mbp);
/* Konvertiere Rufzeichen. */
call2str(call, np->id);
/* Laenge eines Eintrages. */
len = strlen(call) + 16;
width += len;
if (width + len < 169)
{
/* einer passt noch in die Zeile */
len = (79 % len) / (79 / len);
while (len--)
putchr(' ', mbp);
}
else
{
putchr('\r', mbp);
width = 0;
}
}
}
}
putchr('\r', mbp);
}
/**************************************************************************/
/* */
/* ROUTES COMMAND mit Erweiterung. */
/* Ein Routes-Eintrag ausgeben und dazu alle Noden */
/* die ueber diesen Routes-Eintrag geroutet werden. */
/* */
/* THENETMOD */
/* Qualitaet einer Route (nur THENET-Typ) setzen/aendern. */
/**************************************************************************/
static void RoutesViaNodes(void)
{
MBHEAD *mbp = NULL;
char call[L2IDLEN];
skipsp(&clicnt,&clipoi); /* evl. Leerzeichen entfernen. */
/* Pruefe Rufzeichen. */
if ((getcal(&clicnt, &clipoi, TRUE, call)) == YES)
{
PEER *pp;
/* Aktueller Linkblock ist ein Segment. */
if ((pp = isSegment(call)) != NULL)
{
#ifdef THENETMOD
if (pp->typ == THENET) /* L4QUALI, Aenderungen nur am Typ THENET. */
{
if (RoutesL4Para(mbp, pp))
return;
}
#endif /* THENETMOD */
mbp = RoutesMBP();
putrou(pp, mbp, FALSE);
putnodes(pp, mbp);
prompt(mbp);
seteom(mbp);
}
else
/* Es gibt kein Segment mit den angegeben Rufzeichen. */
{
mbp = RoutesMBP();
#ifdef SPEECH
putstr(speech_message(276),mbp);
#else
putstr("Call does not stand in the links List!\r",mbp);
#endif
prompt(mbp);
seteom(mbp);
return;
}
}
else
/* Ungueltiges Rufzeichen . */
{
mbp = RoutesMBP();
#ifdef SPEECH
putstr(speech_message(196),mbp);
#else
putstr("Invalid Call!\r",mbp);
#endif
prompt(mbp);
seteom(mbp);
return;
}
}
#endif /* ROUTESMODVIANODES */
/*------------------------------------------------------------------------*/
/* ROUTES COMMAND Ausgabe einer formatierten Routes-Liste an User. */
/* Eingabe von Routes durch SYSOP. */
/*------------------------------------------------------------------------*/
void ccprou(void)
{
MBHEAD *mbp;
BOOLEAN printver = FALSE;
PEER *i_pp, *j_pp;
int i, j;
int flag[MAX_PEERS];
const int max_peers = netp->max_peers;
memset(flag, 0, sizeof(flag));
if (clicnt != 0)
{
if ( *clipoi == '*'
|| *clipoi == '+')
printver = TRUE; /* Version mit ausgeben */
#ifdef ROUTESMODVIANODES
else
{
RoutesViaNodes();
return;
}
#endif /* ROUTESMODVIANODES */
}
mbp = getmbp(); /* frischen Puffer besorgen */
putstr("Routes of ", mbp); /* Konfiguration zeigen */
putalt(alias, mbp);
putid(myid, mbp);
putprintf(mbp, " (%d/%d)\r", netp->num_peers, netp->max_peers);
putstr("Node------SSID--Typ-Po--Dst/Rou---L3SRTT[ms]---MaxT[ms]-State--", mbp);
#ifdef CONNECTTIME
putstr(printver ? "Software/Version\r"
: "Route----Contime\r", mbp);
#else
putstr(printver ? "Software/Version\r"
: "Route-----------\r", mbp);
#endif /* CONNECTTIME */
for (i = 0, i_pp = netp->peertab; i < max_peers; ++i, ++i_pp)
if (i_pp->used)
if (i_pp->primary == i_pp)
{
putrou(i_pp, mbp, printver);
for (j = 0, j_pp = netp->peertab; j < max_peers; ++j, ++j_pp)
if (j_pp->used)
if (j_pp->primary == i_pp && j_pp != i_pp)
putrou(j_pp, mbp, printver);
}
prompt(mbp);
seteom(mbp);
}
/* End of src/l7showl3.c */