/***************************************************************************** * * $Id$ * Purpose ...............: Read nodelists information * ***************************************************************************** * Copyright (C) 1997-2001 * * 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 "../lib/structs.h" #include "taskutil.h" #include "nodelist.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} }; extern struct sysconfig CFG; 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) { tasklog('?', "$Can't open %s", filexnm); rc = 101; } else { path = calloc(PATH_MAX, sizeof(char)); while (fread(&fdx, sizeof(fdx), 1, dbf) == 1) { sprintf(path, "%s/%s", CFG.nodelists, fdx.filename); if ((fp = fopen(path, "r")) == NULL) { tasklog('?', "$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; static node nodebuf; static char buf[256], *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; 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(128, sizeof(char)); sprintf(path, "%s/%s", CFG.nodelists, "node.index"); if ((fp = fopen(path, "r")) == NULL) { tasklog('?', "$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) { tasklog('?', "$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) { tasklog('?', "$Can't open %s", path); free(path); goto retdummy; } if (fseek(fp, ndx.offset, SEEK_SET) != 0) { tasklog('?', "$Seek failed for nodelist entry"); fclose(fp); goto retdummy; } if (fgets(buf, sizeof(buf)-1, fp) == NULL) { tasklog('?', "$fgets failed for nodelist entry"); fclose(fp); goto retdummy; } fclose(fp); /* * 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 ((fp = fopen(path, "r")) != NULL) { fread(&ndhdr, sizeof(ndhdr), 1, fp); while (fread(&nd, ndhdr.recsize, 1, fp) == 1) { fseek(fp, 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; break; } } if (ndrecord) break; } fclose(fp); } 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) goto badsyntax; if ((q=strchr(p,','))) *q++ = '\0'; p = q; if (p == NULL) goto badsyntax; /* * Get system name */ if ((q=strchr(p,','))) *q++ = '\0'; if (ndrecord && strlen(nd.Nl_hostname)) nodebuf.name = nd.Nl_hostname; else nodebuf.name = p; p = q; if (p == NULL) goto badsyntax; /* * Get location */ if ((q=strchr(p,','))) *q++ = '\0'; nodebuf.location = p; p = q; if (p == NULL) goto badsyntax; /* * Get sysop name */ if ((q=strchr(p,','))) *q++ = '\0'; nodebuf.sysop = p; p = q; if (p == NULL) 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) goto badsyntax; /* * Get modem speed */ if ((q=strchr(p,','))) *q++ = '\0'; nodebuf.speed = atoi(p); /* * Process the nodelist flags, get them from the node override * field if this is present, else use the nodelist. */ if (ndrecord && strlen(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 { /* * Experimental: 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; } } } } 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); free(mydomain); return &nodebuf; badsyntax: tasklog('?', "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; }