/***************************************************************************** * * $Id$ * Purpose ...............: Read nodelists information * ***************************************************************************** * Copyright (C) 1997-2002 * * Michiel Broek FIDO: 2:280/2802 * Beekmansbos 10 * 1971 BV IJmuiden * the Netherlands * * This file is part of MBSE BBS. * * This BBS is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2, or (at your option) any * later version. * * MBSE BBS is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with MBSE BBS; see the file COPYING. If not, write to the Free * Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. *****************************************************************************/ #include "../config.h" #include "libs.h" #include "memwatch.h" #include "structs.h" #include "users.h" #include "records.h" #include "clcomm.h" #include "common.h" #define NULLDOMAIN "nulldomain" struct _pkey pkey[] = { {(char *)"Down", NL_NODE, NL_DOWN}, {(char *)"Hold", NL_NODE, NL_HOLD}, {(char *)"Region", NL_REGION, NL_REGION}, {(char *)"Host", NL_HOST, NL_HOST}, {(char *)"Hub", NL_HUB, NL_HUB}, {(char *)"Point", NL_POINT, NL_POINT}, {(char *)"Pvt", NL_NODE, NL_NODE}, {NULL, 0, 0} }; struct _okey okey[] = { {(char *)"CM", OL_CM}, {(char *)"MO", OL_MO}, {(char *)"LO", OL_LO}, {(char *)"MN", OL_MN}, {NULL, 0} }; struct _fkey fkey[] = { {(char *)"V22", NL_V22}, {(char *)"V29", NL_V29}, {(char *)"V32", NL_V32}, {(char *)"V32B",NL_V32B | NL_V32}, {(char *)"V34", NL_V34}, {(char *)"V42", NL_V42 | NL_MNP}, {(char *)"V42B",NL_V42B | NL_V42 | NL_MNP}, {(char *)"MNP", NL_MNP}, {(char *)"H96", NL_H96}, {(char *)"HST", NL_HST | NL_MNP}, {(char *)"H14", NL_H14 | NL_HST | NL_MNP}, {(char *)"H16", NL_H16 | NL_H14 | NL_HST | NL_MNP | NL_V42 | NL_V42B}, {(char *)"MAX", NL_MAX}, {(char *)"PEP", NL_PEP}, {(char *)"CSP", NL_CSP}, {(char *)"V32T",NL_V32T | NL_V32B | NL_V32}, {(char *)"VFC", NL_VFC}, {(char *)"ZYX", NL_ZYX | NL_V32B | NL_V32 | NL_V42B | NL_V42 | NL_MNP}, {(char *)"X2C", NL_X2C | NL_X2S | NL_V34}, {(char *)"X2S", NL_X2S | NL_V34}, {(char *)"V90C",NL_V90C | NL_V90S | NL_V34}, {(char *)"V90S",NL_V90S | NL_V34}, {(char *)"Z19", NL_Z19 | NL_V32B | NL_V32 | NL_V42B | NL_V42 | NL_MNP | NL_ZYX}, {NULL, 0} }; struct _xkey xkey [] = { {(char *)"XA", RQ_XA}, {(char *)"XB", RQ_XB}, {(char *)"XC", RQ_XC}, {(char *)"XP", RQ_XP}, {(char *)"XR", RQ_XR}, {(char *)"XW", RQ_XW}, {(char *)"XX", RQ_XX}, {NULL, 0} }; struct _dkey dkey [] = { {(char *)"V110L", ND_V110L}, {(char *)"V110H", ND_V110H}, {(char *)"V120L", ND_V120L}, {(char *)"V120H", ND_V120H}, {(char *)"X75", ND_X75}, {NULL, 0} }; struct _ikey ikey [] = { {(char *)"IBN", IP_IBN}, {(char *)"IFC", IP_IFC}, {(char *)"ITN", IP_ITN}, {(char *)"IVM", IP_IVM}, {(char *)"IP", IP_IP}, {(char *)"IFT", IP_IFT}, {NULL, 0} }; int initnl(void) { int rc = 0; FILE *dbf, *fp; char *filexnm, *path; struct _nlfil fdx; filexnm = xstrcpy(CFG.nodelists); filexnm = xstrcat(filexnm,(char *)"/node.files"); if ((dbf = fopen(filexnm, "r")) == NULL) { WriteError("$Can't open %s", filexnm); rc = 101; } else { path = calloc(128, sizeof(char)); while (fread(&fdx, sizeof(fdx), 1, dbf) == 1) { sprintf(path, "%s/%s", CFG.nodelists, fdx.filename); if ((fp = fopen(path, "r")) == NULL) { WriteError("$Can't open %s", path); rc = 101; } else { fclose(fp); } } fclose(dbf); free(path); } free(filexnm); return rc; } int comp_node(struct _nlidx, struct _ixentry); int comp_node(struct _nlidx fap1, struct _ixentry fap2) { if (fap1.zone != fap2.zone) return (fap1.zone - fap2.zone); else if (fap1.net != fap2.net) return (fap1.net - fap2.net); else if (fap1.node != fap2.node) return (fap1.node - fap2.node); else return (fap1.point - fap2.point); } node *getnlent(faddr *addr) { FILE *fp, *np; static node nodebuf; static char buf[2048], ebuf[2048], *p, *q; struct _ixentry xaddr; int i, j, Found = FALSE, ixflag, stdflag, ndrecord = FALSE; char *mydomain, *path; struct _nlfil fdx; struct _nlidx ndx; long lowest, highest, current; struct _nodeshdr ndhdr; static struct _nodes nd; Syslog('s', "getnlent: %s", ascfnode(addr,0xff)); mydomain = xstrcpy(CFG.aka[0].domain); if (mydomain == NULL) mydomain = (char *)NULLDOMAIN; nodebuf.addr.domain = NULL; nodebuf.addr.zone = 0; nodebuf.addr.net = 0; nodebuf.addr.node = 0; nodebuf.addr.point = 0; nodebuf.addr.name = NULL; nodebuf.upnet = 0; nodebuf.upnode = 0; nodebuf.region = 0; nodebuf.type = 0; nodebuf.pflag = 0; nodebuf.name = NULL; nodebuf.location = NULL; nodebuf.sysop = NULL; nodebuf.phone = NULL; nodebuf.speed = 0; nodebuf.mflags = 0L; nodebuf.oflags = 0L; nodebuf.xflags = 0L; nodebuf.iflags = 0L; nodebuf.dflags = 0L; nodebuf.uflags[0] = NULL; nodebuf.t1 = '\0'; nodebuf.t2 = '\0'; if (addr == NULL) goto retdummy; if (addr->zone == 0) addr->zone = CFG.aka[0].zone; xaddr.zone = addr->zone; nodebuf.addr.zone = addr->zone; xaddr.net = addr->net; nodebuf.addr.net = addr->net; xaddr.node = addr->node; nodebuf.addr.node = addr->node; xaddr.point = addr->point; nodebuf.addr.point = addr->point; if (initnl()) goto retdummy; /* * First, lookup node in index. NOTE -- NOT 5D YET */ path = calloc(PATH_MAX, sizeof(char)); sprintf(path, "%s/%s", CFG.nodelists, "node.index"); if ((fp = fopen(path, "r")) == NULL) { WriteError("$Can't open %s", path); free(path); goto retdummy; } fseek(fp, 0, SEEK_END); highest = ftell(fp) / sizeof(ndx); lowest = 0; while (TRUE) { current = ((highest - lowest) / 2) + lowest; fseek(fp, current * sizeof(ndx), SEEK_SET); if (fread(&ndx, sizeof(ndx), 1, fp) != 1) break; if (comp_node(ndx, xaddr) == 0) { Found = TRUE; break; } if (comp_node(ndx, xaddr) < 0) lowest = current; else highest = current; if ((highest - lowest) <= 1) break; } fclose(fp); if (!Found) { free(path); goto retdummy; } sprintf(path, "%s/%s", CFG.nodelists, "node.files"); if ((fp = fopen(path, "r")) == NULL) { WriteError("$Can't open %s", path); free(path); goto retdummy; } /* * Get filename from node.files */ for (i = 0; i < (ndx.fileno +1); i++) fread(&fdx, sizeof(fdx), 1, fp); fclose(fp); /* CHECK DOMAIN HERE */ /* * Open and read in real nodelist */ sprintf(path, "%s/%s", CFG.nodelists, fdx.filename); if ((fp = fopen(path, "r")) == NULL) { WriteError("$Can't open %s", path); free(path); goto retdummy; } if (fseek(fp, ndx.offset, SEEK_SET) != 0) { WriteError("$Seek failed for nodelist entry"); fclose(fp); goto retdummy; } if (fgets(buf, sizeof(buf)-1, fp) == NULL) { WriteError("$fgets failed for nodelist entry"); fclose(fp); goto retdummy; } /* * Load noderecord if this node has one, if there is one then * nodelist overrides in this record will be used instead of * the nodelist entries. */ sprintf(path, "%s/etc/nodes.data", getenv("MBSE_ROOT")); if ((np = fopen(path, "r")) != NULL) { fread(&ndhdr, sizeof(nodeshdr), 1, np); while (fread(&nd, ndhdr.recsize, 1, np) == 1) { fseek(np, ndhdr.filegrp + ndhdr.mailgrp, SEEK_CUR); for (i = 0; i < 20; i++) { if ((addr->zone == nd.Aka[i].zone) && (addr->net == nd.Aka[i].net) && (addr->node == nd.Aka[i].node) && (addr->point == nd.Aka[i].point)) { ndrecord = TRUE; Syslog('s', "getnlent: node record is present"); break; } } if (ndrecord) break; } fclose(np); } free(path); nodebuf.type = ndx.type; nodebuf.pflag = ndx.pflag; if (*(p = buf + strlen(buf) -1) == '\n') *p = '\0'; if (*(p = buf + strlen(buf) -1) == '\r') *p = '\0'; for (p = buf; *p; p++) if (*p == '_') *p = ' '; p = buf; if ((q = strchr(p,','))) *q++ = '\0'; p = q; if (p == NULL) { fclose(fp); goto badsyntax; } if ((q=strchr(p,','))) *q++ = '\0'; p = q; if (p == NULL) { fclose(fp); goto badsyntax; } /* * Get system name */ if ((q=strchr(p,','))) *q++ = '\0'; if (ndrecord && strlen(nd.Nl_hostname)) { Syslog('s', "getnlent: system name override with %s", nd.Nl_hostname); nodebuf.name = nd.Nl_hostname; } else nodebuf.name = p; p = q; if (p == NULL) { fclose(fp); goto badsyntax; } /* * Get location */ if ((q=strchr(p,','))) *q++ = '\0'; nodebuf.location = p; p = q; if (p == NULL) { fclose(fp); goto badsyntax; } /* * Get sysop name */ if ((q=strchr(p,','))) *q++ = '\0'; nodebuf.sysop = p; p = q; if (p == NULL) { fclose(fp); goto badsyntax; } /* * Get phone number */ if ((q=strchr(p,','))) *q++ = '\0'; if (strcasecmp(p, "-Unpublished-") == 0) nodebuf.phone = NULL; else nodebuf.phone = p; p = q; if (p == NULL) { fclose(fp); goto badsyntax; } /* * Get modem speed */ if ((q=strchr(p,','))) *q++ = '\0'; nodebuf.speed = atoi(p); /* * Process the nodelist flags. */ if (ndrecord && strlen(nd.Nl_flags)) { Syslog('s', "getnlent: flags override %s", nd.Nl_flags); q = nd.Nl_flags; } ixflag = 0; stdflag = TRUE; for (p = q; p; p = q) { if ((q = strchr(p, ','))) *q++ = '\0'; if ((strncasecmp(p, "U", 1) == 0) && (strlen(p) == 1)) { stdflag = FALSE; } else { /* * Process authorized flags and user flags both as authorized. */ for (j = 0; fkey[j].key; j++) if (strcasecmp(p, fkey[j].key) == 0) nodebuf.mflags |= fkey[j].flag; for (j = 0; okey[j].key; j++) if (strcasecmp(p, okey[j].key) == 0) nodebuf.oflags |= okey[j].flag; for (j = 0; dkey[j].key; j++) if (strcasecmp(p, dkey[j].key) == 0) nodebuf.dflags |= dkey[j].flag; for (j = 0; ikey[j].key; j++) if (strncasecmp(p, ikey[j].key, strlen(ikey[j].key)) == 0) nodebuf.iflags |= ikey[j].flag; for (j = 0; xkey[j].key; j++) if (strcasecmp(p, xkey[j].key) == 0) nodebuf.xflags |= xkey[j].flag; if ((p[0] == 'T') && (strlen(p) == 3)) { /* * System open hours flag */ nodebuf.t1 = p[1]; nodebuf.t2 = p[2]; } if (!stdflag) { if (ixflag < MAXUFLAGS) { nodebuf.uflags[ixflag++] = p; if (ixflag < MAXUFLAGS) nodebuf.uflags[ixflag] = NULL; } } } } /* * Now we read the next line from the nodelist and see if this * is a ESLF (Extended St. Louis Format) line. This is for test * and nothing is defined yet. For now, debug logging only. */ while (TRUE) { if (fgets(ebuf, sizeof(ebuf)-1, fp) == NULL) { WriteError("$fgets failed for nodelist entry"); break; } /* * Linse starting with ;E space are real errors. */ if (strncmp(ebuf, (char *)";E ", 3) == 0) break; if (strncmp(ebuf, (char *)";E", 2)) break; Syslog('s', "ESLF: \"%s\"", printable(ebuf, 0)); } fclose(fp); nodebuf.addr.name = nodebuf.sysop; nodebuf.addr.domain = xstrcpy(fdx.domain); nodebuf.upnet = ndx.upnet; nodebuf.upnode = ndx.upnode; nodebuf.region = ndx.region; if (addr->domain == NULL) addr->domain = xstrcpy(nodebuf.addr.domain); Syslog('s', "getnlent: system %s, %s", nodebuf.name, nodebuf.location); Syslog('s', "getnlent: sysop %s, %s", nodebuf.sysop, nodebuf.phone); moflags(nodebuf.mflags); diflags(nodebuf.dflags); ipflags(nodebuf.iflags); olflags(nodebuf.oflags); rqflags(nodebuf.xflags); free(mydomain); return &nodebuf; badsyntax: WriteError("nodelist %d offset +%lu: bad syntax in line \"%s\"", ndx.fileno, (unsigned long)ndx.offset, buf); /* fallthrough */ retdummy: memset(&nodebuf, 0, sizeof(nodebuf)); nodebuf.pflag = NL_DUMMY; nodebuf.name = (char *)"Unknown"; nodebuf.location = (char *)"Nowhere"; nodebuf.sysop = (char *)"Sysop"; nodebuf.phone = NULL; nodebuf.speed = 2400; free(mydomain); return &nodebuf; } void olflags(unsigned long flags) { char *t; t = xstrcpy((char *)"Mailer flags :"); if (flags & OL_CM) t = xstrcat(t, (char *)" CM"); if (flags & OL_MO) t = xstrcat(t, (char *)" MO"); if (flags & OL_LO) t = xstrcat(t, (char *)" LO"); if (flags & OL_MN) t = xstrcat(t, (char *)" MN"); Syslog('s', "%s", t); free(t); } void rqflags(unsigned long flags) { char *t; t = xstrcpy((char *)"Request flags:"); if (flags & RQ_RQ_BR) t = xstrcat(t, (char *)" RQ_BR"); if (flags & RQ_RQ_BU) t = xstrcat(t, (char *)" RQ_BU"); if (flags & RQ_RQ_WR) t = xstrcat(t, (char *)" RQ_WR"); if (flags & RQ_RQ_WU) t = xstrcat(t, (char *)" RQ_WU"); Syslog('s', "%s", t); free(t); } void moflags(unsigned long flags) { char *t; if (!flags) return; t = xstrcpy((char *)"Modem flags :"); if (flags & NL_V22) t = xstrcat(t, (char *)" V22"); if (flags & NL_V29) t = xstrcat(t, (char *)" V29"); if (flags & NL_V32) t = xstrcat(t, (char *)" V32"); if (flags & NL_V32B) t = xstrcat(t, (char *)" V32B"); if (flags & NL_V34) t = xstrcat(t, (char *)" V34"); if (flags & NL_V42) t = xstrcat(t, (char *)" V42"); if (flags & NL_V42B) t = xstrcat(t, (char *)" V42B"); if (flags & NL_MNP) t = xstrcat(t, (char *)" MNP"); if (flags & NL_H96) t = xstrcat(t, (char *)" H96"); if (flags & NL_HST) t = xstrcat(t, (char *)" HST"); if (flags & NL_H14) t = xstrcat(t, (char *)" H14"); if (flags & NL_H16) t = xstrcat(t, (char *)" H16"); if (flags & NL_MAX) t = xstrcat(t, (char *)" MAX"); if (flags & NL_PEP) t = xstrcat(t, (char *)" PEP"); if (flags & NL_CSP) t = xstrcat(t, (char *)" CSP"); if (flags & NL_V32T) t = xstrcat(t, (char *)" V32T"); if (flags & NL_VFC) t = xstrcat(t, (char *)" VFC"); if (flags & NL_ZYX) t = xstrcat(t, (char *)" ZYX"); if (flags & NL_X2C) t = xstrcat(t, (char *)" X2C"); if (flags & NL_X2S) t = xstrcat(t, (char *)" X2S"); if (flags & NL_V90C) t = xstrcat(t, (char *)" V90C"); if (flags & NL_V90S) t = xstrcat(t, (char *)" V90S"); Syslog('s', "%s", t); free(t); } void diflags(unsigned long flags) { char *t; if (!flags) return; t = xstrcpy((char *)"ISDN flags :"); if (flags & ND_V110L) t = xstrcat(t, (char *)" V110L"); if (flags & ND_V110H) t = xstrcat(t, (char *)" V110H"); if (flags & ND_V120L) t = xstrcat(t, (char *)" V120L"); if (flags & ND_V120H) t = xstrcat(t, (char *)" V120H"); if (flags & ND_X75) t = xstrcat(t, (char *)" X75"); Syslog('s', "%s", t); free(t); } void ipflags(unsigned long flags) { char *t; if (!flags) return; t = xstrcpy((char *)"TCP/IP flags :"); if (flags & IP_IBN) t = xstrcat(t, (char *)" IBN"); if (flags & IP_IFC) t = xstrcat(t, (char *)" IFC"); if (flags & IP_ITN) t = xstrcat(t, (char *)" ITN"); if (flags & IP_IVM) t = xstrcat(t, (char *)" IVM"); if (flags & IP_IP) t = xstrcat(t, (char *)" IP"); if (flags & IP_IFT) t = xstrcat(t, (char *)" IFT"); Syslog('s', "%s", t); free(t); }