You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
526 lines
10 KiB
C
526 lines
10 KiB
C
/*
|
|
* binkleyforce -- unix FTN mailer project
|
|
*
|
|
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
|
|
*
|
|
* This program 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 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* $Id$
|
|
*/
|
|
|
|
#include "includes.h"
|
|
#include "confread.h"
|
|
#include "logger.h"
|
|
#include "util.h"
|
|
|
|
#define ADDRNUM_MIN 0x0000
|
|
#define ADDRNUM_MAX 0x7fff
|
|
|
|
static int addrstr2int(const char *s)
|
|
{
|
|
int val = atoi(s);
|
|
|
|
if( val < ADDRNUM_MIN )
|
|
val = ADDRNUM_MIN;
|
|
else if( val > ADDRNUM_MAX )
|
|
val = ADDRNUM_MAX;
|
|
|
|
return val;
|
|
}
|
|
|
|
char *addrint2str(char *buffer, int val)
|
|
{
|
|
if( val == -1 )
|
|
strcpy(buffer, "*");
|
|
else if( val < ADDRNUM_MIN )
|
|
strcpy(buffer, "MIN");
|
|
else if( val > ADDRNUM_MAX )
|
|
strcpy(buffer, "MAX");
|
|
else
|
|
sprintf(buffer, "%d", val);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
static int ftn_addrparse_fido(s_faddr *addr, const char *s, bool wildcard)
|
|
{
|
|
bool badaddr = 0;
|
|
bool stop = 0;
|
|
bool gotzone = 0;
|
|
bool gotnet = 0;
|
|
bool gotnode = 0;
|
|
bool gotpoint = 0;
|
|
const char *p = s;
|
|
|
|
ASSERT(s != NULL);
|
|
|
|
while( !stop && !badaddr )
|
|
{
|
|
switch(*p) {
|
|
case ':':
|
|
if( !gotzone && isdigit(*s) )
|
|
{
|
|
gotzone = 1;
|
|
addr->zone = addrstr2int(s);
|
|
s = ++p;
|
|
}
|
|
else if( !gotzone && wildcard && *s == '*' )
|
|
{
|
|
gotzone = 1;
|
|
addr->zone = -1;
|
|
s = ++p;
|
|
}
|
|
else badaddr = 1;
|
|
break;
|
|
|
|
case '/':
|
|
if( !gotnet && isdigit(*s) )
|
|
{
|
|
gotnet = 1;
|
|
addr->net = addrstr2int(s);
|
|
s = ++p;
|
|
}
|
|
else if( !gotnet && wildcard && *s == '*' )
|
|
{
|
|
gotnet = 1;
|
|
addr->net = -1;
|
|
s = ++p;
|
|
}
|
|
else if( *s != '/' ) badaddr = 1;
|
|
else ++p;
|
|
break;
|
|
|
|
case '.':
|
|
if( *s == '/' ) ++s;
|
|
if( !gotnode && isdigit(*s) )
|
|
{
|
|
gotnode = 1;
|
|
addr->node = addrstr2int(s);
|
|
s = ++p;
|
|
}
|
|
else if( !gotnode && wildcard && *s == '*' )
|
|
{
|
|
gotnode = 1;
|
|
addr->node = -1;
|
|
s = ++p;
|
|
}
|
|
else if( *s != '.' ) badaddr = 1;
|
|
else ++p;
|
|
break;
|
|
|
|
case '@':
|
|
case '\0':
|
|
if( gotzone && !gotnet ) { badaddr = 1; break; }
|
|
|
|
if( *s == '/' )
|
|
{
|
|
++s;
|
|
if( !gotnode && isdigit(*s) )
|
|
{
|
|
gotnode = 1;
|
|
addr->node = addrstr2int(s);
|
|
}
|
|
else if( !gotnode && wildcard && *s == '*' )
|
|
{
|
|
gotnode = 1;
|
|
addr->node = -1;
|
|
}
|
|
else badaddr = 1;
|
|
}
|
|
else if( *s == '.' )
|
|
{
|
|
++s;
|
|
if( !gotpoint && isdigit(*s) )
|
|
{
|
|
gotpoint = 1;
|
|
addr->point = addrstr2int(s);
|
|
}
|
|
else if( !gotpoint && wildcard && *s == '*' )
|
|
{
|
|
gotpoint = 1;
|
|
addr->point = -1;
|
|
}
|
|
else badaddr = 1;
|
|
}
|
|
else if( isdigit(*s) )
|
|
{
|
|
if( !gotnode )
|
|
{
|
|
gotnode = 1;
|
|
addr->node = addrstr2int(s);
|
|
}
|
|
else if( !gotpoint )
|
|
{
|
|
gotpoint = 1;
|
|
addr->point = addrstr2int(s);
|
|
}
|
|
else badaddr = 1;
|
|
}
|
|
else if( wildcard && *s == '*' )
|
|
{
|
|
if( !gotnode )
|
|
{
|
|
gotnode = 1;
|
|
addr->node = -1;
|
|
}
|
|
else if( !gotpoint )
|
|
{
|
|
gotpoint = 1;
|
|
addr->point = -1;
|
|
}
|
|
else badaddr = 1;
|
|
}
|
|
else badaddr = 1;
|
|
stop = 1;
|
|
break;
|
|
|
|
default:
|
|
if( isdigit(*p) || (wildcard && *p == '*') )
|
|
{ ++p; }
|
|
else
|
|
{ badaddr = 1; }
|
|
}
|
|
}
|
|
|
|
if( !badaddr && *p++ == '@' && *p )
|
|
{
|
|
strnxcpy(addr->domain, string_printable(p), sizeof(addr->domain));
|
|
}
|
|
|
|
return badaddr;
|
|
}
|
|
|
|
static int ftn_addrparse_inet(s_faddr *addr, const char *s, bool wildcard)
|
|
{
|
|
bool badaddr = 0;
|
|
bool stop = 0;
|
|
bool gotzone = 0;
|
|
bool gotnet = 0;
|
|
bool gotnode = 0;
|
|
bool gotpoint = 0;
|
|
const char *p = s;
|
|
|
|
ASSERT(s != NULL);
|
|
|
|
while( !stop && !badaddr )
|
|
{
|
|
if( *p == '.' || *p == '\0' )
|
|
{
|
|
if( *p == '\0' ) stop = 1;
|
|
|
|
switch(*s++) {
|
|
case 'p':
|
|
case 'P':
|
|
if( !gotpoint && isdigit(*s) )
|
|
{
|
|
gotpoint = 1;
|
|
addr->point = addrstr2int(s);
|
|
s = ++p;
|
|
}
|
|
else badaddr = 1;
|
|
break;
|
|
case 'f':
|
|
case 'F':
|
|
if( !gotnet && !gotzone && !gotnode && isdigit(*s) )
|
|
{
|
|
gotnode = 1;
|
|
addr->node = addrstr2int(s);
|
|
s = ++p;
|
|
}
|
|
else badaddr = 1;
|
|
break;
|
|
case 'n':
|
|
case 'N':
|
|
if( gotnode && !gotzone && !gotnet && isdigit(*s) )
|
|
{
|
|
gotnet = 1;
|
|
addr->net = addrstr2int(s);
|
|
s = ++p;
|
|
}
|
|
else badaddr = 1;
|
|
break;
|
|
case 'z':
|
|
case 'Z':
|
|
if( gotnode && gotnet && !gotzone && isdigit(*s) )
|
|
{
|
|
gotzone = 1;
|
|
addr->zone = addrstr2int(s);
|
|
if( *p++ == '.' && *p )
|
|
{
|
|
strnxcpy(addr->domain, string_printable(p), sizeof(addr->domain));
|
|
}
|
|
stop = 1;
|
|
}
|
|
else badaddr = 1;
|
|
break;
|
|
default:
|
|
badaddr = 1;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
++p;
|
|
}
|
|
}
|
|
|
|
return badaddr;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Parse FTN address (can be specified in traditional form (X:X/X.X) as
|
|
* well as in domain form (pX.fX.nX.zX.domain))
|
|
*
|
|
* Arguments:
|
|
* addr we will put parsed address here
|
|
* s pointer to the null-terminated string with address
|
|
* wildcard set FALSE if you want forbid wildcards processing
|
|
*
|
|
* Return value:
|
|
* zero value if addres was parsed successfuly, and non-zero if wasn't
|
|
*/
|
|
int ftn_addrparse(s_faddr *addr, const char *s, bool wildcard)
|
|
{
|
|
const char *p;
|
|
bool stop = 0;
|
|
bool badaddr = 0;
|
|
|
|
ASSERT(s != NULL);
|
|
|
|
memset(addr, '\0', sizeof(s_faddr));
|
|
|
|
/*
|
|
* Detect the address form (domain or traditional)
|
|
*/
|
|
for( p = s; *p && !stop && !badaddr; p++ )
|
|
{
|
|
switch( *p ) {
|
|
case '*':
|
|
if( wildcard == FALSE ) badaddr = 1;
|
|
case '@':
|
|
stop = 1;
|
|
case ':':
|
|
case '/':
|
|
case '.':
|
|
addr->inetform = 0;
|
|
break;
|
|
case 'p':
|
|
case 'P':
|
|
case 'f':
|
|
case 'F':
|
|
addr->inetform = 1;
|
|
stop = 1;
|
|
break;
|
|
default:
|
|
if( !isdigit(*p) ) badaddr = 1;
|
|
}
|
|
}
|
|
|
|
if( !badaddr )
|
|
{
|
|
addr->zone = DEFAULT_ZONE;
|
|
addr->net = DEFAULT_NET;
|
|
addr->node = DEFAULT_NODE;
|
|
addr->point = 0;
|
|
|
|
if( addr->inetform )
|
|
badaddr = ftn_addrparse_inet(addr, s, wildcard);
|
|
else
|
|
badaddr = ftn_addrparse_fido(addr, s, wildcard);
|
|
}
|
|
|
|
return badaddr;
|
|
}
|
|
|
|
char *ftn_addrstr_fido(char *buf, s_faddr addr)
|
|
{
|
|
char str1[10];
|
|
char str2[10];
|
|
char str3[10];
|
|
char str4[10];
|
|
|
|
if( addr.point )
|
|
{
|
|
sprintf(buf, "%s:%s/%s.%s",
|
|
addrint2str(str1, addr.zone), addrint2str(str2, addr.net),
|
|
addrint2str(str3, addr.node), addrint2str(str4, addr.point));
|
|
}
|
|
else
|
|
{
|
|
sprintf(buf, "%s:%s/%s",
|
|
addrint2str(str1, addr.zone), addrint2str(str2, addr.net),
|
|
addrint2str(str3, addr.node));
|
|
}
|
|
|
|
if( *addr.domain )
|
|
{
|
|
strnxcat(buf, "@", BF_MAXADDRSTR);
|
|
strnxcat(buf, addr.domain, BF_MAXADDRSTR);
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
char *ftn_addrstr_inet(char *buf, s_faddr addr)
|
|
{
|
|
char str1[10];
|
|
char str2[10];
|
|
char str3[10];
|
|
char str4[10];
|
|
|
|
if( addr.point )
|
|
{
|
|
sprintf(buf, "p%s.f%s.n%s.z%s",
|
|
addrint2str(str1, addr.point), addrint2str(str2, addr.node),
|
|
addrint2str(str3, addr.net), addrint2str(str4, addr.zone));
|
|
}
|
|
else
|
|
{
|
|
sprintf(buf, "f%s.n%s.z%s",
|
|
addrint2str(str1, addr.node), addrint2str(str2, addr.net),
|
|
addrint2str(str3, addr.zone));
|
|
}
|
|
|
|
if( *addr.domain )
|
|
{
|
|
strnxcat(buf, ".", BF_MAXADDRSTR);
|
|
strnxcat(buf, addr.domain, BF_MAXADDRSTR);
|
|
}
|
|
|
|
return buf;
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Put FTN address as the null-terminated string to the buffer
|
|
*
|
|
* Arguments:
|
|
* buf pointer to the destination buffer (must be at least
|
|
* BF_MAXADDRSTR bytes length)
|
|
* addr FTN address
|
|
*
|
|
* Return value:
|
|
* pointer to the buffer start
|
|
*/
|
|
char *ftn_addrstr(char *buf, s_faddr addr)
|
|
{
|
|
ASSERT(buf != NULL);
|
|
|
|
return addr.inetform ? ftn_addrstr_inet(buf, addr)
|
|
: ftn_addrstr_fido(buf, addr);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Compare two FTN addresses
|
|
*
|
|
* Arguments:
|
|
* addr1 first FTN address
|
|
* addr2 second FTN address
|
|
*
|
|
* Return value:
|
|
* zero value if addresses are equal, and non-zero if not
|
|
*/
|
|
int ftn_addrcomp(s_faddr addr1, s_faddr addr2)
|
|
{
|
|
return !( addr1.zone == addr2.zone && addr1.net == addr2.net
|
|
&& addr1.node == addr2.node && addr1.point == addr2.point );
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Compare two FTN addresses
|
|
*
|
|
* Arguments:
|
|
* addr1 first FTN address
|
|
* operator logical operator (EQ|GT|LT)
|
|
* addr2 second FTN address
|
|
*
|
|
* Return value:
|
|
* zero value if expression is true, and non-zero if not
|
|
*/
|
|
int ftn_addrcomp_logic(s_faddr addr1, int operator, s_faddr addr2)
|
|
{
|
|
int i;
|
|
int matr1[4] = { addr1.zone, addr1.net, addr1.node, addr1.point };
|
|
int matr2[4] = { addr2.zone, addr2.net, addr2.node, addr2.point };
|
|
|
|
for( i = 0; i < 4; i++ )
|
|
{
|
|
switch(operator) {
|
|
case ADDR_EQ:
|
|
if( matr1[i] != matr2[i] )
|
|
return 1;
|
|
break;
|
|
case ADDR_GT:
|
|
if( matr1[i] > matr2[i] )
|
|
return 0;
|
|
else if( matr1[i] < matr2[i] )
|
|
return 1;
|
|
break;
|
|
case ADDR_LT:
|
|
if( matr1[i] < matr2[i] )
|
|
return 0;
|
|
else if( matr1[i] > matr2[i] )
|
|
return 1;
|
|
break;
|
|
default:
|
|
ASSERT(0);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
/*****************************************************************************
|
|
* Compare two FTN addresses (second address can contain wildcards)
|
|
*
|
|
* Arguments:
|
|
* addr first FTN address
|
|
* mask second FTN address (with wildcards)
|
|
*
|
|
* Return value:
|
|
* zero value if addresses are equal, and non-zero if not
|
|
*/
|
|
int ftn_addrcomp_mask(s_faddr addr, s_faddr mask)
|
|
{
|
|
return !( (addr.zone == mask.zone || mask.zone == -1)
|
|
&& (addr.net == mask.net || mask.net == -1)
|
|
&& (addr.node == mask.node || mask.node == -1)
|
|
&& (addr.point == mask.point || mask.point == -1) );
|
|
}
|
|
|
|
/*****************************************************************************
|
|
* Get the metric of matching two addresses
|
|
*
|
|
* Arguments:
|
|
* addr1 first FTN address
|
|
* addr2 second FTN address
|
|
*
|
|
* Return value:
|
|
* from 0 to 4 (0 - no matching, 4 - equal addresses)
|
|
*/
|
|
int ftn_addrsmetric(s_faddr addr1, s_faddr addr2)
|
|
{
|
|
int metric = 0;
|
|
|
|
if( addr1.zone == addr2.zone )
|
|
{
|
|
++metric;
|
|
if( addr1.net == addr2.net )
|
|
{
|
|
++metric;
|
|
if( addr1.node == addr2.node )
|
|
{
|
|
++metric;
|
|
if( addr1.point == addr2.point )
|
|
{
|
|
++metric;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return metric;
|
|
}
|
|
|