]> git.ipfire.org Git - thirdparty/sarg.git/blame - exclude.c
Rename configure.in as configure.ac
[thirdparty/sarg.git] / exclude.c
CommitLineData
25697a35 1/*
94ff9470 2 * SARG Squid Analysis Report Generator http://sarg.sourceforge.net
110ce984 3 * 1998, 2015
25697a35
GS
4 *
5 * SARG donations:
6 * please look at http://sarg.sourceforge.net/donations.php
1164c474
FM
7 * Support:
8 * http://sourceforge.net/projects/sarg/forums/forum/363374
25697a35
GS
9 * ---------------------------------------------------------------------
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
24 *
25 */
26
27#include "include/conf.h"
5f3cfd1d 28#include "include/defs.h"
25697a35 29
43f18f45 30struct hostip4struct
25697a35 31{
9bd92830
FM
32 //! The IP address.
33 unsigned long int address;
34 //! The mask to match the address of the URL.
35 unsigned long int mask;
43f18f45 36};
25697a35 37
7819e0d5
FM
38struct hostip6struct
39{
40 //! The IP address.
41 unsigned short int address[8];
42 //! The number of bits in the prefix.
43 int nbits;
44};
45
43f18f45
FM
46struct hostnamestruct
47{
9bd92830
FM
48 //! The URL to match without any leading wildcard.
49 char *url;
50 //! The number of dots in the url if a wildcard is present or -1 if the address is complete (no wildcard)
51 int ndots;
43f18f45
FM
52};
53
54static struct hostip4struct *exclude_ip4=NULL;
55static int num_exclude_ip4=0;
7819e0d5
FM
56static struct hostip6struct *exclude_ip6=NULL;
57static int num_exclude_ip6=0;
43f18f45
FM
58static struct hostnamestruct *exclude_name=NULL;
59static int num_exclude_name=0;
60static int ip4allocated=0;
7819e0d5 61static int ip6allocated=0;
43f18f45
FM
62static int nameallocated=0;
63
64static char *excludeuser=NULL;
65
7819e0d5
FM
66/*!
67 Store a IPv4 address to exclude from the reported URL.
b902df7e 68
7819e0d5
FM
69 \param addr The 4 char of the address.
70 \param nbits The number of bits to keep in the prefix.
71 */
72static void store_exclude_ip4(unsigned char *addr,int nbits)
43f18f45 73{
9bd92830
FM
74 int i;
75
76 if (num_exclude_ip4>=ip4allocated) {
77 struct hostip4struct *temp;
78
79 ip4allocated+=5;
80 temp=realloc(exclude_ip4,ip4allocated*sizeof(*temp));
81 if (temp==NULL) {
af961877 82 debuga(__FILE__,__LINE__,_("Not enough memory to store the exlcluded IP addresses\n"));
9bd92830
FM
83 exit(EXIT_FAILURE);
84 }
85 exclude_ip4=temp;
86 }
87 exclude_ip4[num_exclude_ip4].address=0UL;
88 for (i=0 ; i<4 ; i++)
89 exclude_ip4[num_exclude_ip4].address=(exclude_ip4[num_exclude_ip4].address<<8) | (unsigned char)(addr[i] & 0xFFU);
7819e0d5 90 exclude_ip4[num_exclude_ip4].mask=(0xFFFFFFFFUL << (32-nbits));
9bd92830 91 num_exclude_ip4++;
43f18f45
FM
92}
93
7819e0d5
FM
94/*!
95 Store a IPv6 address to exclude from the reported URL.
b902df7e 96
7819e0d5
FM
97 \param addr The 8 short int of the address.
98 \param nbits The number of bits to keep in the prefix.
99 */
100static void store_exclude_ip6(unsigned short *addr,int nbits)
101{
102 int i;
103
104 if (num_exclude_ip6>=ip6allocated) {
105 struct hostip6struct *temp;
106
107 ip6allocated+=5;
108 temp=realloc(exclude_ip6,ip6allocated*sizeof(*temp));
109 if (temp==NULL) {
af961877 110 debuga(__FILE__,__LINE__,_("Not enough memory to store the exlcluded IP addresses\n"));
7819e0d5
FM
111 exit(EXIT_FAILURE);
112 }
113 exclude_ip6=temp;
114 }
115 for (i=0 ; i<8 ; i++)
116 exclude_ip6[num_exclude_ip6].address[i]=addr[i];
117 exclude_ip6[num_exclude_ip6].nbits=nbits;
118 num_exclude_ip6++;
119}
120
121/*!
122 Store a host name to exclude from the report.
b902df7e 123
7819e0d5
FM
124 \param url The host name to exclude.
125 */
126static void store_exclude_url(const char *url,const char *next)
43f18f45 127{
9bd92830
FM
128 int start;
129 int i;
7819e0d5 130 int length;
9bd92830
FM
131 int ndots, firstdot;
132 struct hostnamestruct *item;
133
134 start=0;
135 ndots=-1;
136 firstdot=0;
7819e0d5 137 length=next-url;
9bd92830
FM
138 for (i=0 ; i<length ; i++)
139 if (url[i]=='*') {
140 firstdot=1;
141 } else if (url[i]=='.') {
142 if (firstdot) {
143 firstdot=0;
144 ndots=1;
145 start=i+1;
146 } else if (ndots>=0)
147 ndots++;
148 }
149 if (start>=length || firstdot) return;
150 if (start>0) {
151 url+=start;
152 length-=start;
153 }
154
155 if (num_exclude_name>=nameallocated) {
156 struct hostnamestruct *temp;
157
158 nameallocated+=5;
159 temp=realloc(exclude_name,nameallocated*sizeof(*temp));
160 if (temp==NULL) {
af961877 161 debuga(__FILE__,__LINE__,_("Not enough memory to store the excluded URLs\n"));
9bd92830
FM
162 exit(EXIT_FAILURE);
163 }
164 exclude_name=temp;
165 }
166
167 item=exclude_name+num_exclude_name;
168 num_exclude_name++;
169 item->url=malloc(length+1);
170 if (!item->url) {
af961877 171 debuga(__FILE__,__LINE__,_("Not enough memory to store the excluded URLs\n"));
9bd92830
FM
172 exit(EXIT_FAILURE);
173 }
a87d4d11 174 safe_strcpy(item->url,url,length+1);
9bd92830 175 item->ndots=(ndots>0) ? ndots : -1;
43f18f45
FM
176}
177
7819e0d5
FM
178/*!
179 Read the file listing the host to exclude from the report.
b902df7e 180
7819e0d5
FM
181 \param hexfile The name of the file.
182 \param debug \c True to print debug information.
183 */
43f18f45
FM
184void gethexclude(const char *hexfile, int debug)
185{
9bd92830
FM
186 FILE *fp_ex;
187 char buf[255];
7819e0d5
FM
188 int type;
189 const char *name;
190 unsigned char ipv4[4];
191 unsigned short int ipv6[8];
192 int nbits;
193 const char *next;
9bd92830
FM
194
195 if(access(hexfile, R_OK) != 0) {
af961877 196 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),hexfile,strerror(errno));
9bd92830
FM
197 exit(EXIT_FAILURE);
198 }
199 if(debug)
af961877 200 debuga(__FILE__,__LINE__,_("Loading exclude host file from \"%s\"\n"),hexfile);
9bd92830
FM
201
202 if ((fp_ex = fopen(hexfile, "r")) == NULL) {
af961877 203 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),hexfile,strerror(errno));
9bd92830
FM
204 exit(EXIT_FAILURE);
205 }
206
207 while(fgets(buf,sizeof(buf),fp_ex)!=NULL){
208 if(buf[0]=='#')
209 continue;
210 fixendofline(buf);
7819e0d5
FM
211
212 type=extract_address_mask(buf,&name,ipv4,ipv6,&nbits,&next);
213 if (type<0) {
af961877 214 debuga(__FILE__,__LINE__,_("While reading \"%s\"\n"),hexfile);
7819e0d5 215 exit(EXIT_FAILURE);
9bd92830 216 }
7819e0d5
FM
217
218 if (type==1) {
219 store_exclude_url(name,next);
220 } else if (type==2) {
221 store_exclude_ip4(ipv4,nbits);
222 } else if (type==3) {
223 store_exclude_ip6(ipv6,nbits);
9bd92830
FM
224 }
225 }
226
204781f4 227 if (fclose(fp_ex)==EOF) {
af961877 228 debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),hexfile,strerror(errno));
204781f4
FM
229 exit(EXIT_FAILURE);
230 }
9bd92830 231 return;
43f18f45
FM
232}
233
7819e0d5
FM
234/*!
235 Check if the URL is excluded as per the host exclusion list.
b902df7e 236
7819e0d5 237 \param url The URL to check.
b902df7e 238
7819e0d5
FM
239 \retval 1 Keep the URL.
240 \retval 0 Exclude the URL.
241 */
43f18f45
FM
242int vhexclude(const char *url)
243{
9bd92830
FM
244 int i, j;
245 int length;
7819e0d5
FM
246 int type;
247 const char *name;
248 unsigned char ipv4[4];
249 unsigned short int ipv6[8];
9bd92830 250 unsigned long int addr4;
7819e0d5 251 int dotpos[50];
9bd92830
FM
252 int ndots;
253
7819e0d5
FM
254 type=extract_address_mask(url,&name,ipv4,ipv6,NULL,NULL);
255 if (type==1) {
9bd92830
FM
256 if (exclude_name == NULL) return(1);
257 ndots=0;
7819e0d5
FM
258 for (length=0 ; (unsigned char)name[length]>' ' && name[length]!=':' && name[length]!='/' && name[length]!='?' ; length++)
259 if (name[length]=='.') {
9bd92830
FM
260 /*
261 We store the position of each dots of the URL to match it against any
262 wildcard in the excluded list. The size of dotpos is big enough for the most
263 ambitious URL but we have a safety mechanism that shift the positions should there be too
264 many dots in the URL.
265 */
266 if (ndots<sizeof(dotpos)/sizeof(dotpos[0]))
267 dotpos[ndots++]=length+1;
268 else {
269 for (j=1 ; j<ndots ; j++) dotpos[j-1]=dotpos[j];
270 dotpos[ndots-1]=length+1;
271 }
272 }
273 if (length>0) {
274 for (i=0 ; i<num_exclude_name ; i++) {
275 if (exclude_name[i].ndots>0) {
7819e0d5 276 const char *wurl=name;
9bd92830
FM
277 int len=length;
278 if (exclude_name[i].ndots<=ndots) {
279 wurl+=dotpos[ndots-exclude_name[i].ndots];
280 len-=dotpos[ndots-exclude_name[i].ndots];
281 }
282 if (strncmp(exclude_name[i].url,wurl,len)==0 && exclude_name[i].url[len]=='\0') return(0);
283 } else {
284 if (strncmp(exclude_name[i].url,url,length)==0 && exclude_name[i].url[length]=='\0') return(0);
285 }
286 }
287 }
7819e0d5
FM
288 } else if (type==2) {
289 if (exclude_ip4 == NULL) return(1);
290 addr4=0UL;
291 for (i=0 ; i<4 ; i++) addr4=(addr4 << 8) | ipv4[i];
292 for (i=0 ; i<num_exclude_ip4 ; i++) {
293 if (((exclude_ip4[i].address ^ addr4) & exclude_ip4[i].mask)==0) return(0);
294 }
295 } else if (type==3) {
296 if (exclude_ip6 == NULL) return(1);
297 for (i=0 ; i<num_exclude_ip6 ; i++) {
298 length=exclude_ip6[i].nbits;
299 for (j=length/16-1 ; j>=0 && ipv6[j]==exclude_ip6[i].address[j] ; j--);
300 if (j>=0) return(1);
301 j=length/16;
302 if (j>=8 || length%16==0 || ((ipv6[j] ^ exclude_ip6[i].address[j]) & (0xFFFF<<(length-j*16)))==0)
303 return(0);
304 }
9bd92830 305 }
9bd92830 306 return(1);
25697a35
GS
307}
308
309
43f18f45
FM
310void getuexclude(const char *uexfile, int debug)
311{
9bd92830
FM
312 FILE *fp_ex;
313 char buf[255];
314 long int nreg=0;
315
316 if(debug)
af961877 317 debuga(__FILE__,__LINE__,_("Loading exclude file from \"%s\"\n"),uexfile);
9bd92830
FM
318
319 if ((fp_ex = fopen(uexfile, "r")) == NULL) {
af961877 320 debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),uexfile,strerror(errno));
9bd92830
FM
321 exit(EXIT_FAILURE);
322 }
323
324 if (fseek(fp_ex, 0, SEEK_END)==-1) {
af961877 325 debuga(__FILE__,__LINE__,_("Failed to move till the end of file \"%s\": %s\n"),uexfile,strerror(errno));
9bd92830
FM
326 exit(EXIT_FAILURE);
327 }
328 nreg = ftell(fp_ex);
329 if (nreg<0) {
af961877 330 debuga(__FILE__,__LINE__,_("Cannot get the size of file \"%s\"\n"),uexfile);
9bd92830
FM
331 exit(EXIT_FAILURE);
332 }
333 nreg += 11;
334 if (fseek(fp_ex, 0, SEEK_SET)==-1) {
af961877 335 debuga(__FILE__,__LINE__,_("Failed to rewind file \"%s\": %s\n"),uexfile,strerror(errno));
9bd92830
FM
336 exit(EXIT_FAILURE);
337 }
338
339 if((excludeuser=(char *) malloc(nreg))==NULL){
af961877 340 debuga(__FILE__,__LINE__,_("malloc error (%ld bytes required)\n"),nreg);
9bd92830
FM
341 exit(EXIT_FAILURE);
342 }
343
9c1a94f6 344 memset(excludeuser,0,nreg);
9bd92830
FM
345
346 while(fgets(buf,sizeof(buf),fp_ex)!=NULL){
007905af
FM
347 if(strchr(buf,'#') != NULL)
348 continue;
349 fixendofline(buf);
350 strcat(excludeuser,buf);
351 strcat(excludeuser," ");
9bd92830
FM
352 }
353
354 strcat(excludeuser,"*END* ");
355
204781f4 356 if (fclose(fp_ex)==EOF) {
af961877 357 debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),uexfile,strerror(errno));
204781f4
FM
358 exit(EXIT_FAILURE);
359 }
9bd92830
FM
360
361 return;
43f18f45
FM
362}
363
364int vuexclude(const char *user)
25697a35 365{
9bd92830
FM
366 const char *wuser;
367 int len;
368
369 if (excludeuser) {
370 len=strlen(user);
371 wuser=excludeuser;
372 while ((wuser=strstr(wuser,user))!=NULL) {
373 if (wuser[len]==' ') return(0);
374 wuser+=len;
375 }
376 }
377
378 return(1);
25697a35 379}
43f18f45 380
2824ec9b 381bool is_indexonly(void)
43f18f45 382{
9bd92830
FM
383 if (excludeuser==NULL) return(false);
384 return(strstr(excludeuser,"indexonly") != NULL);
43f18f45
FM
385}
386
387void free_exclude(void)
388{
9bd92830
FM
389 int i;
390
391 if (exclude_ip4) {
392 free(exclude_ip4);
393 exclude_ip4=NULL;
394 }
395
396 if (exclude_name) {
397 for (i=0 ; i<num_exclude_name ; i++)
398 if (exclude_name[i].url) free(exclude_name[i].url);
399 free(exclude_name);
400 exclude_name=NULL;
401 }
402
403 if(excludeuser) {
404 free(excludeuser);
405 excludeuser=NULL;
406 }
43f18f45 407}