unsigned long int mask;
};
+struct hostip6struct
+{
+ //! The IP address.
+ unsigned short int address[8];
+ //! The number of bits in the prefix.
+ int nbits;
+};
+
struct hostnamestruct
{
//! The URL to match without any leading wildcard.
static struct hostip4struct *exclude_ip4=NULL;
static int num_exclude_ip4=0;
+static struct hostip6struct *exclude_ip6=NULL;
+static int num_exclude_ip6=0;
static struct hostnamestruct *exclude_name=NULL;
static int num_exclude_name=0;
static int ip4allocated=0;
+static int ip6allocated=0;
static int nameallocated=0;
static char *excludeuser=NULL;
-static void store_exclude_ip4(unsigned short int *addr,int mask)
+/*!
+ Store a IPv4 address to exclude from the reported URL.
+
+ \param addr The 4 char of the address.
+ \param nbits The number of bits to keep in the prefix.
+ */
+static void store_exclude_ip4(unsigned char *addr,int nbits)
{
int i;
exclude_ip4[num_exclude_ip4].address=0UL;
for (i=0 ; i<4 ; i++)
exclude_ip4[num_exclude_ip4].address=(exclude_ip4[num_exclude_ip4].address<<8) | (unsigned char)(addr[i] & 0xFFU);
- exclude_ip4[num_exclude_ip4].mask=(0xFFFFFFFFUL << (32-mask));
+ exclude_ip4[num_exclude_ip4].mask=(0xFFFFFFFFUL << (32-nbits));
num_exclude_ip4++;
}
-static void store_exclude_url(char *url,int length)
+/*!
+ Store a IPv6 address to exclude from the reported URL.
+
+ \param addr The 8 short int of the address.
+ \param nbits The number of bits to keep in the prefix.
+ */
+static void store_exclude_ip6(unsigned short *addr,int nbits)
+{
+ int i;
+
+ if (num_exclude_ip6>=ip6allocated) {
+ struct hostip6struct *temp;
+
+ ip6allocated+=5;
+ temp=realloc(exclude_ip6,ip6allocated*sizeof(*temp));
+ if (temp==NULL) {
+ debuga(_("Not enough memory to store the exlcluded IP addresses\n"));
+ exit(EXIT_FAILURE);
+ }
+ exclude_ip6=temp;
+ }
+ for (i=0 ; i<8 ; i++)
+ exclude_ip6[num_exclude_ip6].address[i]=addr[i];
+ exclude_ip6[num_exclude_ip6].nbits=nbits;
+ num_exclude_ip6++;
+}
+
+/*!
+ Store a host name to exclude from the report.
+
+ \param url The host name to exclude.
+ */
+static void store_exclude_url(const char *url,const char *next)
{
int start;
int i;
+ int length;
int ndots, firstdot;
struct hostnamestruct *item;
start=0;
ndots=-1;
firstdot=0;
+ length=next-url;
for (i=0 ; i<length ; i++)
if (url[i]=='*') {
firstdot=1;
item->ndots=(ndots>0) ? ndots : -1;
}
-
+/*!
+ Read the file listing the host to exclude from the report.
+
+ \param hexfile The name of the file.
+ \param debug \c True to print debug information.
+ */
void gethexclude(const char *hexfile, int debug)
{
FILE *fp_ex;
char buf[255];
- int i;
- int ip_size;
- unsigned int value4, value6;
- unsigned short int addr[8];
- int addr_len;
- int mask, max_mask;
+ int type;
+ const char *name;
+ unsigned char ipv4[4];
+ unsigned short int ipv6[8];
+ int nbits;
+ const char *next;
if(access(hexfile, R_OK) != 0) {
debuga(_("Cannot open exclude_hosts file: %s - %s\n"),hexfile,strerror(errno));
if(buf[0]=='#')
continue;
fixendofline(buf);
- ip_size=0x60 | 0x04;
- value4=0U;
- value6=0U;
- addr_len=0;
- for (i=0 ; (unsigned char)buf[i]>' ' && buf[i]!='/' ; i++) {
- if (ip_size & 0x04) {
- if (isdigit(buf[i])) {
- value4=value4*10+(buf[i]-'0');
- if (value4>0xFFU) ip_size&=~0x04;
- } else if (buf[i]=='.' && addr_len<4) {
- addr[addr_len++]=(unsigned short)(value4 & 0xFFU);
- value4=0U;
- } else {
- ip_size&=~0x04;
- }
- }
- if (ip_size & 0x60) {
- if (isdigit(buf[i])) {
- value6=(value6<<4)+(buf[i]-'0');
- if (value6>0xFFFFU) ip_size&=~0x60;
- } else if (toupper(buf[i])>='A' && toupper(buf[i])<='F') {
- value6=(value6<<4)+(toupper(buf[i])-'A'+10);
- if (value6>0xFFFFU) ip_size&=~0x60;
- } else if (buf[i]==':' && addr_len<8) {
- addr[addr_len++]=(unsigned short)(value6 & 0xFFFFU);
- value6=0U;
- } else {
- ip_size&=~0x60;
- }
- }
- }
- if (i==0) continue;
- if (ip_size & 0x04) {
- if (addr_len!=3)
- ip_size&=~0x04;
- else
- addr[addr_len++]=(unsigned short)(value4 & 0xFFU);
- }
- if (ip_size & 0x60) {
- if (addr_len>=8)
- ip_size&=~0x60;
- else
- addr[addr_len++]=(unsigned short)(value6 & 0xFFFFU);
+
+ type=extract_address_mask(buf,&name,ipv4,ipv6,&nbits,&next);
+ if (type<0) {
+ debuga(_("While reading \"%s\""),hexfile);
+ exit(EXIT_FAILURE);
}
- if (ip_size) {
- max_mask=(ip_size & 0x04) ? 4*8 : 8*16;
- if (buf[i]=='/') {
- mask=atoi(buf+i+1);
- if (mask<0 || mask>max_mask) mask=max_mask;
- } else
- mask=max_mask;
- if (ip_size & 0x04)
- store_exclude_ip4(addr,mask);
- else {
- debuga(_("IPv6 addresses are not supported (found in %s)\n"),hexfile);
- exit(EXIT_FAILURE);
- }
- } else {
- store_exclude_url(buf,i);
+
+ if (type==1) {
+ store_exclude_url(name,next);
+ } else if (type==2) {
+ store_exclude_ip4(ipv4,nbits);
+ } else if (type==3) {
+ store_exclude_ip6(ipv6,nbits);
}
}
return;
}
+/*!
+ Check if the URL is excluded as per the host exclusion list.
+
+ \param url The URL to check.
+
+ \retval 1 Keep the URL.
+ \retval 0 Exclude the URL.
+ */
int vhexclude(const char *url)
{
int i, j;
int length;
- int ip_size;
- unsigned int value4, value6;
+ int type;
+ const char *name;
+ unsigned char ipv4[4];
+ unsigned short int ipv6[8];
unsigned long int addr4;
- unsigned short int addr6[8];
- int addr_len;
- int dotpos[10];
+ int dotpos[50];
int ndots;
- ip_size=0x60 | 0x04;
- addr4=0UL;
- value4=0U;
- value6=0U;
- addr_len=0;
- for (i=0 ; (unsigned char)url[i]>' ' && url[i]!='/' && url[i]!='?'&& ((ip_size & 0x60)!=0 || url[i]!=':') && ip_size ; i++) {
- if (ip_size & 0x04) {
- if (isdigit(url[i])) {
- value4=value4*10+(url[i]-'0');
- if (value4>0xFFU) ip_size&=~0x04;
- } else if (url[i]=='.' && addr_len<4) {
- addr_len++;
- addr4=(addr4<<8) | (unsigned long int)(value4 & 0xFFU);
- value4=0U;
- } else {
- ip_size&=~0x04;
- }
- }
- if (ip_size & 0x60) {
- if (isdigit(url[i])) {
- value6=(value6<<4)+(url[i]-'0');
- if (value6>0xFFFFU) ip_size&=~0x60;
- } else if (toupper(url[i])>='A' && toupper(url[i])<='F') {
- value6=(value6<<4)+(toupper(url[i])-'A'+10);
- if (value6>0xFFFFU) ip_size&=~0x60;
- } else if (url[i]==':' && addr_len<8) {
- addr6[addr_len++]=(unsigned short)(value6 & 0xFFFFU);
- value6=0U;
- } else {
- ip_size&=~0x60;
- }
- }
- }
- if ((ip_size & 0x04) && addr_len==3) {
- if (exclude_ip4 == NULL) return(1);
- addr4=(addr4<<8) | (unsigned long int)(value4 & 0xFFU);
- for (i=0 ; i<num_exclude_ip4 ; i++)
- if (((exclude_ip4[i].address ^ addr4) & exclude_ip4[i].mask)==0) return(0);
- } else if ((ip_size & 0x60) && addr_len<8) {
- addr6[addr_len++]=(unsigned short)(value6 & 0xFFFFU);
- } else {
+ type=extract_address_mask(url,&name,ipv4,ipv6,NULL,NULL);
+ if (type==1) {
if (exclude_name == NULL) return(1);
ndots=0;
- for (length=0 ; (unsigned char)url[length]>' ' && url[length]!=':' && url[length]!='/' && url[length]!='?' ; length++)
- if (url[length]=='.') {
+ for (length=0 ; (unsigned char)name[length]>' ' && name[length]!=':' && name[length]!='/' && name[length]!='?' ; length++)
+ if (name[length]=='.') {
/*
We store the position of each dots of the URL to match it against any
wildcard in the excluded list. The size of dotpos is big enough for the most
if (length>0) {
for (i=0 ; i<num_exclude_name ; i++) {
if (exclude_name[i].ndots>0) {
- const char *wurl=url;
+ const char *wurl=name;
int len=length;
if (exclude_name[i].ndots<=ndots) {
wurl+=dotpos[ndots-exclude_name[i].ndots];
}
}
}
+ } else if (type==2) {
+ if (exclude_ip4 == NULL) return(1);
+ addr4=0UL;
+ for (i=0 ; i<4 ; i++) addr4=(addr4 << 8) | ipv4[i];
+ for (i=0 ; i<num_exclude_ip4 ; i++) {
+ if (((exclude_ip4[i].address ^ addr4) & exclude_ip4[i].mask)==0) return(0);
+ }
+ } else if (type==3) {
+ if (exclude_ip6 == NULL) return(1);
+ for (i=0 ; i<num_exclude_ip6 ; i++) {
+ length=exclude_ip6[i].nbits;
+ for (j=length/16-1 ; j>=0 && ipv6[j]==exclude_ip6[i].address[j] ; j--);
+ if (j>=0) return(1);
+ j=length/16;
+ if (j>=8 || length%16==0 || ((ipv6[j] ^ exclude_ip6[i].address[j]) & (0xFFFF<<(length-j*16)))==0)
+ return(0);
+ }
}
-
return(1);
}
char *get_param_value(const char *param,char *line);
int compar( const void *, const void * );
void unlinkdir(const char *dir,int contentonly);
-int extract_address_mask(char *buf,char **text,unsigned char *ipv4,unsigned short int *ipv6,int *nbits,char **next);
+int extract_address_mask(const char *buf,const char **text,unsigned char *ipv4,unsigned short int *ipv6,int *nbits,const char **next);
\retval 0 Ignore the line.
\retval -1 Error.
*/
-static int Alias_StoreName(char *name,char *next)
+static int Alias_StoreName(const char *name,const char *next)
{
- char *NameBegin;
- char *NameEnd;
- char *Replace;
- char *str;
+ const char *NameBegin;
+ const char *NameBeginE;
+ const char *NameEnd;
+ const char *NameEndE;
+ const char *Replace;
+ const char *ReplaceE;
+ const char *str;
char sep;
struct hostalias_name *alias;
struct hostalias_name *new_alias;
struct hostalias_name *prev_alias;
char *tmp;
+ int len;
if (*name=='#' || *name==';') return(0);
- sep=*next;
- *next++='\0';
// get host name and split at the wildcard
NameBegin=name;
- for (str=NameBegin ; *str && (unsigned char)*str>' ' && *str!='*' ; str++)
- *str=tolower(*str);
- if (*str=='*') {
- *str++='\0';
- NameEnd=str;
- while (*str && (unsigned char)*str>' ') {
+ for (str=NameBegin ; str<next && (unsigned char)*str>' ' && *str!='*' ; str++);
+ NameBeginE=str;
+ if (NameBegin==NameBeginE) NameBegin=NULL;
+ if (str<next && *str=='*') {
+ NameEnd=++str;
+ while (str<next && (unsigned char)*str>' ') {
if (*str=='*') {
debuga(_("Host name alias \"%s*%s\" contains too many wildcards (*)"),NameBegin,NameEnd);
return(-1);
}
- *str=tolower(*str);
str++;
}
- } else
+ NameEndE=str;
+ if (NameEnd==NameEndE) {
+ debuga(_("Host name alias \"%*s\" must not end with a wildcard"),(int)(next-name),name);
+ return(-1);
+ }
+ } else {
NameEnd=NULL;
- while (*str && (unsigned char)*str<=' ') *str++='\0';
- if (NameEnd && NameEnd[0]=='\0') {
- debuga(_("Host name alias \"%s\" must not end with a wildcard"),NameEnd);
- return(-1);
}
- if (NameBegin[0]=='\0') NameBegin=NULL;
+ while (str<next && (unsigned char)*str<=' ') str++;
if (!NameBegin && !NameEnd) return(0);
// get the alias
+ sep=*next;
if (sep==' ' || sep=='\t') {
Replace=next;
while (*Replace==' ' || *Replace=='\t') Replace++;
Replace=NULL;
} else {
for (str=Replace ; *str && (unsigned char)*str>=' ' ; str++);
- *str='\0';
+ ReplaceE=str;
}
} else
Replace=NULL;
+ if (NameBegin) {
+ len=(int)(NameBeginE-NameBegin);
+ tmp=malloc(len+1);
+ if (!tmp) {
+ debuga(_("Not enough memory to store the host name aliasing directives"));
+ return(-1);
+ }
+ memcpy(tmp,NameBegin,len);
+ tmp[len]='\0';
+ NameBegin=tmp;
+ }
+ if (NameEnd) {
+ len=(int)(NameEndE-NameEnd);
+ tmp=malloc(len+1);
+ if (!tmp) {
+ if (NameBegin) free((void*)NameBegin);
+ debuga(_("Not enough memory to store the host name aliasing directives"));
+ return(-1);
+ }
+ memcpy(tmp,NameEnd,len);
+ tmp[len]='\0';
+ NameEnd=tmp;
+ }
+
// ignore duplicates
prev_alias=NULL;
for (alias=FirstAliasName ; alias ; alias=alias->Next) {
if (((NameBegin && alias->HostName_Prefix && !strcmp(NameBegin,alias->HostName_Prefix)) || (!NameBegin && !alias->HostName_Prefix)) &&
((NameEnd && alias->HostName_Suffix && !strcmp(NameEnd,alias->HostName_Suffix)) || (!NameEnd && !alias->HostName_Suffix))) {
+ if (NameBegin) free((void*)NameBegin);
return(0);
}
prev_alias=alias;
// insert into the list
new_alias=malloc(sizeof(*new_alias));
if (!new_alias) {
+ if (NameBegin) free((void*)NameBegin);
+ if (NameEnd) free((void*)NameEnd);
debuga(_("Not enough memory to store the host name aliasing directives"));
return(-1);
}
new_alias->MinLen=0;
if (NameBegin) {
- new_alias->HostName_Prefix=strdup(NameBegin);
- if (!new_alias->HostName_Prefix) {
- debuga(_("Not enough memory to store the host name aliasing directives"));
- return(-1);
- }
+ new_alias->HostName_Prefix=NameBegin;
new_alias->MinLen+=strlen(NameBegin);
new_alias->PrefixLen=strlen(NameBegin);
} else {
new_alias->PrefixLen=0;
}
if (NameEnd) {
- new_alias->HostName_Suffix=strdup(NameEnd);
- if (!new_alias->HostName_Suffix) {
- debuga(_("Not enough memory to store the host name aliasing directives"));
- return(-1);
- }
+ new_alias->HostName_Suffix=NameEnd;
new_alias->MinLen+=strlen(NameEnd)+1;
new_alias->SuffixLen=strlen(NameEnd);
} else {
new_alias->SuffixLen=0;
}
if (Replace) {
- tmp=malloc(strlen(Replace)+2);
+ len=(int)(ReplaceE-Replace);
+ tmp=malloc(len+2);
if (!tmp) {
debuga(_("Not enough memory to store the host name aliasing directives"));
return(-1);
}
tmp[0]=ALIAS_PREFIX;
- strcpy(tmp+1,Replace);
+ memcpy(tmp+1,Replace,len);
+ tmp[len+1]='\0';
new_alias->Alias=tmp;
} else {
tmp=malloc(new_alias->MinLen+2);
\retval 0 Ignore the line.
\retval -1 Error.
*/
-static int Alias_StoreIpv4(unsigned char *ipv4,int nbits,char *next)
+static int Alias_StoreIpv4(unsigned char *ipv4,int nbits,const char *next)
{
- char *Replace;
- char *str;
+ const char *Replace;
+ const char *ReplaceE;
+ const char *str;
struct hostalias_ipv4 *alias;
struct hostalias_ipv4 *new_alias;
struct hostalias_ipv4 *prev_alias;
int i;
char *tmp;
+ int len;
// get the alias
Replace=next;
Replace=NULL;
} else {
for (str=Replace ; *str && (unsigned char)*str>=' ' ; str++);
- *str='\0';
+ ReplaceE=str;
}
// store more restrictive range first
memcpy(new_alias->Ip,ipv4,4);
new_alias->NBits=nbits;
if (Replace) {
- tmp=malloc(strlen(Replace)+2);
+ len=(int)(ReplaceE-Replace);
+ tmp=malloc(len+2);
if (!tmp) {
debuga(_("Not enough memory to store the host name aliasing directives"));
return(-1);
}
tmp[0]=ALIAS_PREFIX;
- strcpy(tmp+1,Replace);
+ memcpy(tmp+1,Replace,len);
+ tmp[len+1]='\0';
new_alias->Alias=tmp;
} else {
tmp=malloc(5*4+1);
\retval 0 Ignore the line.
\retval -1 Error.
*/
-static int Alias_StoreIpv6(unsigned short *ipv6,int nbits,char *next)
+static int Alias_StoreIpv6(unsigned short *ipv6,int nbits,const char *next)
{
- char *Replace;
- char *str;
+ const char *Replace;
+ const char *ReplaceE;
+ const char *str;
struct hostalias_ipv6 *alias;
struct hostalias_ipv6 *new_alias;
struct hostalias_ipv6 *prev_alias;
int i;
char *tmp;
+ int len;
// get the alias
Replace=next;
Replace=NULL;
} else {
for (str=Replace ; *str && (unsigned char)*str>=' ' ; str++);
- *str='\0';
+ ReplaceE=str;
}
// store more restrictive range first
memcpy(new_alias->Ip,ipv6,8*sizeof(unsigned short int));
new_alias->NBits=nbits;
if (Replace) {
- tmp=malloc(strlen(Replace)+2);
+ len=ReplaceE-Replace;
+ tmp=malloc(len+2);
if (!tmp) {
debuga(_("Not enough memory to store the host name aliasing directives"));
return(-1);
}
tmp[0]=ALIAS_PREFIX;
- strcpy(tmp+1,Replace);
+ memcpy(tmp+1,Replace,len);
+ tmp[len+1]='\0';
new_alias->Alias=tmp;
} else {
tmp=malloc(5*8+5);
longline line;
char *buf;
int type;
- char *name;
+ const char *name;
unsigned char ipv4[4];
unsigned short int ipv6[8];
int nbits;
- char *next;
+ const char *next;
if (debug) debuga(_("Reading host alias file \"%s\"\n"),Filename);
fi=fopen(Filename,"rt");
}
while ((buf=longline_read(fi,line)) != NULL) {
-
type=extract_address_mask(buf,&name,ipv4,ipv6,&nbits,&next);
if (type<0) {
debuga(_("While reading \"%s\""),Filename);
\return The pointer to the host name or its alias.
*/
-const char *alias_url_name(const char *url)
+const char *alias_url_name(const char *url,const char *next)
{
struct hostalias_name *alias;
int len;
- len=strlen(url);
+ len=(int)(next-url);
for (alias=FirstAliasName ; alias ; alias=alias->Next) {
if (len<alias->MinLen) continue;
if (alias->HostName_Prefix) {
if (alias->HostName_Suffix) {
if (strncasecmp(url,alias->HostName_Prefix,alias->PrefixLen)==0 &&
- strcasecmp(url+(len-alias->SuffixLen),alias->HostName_Suffix)==0) {
+ strncasecmp(url+(len-alias->SuffixLen),alias->HostName_Suffix,len)==0) {
return(alias->Alias);
}
} else {
- if (len==alias->PrefixLen && strcasecmp(url,alias->HostName_Prefix)==0) {
+ if (len==alias->PrefixLen && strncasecmp(url,alias->HostName_Prefix,len)==0) {
return(alias->Alias);
}
}
- } else if (strcasecmp(url+(len-alias->SuffixLen),alias->HostName_Suffix)==0) {
+ } else if (strncasecmp(url+(len-alias->SuffixLen),alias->HostName_Suffix,len)==0) {
return(alias->Alias);
}
}
char *str;
const char *start;
int type;
- char *address;
+ const char *address;
unsigned char ipv4[4];
unsigned short int ipv6[8];
- char *next;
+ const char *next;
/*
Remove any scheme:// at the beginning of the URL (see rfc2396 section 3.1).
type=extract_address_mask(url,&address,ipv4,ipv6,NULL,&next);
if (type==1) {
if (FirstAliasName)
- start=alias_url_name(start);
+ start=alias_url_name(start,next);
} else if (type==2) {
if (FirstAliasIpv4)
start=alias_url_ipv4(start,ipv4);
\retval 1 The patter is a string.
\retval 0 Empty pattern.
*/
-int extract_address_mask(char *buf,char **text,unsigned char *ipv4,unsigned short int *ipv6,int *nbits,char **next)
+int extract_address_mask(const char *buf,const char **text,unsigned char *ipv4,unsigned short int *ipv6,int *nbits,const char **next)
{
int i;
int j;
*text=buf;
if (bracket) (*text)--;
while ((unsigned char)buf[i]>' ') i++;
- *next=buf+i;
+ if (next) *next=buf+i;
return(1);
}
max_mask=(ip_size & 0x04) ? 4*8 : 8*16;
} else
mask=max_mask;
if (ip_size & 0x60 && bracket && buf[i]==']') i++;
- *next=buf+i;
+ if (next) *next=buf+i;
if (ip_size & 0x04) {
if (nbits) *nbits=mask;
for (i=0 ; i<addr_len ; i++)