// --------------------------------------------------------------------
// N o d e l i s t . c p p
//
// Fido messages tracker
// Nodelist.
// --------------------------------------------------------------------
// Copyright (c) 1998-2001 by Fyodor Ustinov
// FIDONet 2:5020/79
//
// All rights reserved.
// --------------------------------------------------------------------
#ifndef __GNUC__
#include <io.h>
#include <direct.h>
#else
#include <unistd.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "constant.hpp"
#include "vars.hpp"
#include "configure.hpp"
#include "log.hpp"
#include "nodelist.hpp"
#include "age.hpp"
#include "utils.hpp"
char *NodelistPath;
static int NodelistTurnOff = FALSE;
static int NodelistLineNum = 0;
static char mErrReadIndex[] = "Error reading index file.";
static char mNdlChanged[] = "Some nodelists is changed. Recompile need.";
static char mIndNFound[] = "Index file not found. Create new index file.";
static char mErrNdlMustFull[] = "Error: You must define default Zone for Regional and Network verisons of nodelist.";
static char mErrNdlFormat[] = "Incorrect nodelist format.";
#define ErrReadIndex Log.Level(LOGE) << mErrReadIndex << EOL
#define IndexChanged Log.Level(LOGI) << mNdlChanged << EOL
#define IndexNotFound Log.Level(LOGI) << mIndNFound << EOL
typedef struct _Ntr {
dword Number;
dword Attrib;
struct _Ntr *Next;
struct _Ntr *Sub;
} Ntr;
void ErrNdlFormat(char *m) {
Log.Level(LOGE) << "Error in line " << NodelistLineNum << ", " << mErrNdlFormat << EOL;
Log.Level(LOGE) << m << EOL;
}
int FindNodelist(char *Mask, char *Name) {
int maxext;
DIR *dd;
struct dirent *ff;
char NDir[512], Path[512], Fname[512];
char *tmt = NULL;
FILE *ft;
*Name = '\0';
Path[1] = '\0';
maxext = (-1);
GetFilePath(Path,Mask);
if (NodelistPath != NULL && *Path != PATHDELIMC
#ifndef UNIX
&& Path[1] != ':'
#endif
) {
strcpy(NDir,NodelistPath);
strcat(NDir,Path);
strcpy(Path,NDir);
}
GetFileName(Fname,Mask);
if (strchr(Fname,'*') || strchr(Fname,'?')) {
if ((dd = opendir(dirslashbug(Path))) != 0) {
while((ff = readdir(dd)) != NULL) {
if (fsCompareName(ff->d_name,Fname) != 0 && (tmt = strrchr(ff->d_name,'.')) != NULL) {
tmt++;
if (StrIsNum(tmt) && atoi(tmt) > maxext) {
maxext = atoi(tmt);
strcpy(Name,Path);
strcat(Name,ff->d_name);
}
}
}
closedir(dd);
} else {
yyerror("Nodelist not found.");
return (-1);
}
} else {
strcpy(Name,Path);
strcat(Name,Fname);
}
if (*Name == '\0') {
yyerror("Nodelist not found.");
return (-1);
}
if ((ft = fopen(Name,"rt")) == NULL) {
yyerror("Unable to open Nodelist.");
return (-1);
} else {
fclose (ft);
}
return (0);
}
// ------------------- Compile and writing one nodelist --------------------
static FILE *nh;
static int CurrentNet = -1;
static int CurrentZone = -1;
static Ntr **CurrentHub = NULL;
static Ntr *_pNodeList = NULL;
static int PointListMode = FALSE;
static Ntr *BossNode = NULL;
int OpenNodelist(char *FName) {
nh = fopen(FName,"rt");
if (nh == NULL) {
Log.Level(LOGE) << "Unable to open nodelist '" << FName << "'" << EOL;
return FALSE;
}
return TRUE;
}
int CloseNodelist(void) {
return (fclose (nh) == 0);
}
int ReadNdlLine (char *Buff, int Count) {
char *tmt;
Buff[0] = ';';
while (Buff[0] == ';') {
NodelistLineNum++;
if (fgets(Buff, Count, nh) == NULL) {
Buff[0] = '\0';
return (-1);
}
tmt = strchr(Buff,'\n');
if (tmt != NULL) *tmt = '\0';
tmt = strchr(Buff,'\r');
if (tmt != NULL) *tmt = '\0';
tmt = strchr(Buff,(char)0x1a);
if (tmt != NULL) *tmt = '\0';
if (strlen(Buff) == 0) {
Buff[0] = ';';
}
}
return(strlen(Buff));
}
Ntr *ExistByNumber(Ntr *Addr, unsigned int Number) {
Ntr *tmt;
tmt = Addr;
while (tmt != NULL) {
if ((tmt->Number & 0xffff) == (Number & 0xffff)) {
return tmt;
}
tmt = tmt->Next;
}
return NULL;
}
Ntr *GetCurrentZone(void) {
return(ExistByNumber(_pNodeList,CurrentZone));
}
Ntr *GetCurrentNet(void) {
Ntr *tmt;
if ((tmt = GetCurrentZone()) != NULL) {
if (tmt->Sub != NULL) {
return (ExistByNumber(tmt->Sub,CurrentNet));
} else {
return NULL;
}
} else {
return NULL;
}
}
int DelDupNode(unsigned int Node) {
// Удаляем ноду из списка, если она там уже есть. Но! При этом проверяем,
// а не в виде-ли хаба она есть? Если в виде хаба, то не удаляем. А если при
// этом выясняется, что она и сейчас хаб - то устанавливаем указатель
// текущего хаба на это место.
// Return TRUE - успешно удалили, или этой ноды вообще небыло в списке
// FALSE - нода была в списке в виде хаба, да и сейчас - хаб.
Ntr *tr;
tr = GetCurrentNet();
assert(tr != NULL);
tr = tr->Sub;
while (tr != NULL) {
if ((tr->Number & 0xffff) == (Node & 0xffff)) {
if ((tr->Number & A_MASK) != A_HUB) {
tr->Number = (unsigned int)-1;
return TRUE;
} else if (((tr->Number & A_MASK) == A_HUB) && ((Node & A_MASK) == A_HUB)) {
// Log.Level(LOGD) << "Two nodes? " << tr->Number << " " << Node << EOL;
// Log.Level(LOGD) << "Net: " << CurrentZone << ":" << CurrentNet << EOL;
CurrentHub = &(tr->Next);
return FALSE;
}
}
tr = tr->Next;
}
return TRUE;
}
void AddElemToList(Ntr **Addr, unsigned int Number) {
Ntr *tmt;
tmt = (Ntr *) malloc(sizeof(Ntr));
CheckMem((char *)tmt);
memset(tmt,0,sizeof(Ntr));
tmt->Number = Number;
while ((*Addr) != 0) {
Addr = &((*Addr)->Next);
}
*Addr = tmt;
}
void AddNetToList(void) {
Ntr *tr;
tr = GetCurrentZone();
assert(tr != NULL);
AddElemToList(&(tr->Sub),CurrentNet);
}
void AddZoneToList(void) {
AddElemToList(&_pNodeList,CurrentZone);
AddNetToList();
}
void _SetCurrentZone(unsigned int Zone) {
CurrentZone = Zone;
CurrentNet = Zone;
CurrentHub = NULL;
if (GetCurrentZone() == 0) {
AddZoneToList();
}
}
void _AddNode(unsigned int Node) {
// Добавляем ноду в список. Если ее там еще небыло -
// то просто тупо приписываем в начало списка CurrentHub. Но если он не
// установлен, то добавляем в список как обычно.
// Если была, то нифига не делаем, за нас уже все сделали в DelDupNode.
Ntr *tr, *tmt;
if (DelDupNode(Node) == TRUE) {
if (CurrentHub != NULL) {
tmt = (Ntr *) malloc(sizeof(Ntr));
CheckMem((char *)tmt);
memset(tmt,0,sizeof(Ntr));
tmt->Number = Node;
tr = (*CurrentHub)->Next;
(*CurrentHub)->Next = tmt;
tmt->Next = tr;
} else {
tr = GetCurrentNet();
assert(tr != NULL);
AddElemToList(&(tr->Sub),Node);
}
}
}
void _SetCurrentNet(unsigned int Net) {
CurrentNet = Net;
CurrentHub = NULL;
if (GetCurrentNet() == NULL) {
AddNetToList();
}
}
int _SetCurrentBoss(char *tmt) {
FA f;
Ntr *tp;
BossNode = NULL;
f.Parse(tmt);
if (f.Masked()) return FALSE;
if ((f.Point() & 0xffff) != 0) return FALSE;
tp = ExistByNumber(_pNodeList,f.Zone());
if (tp == NULL) return TRUE;
if (tp->Sub == NULL) return TRUE;
tp = ExistByNumber(tp->Sub,f.Net());
if (tp == NULL) return TRUE;
if (tp->Sub == NULL) return TRUE;
tp = ExistByNumber(tp->Sub,f.Node());
if (tp == NULL) return TRUE;
BossNode = tp;
return TRUE;
}
void _AddPoint(int pnt) {
if (BossNode != NULL) {
AddElemToList(&(BossNode->Sub),pnt);
}
}
int ParseNodeLine(char *tmt) {
unsigned int tmp;
// DumpNdl();
// fprintf(stderr,"%s\n",tmt);
// printf("'%s'\n",tmt);
switch(*tmt) {
case 'B': // Boss record. Pointlist?
case 'b':
PointListMode = TRUE;
if (_SetCurrentBoss(tmt+5) != TRUE) {
ErrNdlFormat("Bad BOSS record");
return FALSE;
}
break;
case 'Z': // Zone record
PointListMode = FALSE;
_SetCurrentZone(atoi(tmt+5));
break;
case 'R': // Region record
PointListMode = FALSE;
if (CurrentZone == 0) {
Log.Level(LOGE) << mErrNdlMustFull << EOL;
return FALSE;
}
tmp = atoi(tmt+7);
tmp |= A_REGION;
_SetCurrentNet(tmp); // Region is a strange type of net.
break;
case 'H': // Host, Hub, or Hold record
switch(*(tmt+2)) {
case 's': // Host
PointListMode = FALSE;
if (CurrentZone == 0) {
Log.Level(LOGE) << mErrNdlMustFull << EOL;
return FALSE;
}
_SetCurrentNet(atoi(tmt+5));
break;
case 'b': // Hub
if (PointListMode == TRUE) {
ErrNdlFormat("HUB record in pointlist!");
return FALSE;
}
if (CurrentZone == 0) {
ErrNdlFormat("HUB record without Zone record!");
return FALSE;
}
tmp = atoi(tmt+4);
tmp |= A_HUB;
_AddNode(tmp);
break;
case 'l': // Hold
if (PointListMode == TRUE) {
ErrNdlFormat("Node or point with HOLD flag!");
return FALSE;
}
if (CurrentZone == 0) {
ErrNdlFormat("HOLD record without Zone record!");
return FALSE;
}
tmp = atoi(tmt+5);
tmp |= A_HOLD;
_AddNode(tmp);
break;
default:
ErrNdlFormat("Unknown format!");
return FALSE;
}
break;
case ',': // Simple node
if (PointListMode == TRUE) {
_AddPoint(atoi(tmt+1));
} else {
if (CurrentZone == 0) {
ErrNdlFormat("Node record without HOST!");
return FALSE;
}
_AddNode(atoi(tmt+1));
}
break;
case 'D': // Down
if (PointListMode == TRUE) {
ErrNdlFormat("DOWN record in pointlist!");
return FALSE;
}
if (CurrentZone == 0) {
ErrNdlFormat("Node record without HOST!");
return FALSE;
}
tmp = atoi(tmt+5);
tmp |= A_DOWN;
_AddNode(tmp);
break;
case 'P': // Pvt or Point
case 'p':
switch(*(tmt+1)) {
case 'v': // Pvt
if (PointListMode == TRUE) {
ErrNdlFormat("PVT record in pointlist!");
return FALSE;
}
if (CurrentZone == 0) {
ErrNdlFormat("Node record without HOST!");
return FALSE;
}
tmp = atoi(tmt+4);
tmp |= A_PVT;
_AddNode(tmp);
break;
case 'o': // Point
if (PointListMode == FALSE) {
ErrNdlFormat("POINT record not in pointlist!");
return FALSE;
}
tmp = atoi(tmt+6);
_AddPoint(tmp);
break;
default:
ErrNdlFormat("Unknown format!");
return FALSE;
}
break;
default: // No one? Hmm...
ErrNdlFormat("Unknown format!");
return FALSE;
}
return TRUE;
}
int ParseOneNodelist (NodeListElem *Elem) {
char Buff[512];
Log.Level(LOGI) << "Compile nodelist '" << Elem->Name << "'..." << EOL;
if (Elem->StartZone != 0) {
_SetCurrentZone(Elem->StartZone);
} else {
CurrentZone = 0;
}
CurrentNet = 0;
if (!OpenNodelist(Elem->Name)) {
return FALSE;
}
NodelistLineNum = 0;
while(ReadNdlLine(Buff,510) > 0) {
if (!ParseNodeLine(Buff)) {
CloseNodelist();
return FALSE;
}
}
CloseNodelist();
Log.Level(LOGI) << "Done" << EOL;
return TRUE;
}
// ------------------------------------------------------
// Flush compiled nodelist to disk
// ------------------------------------------------------
#if 0
void PrintNtr(Ntr *tmt, char *Buff) {
int len;
Ntr *tmt2;
len = strlen(Buff);
tmt2= tmt;
while (tmt != NULL) {
sprintf(Buff+len,"%d ",tmt->Number & 0xffff);
PrintNtr(tmt->Sub,Buff);
tmt = tmt->Next;
}
if (tmt2 == NULL) printf("%s\n",Buff);
}
#endif
int ElementsInList (Ntr *Addr) {
Ntr *tmt;
int Elems;
tmt = Addr;
Elems = 0;
while (tmt != NULL) {
if (tmt->Number != (unsigned int)-1) {
Elems++;
}
tmt = tmt->Next;
}
return Elems;
}
int SaveElements(FILE *fh, Ntr *Addr) {
Ntr *tmt;
tmt = Addr;
while (tmt != NULL) {
if (tmt->Number != (unsigned int)-1) {
if (fwrite(&tmt->Number,sizeof(int),1,fh) != 1) {
Log.Level(LOGE) << "Unable to write body of Elems" << EOL;
return FALSE;
}
}
tmt = tmt->Next;
}
return TRUE;
}
int FlushElements(FILE *fh, Ntr *tmt) {
int Elems;
Elems = ElementsInList(tmt);
if (fwrite(&Elems,sizeof(Elems),1,fh) != 1) {
Log.Level(LOGE) << "Unable to write Elems" << EOL;
return FALSE;
}
if (!SaveElements(fh,tmt)) return FALSE;
return TRUE;
}
int FlushSubElements(FILE *fh, Ntr *tmt) {
if (FlushElements(fh,tmt) == FALSE) return FALSE;
while (tmt != NULL) {
if (tmt->Number != (unsigned int)-1) {
if (FlushSubElements(fh,tmt->Sub) == FALSE) return FALSE;
}
tmt = tmt->Next;
}
return TRUE;
}
int FlushElementsTree(FILE *fh) {
return (FlushSubElements(fh, _pNodeList));
}
// ------------------------------------------------------
// Free parser memory
// ------------------------------------------------------
void FreeSubElements(Ntr *tmt) {
Ntr *tmt2;
if (tmt == NULL) return;
while (tmt != NULL) {
FreeSubElements(tmt->Sub);
tmt2 = tmt->Next;
free(tmt);
tmt = tmt2;
}
}
void FreeParserMem(void) {
FreeSubElements(_pNodeList);
_pNodeList = NULL;
}
// ------------------------------------------------------
int FlushNodelist (FILE *fh) {
#if 0
char Buff[1024];
PrintNtr(_pNodeList,Buff);
#endif
if (FlushElementsTree(fh) == FALSE) return FALSE;
FreeParserMem();
return TRUE;
}
// ------------------------- class NodeLists -----------------------
NodeLists::NodeLists() {
NList = NULL;
Lists = 0;
StartZone = 0;
IndexName = strdup(DefaultIndex);
}
NodeLists::~NodeLists() {
if (NList != NULL) {
free(NList);
NList= NULL;
}
Lists = 0;
if (IndexName != NULL) {
free(IndexName);
IndexName = NULL;
}
}
#if 0
void PrintNch(Nch *tmt, char *Buff) {
int i;
int len;
len = strlen(Buff);
i = 0;
while (tmt[i].Number != -1) {
sprintf(Buff+len,"%d ",tmt[i].Number & 0xffff);
PrintNch(tmt[i].Sub,Buff);
i++;
}
if (tmt[0].Number == -1) printf("%s\n",Buff);
}
#endif
void NodeLists::Print(void) {
#if 0
int tmc;
char Buff[1024];
NodeListElem *tmt;
printf("Index file: '%s'\n",IndexName);
printf("Total nodelists: '%d'\n",Lists);
tmt = NList;
tmc = Lists;
while (tmc != 0) {
printf("Nodelist name: '%s'\n",tmt->Name);
printf("Nodelist Date: '%d'\n",tmt->Time);
tmc--;
tmt++;
}
Buff[0] = '\0';
PrintNch(Index,Buff);
#endif
}
void NodeLists::IndexFile(char *File) {
if (IndexName != NULL) {
free(IndexName);
IndexName = NULL;
}
IndexName = strdup(File);
}
int NodeLists::CompileNeed(void) {
FILE *fh;
unsigned int tmp;
NodeListElem Elem;
// 1 - index file exist?
if (access(IndexName,F_OK) != 0) {
IndexNotFound;
return TRUE;
}
// 2 - We can open him?
fh = fopen(IndexName,"r+b");
if (fh == NULL) {
Log.Level(LOGE) << "Unable to open index file." << EOL;
return TRUE;
}
// 3 - We can read signature from him?
if (fread(&tmp,sizeof(tmp),1,fh) != 1) {
ErrReadIndex;
fclose(fh);
return TRUE;
}
// 4 - Signature is correct?
if (tmp != NdlSign) {
Log.Level(LOGE) << "Index file from old version of FTrack. Recompile need." << EOL;
fclose(fh);
return TRUE;
}
// 5 - We can read nodelist count?
if (fread(&tmp,sizeof(tmp),1,fh) != 1) {
ErrReadIndex;
fclose(fh);
return TRUE;
}
// 6 - count of nodelists the same?
if (tmp != (unsigned int) Lists) {
IndexChanged;
fclose(fh);
return TRUE;
}
// 7 - Node lists is no changed?
for (unsigned int i = 0; i < tmp; i++) {
if (fread(&Elem,sizeof(Elem),1,fh) != 1) {
ErrReadIndex;
fclose(fh);
return TRUE;
}
if ((MaxNodelistAge != (time_t)-1) && (NodelistTurnOff != TRUE)) {
if ((time(NULL) - (NList+i)->Time) > MaxNodelistAge) {
Log.Level(LOGI) << "Nodelist '" << (NList+i)->Name << "' too old." << EOL;
Log.Level(LOGI) << "Checking existance in nodelists turned off." << EOL;
NodelistTurnOff = TRUE;
Log.Level(LOGD) << "Time : " << (int) (time(NULL)) << EOL;
Log.Level(LOGD) << "NTime : " << (int) (NList+i)->Time << EOL;
Log.Level(LOGD) << "Age : " << (int) (time(NULL) - (NList+i)->Time) << EOL;
Log.Level(LOGD) << "MaxAge: " << (int) MaxNodelistAge << EOL;
}
}
if (memcmp(&Elem,NList+i,sizeof(Elem)) != 0) {
Log.Level(LOGD) << "NodeLists::CompileNeed. memcmp failed. Nodelist changed." << EOL;
Log.Level(LOGD) << "--Information should be:" << EOL;
Log.Level(LOGD) << "NName : " << (NList+i)->Name << EOL;
Log.Level(LOGD) << "NTime : " << (int) (NList+i)->Time << EOL;
Log.Level(LOGD) << "Zone : " << (int) (NList+i)->StartZone << EOL;
Log.Level(LOGD) << "--Information in index file:" << EOL;
Log.Level(LOGD) << "NName : " << Elem.Name << EOL;
Log.Level(LOGD) << "NTime : " << Elem.Time << EOL;
Log.Level(LOGD) << "Zone : " << Elem.StartZone << EOL;
IndexChanged;
fclose(fh);
return TRUE;
}
}
fclose (fh);
return FALSE;
}
char *NodeLists::Names(char *Buff) {
NodeListElem *Elem;
int i;
char *tmt;
Buff[0] = '\0';
for (Elem = NList, i=0; i < Lists; Elem++, i++) {
tmt = strrchr(Elem->Name,PATHDELIMC);
if (tmt != NULL) {
tmt++;
} else {
tmt = Elem->Name;
}
strcat(Buff,tmt);
if (i+1 < Lists) strcat(Buff,", ");
}
return Buff;
}
int NodeLists::Compile(void) {
FILE *fh;
char *tmt;
int tmp;
int i;
// 1 - Write new _empty_ header.
fh = fopen(IndexName,"wb");
if (fh == NULL) {
Log.Level(LOGE) << "Unable to create index file." << EOL;
return FALSE;
}
tmt = (char *) malloc(sizeof(NdlSign) + sizeof(int) + sizeof(NodeListElem)*Lists);
CheckMem(tmt);
memset(tmt,'\0',sizeof(NdlSign) + sizeof(int) + sizeof(NodeListElem)*Lists);
if (fwrite(tmt,sizeof(NdlSign) + sizeof(int) + sizeof(NodeListElem)*Lists,1,fh) != 1) {
Log.Level(LOGE) << "Unable to write temporary header to index file." << EOL;
fclose(fh);
free(tmt);
return FALSE;
}
free(tmt);
// 2 - Write compiled nodelists.
for (i = 0; i < Lists; i++) {
if (!ParseOneNodelist(NList + i)) {
fclose (fh);
return FALSE;
}
}
if (!FlushNodelist(fh)) {
fclose(fh);
return FALSE;
}
// 3 - Write new, true header.
if (fseek(fh,0,SEEK_SET) != 0) {
Log.Level(LOGE) << "Unable to set pointer to begin of index file." << EOL;
fclose(fh);
return FALSE;
}
tmp = NdlSign;
if (fwrite(&tmp,sizeof(tmp),1,fh) != 1) {
Log.Level(LOGE) << "Unable to write signature to index file." << EOL;
fclose(fh);
return FALSE;
}
if (fwrite(&Lists,sizeof(Lists),1,fh) != 1) {
Log.Level(LOGE) << "Unable to write Nodelist counter to index file." << EOL;
fclose(fh);
return FALSE;
}
for (i=0; i < Lists; i++) {
if ((MaxNodelistAge != (time_t)-1) && (NodelistTurnOff != TRUE)) {
if ((time(NULL) - (NList+i)->Time) > MaxNodelistAge) {
Log.Level(LOGI) << "Nodelist '" << (NList+i)->Name << "' too old." << EOL;
Log.Level(LOGI) << "Checking existance in nodelists turned off." << EOL;
NodelistTurnOff = TRUE;
Log.Level(LOGD) << "Age : " << (int) (time(NULL) - (NList+i)->Time) << EOL;
Log.Level(LOGD) << "MaxAge: " << (int) MaxNodelistAge << EOL;
}
}
if (fwrite(NList+i,sizeof(NodeListElem),1,fh) != 1) {
Log.Level(LOGE) << "Unable to write Nodelist information to index file." << EOL;
fclose(fh);
return FALSE;
}
}
fclose(fh);
return TRUE;
}
#ifdef _DEBUG
void IPrint(Nch *Ind) {
if (Ind != NULL) {
fprintf(stderr,"---%p>",Ind);
while (Ind->Number != -1) {
fprintf(stderr," %u",Ind->Number);
Ind++;
}
fprintf(stderr,"\n");
}
}
#endif
int NodeLists::LoadOneIndex(FILE *fh, Nch *&Ind) {
unsigned int tmp;
Nch *tmt;
unsigned int i;
if (fread(&tmp,sizeof(tmp),1,fh) != 1) return FALSE;
tmt = (Nch *) malloc((tmp+1)*sizeof(Nch));
CheckMem((char *)tmt);
memset(tmt,0,(tmp+1)*sizeof(Nch));
tmt[tmp].Number = (unsigned int) -1;
for (i = 0; i < tmp; i++) {
if (fread(&tmt[i].Number,sizeof(int),1,fh) != 1) return FALSE;
}
Ind = tmt;
for (i = 0; i < tmp; i++) {
if (LoadOneIndex(fh,Ind[i].Sub) == FALSE) return FALSE;
}
return TRUE;
}
int NodeLists::Load(void) {
FILE *fh;
if (!Enabled()) {
return TRUE;
}
if (CompileNeed()) {
if (!Compile()) {
return FALSE;
}
}
fh = fopen(IndexName,"rb");
if (fh == NULL) {
Log.Level(LOGE) << "Unable to open index file." << EOL;
return FALSE;
}
if (fseek(fh,sizeof(NdlSign) + sizeof(int) + sizeof(NodeListElem)*Lists,SEEK_SET) != 0) {
Log.Level(LOGE) << "Unable to seek in index file." << EOL;
return FALSE;
}
if (!LoadOneIndex(fh,Index)) {
Log.Level(LOGE) << "Unable to load index file." << EOL;
return FALSE;
}
fclose(fh);
return TRUE;
}
Nch *NodeLists::Srch(Nch *Addr, unsigned int Number) {
if (Addr == NULL) return NULL;
while (Addr->Number != (unsigned int)-1) {
if ((Addr->Number & 0xffff) == (Number & 0xffff)) {
return Addr;
}
Addr++;
}
return NULL;
}
unsigned int NodeLists::ExistInNodelist(FA const &f) {
Nch *tmt;
// if nodelists turned off or need say that node exist then return to any
// adress - A_HOST
// in another part of this programm compare return of this
// function only with (-1).
if (NodelistTurnOff) {
return (A_HOST);
}
tmt = Srch(Index,f.Zone() & 0xffff);
if (tmt == NULL) return ((SoftCheckInNodelists == FALSE) ? (unsigned int)-1 : A_HOST);
tmt = tmt->Sub;
tmt = Srch(tmt,f.Net() & 0xffff);
if (tmt == NULL) return ((SoftCheckInNodelists == FALSE) ? (unsigned int)-1 : A_HOST);
if (f.Node() == 0) {
return A_HOST;
}
tmt = tmt->Sub;
tmt = Srch(tmt,f.Node() & 0xffff);
if (tmt == NULL) {
return (unsigned int)-1;
}
if ((f.Point() & 0xffff) != 0) {
switch (CheckPoints) {
case CHECKPNT_HARD:
if (Srch(tmt->Sub,f.Point() & 0xffff) == NULL) {
return (unsigned int)-1;
}
break;
case CHECKPNT_SOFT:
if (tmt->Sub == NULL) break;
if (tmt->Sub->Number == (unsigned int)-1) break;
if (Srch(tmt->Sub,f.Point() & 0xffff) == NULL) return (unsigned int)-1;
break;
case CHECKPNT_NEVER:
break;
}
}
return tmt->Number;
}
unsigned int NodeLists::GetFlags(FA const &f) {
Nch *tmt;
if (NodelistTurnOff) {
return (A_NONE);
}
tmt = Srch(Index,f.Zone() & 0xffff);
if (tmt == NULL) return A_NONODE;
tmt = tmt->Sub;
tmt = Srch(tmt,f.Net() & 0xffff);
if (tmt == NULL) return A_NONODE;
if (f.Node() == 0) {
return A_HOST;
}
tmt = tmt->Sub;
tmt = Srch(tmt,f.Node() & 0xffff);
if (tmt == NULL) {
return A_NONODE;
}
return tmt->Number;
}
void SayNodelistFlags(FA const &f) {
unsigned int i;
i = Ndl.GetFlags(f);
if (i == A_NONODE) {
Log.Level(LOGD) << "NONODE";
return;
}
i &= A_MASK;
if (i == A_DOWN) Log.Level(LOGD) << "DOWN";
if (i == A_HOLD) Log.Level(LOGD) << "HOLD";
if (i == A_HUB) Log.Level(LOGD) << "HUB";
if (i == A_HOST) Log.Level(LOGD) << "HOST";
if (i == A_PVT) Log.Level(LOGD) << "PVT";
if (i == A_REGION) Log.Level(LOGD) << "REGION";
}
int NodeLists::InSubHubs(FA const &Addr, FA const &Mask) {
Nch *tmt;
int Existing;
// Если узел используемый в качестве маски есть в нодлисте и он хаб или хост
// то проверяем адрес на наличие у него в подхабнике. Иначе - проверяем поинт.
// Ну и еще некоторые заморочки с регионами. Будь они трижды неладны в месте
// с теми, кто придумывал фидошные стандарты.
Existing = (ExistInNodelist(Addr) == (unsigned int) -1 ? FALSE : TRUE);
// Node is equal Mask?
if ((Addr.Zone() & 0xffff) == (Mask.Zone() & 0xffff) &&
(Addr.Net() & 0xffff) == (Mask.Net() & 0xffff) &&
(Addr.Node() & 0xffff) == (Mask.Node() & 0xffff)) {
if ((Addr.Point() & 0xffff) != 0) {
return (Existing);
}
return TRUE;
}
if (Existing == FALSE) return FALSE;
// Node in the same zone?
if ((Addr.Zone() & 0xffff) != (Mask.Zone() & 0xffff)) return FALSE;
// Search zone of mask.
tmt = Srch(Index,Mask.Zone() & 0xffff);
if (tmt == NULL) {
// Log.Level(LOGD) << "Zone " << (Mask.Zone() & 0xffff) << " missing" << EOL;
return FALSE;
}
tmt = tmt->Sub;
if (tmt == NULL) {
// Log.Level(LOGD) << "Zone " << (Mask.Zone() & 0xffff) << " Empty" << EOL;
return FALSE;
}
// Search Net of mask.
tmt = Srch(tmt,Mask.Net() & 0xffff);
if (tmt == NULL) {
// Log.Level(LOGD) << "Net " << (Mask.Zone() & 0xffff) << ":" << (Mask.Net() & 0xffff) << " missing" << EOL;
return FALSE;
}
if ((tmt->Number & A_MASK) == A_REGION) {
if ((Mask.Node() & 0xffff) == 0) {
// Mask to region. Search net.
while (tmt->Number != (unsigned int) -1) {
if ((tmt->Number & 0xffff) == (Addr.Net() & 0xffff)) {
// Net is Found. Search node.
tmt = tmt->Sub;
if (tmt == NULL) return FALSE;
if ((Addr.Node() & 0xffff) == 0) return TRUE;
if (Srch(tmt,Addr.Node() & 0xffff) == NULL) {
return FALSE;
} else {
return TRUE;
}
}
tmt++;
if ((tmt->Number & A_MASK) == A_REGION) {
// Next region started, but net not found...
return FALSE;
}
}
return FALSE;
}
}
if ((Addr.Net() & 0xffff) != (Mask.Net() & 0xffff)) {
// Log.Level(LOGD) << "Node " << Addr << " not equal to mask " << Mask << " and mask is not a regional mask." << EOL;
return FALSE;
}
tmt = tmt->Sub;
if (tmt == NULL) {
// Log.Level(LOGD) << "Node " << Addr << " not equal to mask " << Mask << " and no nodes in mask net." << EOL;
return FALSE;
}
// if mask is a HOST, then start already founded. Continue search otherwise.
if ((Mask.Node() & 0xffff) != 0) {
tmt = Srch(tmt,Mask.Node() & 0xffff);
if (tmt == NULL) return FALSE;
// if Mask is not a hub - leave.
if ((tmt->Number & A_MASK) != A_HUB) return FALSE;
tmt++;
}
// Ok. We hawe start of list. Search node to hub or end of list.
while (tmt->Number != (unsigned int) -1 && (tmt->Number & A_MASK) != A_HUB) {
if ((tmt->Number & 0xffff) == (Addr.Node() & 0xffff)) {
return Existing;
}
tmt++;
}
return FALSE;
}
int NodeLists::AddNodelist(char *tmt, int TempZone) {
char Buff[512];
struct stat NdlStat;
NodeListElem *Elem;
memset(Buff,0,512);
if (strlen(tmt) == 0) {
yyerror("Missed parameter: nodelist name or mask.");
return (-1);
}
if ((TempZone <= 0) && (TempZone != -3)) {
yyerror("Zone number must be between 1 and 65535");
return (-1);
}
if (TempZone != -3) {
StartZone = TempZone;
} else {
StartZone = 0;
}
if (FindNodelist(tmt,Buff) != 0) {
return (-1);
}
if (stat(Buff,&NdlStat) != 0) {
Log.Level(LOGE) << "Unable to get information about nodelist '" << Buff << "'." << EOL;
return (-1);
}
Elem = (NodeListElem *) malloc(sizeof(NodeListElem)+100);
CheckMem((char *)Elem);
memcpy(Elem->Name,Buff,512);
Elem->Time = NdlStat.st_mtime;
Elem->StartZone = StartZone;
Log.Level(LOGD) << "NTime : " << (int) Elem->Time << EOL;
if (NList == NULL) {
NList = Elem;
Lists = 1;
} else {
tmt = (char *) realloc(NList, (Lists + 1) * sizeof(NodeListElem));
CheckMem((char *)tmt);
NList = (NodeListElem *)tmt;
memcpy(NList + Lists,Elem,sizeof(NodeListElem));
Lists++;
free(Elem);
}
return (0);
}
// --------------------------------------------------------------------
int SetMaxNodelistAge(int tmt) {
if (MaxNodelistAge != (time_t)-1) {
yyerror("Max nodelists age already set.");
return(-1);
}
if (tmt < 1) {
yyerror("Parameter must be a number great than 0.");
return (-1);
}
MaxNodelistAge = tmt * 24 * 60 * 60;
return 0;
}
// --------------------------------------------------------------------
int SetNodelist(char *tmt, int TempZone) {
return Ndl.AddNodelist(tmt,TempZone);
}
syntax highlighted by Code2HTML, v. 0.9.1