]>
Commit | Line | Data |
---|---|---|
25697a35 | 1 | /* |
94ff9470 | 2 | * SARG Squid Analysis Report Generator http://sarg.sourceforge.net |
e99bf0c0 | 3 | * 1998, 2013 |
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 | 30 | struct 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 |
38 | struct 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 |
46 | struct 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 | ||
54 | static struct hostip4struct *exclude_ip4=NULL; | |
55 | static int num_exclude_ip4=0; | |
7819e0d5 FM |
56 | static struct hostip6struct *exclude_ip6=NULL; |
57 | static int num_exclude_ip6=0; | |
43f18f45 FM |
58 | static struct hostnamestruct *exclude_name=NULL; |
59 | static int num_exclude_name=0; | |
60 | static int ip4allocated=0; | |
7819e0d5 | 61 | static int ip6allocated=0; |
43f18f45 FM |
62 | static int nameallocated=0; |
63 | ||
64 | static char *excludeuser=NULL; | |
65 | ||
7819e0d5 FM |
66 | /*! |
67 | Store a IPv4 address to exclude from the reported URL. | |
68 | ||
69 | \param addr The 4 char of the address. | |
70 | \param nbits The number of bits to keep in the prefix. | |
71 | */ | |
72 | static 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) { | |
82 | debuga(_("Not enough memory to store the exlcluded IP addresses\n")); | |
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. | |
96 | ||
97 | \param addr The 8 short int of the address. | |
98 | \param nbits The number of bits to keep in the prefix. | |
99 | */ | |
100 | static 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) { | |
110 | debuga(_("Not enough memory to store the exlcluded IP addresses\n")); | |
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. | |
123 | ||
124 | \param url The host name to exclude. | |
125 | */ | |
126 | static 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) { | |
161 | debuga(_("Not enough memory to store the excluded URLs\n")); | |
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) { | |
171 | debuga(_("Not enough memory to store the excluded URLs\n")); | |
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. | |
180 | ||
181 | \param hexfile The name of the file. | |
182 | \param debug \c True to print debug information. | |
183 | */ | |
43f18f45 FM |
184 | void 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) { | |
4b06d570 | 196 | debuga(_("Cannot open file \"%s\": %s\n"),hexfile,strerror(errno)); |
9bd92830 FM |
197 | exit(EXIT_FAILURE); |
198 | } | |
199 | if(debug) | |
200 | debuga(_("Loading exclude host file from: %s\n"),hexfile); | |
201 | ||
202 | if ((fp_ex = fopen(hexfile, "r")) == NULL) { | |
4b06d570 | 203 | debugapos("gethexclude",_("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) { | |
c4633554 | 214 | debuga(_("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 | ||
227 | fclose(fp_ex); | |
228 | return; | |
43f18f45 FM |
229 | } |
230 | ||
7819e0d5 FM |
231 | /*! |
232 | Check if the URL is excluded as per the host exclusion list. | |
233 | ||
234 | \param url The URL to check. | |
235 | ||
236 | \retval 1 Keep the URL. | |
237 | \retval 0 Exclude the URL. | |
238 | */ | |
43f18f45 FM |
239 | int vhexclude(const char *url) |
240 | { | |
9bd92830 FM |
241 | int i, j; |
242 | int length; | |
7819e0d5 FM |
243 | int type; |
244 | const char *name; | |
245 | unsigned char ipv4[4]; | |
246 | unsigned short int ipv6[8]; | |
9bd92830 | 247 | unsigned long int addr4; |
7819e0d5 | 248 | int dotpos[50]; |
9bd92830 FM |
249 | int ndots; |
250 | ||
7819e0d5 FM |
251 | type=extract_address_mask(url,&name,ipv4,ipv6,NULL,NULL); |
252 | if (type==1) { | |
9bd92830 FM |
253 | if (exclude_name == NULL) return(1); |
254 | ndots=0; | |
7819e0d5 FM |
255 | for (length=0 ; (unsigned char)name[length]>' ' && name[length]!=':' && name[length]!='/' && name[length]!='?' ; length++) |
256 | if (name[length]=='.') { | |
9bd92830 FM |
257 | /* |
258 | We store the position of each dots of the URL to match it against any | |
259 | wildcard in the excluded list. The size of dotpos is big enough for the most | |
260 | ambitious URL but we have a safety mechanism that shift the positions should there be too | |
261 | many dots in the URL. | |
262 | */ | |
263 | if (ndots<sizeof(dotpos)/sizeof(dotpos[0])) | |
264 | dotpos[ndots++]=length+1; | |
265 | else { | |
266 | for (j=1 ; j<ndots ; j++) dotpos[j-1]=dotpos[j]; | |
267 | dotpos[ndots-1]=length+1; | |
268 | } | |
269 | } | |
270 | if (length>0) { | |
271 | for (i=0 ; i<num_exclude_name ; i++) { | |
272 | if (exclude_name[i].ndots>0) { | |
7819e0d5 | 273 | const char *wurl=name; |
9bd92830 FM |
274 | int len=length; |
275 | if (exclude_name[i].ndots<=ndots) { | |
276 | wurl+=dotpos[ndots-exclude_name[i].ndots]; | |
277 | len-=dotpos[ndots-exclude_name[i].ndots]; | |
278 | } | |
279 | if (strncmp(exclude_name[i].url,wurl,len)==0 && exclude_name[i].url[len]=='\0') return(0); | |
280 | } else { | |
281 | if (strncmp(exclude_name[i].url,url,length)==0 && exclude_name[i].url[length]=='\0') return(0); | |
282 | } | |
283 | } | |
284 | } | |
7819e0d5 FM |
285 | } else if (type==2) { |
286 | if (exclude_ip4 == NULL) return(1); | |
287 | addr4=0UL; | |
288 | for (i=0 ; i<4 ; i++) addr4=(addr4 << 8) | ipv4[i]; | |
289 | for (i=0 ; i<num_exclude_ip4 ; i++) { | |
290 | if (((exclude_ip4[i].address ^ addr4) & exclude_ip4[i].mask)==0) return(0); | |
291 | } | |
292 | } else if (type==3) { | |
293 | if (exclude_ip6 == NULL) return(1); | |
294 | for (i=0 ; i<num_exclude_ip6 ; i++) { | |
295 | length=exclude_ip6[i].nbits; | |
296 | for (j=length/16-1 ; j>=0 && ipv6[j]==exclude_ip6[i].address[j] ; j--); | |
297 | if (j>=0) return(1); | |
298 | j=length/16; | |
299 | if (j>=8 || length%16==0 || ((ipv6[j] ^ exclude_ip6[i].address[j]) & (0xFFFF<<(length-j*16)))==0) | |
300 | return(0); | |
301 | } | |
9bd92830 | 302 | } |
9bd92830 | 303 | return(1); |
25697a35 GS |
304 | } |
305 | ||
306 | ||
43f18f45 FM |
307 | void getuexclude(const char *uexfile, int debug) |
308 | { | |
9bd92830 FM |
309 | FILE *fp_ex; |
310 | char buf[255]; | |
311 | long int nreg=0; | |
312 | ||
313 | if(debug) | |
314 | debuga(_("Loading exclude file from: %s\n"),uexfile); | |
315 | ||
316 | if ((fp_ex = fopen(uexfile, "r")) == NULL) { | |
4b06d570 | 317 | debugapos("gethexclude",_("Cannot open file \"%s\": %s\n"),uexfile,strerror(errno)); |
9bd92830 FM |
318 | exit(EXIT_FAILURE); |
319 | } | |
320 | ||
321 | if (fseek(fp_ex, 0, SEEK_END)==-1) { | |
b2dad7e7 | 322 | debuga(_("Failed to move till the end of file \"%s\": %s\n"),uexfile,strerror(errno)); |
9bd92830 FM |
323 | exit(EXIT_FAILURE); |
324 | } | |
325 | nreg = ftell(fp_ex); | |
326 | if (nreg<0) { | |
b2dad7e7 | 327 | debuga(_("Cannot get the size of file \"%s\": %s\n"),uexfile,strerror(errno)); |
9bd92830 FM |
328 | exit(EXIT_FAILURE); |
329 | } | |
330 | nreg += 11; | |
331 | if (fseek(fp_ex, 0, SEEK_SET)==-1) { | |
4b06d570 | 332 | debuga(_("Failed to rewind file \"%s\": %s\n"),uexfile,strerror(errno)); |
9bd92830 FM |
333 | exit(EXIT_FAILURE); |
334 | } | |
335 | ||
336 | if((excludeuser=(char *) malloc(nreg))==NULL){ | |
b2dad7e7 | 337 | debuga(_("malloc failed to allocate %ld bytes\n"),nreg); |
9bd92830 FM |
338 | exit(EXIT_FAILURE); |
339 | } | |
340 | ||
341 | bzero(excludeuser,nreg); | |
342 | ||
343 | while(fgets(buf,sizeof(buf),fp_ex)!=NULL){ | |
007905af FM |
344 | if(strchr(buf,'#') != NULL) |
345 | continue; | |
346 | fixendofline(buf); | |
347 | strcat(excludeuser,buf); | |
348 | strcat(excludeuser," "); | |
9bd92830 FM |
349 | } |
350 | ||
351 | strcat(excludeuser,"*END* "); | |
352 | ||
353 | fclose(fp_ex); | |
354 | ||
355 | return; | |
43f18f45 FM |
356 | } |
357 | ||
358 | int vuexclude(const char *user) | |
25697a35 | 359 | { |
9bd92830 FM |
360 | const char *wuser; |
361 | int len; | |
362 | ||
363 | if (excludeuser) { | |
364 | len=strlen(user); | |
365 | wuser=excludeuser; | |
366 | while ((wuser=strstr(wuser,user))!=NULL) { | |
367 | if (wuser[len]==' ') return(0); | |
368 | wuser+=len; | |
369 | } | |
370 | } | |
371 | ||
372 | return(1); | |
25697a35 | 373 | } |
43f18f45 | 374 | |
2824ec9b | 375 | bool is_indexonly(void) |
43f18f45 | 376 | { |
9bd92830 FM |
377 | if (excludeuser==NULL) return(false); |
378 | return(strstr(excludeuser,"indexonly") != NULL); | |
43f18f45 FM |
379 | } |
380 | ||
381 | void free_exclude(void) | |
382 | { | |
9bd92830 FM |
383 | int i; |
384 | ||
385 | if (exclude_ip4) { | |
386 | free(exclude_ip4); | |
387 | exclude_ip4=NULL; | |
388 | } | |
389 | ||
390 | if (exclude_name) { | |
391 | for (i=0 ; i<num_exclude_name ; i++) | |
392 | if (exclude_name[i].url) free(exclude_name[i].url); | |
393 | free(exclude_name); | |
394 | exclude_name=NULL; | |
395 | } | |
396 | ||
397 | if(excludeuser) { | |
398 | free(excludeuser); | |
399 | excludeuser=NULL; | |
400 | } | |
43f18f45 | 401 | } |