]> git.ipfire.org Git - thirdparty/sarg.git/blobdiff - exclude.c
Use the proper exit constant instead of the hard coded numérical value.
[thirdparty/sarg.git] / exclude.c
index c60c0a1d030cae7b3d4e28e364c8260c0dbdc806..29c1e296859e2c8642efbae44d07c811a43e2f65 100644 (file)
--- a/exclude.c
+++ b/exclude.c
@@ -1,6 +1,6 @@
 /*
  * SARG Squid Analysis Report Generator      http://sarg.sourceforge.net
- *                                                            1998, 2010
+ *                                                            1998, 2015
  *
  * SARG donations:
  *      please look at http://sarg.sourceforge.net/donations.php
@@ -35,6 +35,14 @@ struct hostip4struct
        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.
@@ -45,14 +53,23 @@ struct hostnamestruct
 
 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;
 
@@ -62,7 +79,7 @@ static void store_exclude_ip4(unsigned short int *addr,int mask)
                ip4allocated+=5;
                temp=realloc(exclude_ip4,ip4allocated*sizeof(*temp));
                if (temp==NULL) {
-                       debuga(_("Not enough memory to store the exlcluded IP addresses\n"));
+                       debuga(__FILE__,__LINE__,_("Not enough memory to store the exlcluded IP addresses\n"));
                        exit(EXIT_FAILURE);
                }
                exclude_ip4=temp;
@@ -70,20 +87,54 @@ static void store_exclude_ip4(unsigned short int *addr,int mask)
        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(__FILE__,__LINE__,_("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;
@@ -107,7 +158,7 @@ static void store_exclude_url(char *url,int length)
                nameallocated+=5;
                temp=realloc(exclude_name,nameallocated*sizeof(*temp));
                if (temp==NULL) {
-                       debuga(_("Not enough memory to store the excluded URLs\n"));
+                       debuga(__FILE__,__LINE__,_("Not enough memory to store the excluded URLs\n"));
                        exit(EXIT_FAILURE);
                }
                exclude_name=temp;
@@ -117,35 +168,39 @@ static void store_exclude_url(char *url,int length)
        num_exclude_name++;
        item->url=malloc(length+1);
        if (!item->url) {
-               debuga(_("Not enough memory to store the excluded URLs\n"));
+               debuga(__FILE__,__LINE__,_("Not enough memory to store the excluded URLs\n"));
                exit(EXIT_FAILURE);
        }
-       strncpy(item->url,url,length);
-       item->url[length]='\0';
+       safe_strcpy(item->url,url,length+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));
+               debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),hexfile,strerror(errno));
                exit(EXIT_FAILURE);
        }
        if(debug)
-               debuga(_("Loading exclude host file from: %s\n"),hexfile);
+               debuga(__FILE__,__LINE__,_("Loading exclude host file from \"%s\"\n"),hexfile);
 
        if ((fp_ex = fopen(hexfile, "r")) == NULL) {
-               debuga(_("(gethexclude) Cannot open file %s - %s\n"),hexfile,strerror(errno));
+               debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),hexfile,strerror(errno));
                exit(EXIT_FAILURE);
        }
 
@@ -153,129 +208,55 @@ void gethexclude(const char *hexfile, int debug)
                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(__FILE__,__LINE__,_("While reading \"%s\"\n"),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);
                }
        }
 
-       fclose(fp_ex);
+       if (fclose(fp_ex)==EOF) {
+               debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),hexfile,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
        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
@@ -292,7 +273,7 @@ int vhexclude(const char *url)
                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];
@@ -304,8 +285,24 @@ int vhexclude(const char *url)
                                }
                        }
                }
+       } 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);
 }
 
@@ -317,34 +314,34 @@ void getuexclude(const char *uexfile, int debug)
        long int nreg=0;
 
        if(debug)
-               debuga(_("Loading exclude file from: %s\n"),uexfile);
+               debuga(__FILE__,__LINE__,_("Loading exclude file from \"%s\"\n"),uexfile);
 
        if ((fp_ex = fopen(uexfile, "r")) == NULL) {
-               debuga(_("(gethexclude) Cannot open file %s - %s\n"),uexfile,strerror(errno));
+               debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),uexfile,strerror(errno));
                exit(EXIT_FAILURE);
        }
 
        if (fseek(fp_ex, 0, SEEK_END)==-1) {
-               debuga(_("Failed to move till the end of the excluded users file %s: %s\n"),uexfile,strerror(errno));
+               debuga(__FILE__,__LINE__,_("Failed to move till the end of file \"%s\": %s\n"),uexfile,strerror(errno));
                exit(EXIT_FAILURE);
        }
        nreg = ftell(fp_ex);
        if (nreg<0) {
-               debuga(_("Cannot get the size of file %s\n"),uexfile);
+               debuga(__FILE__,__LINE__,_("Cannot get the size of file \"%s\"\n"),uexfile);
                exit(EXIT_FAILURE);
        }
        nreg += 11;
        if (fseek(fp_ex, 0, SEEK_SET)==-1) {
-               debuga(_("Failed to rewind the excluded users file %s: %s\n"),uexfile,strerror(errno));
+               debuga(__FILE__,__LINE__,_("Failed to rewind file \"%s\": %s\n"),uexfile,strerror(errno));
                exit(EXIT_FAILURE);
        }
 
        if((excludeuser=(char *) malloc(nreg))==NULL){
-               debuga(_("malloc error (%ld bytes required)\n"),nreg);
+               debuga(__FILE__,__LINE__,_("malloc error (%ld bytes required)\n"),nreg);
                exit(EXIT_FAILURE);
        }
 
-       bzero(excludeuser,nreg);
+       memset(excludeuser,0,nreg);
 
        while(fgets(buf,sizeof(buf),fp_ex)!=NULL){
                if(strchr(buf,'#') != NULL)
@@ -356,7 +353,10 @@ void getuexclude(const char *uexfile, int debug)
 
        strcat(excludeuser,"*END* ");
 
-       fclose(fp_ex);
+       if (fclose(fp_ex)==EOF) {
+               debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),uexfile,strerror(errno));
+               exit(EXIT_FAILURE);
+       }
 
        return;
 }