/*!
A host name and the name to report.
*/
-struct hostalias
+struct hostalias_name
{
//! The next host name in the list or NULL for the last item.
- struct hostalias *Next;
+ struct hostalias_name *Next;
//! The minimum length of a candidate host name.
int MinLen;
//! The length of the constant part at the beginning of the mask.
const char *Alias;
};
+/*!
+An IPv4 address and the name to report.
+*/
+struct hostalias_ipv4
+{
+ //! The next host name in the list or NULL for the last item.
+ struct hostalias_ipv4 *Next;
+ //! The IP address.
+ unsigned char Ip[4];
+ //! The number of bits in the prefix.
+ int NBits;
+ //! The replacement name.
+ const char *Alias;
+};
+
+/*!
+An IPv6 address and the name to report.
+*/
+struct hostalias_ipv6
+{
+ //! The next host name in the list or NULL for the last item.
+ struct hostalias_ipv6 *Next;
+ //! The IP address.
+ unsigned short Ip[6];
+ //! The number of bits in the prefix.
+ int NBits;
+ //! The replacement name.
+ const char *Alias;
+};
+
//! The first host name.
-struct hostalias *FirstAlias=NULL;
+static struct hostalias_name *FirstAliasName=NULL;
+//! The first IPv4 address.
+static struct hostalias_ipv4 *FirstAliasIpv4=NULL;
+//! The first IPv§ address.
+static struct hostalias_ipv6 *FirstAliasIpv6=NULL;
/*!
-Read the file containing the host names to alias in the report.
+ Store a name to alias.
-\param Filename The name of the file.
-*/
-void read_hostalias(const char *Filename)
+ \param name The name to match including the wildcard.
+ \param next A pointer to the first character after the name.
+
+ \retval 1 Alias added.
+ \retval 0 Ignore the line.
+ \retval -1 Error.
+ */
+static int Alias_StoreName(char *name,char *next)
{
- FILE *fi;
- longline line;
- char *buf;
- char *str;
char *NameBegin;
char *NameEnd;
char *Replace;
+ char *str;
+ char sep;
+ struct hostalias_name *alias;
+ struct hostalias_name *new_alias;
+ struct hostalias_name *prev_alias;
char *tmp;
- struct hostalias *alias;
- struct hostalias *prev_alias;
- struct hostalias *new_alias;
- int cmp;
- if (debug) debuga(_("Reading host alias file \"%s\"\n"),Filename);
- fi=fopen(Filename,"rt");
- if (!fi) {
- debuga(_("Cannot read host name alias file \"%s\" - %s\n"),Filename,strerror(errno));
- exit(EXIT_FAILURE);
- }
-
- if ((line=longline_create())==NULL) {
- debuga(_("Not enough memory to read the host name aliases\n"));
- exit(EXIT_FAILURE);
- }
+ if (*name=='#' || *name==';') return(0);
+ sep=*next;
+ *next++='\0';
- prev_alias=NULL;
- while ((buf=longline_read(fi,line)) != NULL) {
- // get host name and split at the first wildcards
- NameBegin=buf;
- while (*NameBegin==' ' || *NameBegin=='\t') NameBegin++;
- if ((unsigned char)*NameBegin<' ' || *NameBegin=='#' || *NameBegin==';') continue;
- for (str=NameBegin ; *str && (unsigned char)*str>' ' && *str!='*' ; str++)
- *str=tolower(*str);
- if (*str=='*') {
- *str++='\0';
- NameEnd=str;
- while (*str && (unsigned char)*str>' ') {
- if (*str=='*') {
- debuga(_("Host name alias \"%s*%s\" contains too many wildcards (*) in \"%s\""),NameBegin,NameEnd,Filename);
- exit(EXIT_FAILURE);
- }
- *str=tolower(*str);
- str++;
+ // 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>' ') {
+ if (*str=='*') {
+ debuga(_("Host name alias \"%s*%s\" contains too many wildcards (*)"),NameBegin,NameEnd);
+ 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);
- exit(EXIT_FAILURE);
+ *str=tolower(*str);
+ str++;
}
- if (NameBegin[0]=='\0') NameBegin=NULL;
- if (!NameBegin && !NameEnd) continue;
+ } 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;
+ if (!NameBegin && !NameEnd) return(0);
- // get the alias
- Replace=str;
+ // get the alias
+ if (sep==' ' || sep=='\t') {
+ Replace=next;
while (*Replace==' ' || *Replace=='\t') Replace++;
if ((unsigned char)*Replace<' ') {
Replace=NULL;
for (str=Replace ; *str && (unsigned char)*str>=' ' ; str++);
*str='\0';
}
+ } else
+ Replace=NULL;
- // ignore duplicates
- cmp=1;
- for (alias=FirstAlias ; 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))) {
- cmp=0;
- break;
- }
+ // 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))) {
+ return(0);
}
- if (!cmp) continue;
+ prev_alias=alias;
+ }
- // insert into the list
- new_alias=malloc(sizeof(*new_alias));
- if (!new_alias) {
- debuga(_("Not enough memory to store the host name aliasing directives read in \"%s\""),Filename);
- exit(EXIT_FAILURE);
+ // insert into the list
+ new_alias=malloc(sizeof(*new_alias));
+ if (!new_alias) {
+ 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->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 read in \"%s\""),Filename);
- exit(EXIT_FAILURE);
- }
- new_alias->MinLen+=strlen(NameBegin);
- new_alias->PrefixLen=strlen(NameBegin);
- } else {
- new_alias->HostName_Prefix=NULL;
- new_alias->PrefixLen=0;
+ new_alias->MinLen+=strlen(NameBegin);
+ new_alias->PrefixLen=strlen(NameBegin);
+ } else {
+ new_alias->HostName_Prefix=NULL;
+ 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);
}
- if (NameEnd) {
- new_alias->HostName_Suffix=strdup(NameEnd);
- if (!new_alias->HostName_Suffix) {
- debuga(_("Not enough memory to store the host name aliasing directives read in \"%s\""),Filename);
- exit(EXIT_FAILURE);
- }
- new_alias->MinLen+=strlen(NameEnd)+1;
- new_alias->SuffixLen=strlen(NameEnd);
- } else {
- new_alias->HostName_Suffix=NULL;
- new_alias->SuffixLen=0;
+ new_alias->MinLen+=strlen(NameEnd)+1;
+ new_alias->SuffixLen=strlen(NameEnd);
+ } else {
+ new_alias->HostName_Suffix=NULL;
+ new_alias->SuffixLen=0;
+ }
+ if (Replace) {
+ tmp=malloc(strlen(Replace)+2);
+ if (!tmp) {
+ debuga(_("Not enough memory to store the host name aliasing directives"));
+ return(-1);
}
- if (Replace) {
- tmp=malloc(strlen(Replace)+2);
- if (!tmp) {
- debuga(_("Not enough memory to store the host name aliasing directives read in \"%s\""),Filename);
- exit(EXIT_FAILURE);
- }
- tmp[0]=ALIAS_PREFIX;
- strcpy(tmp+1,Replace);
- new_alias->Alias=tmp;
- } else {
- tmp=malloc(new_alias->MinLen+2);
- if (!tmp) {
- debuga(_("Not enough memory to store the host name aliasing directives read in \"%s\""),Filename);
- exit(EXIT_FAILURE);
- }
- tmp[0]=ALIAS_PREFIX;
- if (new_alias->HostName_Prefix) strcpy(tmp+1,new_alias->HostName_Prefix);
- if (new_alias->HostName_Suffix) {
- tmp[new_alias->PrefixLen+1]='*';
- strcpy(tmp+new_alias->PrefixLen+2,new_alias->HostName_Suffix);
- }
- new_alias->Alias=tmp;
+ tmp[0]=ALIAS_PREFIX;
+ strcpy(tmp+1,Replace);
+ new_alias->Alias=tmp;
+ } else {
+ tmp=malloc(new_alias->MinLen+2);
+ if (!tmp) {
+ debuga(_("Not enough memory to store the host name aliasing directives"));
+ return(-1);
+ }
+ tmp[0]=ALIAS_PREFIX;
+ if (new_alias->HostName_Prefix) strcpy(tmp+1,new_alias->HostName_Prefix);
+ if (new_alias->HostName_Suffix) {
+ tmp[new_alias->PrefixLen+1]='*';
+ strcpy(tmp+new_alias->PrefixLen+2,new_alias->HostName_Suffix);
+ }
+ new_alias->Alias=tmp;
+ }
+
+ new_alias->Next=NULL;
+ if (prev_alias)
+ prev_alias->Next=new_alias;
+ else
+ FirstAliasName=new_alias;
+ return(1);
+}
+
+/*!
+ Store a IPv4 to alias.
+
+ \param ipv4 The IPv4 to match.
+ \param nbits The number of bits in the prefix
+ \param next A pointer to the first character after the address.
+
+ \retval 1 Alias added.
+ \retval 0 Ignore the line.
+ \retval -1 Error.
+ */
+static int Alias_StoreIpv4(unsigned char *ipv4,int nbits,char *next)
+{
+ char *Replace;
+ char *str;
+ struct hostalias_ipv4 *alias;
+ struct hostalias_ipv4 *new_alias;
+ struct hostalias_ipv4 *prev_alias;
+ int i;
+ char *tmp;
+
+ // get the alias
+ Replace=next;
+ while (*Replace==' ' || *Replace=='\t') Replace++;
+ if ((unsigned char)*Replace<' ') {
+ Replace=NULL;
+ } else {
+ for (str=Replace ; *str && (unsigned char)*str>=' ' ; str++);
+ *str='\0';
+ }
+
+ // store more restrictive range first
+ prev_alias=NULL;
+ for (alias=FirstAliasIpv4 ; alias ; alias=alias->Next) {
+ i=(nbits<alias->NBits) ? nbits : alias->NBits;
+ if ((i<8 || memcmp(ipv4,alias->Ip,i/8)==0) && ((i%8)==0 || (ipv4[i/8] ^ alias->Ip[i/8]) & (0xFFU<<(8-i%8)))==0) {
+ break;
+ }
+ prev_alias=alias;
+ }
+
+ // insert into the list
+ new_alias=malloc(sizeof(*new_alias));
+ if (!new_alias) {
+ debuga(_("Not enough memory to store the host name aliasing directives"));
+ return(-1);
+ }
+ memcpy(new_alias->Ip,ipv4,4);
+ new_alias->NBits=nbits;
+ if (Replace) {
+ tmp=malloc(strlen(Replace)+2);
+ if (!tmp) {
+ debuga(_("Not enough memory to store the host name aliasing directives"));
+ return(-1);
+ }
+ tmp[0]=ALIAS_PREFIX;
+ strcpy(tmp+1,Replace);
+ new_alias->Alias=tmp;
+ } else {
+ tmp=malloc(5*4+1);
+ if (!tmp) {
+ debuga(_("Not enough memory to store the host name aliasing directives"));
+ return(-1);
}
+ sprintf(tmp,"%c%d.%d.%d.%d/%d",ALIAS_PREFIX,ipv4[0],ipv4[1],ipv4[2],ipv4[3],nbits);
+ new_alias->Alias=tmp;
+ }
+ if (prev_alias) {
+ new_alias->Next=prev_alias->Next;
+ prev_alias->Next=new_alias;
+ } else {
new_alias->Next=NULL;
- if (prev_alias)
- prev_alias->Next=new_alias;
- else
- FirstAlias=new_alias;
- prev_alias=new_alias;
+ FirstAliasIpv4=new_alias;
+ }
+ return(1);
+}
+
+/*!
+ Store a IPv6 to alias.
+
+ \param ipv6 The IPv6 to match.
+ \param nbits The number of bits in the prefix
+ \param next A pointer to the first character after the address.
+
+ \retval 1 Alias added.
+ \retval 0 Ignore the line.
+ \retval -1 Error.
+ */
+static int Alias_StoreIpv6(unsigned short *ipv6,int nbits,char *next)
+{
+ char *Replace;
+ char *str;
+ struct hostalias_ipv6 *alias;
+ struct hostalias_ipv6 *new_alias;
+ struct hostalias_ipv6 *prev_alias;
+ int i;
+ char *tmp;
+
+ // get the alias
+ Replace=next;
+ while (*Replace==' ' || *Replace=='\t') Replace++;
+ if ((unsigned char)*Replace<' ') {
+ Replace=NULL;
+ } else {
+ for (str=Replace ; *str && (unsigned char)*str>=' ' ; str++);
+ *str='\0';
+ }
+
+ // store more restrictive range first
+ prev_alias=NULL;
+ for (alias=FirstAliasIpv6 ; alias ; alias=alias->Next) {
+ i=(nbits<alias->NBits) ? nbits : alias->NBits;
+ if ((i<16 || memcmp(ipv6,alias->Ip,i/16*2)==0) && ((i%16)==0 || (ipv6[i/16] ^ alias->Ip[i/16]) & (0xFFFFU<<(16-i%16)))==0) {
+ break;
+ }
+ prev_alias=alias;
+ }
+
+ // insert into the list
+ new_alias=malloc(sizeof(*new_alias));
+ if (!new_alias) {
+ debuga(_("Not enough memory to store the host name aliasing directives"));
+ return(-1);
+ }
+ memcpy(new_alias->Ip,ipv6,8);
+ new_alias->NBits=nbits;
+ if (Replace) {
+ tmp=malloc(strlen(Replace)+2);
+ if (!tmp) {
+ debuga(_("Not enough memory to store the host name aliasing directives"));
+ return(-1);
+ }
+ tmp[0]=ALIAS_PREFIX;
+ strcpy(tmp+1,Replace);
+ new_alias->Alias=tmp;
+ } else {
+ tmp=malloc(5*4+1);
+ if (!tmp) {
+ debuga(_("Not enough memory to store the host name aliasing directives"));
+ return(-1);
+ }
+ sprintf(tmp,"%c%x:%x:%x:%x:%x:%x:%x:%x/%d",ALIAS_PREFIX,ipv6[0],ipv6[1],ipv6[2],ipv6[3],ipv6[4],ipv6[5],ipv6[6],ipv6[7],nbits);
+ new_alias->Alias=tmp;
+ }
+
+ if (prev_alias) {
+ new_alias->Next=prev_alias->Next;
+ prev_alias->Next=new_alias;
+ } else {
+ new_alias->Next=NULL;
+ FirstAliasIpv6=new_alias;
+ }
+ return(1);
+}
+
+/*!
+Read the file containing the host names to alias in the report.
+
+\param Filename The name of the file.
+*/
+void read_hostalias(const char *Filename)
+{
+ FILE *fi;
+ longline line;
+ char *buf;
+ int type;
+ char *name;
+ unsigned char ipv4[4];
+ unsigned short int ipv6[8];
+ int nbits;
+ char *next;
+
+ if (debug) debuga(_("Reading host alias file \"%s\"\n"),Filename);
+ fi=fopen(Filename,"rt");
+ if (!fi) {
+ debuga(_("Cannot read host name alias file \"%s\" - %s\n"),Filename,strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ if ((line=longline_create())==NULL) {
+ debuga(_("Not enough memory to read the host name aliases\n"));
+ exit(EXIT_FAILURE);
+ }
+
+ 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);
+ exit(EXIT_FAILURE);
+ }
+
+ if (type==1) {
+ Alias_StoreName(name,next);
+ } else if (type==2) {
+ Alias_StoreIpv4(ipv4,nbits,next);
+ } else if (type==3) {
+ Alias_StoreIpv6(ipv6,nbits,next);
+ }
}
longline_destroy(&line);
fclose(fi);
if (debug) {
+ struct hostalias_name *alias1;
+ struct hostalias_ipv4 *alias4;
+ struct hostalias_ipv6 *alias6;
+
debuga(_("List of host names to alias:\n"));
- for (alias=FirstAlias ; alias ; alias=alias->Next) {
- if (alias->HostName_Prefix && alias->HostName_Suffix)
- debuga(_(" %s*%s => %s\n"),alias->HostName_Prefix,alias->HostName_Suffix,alias->Alias);
- else if (alias->HostName_Prefix)
- debuga(_(" %s => %s\n"),alias->HostName_Prefix,alias->Alias);
+ for (alias1=FirstAliasName ; alias1 ; alias1=alias1->Next) {
+ if (alias1->HostName_Prefix && alias1->HostName_Suffix)
+ debuga(_(" %s*%s => %s\n"),alias1->HostName_Prefix,alias1->HostName_Suffix,alias1->Alias);
+ else if (alias1->HostName_Prefix)
+ debuga(_(" %s => %s\n"),alias1->HostName_Prefix,alias1->Alias);
else
- debuga(_(" *%s => %s\n"),alias->HostName_Suffix,alias->Alias);
+ debuga(_(" *%s => %s\n"),alias1->HostName_Suffix,alias1->Alias);
+ }
+ for (alias4=FirstAliasIpv4 ; alias4 ; alias4=alias4->Next) {
+ debuga(_(" %d.%d.%d.%d/%d => %s\n"),alias4->Ip[0],alias4->Ip[1],alias4->Ip[2],alias4->Ip[3],alias4->NBits,alias4->Alias);
+ }
+ for (alias6=FirstAliasIpv6 ; alias6 ; alias6=alias6->Next) {
+ debuga(_(" %x:%x:%x:%x:%x:%x:%x:%x/%d => %s\n"),alias6->Ip[0],alias6->Ip[1],alias6->Ip[2],alias6->Ip[3],
+ alias6->Ip[4],alias6->Ip[5],alias6->Ip[6],alias6->Ip[7],alias6->NBits,alias6->Alias);
}
}
}
*/
void free_hostalias(void)
{
- struct hostalias *alias;
- struct hostalias *next;
+ struct hostalias_name *alias1;
+ struct hostalias_name *next1;
+ struct hostalias_ipv4 *alias4;
+ struct hostalias_ipv4 *next4;
+ struct hostalias_ipv6 *alias6;
+ struct hostalias_ipv6 *next6;
- for (alias=FirstAlias ; alias ; alias=next) {
- next=alias->Next;
- if (alias->HostName_Prefix) free((void *)alias->HostName_Prefix);
- if (alias->HostName_Suffix) free((void *)alias->HostName_Suffix);
- free((void *)alias->Alias);
- free(alias);
+ for (alias1=FirstAliasName ; alias1 ; alias1=next1) {
+ next1=alias1->Next;
+ if (alias1->HostName_Prefix) free((void *)alias1->HostName_Prefix);
+ if (alias1->HostName_Suffix) free((void *)alias1->HostName_Suffix);
+ free((void *)alias1->Alias);
+ free(alias1);
+ }
+ FirstAliasName=NULL;
+ for (alias4=FirstAliasIpv4 ; alias4 ; alias4=next4) {
+ next4=alias4->Next;
+ free((void *)alias4->Alias);
+ free(alias4);
+ }
+ FirstAliasIpv4=NULL;
+ for (alias6=FirstAliasIpv6 ; alias6 ; alias6=next6) {
+ next6=alias6->Next;
+ free((void *)alias6->Alias);
+ free(alias6);
}
- FirstAlias=NULL;
+ FirstAliasIpv6=NULL;
}
/*!
Replace the host name by its alias if it is in our list.
-\param host The host name.
+\param url The host name.
\return The pointer to the host name or its alias.
*/
-const char *alias_url(const char *url)
+const char *alias_url_name(const char *url)
{
- struct hostalias *alias;
+ struct hostalias_name *alias;
int len;
len=strlen(url);
- for (alias=FirstAlias ; alias ; alias=alias->Next) {
+ for (alias=FirstAliasName ; alias ; alias=alias->Next) {
if (len<alias->MinLen) continue;
if (alias->HostName_Prefix) {
if (alias->HostName_Suffix) {
return(url);
}
+/*!
+Replace the IPv4 address by its alias if it is in our list.
+
+\param url The host name.
+\param ipv4 The address.
+
+\return The pointer to the host name or its alias.
+*/
+const char *alias_url_ipv4(const char *url,unsigned char *ipv4)
+{
+ struct hostalias_ipv4 *alias;
+ int len;
+
+ for (alias=FirstAliasIpv4 ; alias ; alias=alias->Next) {
+ len=alias->NBits;
+ if ((len<8 || memcmp(ipv4,alias->Ip,len/8)==0) && ((len%8)==0 || (ipv4[len/8] ^ alias->Ip[len/8]) & (0xFFU<<(8-len%8)))==0) {
+ return(alias->Alias);
+ }
+ }
+ return(url);
+}
+
/*!
Get the part of the URL necessary to generate the report.
{
char *str;
const char *start;
+ int type;
+ char *address;
+ unsigned char ipv4[4];
+ unsigned short int ipv6[8];
+ char *next;
/*
Remove any scheme:// at the beginning of the URL (see rfc2396 section 3.1).
if (!full_url) {
for (str=url ; *str && *str!='/' ; str++);
if (*str=='/') *str='\0';
- if (FirstAlias)
- start=alias_url(start);
+ type=extract_address_mask(url,&address,ipv4,ipv6,NULL,&next);
+ if (type==1) {
+ if (FirstAliasName)
+ start=alias_url_name(start);
+ } else if (type==2) {
+ if (FirstAliasIpv4)
+ start=alias_url_ipv4(start,ipv4);
+ }
}
return(start);
}