// -------------------------------------------------------------------- // 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 #include #else #include #include #include #include #endif #include #include #include #include #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); }