This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-mbse/lib/nodelist.c

1267 lines
33 KiB
C

/*****************************************************************************
*
* Purpose ...............: Read nodelists information
*
*****************************************************************************
* Copyright (C) 1997-2011
*
* 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, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*****************************************************************************/
#include "../config.h"
#include "mbselib.h"
#include "nodelist.h"
#define NULLDOMAIN "nulldomain"
static char *k, *v;
static char *nlpath = NULL;
static int nlinitdone = FALSE;
static int linecnt = 0;
static unsigned int mypots = 0, myisdn = 0, mytcpip =0;
static int getkwd(char**);
static int getmdm(char**);
static int getarr(char**);
static int getdom(char**);
static int getsrv(char**);
/*
* Table to parse the ~/etc/nodelist.conf file
*/
static struct _keytab {
char *key;
int (*prc)(char **);
char** dest;
} keytab[] = {
{(char *)"online", getkwd, (char **)&nl_online},
{(char *)"request", getkwd, (char **)&nl_request},
{(char *)"reqbits", getkwd, (char **)&nl_reqbits},
{(char *)"pots", getmdm, (char **)&nl_pots},
{(char *)"isdn", getmdm, (char **)&nl_isdn},
{(char *)"tcpip", getmdm, (char **)&nl_tcpip},
{(char *)"search", getarr, (char **)&nl_search},
{(char *)"dialer", getarr, (char **)&nl_dialer},
{(char *)"ipprefix", getarr, (char **)&nl_ipprefix},
{(char *)"domsuffix", getdom, (char **)&nl_domsuffix},
{(char *)"service", getsrv, (char **)&nl_service},
{NULL, NULL, NULL}
};
/*
* Get a keyword, string, unsigned int
*/
static int getkwd(char **dest)
{
char *p;
unsigned int tmp;
nodelist_flag **tmpm;
for (p = v; *p && !isspace(*p); p++);
if (*p)
*p++ = '\0';
while (*p && isspace(*p))
p++;
if (*p == '\0') {
WriteError("%s(%s): less then two tokens", nlpath, linecnt);
return MBERR_INIT_ERROR;
}
for (tmpm = (nodelist_flag**)dest; *tmpm; tmpm=&((*tmpm)->next));
(*tmpm) = (nodelist_flag *) xmalloc(sizeof(nodelist_flag));
(*tmpm)->next = NULL;
(*tmpm)->name = xstrcpy(v);
tmp = strtoul(p, NULL, 0);
(*tmpm)->value = tmp;
return 0;
}
/*
* Get a keyword, string, unsigned int, unsigned int
*/
static int getmdm(char **dest)
{
char *p, *q;
unsigned int tmp1, tmp2;
nodelist_modem **tmpm;
for (p = v; *p && !isspace(*p); p++);
if (*p)
*p++ = '\0';
while (*p && isspace(*p))
p++;
if (*p == '\0') {
WriteError("%s(%s): less then two tokens", nlpath, linecnt);
return MBERR_INIT_ERROR;
}
for (q = p; *q && !isspace(*q); q++);
if (*q)
*q++ = '\0';
while (*q && isspace(*q))
q++;
if (*q == '\0') {
WriteError("%s(%s): less then three tokens", nlpath, linecnt);
return MBERR_INIT_ERROR;
}
for (tmpm = (nodelist_modem**)dest; *tmpm; tmpm=&((*tmpm)->next));
(*tmpm) = (nodelist_modem *) xmalloc(sizeof(nodelist_modem));
(*tmpm)->next = NULL;
(*tmpm)->name = xstrcpy(v);
tmp1 = strtoul(p, NULL, 0);
tmp2 = strtoul(q, NULL, 0);
(*tmpm)->mask = tmp1;
(*tmpm)->value = tmp2;
return 0;
}
/*
* Get a keyword, string array
*/
static int getarr(char **dest)
{
char *p;
nodelist_array **tmpm;
for (p = v; *p && !isspace(*p); p++);
if (*p)
*p++ = '\0';
for (tmpm = (nodelist_array**)dest; *tmpm; tmpm=&((*tmpm)->next));
(*tmpm) = (nodelist_array *) xmalloc(sizeof(nodelist_array));
(*tmpm)->next = NULL;
(*tmpm)->name = xstrcpy(v);
return 0;
}
/*
* Get a keyword, unsigned short, string
*/
static int getdom(char **dest)
{
char *p;
unsigned short tmp;
nodelist_domsuf **tmpm;
for (p = v; *p && !isspace(*p); p++);
if (*p)
*p++ = '\0';
while (*p && isspace(*p))
p++;
if (*p == '\0') {
WriteError("%s(%s): less then two tokens", nlpath, linecnt);
return MBERR_INIT_ERROR;
}
for (tmpm = (nodelist_domsuf**)dest; *tmpm; tmpm=&((*tmpm)->next));
(*tmpm) = (nodelist_domsuf *) xmalloc(sizeof(nodelist_domsuf));
(*tmpm)->next = NULL;
tmp = strtod(v, NULL);
(*tmpm)->zone = tmp;
(*tmpm)->name = xstrcpy(p);
return 0;
}
/*
* Get a keyword, string, string, unsigned int
*/
static int getsrv(char **dest)
{
char *p, *q;
unsigned int tmp;
nodelist_service **tmpm;
for (p = v; *p && !isspace(*p); p++);
if (*p)
*p++ = '\0';
while (*p && isspace(*p))
p++;
if (*p == '\0') {
WriteError("%s(%s): less then two tokens", nlpath, linecnt);
return MBERR_INIT_ERROR;
}
for (q = p; *q && !isspace(*q); q++);
if (*q)
*q++ = '\0';
while (*q && isspace(*q))
q++;
if (*q == '\0') {
WriteError("%s(%s): less then three tokens", nlpath, linecnt);
return MBERR_INIT_ERROR;
}
for (tmpm = (nodelist_service**)dest; *tmpm; tmpm=&((*tmpm)->next));
(*tmpm) = (nodelist_service *) xmalloc(sizeof(nodelist_service));
(*tmpm)->next = NULL;
(*tmpm)->flag = xstrcpy(v);
(*tmpm)->service = xstrcpy(p);
tmp = strtoul(q, NULL, 0);
(*tmpm)->defport = (*tmpm)->tmpport = tmp;
return 0;
}
void tidy_nl_flag(nodelist_flag **);
void tidy_nl_flag(nodelist_flag **fap)
{
nodelist_flag *tmp, *old;
for (tmp = *fap; tmp; tmp = old) {
old = tmp->next;
if (tmp->name)
free(tmp->name);
free(tmp);
}
*fap = NULL;
}
void tidy_nl_modem(nodelist_modem **);
void tidy_nl_modem(nodelist_modem **fap)
{
nodelist_modem *tmp, *old;
for (tmp = *fap; tmp; tmp = old) {
old = tmp->next;
if (tmp->name)
free(tmp->name);
free(tmp);
}
*fap = NULL;
}
void tidy_nl_array(nodelist_array **);
void tidy_nl_array(nodelist_array **fap)
{
nodelist_array *tmp, *old;
for (tmp = *fap; tmp; tmp = old) {
old = tmp->next;
if (tmp->name)
free(tmp->name);
free(tmp);
}
*fap = NULL;
}
void tidy_nl_domsuf(nodelist_domsuf **);
void tidy_nl_domsuf(nodelist_domsuf **fap)
{
nodelist_domsuf *tmp, *old;
for (tmp = *fap; tmp; tmp = old) {
old = tmp->next;
if (tmp->name)
free(tmp->name);
free(tmp);
}
*fap = NULL;
}
void tidy_nl_service(nodelist_service **);
void tidy_nl_service(nodelist_service **fap)
{
nodelist_service *tmp, *old;
for (tmp = *fap; tmp; tmp = old) {
old = tmp->next;
if (tmp->flag)
free(tmp->flag);
if (tmp->service)
free(tmp->service);
free(tmp);
}
*fap = NULL;
}
/*
* De-init nodelists, free all allocated memory
*/
void deinitnl(void)
{
if (!nlinitdone)
return;
tidy_nl_flag(&nl_online);
tidy_nl_flag(&nl_request);
tidy_nl_flag(&nl_reqbits);
tidy_nl_modem(&nl_pots);
tidy_nl_modem(&nl_isdn);
tidy_nl_modem(&nl_tcpip);
tidy_nl_array(&nl_search);
tidy_nl_array(&nl_dialer);
tidy_nl_array(&nl_ipprefix);
tidy_nl_domsuf(&nl_domsuffix);
tidy_nl_service(&nl_service);
nlinitdone = FALSE;
}
/*
* Init nodelists.
*/
int initnl(void)
{
int i, rc = 0;
FILE *dbf, *fp;
char *filexnm, buf[256], *p, *q;
struct _nlfil fdx;
struct taskrec TCFG;
nodelist_modem **tmpm;
if (nlinitdone == TRUE)
return 0;
nl_online = NULL;
nl_pots = NULL;
nl_request = NULL;
nl_reqbits = NULL;
nl_isdn = NULL;
nl_tcpip = NULL;
nl_search = NULL;
nl_domsuffix = NULL;
nl_ipprefix = NULL;
nl_dialer = NULL;
nl_service = NULL;
filexnm = xstrcpy(CFG.nodelists);
filexnm = xstrcat(filexnm,(char *)"/node.files");
nlpath = calloc(PATH_MAX, sizeof(char));
/*
* Check if all installed nodelists are present.
*/
if ((dbf = fopen(filexnm, "r")) == NULL) {
WriteError("$Can't open %s", filexnm);
rc = MBERR_INIT_ERROR;
} else {
while (fread(&fdx, sizeof(fdx), 1, dbf) == 1) {
snprintf(nlpath, PATH_MAX -1, "%s/%s", CFG.nodelists, fdx.filename);
if ((fp = fopen(nlpath, "r")) == NULL) {
WriteError("$Can't open %s", nlpath);
rc = MBERR_INIT_ERROR;
} else {
fclose(fp);
}
}
fclose(dbf);
}
free(filexnm);
/*
* Read and parse ~/etc/nodelist.conf
*/
snprintf(nlpath, PATH_MAX -1, "%s/etc/nodelist.conf", getenv("MBSE_ROOT"));
if ((dbf = fopen(nlpath, "r")) == NULL) {
WriteError("$Can't open %s", nlpath);
rc = MBERR_INIT_ERROR;
} else {
while (fgets(buf, sizeof(buf) -1, dbf)) {
linecnt++;
if (*(p = buf + strlen(buf) -1) != '\n') {
WriteError("%s(%d): \"%s\" - line too long", nlpath, linecnt, buf);
rc = MBERR_INIT_ERROR;
break;
}
*p-- = '\0';
while ((p >= buf) && isspace(*p))
*p-- = '\0';
k = buf;
while (*k && isspace(*k))
k++;
p = k;
while (*p && !isspace(*p))
p++;
*p++='\0';
v = p;
while (*v && isspace(*v))
v++;
if ((*k == '\0') || (*k == '#')) {
continue;
}
for (i = 0; keytab[i].key; i++)
if (strcasecmp(k,keytab[i].key) == 0)
break;
if (keytab[i].key == NULL) {
WriteError("%s(%d): %s %s - unknown keyword", nlpath, linecnt, MBSE_SS(k), MBSE_SS(v));
rc = MBERR_INIT_ERROR;
break;
} else if ((keytab[i].prc(keytab[i].dest))) {
rc = MBERR_INIT_ERROR;
break;
}
}
fclose(dbf);
}
/*
* Howmany TCP sessions are allowd
*/
snprintf(nlpath, PATH_MAX -1, "%s/etc/task.data", getenv("MBSE_ROOT"));
if ((fp = fopen(nlpath, "r"))) {
fread(&TCFG, sizeof(TCFG), 1, fp);
fclose(fp);
} else {
TCFG.max_tcp = 0;
}
/*
* Read all our TCP/IP capabilities and set the global flag.
*/
if (TCFG.max_tcp) {
snprintf(buf, 256, "%s", CFG.IP_Flags);
q = buf;
for (p = q; p; p = q) {
if ((q = strchr(p, ',')))
*q++ = '\0';
for (tmpm = &nl_tcpip; *tmpm; tmpm=&((*tmpm)->next))
if (strncasecmp((*tmpm)->name, p, strlen((*tmpm)->name)) == 0)
mytcpip |= (*tmpm)->value;
}
}
/*
* Read the ports configuration for all pots and isdn lines.
* All lines are ORed so we have a global and total lines
* capability.
*/
snprintf(nlpath, PATH_MAX -1, "%s/etc/ttyinfo.data", getenv("MBSE_ROOT"));
if ((fp = fopen(nlpath, "r"))) {
fread(&ttyinfohdr, sizeof(ttyinfohdr), 1, fp);
while (fread(&ttyinfo, ttyinfohdr.recsize, 1, fp) == 1) {
if (((ttyinfo.type == POTS) || (ttyinfo.type == ISDN)) && (ttyinfo.available) && (ttyinfo.callout)) {
snprintf(buf, 256, "%s", ttyinfo.flags);
q = buf;
for (p = q; p; p = q) {
if ((q = strchr(p, ',')))
*q++ = '\0';
for (tmpm = &nl_pots; *tmpm; tmpm=&((*tmpm)->next))
if (strcasecmp((*tmpm)->name, p) == 0)
mypots |= (*tmpm)->value;
for (tmpm = &nl_isdn; *tmpm; tmpm=&((*tmpm)->next))
if (strcasecmp((*tmpm)->name, p) == 0)
myisdn |= (*tmpm)->value;
}
}
}
fclose(fp);
}
free(nlpath);
nlinitdone = TRUE;
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[MAXNLLINELEN], ebuf[MAXNLLINELEN], *p, *q, tbuf[256];
struct _ixentry xaddr;
int i, Found = FALSE, ixflag, stdflag, ndrecord = FALSE;
char *mydomain, *path, *r, *s;
struct _nlfil fdx;
struct _nlidx ndx;
int lowest, highest, current;
struct _nodeshdr ndhdr;
static struct _nodes nd;
nodelist_modem **tmpm;
nodelist_flag **tmpf;
nodelist_service **tmps;
nodelist_array **tmpa, **tmpaa;
nodelist_domsuf **tmpd;
unsigned int tport = 0;
Syslog('n', "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';
nodebuf.url = NULL;
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;
/*
* Search domainname for the requested aka, should not fail.
*/
path = calloc(PATH_MAX, sizeof(char));
snprintf(path, PATH_MAX -1, "%s/etc/fidonet.data", getenv("MBSE_ROOT"));
if ((fp = fopen(path, "r"))) {
fread(&fidonethdr, sizeof(fidonethdr), 1, fp);
while (fread(&fidonet, fidonethdr.recsize, 1, fp) == 1) {
for (i = 0; i < 6; i++) {
if (addr->zone == fidonet.zone[i]) {
nodebuf.addr.domain = xstrcpy(fidonet.domain);
Found = TRUE;
break;
}
}
if (Found)
break;
}
fclose(fp);
}
Found = FALSE;
/*
* First, lookup node in index. NOTE -- NOT 5D YET
*/
snprintf(path, PATH_MAX -1, "%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;
}
snprintf(path, PATH_MAX -1, "%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
*/
snprintf(path, PATH_MAX -1, "%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;
}
Syslog('n', "getnlent: %s", buf);
/*
* 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.
*/
snprintf(path, PATH_MAX -1, "%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;
break;
}
}
if (ndrecord)
break;
}
fclose(np);
}
free(path);
nodebuf.type = ndx.type;
nodebuf.pflag = ndx.pflag;
/*
* If an override exists on Hold and Down status,
* clear these bits.
*/
if (ndrecord && nd.IgnHold && (nodebuf.pflag & (NL_HOLD + NL_DOWN))) {
nodebuf.pflag &= ~NL_DOWN;
nodebuf.pflag &= ~NL_HOLD;
Syslog('+', "getnlent: %s override node Down/Hold status", ascfnode(addr,0xff));
}
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('+', "getnlent: %s system name override with %s", ascfnode(addr,0xff), 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);
/*
* Reset all possible overridden portnumbers to the default from nodelist.conf
*/
for (tmps = &nl_service; *tmps; tmps=&((*tmps)->next))
(*tmps)->tmpport = (*tmps)->defport;
/*
* Process the nodelist flags.
*/
if (ndrecord && strlen(nd.Nl_flags)) {
Syslog('+', "getnlent: %s flags override %s", ascfnode(addr,0xff), 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 (tmpf = &nl_online; *tmpf; tmpf=&((*tmpf)->next))
if (strcasecmp(p, (*tmpf)->name) == 0)
nodebuf.oflags |= (*tmpf)->value;
for (tmpm = &nl_pots; *tmpm; tmpm=&((*tmpm)->next))
if (strcasecmp(p, (*tmpm)->name) == 0)
nodebuf.mflags |= (*tmpm)->value;
for (tmpm = &nl_isdn; *tmpm; tmpm=&((*tmpm)->next))
if (strcasecmp(p, (*tmpm)->name) == 0)
nodebuf.dflags |= (*tmpm)->value;
for (tmpm = &nl_tcpip; *tmpm; tmpm=&((*tmpm)->next))
if (strncasecmp(p, (*tmpm)->name, strlen((*tmpm)->name)) == 0) {
nodebuf.iflags |= (*tmpm)->value;
/*
* Parse the IP flag for a optional port number.
*/
if ((r = strrchr(p, ':'))) {
r++;
for (tmps = &nl_service; *tmps; tmps=&((*tmps)->next)) {
if (strncmp(p, (*tmps)->flag, 3) == 0) {
/*
* Check for format IBN:70.66.52.252 because this is not
* a port number but a dotted IP quad with default port number.
*/
if ((strchr(r, '.') == NULL) && atoi(r)) {
(*tmps)->tmpport = atoi(r);
Syslog('n', "getnlent: port override %s %d to %d",
(*tmpm)->name, (*tmps)->defport, (*tmps)->tmpport);
}
}
}
}
}
for (tmpf = &nl_request; *tmpf; tmpf=&((*tmpf)->next))
if (strcasecmp(p, (*tmpf)->name) == 0)
nodebuf.xflags = (*tmpf)->value;
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"); Errors are allowed here.
break;
}
/*
* Lines starting with ;E space are real errors.
*/
if (strncmp(ebuf, (char *)";E ", 3) == 0)
break;
if (strncmp(ebuf, (char *)";E", 2))
break;
Syslog('n', "ESLF: \"%s\"", printable(ebuf, 0));
}
/*
* Build the connection URL
*
* If the node has some IP flags and we allow TCP, then search the best protocol.
*/
if (nodebuf.iflags & mytcpip) {
memset(&tbuf, 0, sizeof(tbuf));
for (tmpm = &nl_tcpip; *tmpm; tmpm=&((*tmpm)->next)) {
if ((*tmpm)->mask & nodebuf.iflags) {
for (tmps = &nl_service; *tmps; tmps=&((*tmps)->next)) {
if (strcmp((*tmps)->flag, (*tmpm)->name) == 0) {
snprintf(tbuf, 256, "%s", (*tmps)->service);
tport = (*tmps)->tmpport;
}
}
}
}
/*
* The last setting is the best
*/
nodebuf.url = xstrcpy(tbuf);
nodebuf.url = xstrcat(nodebuf.url, (char *)"://");
/*
* Next, try to find out the FQDN for this node, we have a search
* preference list in the nodelist.conf file.
*/
memset(&tbuf, 0, sizeof(tbuf));
if (ndrecord && strlen(nd.Nl_hostname)) {
Syslog('n', "getnlent: using override %s for FQDN", nd.Nl_hostname);
snprintf(tbuf, 256, nodebuf.name);
nodebuf.url = xstrcat(nodebuf.url, tbuf);
} else {
for (tmpa = &nl_search; *tmpa; tmpa=&((*tmpa)->next)) {
Syslog('n', "getnlent: search FQDN method %s", (*tmpa)->name);
if (strcasecmp((*tmpa)->name, "field3") == 0) {
snprintf(tbuf, 256, nodebuf.name);
if (strchr(tbuf, '.')) {
/*
* Okay, there are dots, this can be a FQDN or IP address.
*/
Syslog('n', "getnlent: using field3 \"%s\"", tbuf);
nodebuf.url = xstrcat(nodebuf.url, tbuf);
break;
} else {
memset(&tbuf, 0, sizeof(tbuf));
}
} else if (strcasecmp((*tmpa)->name, "field6") == 0) {
memset(&tbuf, 0, sizeof(tbuf));
for (tmpaa = &nl_ipprefix; *tmpaa; tmpaa=&((*tmpaa)->next)) {
if (nodebuf.phone && strncmp(nodebuf.phone, (*tmpaa)->name, strlen((*tmpaa)->name)) == 0) {
Syslog('n', "getnlent: found %s prefix", (*tmpaa)->name);
snprintf(tbuf, 256, "%s", nodebuf.phone+strlen((*tmpaa)->name));
for (i = 0; i < strlen(tbuf); i++)
if (tbuf[i] == '-')
tbuf[i] = '.';
Syslog('n', "getnlent: using field6 \"%s\"", tbuf);
nodebuf.url = xstrcat(nodebuf.url, tbuf);
break;
}
}
if (strlen(tbuf))
break;
} else if (strcasecmp((*tmpa)->name, "field8") == 0) {
/*
* Read nodelist line again in another buffer, the original
* buffer is divided into pieces by all previous actions.
*/
memset(&tbuf, 0, sizeof(tbuf));
if (fseek(fp, ndx.offset, SEEK_SET) != 0) {
WriteError("$Seek failed for nodelist entry");
fclose(fp);
goto retdummy;
}
if (fgets(ebuf, sizeof(ebuf)-1, fp) == NULL) {
WriteError("$fgets failed for nodelist entry");
fclose(fp);
goto retdummy;
}
if (*(p = ebuf + strlen(ebuf) -1) == '\n')
*p = '\0';
if (*(p = ebuf + strlen(ebuf) -1) == '\r')
*p = '\0';
p = ebuf;
/*
* Shift to field 8
*/
for (i = 0; i < 7; i++) {
if ((q = strchr(p,',')))
*q++ = '\0';
p = q;
if (p == NULL) {
fclose(fp);
goto badsyntax;
}
}
for (p = q; p; p = q) {
if ((q = strchr(p, ',')))
*q++ = '\0';
if ((r = strchr(p, ':'))) {
r++;
/*
* If there is a user@domain then strip the userpart.
*/
if (strchr(r, '@')) {
r = strchr(r, '@');
r++;
}
if (*r == '*') {
Syslog('n', "getnlent: possible default domain marking \"%s\"", MBSE_SS(r));
for (tmpd = &nl_domsuffix; *tmpd; tmpd=&((*tmpd)->next)) {
if ((*tmpd)->zone == nodebuf.addr.zone) {
if (*r++ == '\0')
snprintf(tbuf, 256, "f%d.n%d.z%d.%s.%s", nodebuf.addr.node, nodebuf.addr.net,
nodebuf.addr.zone, nodebuf.addr.domain, (*tmpd)->name);
else
snprintf(tbuf, 256, "f%d.n%d.z%d.%s.%s%s", nodebuf.addr.node, nodebuf.addr.net,
nodebuf.addr.zone, nodebuf.addr.domain, (*tmpd)->name, r);
Syslog('n', "getnlent: will try default domain \"%s\"", tbuf);
nodebuf.url = xstrcat(nodebuf.url, tbuf);
break;
}
}
if (strlen(tbuf))
break;
Syslog('n', "getnlent: no matching default domain found for zone %d", nodebuf.addr.zone);
}
if (strchr(r, '.')) {
Syslog('n', "getnlent: found a FQDN \"%s\"", MBSE_SS(r));
snprintf(tbuf, 256, "%s", r);
nodebuf.url = xstrcat(nodebuf.url, tbuf);
break;
}
}
}
if (strlen(tbuf))
break;
memset(&tbuf, 0, sizeof(tbuf));
} else if (strcasecmp((*tmpa)->name, "defdomain") == 0) {
Syslog('n', "getnlent: trying default domain");
if (nodebuf.addr.domain) {
for (tmpd = &nl_domsuffix; *tmpd; tmpd=&((*tmpd)->next)) {
if ((*tmpd)->zone == nodebuf.addr.zone) {
snprintf(tbuf, 256, "f%d.n%d.z%d.%s.%s", nodebuf.addr.node, nodebuf.addr.net,
nodebuf.addr.zone, nodebuf.addr.domain, (*tmpd)->name);
Syslog('n', "getnlent: will try default domain \"%s\"", tbuf);
nodebuf.url = xstrcat(nodebuf.url, tbuf);
break;
}
}
} else {
Syslog('+', "getnlent: no domain name for zone %d, check setup", nodebuf.addr.zone);
}
if (strlen(tbuf))
break;
Syslog('n', "getnlent: no matching default domain found for zone %d", nodebuf.addr.zone);
memset(&tbuf, 0, sizeof(tbuf));
}
}
}
if (strlen(tbuf) == 0) {
Syslog('+', "getnlent: no FQDN found, cannot call");
if (nodebuf.url)
free(nodebuf.url);
nodebuf.url = NULL;
} else if (strchr(tbuf, ':') == NULL) {
/*
* No optional port number, add one from the default
* for this protocol.
*/
snprintf(tbuf, 256, ":%u", tport);
nodebuf.url = xstrcat(nodebuf.url, tbuf);
} else if (tbuf[0] == '[') {
/*
* Literal IPv6 address, check for port number after
* ending bracket.
*/
s = strchr(tbuf, ']');
if (s == NULL) {
Syslog('+', "getnlent: invalid IPv6 address, cannot call");
if (nodebuf.url)
free(nodebuf.url);
nodebuf.url = NULL;
}
if (strchr(s, ':') == NULL) {
/*
* No port number given; add default.
*/
snprintf(tbuf, 256, ":%u", tport);
nodebuf.url = xstrcat(nodebuf.url, tbuf);
}
}
} else if (nodebuf.dflags & myisdn) {
nodebuf.url = xstrcpy((char *)"isdn://");
nodebuf.url = xstrcat(nodebuf.url, nodebuf.phone);
} else if (nodebuf.mflags & mypots) {
nodebuf.url = xstrcpy((char *)"pots://");
nodebuf.url = xstrcat(nodebuf.url, nodebuf.phone);
}
fclose(fp);
nodebuf.addr.name = nodebuf.sysop;
if (nodebuf.addr.domain)
free(nodebuf.addr.domain);
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);
/*
* FSP-1033, the ICM (IP Continuous Mail) flag.
*/
nodebuf.can_pots = (nodebuf.mflags || nodebuf.dflags) ? TRUE : FALSE;
nodebuf.can_ip = (nodebuf.iflags) ? TRUE : FALSE;
nodebuf.is_cm = (nodebuf.oflags & 0x00000001) ? TRUE : FALSE;
nodebuf.is_icm = (nodebuf.oflags & 0x00000002) ? TRUE : FALSE;
/*
* Now correct if node is ION with a CM flag instead of ICM flag.
* This is the case the first months after approval of the ICM flag
* and with nodes who won't change flags.
*/
if (!nodebuf.can_pots && nodebuf.can_ip && nodebuf.is_cm && !nodebuf.is_icm) {
Syslog('n', "getnlent: correct CM into ICM flag");
nodebuf.is_cm = FALSE;
nodebuf.is_icm = TRUE;
}
Syslog('n', "getnlent: system %s, %s", nodebuf.name, nodebuf.location);
Syslog('n', "getnlent: sysop %s, %s", nodebuf.sysop, nodebuf.phone);
Syslog('n', "getnlent: URL %s", printable(nodebuf.url, 0));
Syslog('n', "getnlent: online POTS %s CM %s, IP %s ICM %s", nodebuf.can_pots ?"Yes":"No",
nodebuf.is_cm ?"Yes":"No", nodebuf.can_ip ?"Yes":"No", nodebuf.is_icm ?"Yes":"No");
free(mydomain);
return &nodebuf;
badsyntax:
WriteError("nodelist %d offset +%lu: bad syntax in line \"%s\"", ndx.fileno, (unsigned int)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;
nodebuf.url = NULL;
free(mydomain);
return &nodebuf;
}
node_list *searchSysop( char *SysopName )
{
char nodeuserpath[256];
FILE *fp;
char fixedSysopName[36];
nlusr nluEntry;
faddr addr;
node_list *result;
node *nlEntry;
Syslog('n', "searchSysop: Arg(%s) started", SysopName );
result = NULL;
snprintf(nodeuserpath, 256, "%s/%s", CFG.nodelists, "node.users");
if ((fp = fopen(nodeuserpath, "r")) == NULL) {
WriteError("$Can't open %s", nodeuserpath);
return NULL;
}
/*
* fixup incoming sysop name to have _ for space
*/
memset( fixedSysopName, 0, 36 );
int i;
for ( i=0; i<strlen( SysopName ); i++ ){
if ( SysopName[i] == ' ' ){
fixedSysopName[i] = '_';
} else {
fixedSysopName[i] = SysopName[i];
}
}
while (fread(&nluEntry, sizeof(nluEntry), 1, fp) == 1) {
if ( strcmp( fixedSysopName, nluEntry.user ) == 0 ){
addr.zone = nluEntry.zone;
addr.net = nluEntry.net;
addr.node = nluEntry.node;
addr.point = nluEntry.point;
addr.name = fixedSysopName;
addr.domain = NULL;
nlEntry = getnlent( &addr );
if ( NULL == nlEntry ) {
/* yikes */
Syslog('n',"searchSysop: Something terribly wrong happened with getnlent looking up (%d:%d/%d.%d)",
addr.zone, addr.net, addr.node, addr.point );
return NULL;
}
Syslog('n',"searchSysop: found NL Entry: Name:(%s) @ (%s)", nlEntry->name, nlEntry->location);
node_list *thisresult = result;
if (thisresult == NULL) {
result = malloc( sizeof(node_list));
result->next = NULL;
thisresult = result;
} else {
while ( thisresult->next != NULL ){
thisresult = thisresult->next;
}
thisresult->next = malloc( sizeof(node_list));
thisresult = thisresult->next;
thisresult->next = NULL;
}
thisresult->addr.zone = nlEntry->addr.zone;
thisresult->addr.net = nlEntry->addr.net;
thisresult->addr.node = nlEntry->addr.node;
thisresult->addr.point = nlEntry->addr.point;
strcpy( thisresult->Sysop, nlEntry->sysop );
strcpy( thisresult->Location, nlEntry->location);
strcpy( thisresult->Name, nlEntry->name );
}
if ( nluEntry.user[0] > fixedSysopName[0] ) { // Since list is sorted, abort once we get names that start after this one
break;
}
}
fclose( fp );
Syslog('n', "searchSysop: Arg(%s) ended", SysopName );
return result;
}