Fixed nlookup and bfindex for pointlist handling. Added -C config option to utils. Updated man-files
All checks were successful
Altlinux build / build-alt (push) Successful in 2m46s
Archlinux build / build-arch (push) Successful in 3m19s
Archlinux build / make-test (push) Successful in 1m0s
Debian build / build-ubuntu (push) Successful in 4m7s

This commit is contained in:
Alexey Khromov 2025-04-20 21:56:44 +03:00
parent ff329a7602
commit 3a9ee4727a
13 changed files with 174 additions and 23 deletions

View File

@ -284,3 +284,5 @@ Alexey Khromov (zx@zxalexis.ru)
+ Added tests with socat and integrate it with CI + Added tests with socat and integrate it with CI
+ Fixed some minor lint errors by PVS-Studio + Fixed some minor lint errors by PVS-Studio
+ Fixed RPM spec-file to make builds for AltLinux + Fixed RPM spec-file to make builds for AltLinux
+ Added fail2ban filter to contrib
+ Fixed node/point-lists indexing and parsing for points listed

1
debian/changelog vendored
View File

@ -1,6 +1,7 @@
bforce (0.26.2) UNRELEASED; urgency=medium bforce (0.26.2) UNRELEASED; urgency=medium
* Added tests to CI actions * Added tests to CI actions
* Fixed nodelist indexing for points handling
-- Alexey Khromov <zx@zxalexis.ru> Sat, 19 Apr 2025 07:43:54 +0300 -- Alexey Khromov <zx@zxalexis.ru> Sat, 19 Apr 2025 07:43:54 +0300

View File

@ -2,7 +2,7 @@
.SH NAME .SH NAME
bfindex \- nodelist compiler for bforce bfindex \- nodelist compiler for bforce
.SH SYNOPSYS .SH SYNOPSYS
\fBbfindex [-fh]\fR \fBbfindex [-fh] [-C\fIconfig\fB]\fR
.SH DESCRIPTION .SH DESCRIPTION
\fBbfindex\fP is a nodelist compiler for BinkleyForce FTN mailer. \fBbfindex\fP is a nodelist compiler for BinkleyForce FTN mailer.

View File

@ -2,7 +2,7 @@
.SH NAME .SH NAME
bfstat \- binkley style outbound statistic bfstat \- binkley style outbound statistic
.SH SYNOPSYS .SH SYNOPSYS
\fBbfstat [-afhprst] [-n \fInumber\fB]\fR \fBbfstat [-afhprst] [-n \fInumber\fB] [-C\fIconfig\fB]\fR
.SH DESCRIPTION .SH DESCRIPTION
\fBbfstat\fP help you to see your outbound statistic in human readable \fBbfstat\fP help you to see your outbound statistic in human readable
form. form.

View File

@ -2,7 +2,7 @@
.SH NAME .SH NAME
Bnlookup \- Nodelist search tool for bforce Bnlookup \- Nodelist search tool for bforce
.SH SYNOPSYS .SH SYNOPSYS
\fBnlookup [-rh]\fR \fBnlookup [-rh] [-C\fIconfig\fB]\fR
.SH DESCRIPTION .SH DESCRIPTION
\fBnlookup\fP is a nodelist search tool for BinkleyForce FTN mailer. \fBnlookup\fP is a nodelist search tool for BinkleyForce FTN mailer.

View File

@ -58,6 +58,7 @@ struct debuglevel {
{ "Daemon", D_DAEMON }, { "Daemon", D_DAEMON },
{ "Free", D_FREE }, { "Free", D_FREE },
{ "24554", D_24554 }, { "24554", D_24554 },
{ "Index", D_INDEX },
// { "Daemon", D_DAEMON }, // { "Daemon", D_DAEMON },
{ "Full", D_FULL }, { "Full", D_FULL },
{ NULL, 0 } { NULL, 0 }

View File

@ -198,6 +198,54 @@ int nodelist_parse_Txy(s_node *node, const char *xy)
return 0; return 0;
} }
/*****************************************************************************
* Pointlist string parser
*
* Arguments:
* node put here all obtained information
* str pointer to the nodelist string
*
* Return value:
* zero value if string was parsed successfuly, and non-zero if wasn't
*/
int nodelist_parsepoint(s_node *node, char *str)
{
char *argv[NODELIST_POSFLAGS+1];
char *p;
int cnt;
DEB((D_NODELIST,"nodelist: parsepoint %s", str));
cnt = string_parse(argv, NODELIST_POSFLAGS+1, str, ',');
if( cnt < NODELIST_POSFLAGS-1 )
return -1;
DEB((D_NODELIST,"nodelist: parsepoint OK: %d", cnt));
strnxcpy(node->name, argv[NODELIST_POSNAME], sizeof(node->name));
DEB((D_NODELIST,"nodelist: parsepoint sys: %s", node->name));
strnxcpy(node->location, argv[NODELIST_POSLOCATION], sizeof(node->location));
DEB((D_NODELIST,"nodelist: parsepoint loc: %s", node->location));
strnxcpy(node->sysop, argv[NODELIST_POSSYSOP], sizeof(node->sysop));
DEB((D_NODELIST,"nodelist: parsepoint zyz: %s", node->sysop));
strnxcpy(node->phone, argv[NODELIST_POSPHONE], sizeof(node->phone));
DEB((D_NODELIST,"nodelist: parsepoint pho: %s", node->phone));
if (argv[NODELIST_POSFLAGS])
strnxcpy(node->flags, argv[NODELIST_POSFLAGS], sizeof(node->flags));
DEB((D_NODELIST,"nodelist: parsepoint fl: %s", node->flags));
if (argv[NODELIST_POSSPEED])
node->speed = atoi(argv[NODELIST_POSSPEED]);
DEB((D_NODELIST, "nodelist: Parsed common values SYS: %s, ZYZ: %s, LOC: %s, PHONE: %s", node->name, node->sysop, node->location, node->phone));
/*
* Replace all '_' by space character
*/
string_replchar(node->name, '_', ' ');
string_replchar(node->location, '_', ' ');
string_replchar(node->sysop, '_', ' ');
node->keyword = KEYWORD_POINT;
return 0;
}
/***************************************************************************** /*****************************************************************************
* Nodelist string parser * Nodelist string parser
* *
@ -212,7 +260,7 @@ int nodelist_parsestring(s_node *node, char *str)
{ {
char *argv[NODELIST_POSFLAGS+1]; char *argv[NODELIST_POSFLAGS+1];
char *p; char *p;
DEB((D_NODELIST,"nodelist: parsestring %s", str));
if( string_parse(argv, NODELIST_POSFLAGS+1, str, ',') != NODELIST_POSFLAGS+1 ) if( string_parse(argv, NODELIST_POSFLAGS+1, str, ',') != NODELIST_POSFLAGS+1 )
return -1; return -1;
@ -671,6 +719,7 @@ int nodelist_lookup_string(char *buffer, size_t buflen, s_faddr addr)
*/ */
for( ptrl = conf_first(cf_nodelist); ptrl; ptrl = conf_next(ptrl) ) for( ptrl = conf_first(cf_nodelist); ptrl; ptrl = conf_next(ptrl) )
{ {
DEB((D_NODELIST,"nl_lookup_string: using %s",ptrl->d.falist.what));
if( ftn_addrcomp_mask(addr, ptrl->d.falist.addr) == 0 ) if( ftn_addrcomp_mask(addr, ptrl->d.falist.addr) == 0 )
{ {
if( (nlp = nodelist_open(ndldir, ptrl->d.falist.what, NODELIST_READ)) ) if( (nlp = nodelist_open(ndldir, ptrl->d.falist.what, NODELIST_READ)) )
@ -701,10 +750,24 @@ int nodelist_lookup(s_node *node, s_faddr addr)
if( nodelist_lookup_string(buf, sizeof(buf), addr) == 0 ) if( nodelist_lookup_string(buf, sizeof(buf), addr) == 0 )
{ {
node->listed = TRUE; node->listed = TRUE;
if( nodelist_parsestring(node, buf) == -1 ) if (addr.point == 0)
{ {
log("invalid nodelist string for address %s", if( nodelist_parsestring(node, buf) == -1 )
ftn_addrstr(abuf, addr)); {
DEB((D_NODELIST,"invalid nodelist string for address %s",
ftn_addrstr(abuf, addr)));
log("invalid nodelist string for address %s",
ftn_addrstr(abuf, addr));
}
} else {
if ( nodelist_parsepoint(node, buf) == -1 )
{
DEB((D_NODELIST,"invalid nodelist string for address %s",
ftn_addrstr(abuf, addr)));
log("invalid nodelist string for address %s",
ftn_addrstr(abuf, addr));
}
node->addr = addr;
} }
return 0; return 0;
} }

View File

@ -598,6 +598,8 @@ int string_parse(char **dest, int items, char *str, int separator)
{ {
int count = 0; int count = 0;
char *p = str; char *p = str;
//if ( *((unsigned char *)p) == separator )
// p++;
dest[count++] = str; dest[count++] = str;
@ -606,6 +608,7 @@ int string_parse(char **dest, int items, char *str, int separator)
if( *((unsigned char *)p) == separator ) if( *((unsigned char *)p) == separator )
{ {
*p++ = '\0'; *p++ = '\0';
// DEB((D_INDEX,"Parsed string: %s", dest[count]));
dest[count++] = p; dest[count++] = p;
} else } else
++p; ++p;

View File

@ -29,11 +29,12 @@ bool eventexpr(s_expr *expr)
static void usage(void) static void usage(void)
{ {
printf_usage("nodelist compiler", printf_usage("nodelist compiler",
"usage: bfindex [-fh]\n" "usage: bfindex [-fh] [-C config]\n"
"\n" "\n"
"options:\n" "options:\n"
" -f force nodelist compiling\n" " -f force nodelist compiling\n"
" -h show this help message\n" " -h show this help message\n"
" -C config use config\n"
"\n" "\n"
); );
} }
@ -42,6 +43,7 @@ static int nodelist_makeindex(s_nodelist *nlp, s_faddr addr)
{ {
s_bni bni; s_bni bni;
char buf[1024]; char buf[1024];
bool modepoint = FALSE;
long countnodes = 0L; long countnodes = 0L;
long countlines = 0L; long countlines = 0L;
enum nodelist_keyword keyword; enum nodelist_keyword keyword;
@ -52,6 +54,9 @@ static int nodelist_makeindex(s_nodelist *nlp, s_faddr addr)
bni.node = addr.node; bni.node = addr.node;
bni.point = addr.point; bni.point = addr.point;
DEB((D_INDEX, "Start create index for addr: %u:%u/%u.%u", bni.zone,
bni.net, bni.node, bni.point));
if( nodelist_createheader(nlp) == -1 ) if( nodelist_createheader(nlp) == -1 )
{ {
log("cannot create nodelist index header"); log("cannot create nodelist index header");
@ -80,13 +85,16 @@ static int nodelist_makeindex(s_nodelist *nlp, s_faddr addr)
if( (p = strchr(buf, ',')) ) if( (p = strchr(buf, ',')) )
{ {
//DEB((D_INDEX, "index: parse comma: %s", p ));
*p++ = '\0'; *p++ = '\0';
if( (q = strchr(p, ',')) ) *q = '\0'; if( (q = strchr(p, ',')) ) *q = '\0';
} }
if( p == NULL || *p == '\0' ) if( p == NULL || *p == '\0' )
{ {
log("incorrect nodelist line %ld: Short line", countlines); log("incorrect nodelist line %ld: Short line", countlines);
DEB((D_INDEX,"incorrect nodelist line %ld: Short line", countlines));
continue; continue;
} }
@ -94,20 +102,28 @@ static int nodelist_makeindex(s_nodelist *nlp, s_faddr addr)
{ {
log("incorrect nodelist line %d: Bad keyword \"%s\"", log("incorrect nodelist line %d: Bad keyword \"%s\"",
countlines, buf); countlines, buf);
DEB((D_INDEX,"incorrect nodelist line %d: Bad keyword \"%s\"",
countlines, buf));
continue; continue;
} }
//DEB((D_INDEX,"index: keyword=%d", keyword));
if( keyword == KEYWORD_BOSS ) if( keyword == KEYWORD_BOSS )
{ {
s_faddr tmpaddr; s_faddr tmpaddr;
if( ftn_addrparse(&tmpaddr, p, FALSE) ) if( ftn_addrparse(&tmpaddr, p, FALSE) )
{ {
DEB((D_INDEX,"incorrect nodelist line %ld: Bad boss address \"%s\"",
countlines, p));
log("incorrect nodelist line %ld: Bad boss address \"%s\"", log("incorrect nodelist line %ld: Bad boss address \"%s\"",
countlines, p); countlines, p);
} }
else else
{ {
DEB((D_INDEX,"index: parsing Boss %u:%u/%u.0",
tmpaddr.zone, tmpaddr.net, tmpaddr.node));
if (addr.point == -1 )
modepoint = true;
bni.zone = tmpaddr.zone; bni.zone = tmpaddr.zone;
bni.net = tmpaddr.net; bni.net = tmpaddr.net;
bni.node = tmpaddr.node; bni.node = tmpaddr.node;
@ -131,36 +147,49 @@ static int nodelist_makeindex(s_nodelist *nlp, s_faddr addr)
bni.node = 0; bni.node = 0;
bni.point = 0; bni.point = 0;
bni.hub = 0; bni.hub = 0;
modepoint = false;
break; break;
case KEYWORD_REGION: case KEYWORD_REGION:
bni.net = value; bni.net = value;
bni.node = 0; bni.node = 0;
bni.point = 0; bni.point = 0;
bni.hub = 0; bni.hub = 0;
modepoint = false;
break; break;
case KEYWORD_HOST: case KEYWORD_HOST:
bni.net = value; bni.net = value;
bni.node = 0; bni.node = 0;
bni.point = 0; bni.point = 0;
bni.hub = 0; bni.hub = 0;
modepoint = false;
break; break;
case KEYWORD_HUB: case KEYWORD_HUB:
bni.node = value; bni.node = value;
bni.point = 0; bni.point = 0;
bni.hub = value; bni.hub = value;
modepoint = false;
break; break;
case KEYWORD_EMPTY: case KEYWORD_EMPTY:
if (modepoint)
{
//DEB((D_INDEX,"found empty value=%u",value ));
bni.point = value;
break;
}
case KEYWORD_PVT: case KEYWORD_PVT:
case KEYWORD_HOLD: case KEYWORD_HOLD:
case KEYWORD_DOWN: case KEYWORD_DOWN:
bni.node = value; bni.node = value;
bni.point = 0; bni.point = 0;
modepoint = false;
break; break;
case KEYWORD_POINT: case KEYWORD_POINT:
DEB((D_INDEX,"index: kw point"));
bni.point = value; bni.point = value;
break; break;
default: default:
ASSERT_MSG(); ASSERT_MSG();
DEB((D_INDEX,"index: default assert"));
} }
if( nodelist_putindex(nlp, &bni) == -1 ) if( nodelist_putindex(nlp, &bni) == -1 )
@ -182,10 +211,12 @@ int main(int argc, char *argv[])
{ {
s_cval_entry *cfptr; s_cval_entry *cfptr;
char *nodelistdir = NULL; char *nodelistdir = NULL;
char *confname = NULL;
time_t starttime = 0L; time_t starttime = 0L;
bool forcecompile = FALSE; bool forcecompile = FALSE;
long countnodes = 0L; long countnodes = 0L;
char c; char c;
int rc = 0;
/* Initialise random number generation */ /* Initialise random number generation */
(void)srand((unsigned)time(0)); (void)srand((unsigned)time(0));
@ -193,7 +224,7 @@ int main(int argc, char *argv[])
(void)setlocale(LC_ALL, ""); (void)setlocale(LC_ALL, "");
/* Set our name (for logging only) */ /* Set our name (for logging only) */
while( (c = getopt(argc, argv, "hf")) != (char)-1 ) while( (c = getopt(argc, argv, "hfC:")) != (char)-1 )
{ {
switch( c ) { switch( c ) {
case 'f': case 'f':
@ -202,6 +233,10 @@ int main(int argc, char *argv[])
case 'h': case 'h':
usage(); usage();
exit(0); exit(0);
case 'C':
if( confname || !optarg ) { usage(); exit(5); }
confname = (char *)xstrcpy(optarg);
break;
default: default:
usage(); usage();
exit(5); exit(5);
@ -209,8 +244,14 @@ int main(int argc, char *argv[])
} }
if( conf_readconf(conf_getconfname(), 0, false) ) if( confname && *confname )
rc = conf_readconf(confname, 0, false);
else
rc = conf_readconf(conf_getconfname(), 0, false);
if( rc )
{ {
log("Can not find config");
exit(1); exit(1);
} }

View File

@ -44,7 +44,7 @@ bool eventexpr(s_expr *expr)
static void usage(void) static void usage(void)
{ {
printf_usage("outbound viewer", printf_usage("outbound viewer",
"usage: bfstat [-afhprst] [-n<number>]\n" "usage: bfstat [-C config] [-afhprst] [-n<number>]\n"
"\n" "\n"
"options:\n" "options:\n"
" -a sort by FTN address (default)\n" " -a sort by FTN address (default)\n"
@ -56,6 +56,7 @@ static void usage(void)
" -r reverse order while sorting\n" " -r reverse order while sorting\n"
" -s sort by total files size\n" " -s sort by total files size\n"
" -t disable total sizes printing\n" " -t disable total sizes printing\n"
" -C config use config file\n"
"\n" "\n"
); );
} }
@ -248,8 +249,10 @@ int main(int argc, char *argv[])
s_opts opts; s_opts opts;
s_sysqueue queue; s_sysqueue queue;
s_outbound_callback_data ocb; s_outbound_callback_data ocb;
char *confname = NULL;
char c; char c;
int i; int i;
int rc = 0;
bfstat_opts_default(&opts); bfstat_opts_default(&opts);
@ -288,6 +291,10 @@ int main(int argc, char *argv[])
if( ISDEC(optarg) ) if( ISDEC(optarg) )
opts.nodeslimit = atoi(optarg); opts.nodeslimit = atoi(optarg);
break; break;
case 'C':
if( confname || !optarg ) { usage(); exit(BFERR_FATALERROR); }
confname = (char *)xstrcpy(optarg);
break;
default: default:
usage(); usage();
exit(1); exit(1);
@ -301,8 +308,16 @@ int main(int argc, char *argv[])
/* Initialise current locale */ /* Initialise current locale */
(void)setlocale(LC_ALL, ""); (void)setlocale(LC_ALL, "");
if( conf_readconf(conf_getconfname(), 0, false) ) if( confname && *confname )
exit(1); rc = conf_readconf(confname, 0, false);
else
rc = conf_readconf(conf_getconfname(), 0, false);
if( rc )
{
log("Can not find config");
exit(BFERR_FATALERROR);
}
memset(&ocb, '\0', sizeof(s_outbound_callback_data)); memset(&ocb, '\0', sizeof(s_outbound_callback_data));
ocb.callback = out_handle_sysqueue; ocb.callback = out_handle_sysqueue;

View File

@ -28,12 +28,13 @@ bool eventexpr(s_expr *expr)
static void usage(void) static void usage(void)
{ {
printf_usage("nodelist lookup utility", printf_usage("nodelist lookup utility",
"usage: nlookup [-rmh] <address>\n" "usage: nlookup [-C config] [-rmh] <address>\n"
"\n" "\n"
"options:\n" "options:\n"
" -r show nodelist string\n" " -r show nodelist string\n"
" -m show email address\n" " -m show email address\n"
" -h show this help message\n" " -h show this help message\n"
" -C config use config file\n"
"\n" "\n"
); );
} }
@ -82,7 +83,7 @@ void print_nodeinfo(const s_node *node)
timevec_check(&node->worktime, now) ? "false" : "true"); timevec_check(&node->worktime, now) ? "false" : "true");
} }
if( node->sysop && *node->sysop && strcmp(node->sysop, "<none>") ) if( (node->keyword != KEYWORD_POINT) && node->sysop && *node->sysop && strcmp(node->sysop, "<none>") )
{ {
char username[BNI_MAXSYSOP+1]; char username[BNI_MAXSYSOP+1];
@ -127,6 +128,8 @@ int main(int argc, char *argv[])
s_node node; s_node node;
s_faddr addr; s_faddr addr;
char ch; char ch;
int rc = 0;
char *confname = NULL;
bool rawstring = FALSE; bool rawstring = FALSE;
bool emailaddr = FALSE; bool emailaddr = FALSE;
@ -135,7 +138,7 @@ int main(int argc, char *argv[])
/* Initialise current locale */ /* Initialise current locale */
(void)setlocale(LC_ALL, ""); (void)setlocale(LC_ALL, "");
while( (ch=getopt(argc, argv, "hrm")) != (char)-1 ) while( (ch=getopt(argc, argv, "hdrmC:")) != (char)-1 )
{ {
switch( ch ) { switch( ch ) {
case 'h': case 'h':
@ -147,6 +150,10 @@ int main(int argc, char *argv[])
case 'm': case 'm':
emailaddr = TRUE; emailaddr = TRUE;
break; break;
case 'C':
if( confname || !optarg ) { usage(); exit(BFERR_FATALERROR); }
confname = (char *)xstrcpy(optarg);
break;
default: default:
usage(); usage();
exit(BFERR_FATALERROR); exit(BFERR_FATALERROR);
@ -159,8 +166,18 @@ int main(int argc, char *argv[])
exit(BFERR_FATALERROR); exit(BFERR_FATALERROR);
} }
if( conf_readconf(conf_getconfname(), 0, false) ) if( confname && *confname )
rc = conf_readconf(confname, 0, false);
else
rc = conf_readconf(conf_getconfname(), 0, false);
if( rc )
{
DEB((D_NODELIST,"nlookup: Can not find config"));
exit(BFERR_FATALERROR); exit(BFERR_FATALERROR);
}
DEB((D_NODELIST,"Starting nlookup"));
if( rawstring ) if( rawstring )
{ {
@ -171,10 +188,16 @@ int main(int argc, char *argv[])
} }
else if( nodelist_lookup(&node, addr) == 0 ) else if( nodelist_lookup(&node, addr) == 0 )
{ {
if( emailaddr ) if (addr.point == 0) {
print_nodemail(&node); if( emailaddr )
else print_nodemail(&node);
print_nodeinfo(&node); else
print_nodeinfo(&node);
}
else
{
print_nodeinfo(&node);
}
} }
deinit_conf(); deinit_conf();

View File

@ -48,6 +48,7 @@ enum { LOG_FILE_DAEMON, LOG_FILE_SESSION, LOG_FILE_DEBUG, LOG_FILE_HISTORY };
#define D_DAEMON 0x0001000L #define D_DAEMON 0x0001000L
#define D_24554 0x0002000L #define D_24554 0x0002000L
#define D_FREE 0x0004000L #define D_FREE 0x0004000L
#define D_INDEX 0x0008000L
#define D_FULL 0xfffffffL #define D_FULL 0xfffffffL
#endif #endif

View File

@ -159,6 +159,7 @@ s_node;
int nodelist_checkflag(const char *nodeflags, const char *flag); int nodelist_checkflag(const char *nodeflags, const char *flag);
int nodelist_keywordval(const char *keyword); int nodelist_keywordval(const char *keyword);
int nodelist_parsepoint(s_node *node, char *str);
int nodelist_parsestring(s_node *node, char *str); int nodelist_parsestring(s_node *node, char *str);
s_nodelist *nodelist_open(const char *dir, char *name, int mode); s_nodelist *nodelist_open(const char *dir, char *name, int mode);
int nodelist_checkheader(s_nodelist *nlp); int nodelist_checkheader(s_nodelist *nlp);