2 wcmgr - Webalizer (DNS) Cache file Manager
4 webalizer - a web server log analysis program
6 Copyright (C) 1997-2011 Bradford L. Barrett
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version, and provided that the above
12 copyright and permission notice is included with all distributed
13 copies of this or derived software.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
26 /*********************************************/
27 /* STANDARD INCLUDES */
28 /*********************************************/
38 /* ********************************************************** */
39 /* If DNS support is not enabled, then we just compile a stub */
40 /* program that displays an appropriate warning when run. */
41 /* ********************************************************** */
45 printf("********************* NOTICE!! *********************\n");
46 printf("This version of the Webalizer was not compiled with\n");
47 printf("DNS support. In order to use this program, you must\n");
48 printf("configure the Webalizer at build time with the DNS\n");
49 printf("support enabled (--enable-dns configure option).\n");
50 printf("****************************************************\n\n");
51 exit(1); /* exit with error code */
54 #else /* USE_DNS defined */
57 #include <unistd.h> /* normal stuff */
60 #include <sys/utsname.h>
68 /* ensure sys/types */
70 #include <sys/types.h>
74 #include "webalizer.h"
76 /*********************************************/
77 /* Forward reference local functions */
78 /*********************************************/
80 void list_cache(void);
81 void stat_cache(void);
82 void export_cache(void);
83 void import_cache(void);
87 void purge_cache(void);
88 void create_cache(void);
89 static int db_put(char *, char *, int, time_t);
91 /*********************************************/
92 /* GLOBAL VARIABLES */
93 /*********************************************/
95 char *pname
= "WCMGR - Webalizer (DNS) Cache file Manager";
96 char *version
= "1.00"; /* program version */
97 char *editlvl
= "03"; /* edit level */
98 char *moddate
= "12-Jul-2008"; /* modification date */
99 char *copyright
= "Copyright 2007-2011 by Bradford L. Barrett";
101 int action
= 'l'; /* action flag (default=list) */
102 int create
= 0; /* cache creation flag */
103 int verbose
= 0; /* Verbose flag (1=be verbose) */
104 int rec_ttl
= 7; /* purge TTL in days */
105 DB
*dns_db
= NULL
; /* DNS cache database */
106 DB
*out_db
= NULL
; /* output cache db if needed */
107 DBC
*cursorp
= NULL
; /* database cursor */
108 DBT q
, r
; /* query/reply structures */
109 char *in_file
= NULL
; /* input cache filename */
110 char out_file
[MAXHOST
+4]; /* output cache filename */
111 int dns_fd
= 0; /* database file descriptor */
112 time_t runtime
; /* runtime for TTL calcs */
113 char addr
[129]; /* buffer for IP search addr */
114 char name
[MAXHOST
+1]; /* buffer for name value */
116 extern char *optarg
; /* command line processing */
120 /* dnsRecord structure used in wcmgr */
123 time_t timeStamp
; /* Timestamp of resolv data */
124 int numeric
; /* 0: Name, 1: IP-address */
125 char hostName
[MAXHOST
+1]; /* Hostname buffer (variable) */
128 /*********************************************/
129 /* PRINT_VER - display version information */
130 /*********************************************/
135 struct utsname system_info
;
137 printf("%s V%s-%s\n%s\n",pname
,version
,editlvl
,copyright
);
140 db_version(&v
,&r
,&l
);
141 printf("System : %s %s (%s)\n",
144 system_info
.machine
);
145 printf("DB Ver. : V%d.%d.%d\n",v
,r
,l
);
146 printf("Mod Date: %s\n",moddate
);
152 /*********************************************/
153 /* PRINT_HELP - Command help display */
154 /*********************************************/
156 void print_help(void)
158 printf("Usage: wcmgr [options] cache-file\n\n");
159 printf("Options:\n");
160 printf(" -h This help display\n");
161 printf(" -V Version information\n");
162 printf(" -v be verbose\n");
163 printf(" -a addr Add DNS record\n");
164 printf(" -c Create new cache file\n");
165 printf(" -d addr Delete DNS record\n");
166 printf(" -f addr Find DNS record\n");
167 printf(" -i name Import cache from file\n");
168 printf(" -l List cache file contents\n");
169 printf(" -n name hostname (used for add)\n");
170 printf(" -p num Purge after num days\n");
171 printf(" -s Display cache file stats/info\n");
172 printf(" -t num TTL value (for add and stats)\n");
173 printf(" -x name Export cache to tab file\n");
175 printf("If no options are specified, the default\n");
176 printf("action is to list the cache file contents.\n\n");
180 /*********************************************/
181 /* TTL_AGE - format TTL age for printing */
182 /*********************************************/
184 const char *ttl_age(time_t now
, time_t then
)
186 static char our_buffer
[32]; /* string return buffer */
187 time_t age
; /* age value in seconds */
188 int days
, hours
, mins
; /* day/hour/min counters */
190 /* get age in seconds */
193 /* now calc days/hours/min */
194 days
=age
/86400; age
=age
-(days
*86400);
195 hours
=age
/3600; age
=age
-(hours
*3600);
198 /* format the string */
199 sprintf(our_buffer
,"%02dd:%02dh:%02dm",days
, hours
, mins
);
201 /* and return to caller */
205 /*********************************************/
206 /* MAIN entry point here */
207 /*********************************************/
209 int main(int argc
, char *argv
[])
211 int i
; /* gotta have one of these :-) */
213 /* some systems need this */
214 setlocale(LC_CTYPE
,"");
216 /* initalize name/addr */
217 memset(addr
, 0, sizeof(addr
));
218 memset(name
, 0, sizeof(name
));
219 memset(out_file
,0,sizeof(out_file
));
221 /* Get our command line arguments */
223 while ((i
=getopt(argc
,argv
,"a:cd:f:hi:ln:p::st:vVx:"))!=EOF
)
227 case 'a': action
='a'; strncpy(addr
,optarg
,sizeof(addr
)-1); break;
228 case 'c': if (action
!='i') action
='c'; create
=1; break;
229 case 'd': action
='d'; strncpy(addr
,optarg
,sizeof(addr
)-1); break;
230 case 'f': action
='f'; strncpy(addr
,optarg
,sizeof(addr
)-1); break;
231 case 'i': action
='i'; strncpy(out_file
,optarg
,sizeof(out_file
)-1);
233 case 'h': print_help(); break;
234 case 'n': strncpy(name
,optarg
,sizeof(name
)-1); break;
235 case 'p': action
='p'; if (optarg
!=NULL
) rec_ttl
=atoi(optarg
); break;
236 case 's': action
='s'; break;
237 case 't': rec_ttl
=atoi(optarg
); break;
238 case 'v': verbose
=1; break;
239 case 'V': print_ver(); break;
240 case 'x': action
='x'; strncpy(out_file
,optarg
,sizeof(out_file
)-1);
242 case ':': /* catch invalid options here */
244 case 'l': /* This is the default action */
245 default: action
='l'; break;
249 /* Get cache filename if specified */
250 if (argc
- optind
== 0) print_help(); /* gots to have a filename!! */
251 in_file
= argv
[optind
];
253 /* Try to create our DB handle */
254 if ( db_create(&dns_db
, NULL
, 0) )
256 fprintf(stderr
,"Error: unable to create db handle!\n");
260 /* force sane TTL value */
261 if (rec_ttl
> 99) rec_ttl
=99;
262 if (rec_ttl
< 0 ) rec_ttl
=7;
264 /* Branch on 'action' specified */
267 case 'a': add_rec(); break;
268 case 'c': create_cache(); break;
269 case 'd': del_rec(); break;
270 case 'f': find_rec(); break;
271 case 'i': import_cache(); break;
272 case 's': stat_cache(); break;
273 case 'p': purge_cache(); break;
274 case 'x': export_cache(); break;
276 default: list_cache(); break;
281 /*********************************************/
282 /* LIST_CACHE - Dump out cache contents */
283 /*********************************************/
292 /* open the database (read-only) */
293 if ((i
=dns_db
->open(dns_db
, NULL
, in_file
, NULL
, DB_HASH
, DB_RDONLY
, 0)))
295 /* Error opening the cache file.. tell user and exit */
296 fprintf(stderr
,"Error: %s: %s\n",in_file
,db_strerror(i
));
300 /* Create a cursor */
301 if ( dns_db
->cursor(dns_db
, NULL
, &cursorp
, 0) )
303 fprintf(stderr
,"Error: Unable to create cursor!\n");
307 /* get our runtime for TTL calculations */
312 printf("Webalizer DNS Cache file listing generated %s\n",ctime(&runtime
));
313 printf("IP Address TTL Age Hostname\n");
314 printf("--------------- ------------- ------------------------" \
315 "-----------------------\n");
318 /* initalize data areas */
319 memset(&q
, 0, sizeof(DBT
));
320 memset(&r
, 0, sizeof(DBT
));
321 memset(&dns_rec
, 0, sizeof(struct dnsRec
));
323 /* Loop through database */
324 while (!cursorp
->c_get(cursorp
, &q
, &r
, DB_NEXT
))
328 memset(ip_buf
, 0, sizeof(ip_buf
));
329 strncpy(ip_buf
, q
.data
, (q
.size
>47)?47:q
.size
); /* save IP address */
330 memcpy(&dns_rec
, r
.data
, r
.size
);
331 if (dns_rec
.numeric
) t_num
++;
332 printf("%-15s [%s] %s\n",ip_buf
,
334 ttl_age(runtime
, dns_rec
.timeStamp
):
338 /* done, clear for next rec */
339 memset(&q
, 0, sizeof(DBT
));
340 memset(&r
, 0, sizeof(DBT
));
345 printf("------------------------------------------------------" \
346 "-----------------------\n");
347 printf("Filename: %s (%llu records)\n",in_file
, t_rec
);
351 /*********************************************/
352 /* PURGE_CACHE - Purge cache of expired recs */
353 /*********************************************/
364 /* file control struct */
365 struct flock our_flock
;
367 if (verbose
) printf("Purging records over %d days from '%s'\n",
370 /* open the input database (read-write) */
371 if ((i
=dns_db
->open(dns_db
, NULL
, in_file
, NULL
, DB_HASH
, 0, 0)))
373 /* Error opening the cache file.. tell user and exit */
374 fprintf(stderr
,"Error: %s: %s\n",in_file
,db_strerror(i
));
378 /* get file descriptor */
379 dns_db
->fd(dns_db
, &dns_fd
);
381 /* Try to lock the file */
382 our_flock
.l_whence
=SEEK_SET
;
385 our_flock
.l_type
=F_WRLCK
;
387 if (fcntl(dns_fd
,F_SETLK
,&our_flock
) <0)
389 /* Error - can't lock file */
390 printf("Error: Unable to lock cache file: %s\n",strerror(errno
));
394 /* Create a cursor */
395 if ( dns_db
->cursor(dns_db
, NULL
, &cursorp
, 0) )
397 fprintf(stderr
,"Error: Unable to create cursor!\n");
401 /* Try to create our output DB handle */
402 if ( db_create(&out_db
, NULL
, 0) )
404 fprintf(stderr
,"Error: unable to create output db handle!\n");
408 /* generate output filename */
409 memset(out_file
, 0, sizeof(out_file
));
410 sprintf(out_file
, "%s.new", in_file
);
412 /* open the output database (read-write) */
413 if ((i
=out_db
->open(out_db
, NULL
, out_file
, NULL
,
414 DB_HASH
, DB_CREATE
|DB_EXCL
, 0644)))
416 /* Error opening the cache file.. tell user and exit */
417 fprintf(stderr
,"Error: %s: %s\n",out_file
,db_strerror(i
));
421 /* get our runtime for TTL calculations */
424 /* initalize data areas */
425 memset(&q
, 0, sizeof(DBT
));
426 memset(&r
, 0, sizeof(DBT
));
428 /* Loop through database */
429 while (!cursorp
->c_get(cursorp
, &q
, &r
, DB_NEXT
))
433 memcpy(&dns_rec
, r
.data
, r
.size
);
435 /* get record ttl age */
436 if (dns_rec
.timeStamp
==0) age
=0;
437 else age
= runtime
- dns_rec
.timeStamp
;
439 if ( age
<= (rec_ttl
*86400) )
441 /* Good record.. insert into new cache file */
442 if ( (i
=out_db
->put(out_db
, NULL
, &q
, &r
, 0)) != 0 )
444 fprintf(stderr
,"Error: db_put fail: %s!\n",db_strerror(i
));
455 memset(ip_buf
, 0, sizeof(ip_buf
));
456 strncpy(ip_buf
, q
.data
, (q
.size
>47)?47:q
.size
);
457 printf("Purging %-16s [%s]\n",ip_buf
,
458 ttl_age(runtime
,dns_rec
.timeStamp
));
462 /* done, clear for next rec */
463 memset(&q
, 0, sizeof(DBT
));
464 memset(&r
, 0, sizeof(DBT
));
467 /* Successful exit! */
468 our_flock
.l_type
=F_UNLCK
;
469 fcntl(dns_fd
, F_SETLK
, &our_flock
);
470 dns_db
->close(dns_db
, 0);
471 out_db
->close(out_db
, 0);
474 if (rename(out_file
, in_file
))
476 fprintf(stderr
,"Error renaming file: %s\n",strerror(errno
));
481 printf("%llu of %llu records purged from '%s'\n",t_exp
,t_in
,in_file
);
484 /*********************************************/
485 /* STAT_CACHE - Display cache stats/info */
486 /*********************************************/
490 /* Define some variables */
492 time_t min_age
=0; /* min/max TTL age in cache */
494 u_int64_t t_rec
=0; /* Various record totals */
502 /* open the database (read-only) */
503 if ((i
=dns_db
->open(dns_db
, NULL
, in_file
, NULL
, DB_HASH
, DB_RDONLY
, 0)))
505 /* Error opening the cache file.. tell user and exit */
506 fprintf(stderr
,"Error: %s: %s\n",in_file
,db_strerror(i
));
510 /* Create a cursor */
511 if ( dns_db
->cursor(dns_db
, NULL
, &cursorp
, 0) )
513 fprintf(stderr
,"Error: Unable to create cursor!\n");
517 /* get our runtime for TTL calculations */
520 /* initalize data areas */
521 memset(&q
, 0, sizeof(DBT
));
522 memset(&r
, 0, sizeof(DBT
));
523 memset(&dns_rec
, 0, sizeof(struct dnsRec
));
525 /* Loop through database */
526 while (!cursorp
->c_get(cursorp
, &q
, &r
, DB_NEXT
))
528 t_rec
++; /* add to total */
529 if (r
.size
>= sizeof(dns_rec
)) { t_err
++; continue; } /* size error? */
530 memcpy(&dns_rec
, r
.data
, r
.size
); /* get record */
531 if (dns_rec
.numeric
) t_num
++; else t_name
++; /* resolved? */
533 if (dns_rec
.timeStamp
!=0) /* permanent? */
535 age
=runtime
-dns_rec
.timeStamp
; /* calc age */
536 if ((age
< min_age
) || (t_rec
==1) ) min_age
=age
; /* min/max age */
537 if ( age
> max_age
) max_age
=age
; /* if not perm */
538 if ( age
> (rec_ttl
*86400)) t_old
++; /* purgable? */
540 else t_perm
++; /* inc counter */
542 /* done, clear for next rec */
543 memset(&q
, 0, sizeof(DBT
));
544 memset(&r
, 0, sizeof(DBT
));
547 /* Print actual record counts */
548 printf("Report generated on: %s",ctime(&runtime
));
549 printf("DNS Cache Filename : %s\n",in_file
);
551 printf("Total Records : %llu\n",t_rec
);
552 printf("Total Resolved : %llu\n",t_name
);
553 printf("Total Unresolved : %llu\n",t_num
);
554 printf("Total Permanent : %llu\n",t_perm
);
555 printf("Newest Record age : %s\n",ttl_age(min_age
,0));
556 printf("Oldest Record age : %s\n",ttl_age(max_age
,0));
557 printf("Total over %02d days : %llu\n",rec_ttl
,t_old
);
558 if (t_err
) printf("Record Size Errors : %llu\n",t_err
);
562 /*********************************************/
563 /* FIND_REC - Find IP record in cache */
564 /*********************************************/
571 /* open the database (read-only) */
572 if ((i
=dns_db
->open(dns_db
, NULL
, in_file
, NULL
, DB_HASH
, DB_RDONLY
, 0)))
574 /* Error opening the cache file.. tell user and exit */
575 fprintf(stderr
,"Error: %s: %s\n",in_file
,db_strerror(i
));
579 /* get our runtime for TTL calculations */
582 /* initalize data areas */
583 memset(&q
, 0, sizeof(DBT
));
584 memset(&r
, 0, sizeof(DBT
));
585 memset(&dns_rec
, 0, sizeof(struct dnsRec
));
587 /* search the cache */
589 q
.size
= strlen(addr
);
590 if ( (i
=dns_db
->get(dns_db
, NULL
, &q
, &r
, 0)) == 0)
592 /* We found it! display info */
593 memset(ip_buf
, 0, sizeof(ip_buf
));
594 strncpy(ip_buf
, q
.data
, (q
.size
>47)?47:q
.size
); /* save IP address */
595 memcpy(&dns_rec
, r
.data
, r
.size
);
598 /* Verbose display */
599 printf("Address : %s\n",ip_buf
);
600 printf("Hostname : %s\n",dns_rec
.hostName
);
601 printf("Resolved : %s\n",(dns_rec
.numeric
)?"No":"Yes");
602 if (dns_rec
.timeStamp
)
605 printf("Timestamp: %s",ctime(&dns_rec
.timeStamp
));
606 printf("TTL age : %s\n\n",ttl_age(runtime
, dns_rec
.timeStamp
));
610 printf("Timestamp: N/A\n");
611 printf("TTL age : Permanent\n");
616 /* Standard 1 line display */
617 printf("%-15s [%s] %s\n",ip_buf
,
619 ttl_age(runtime
, dns_rec
.timeStamp
):
627 printf("%s not found!\n",addr
);
629 printf("Error: %s\n",db_strerror(i
));
633 /*********************************************/
634 /* DEL_REC - Delete record from cache file */
635 /*********************************************/
642 /* ensure we have addr string */
643 if (addr
[0]!='\0') cp
=addr
;
646 fprintf(stderr
,"Error: No IP address specified!\n");
650 /* ensure IPv6 addresses are lowercase */
651 cp
=addr
; while (*cp
!='\0') *cp
++=tolower(*cp
);
653 /* open the database (read-write) */
654 if ((i
=dns_db
->open(dns_db
, NULL
, in_file
, NULL
, DB_HASH
, 0, 0)))
656 /* Error opening the cache file.. tell user and exit */
657 fprintf(stderr
,"Error: %s: %s\n",in_file
,db_strerror(i
));
661 /* initalize data areas */
662 memset(&q
, 0, sizeof(DBT
));
663 memset(&r
, 0, sizeof(DBT
));
664 memset(&dns_rec
, 0, sizeof(struct dnsRec
));
666 /* search the cache */
668 q
.size
= strlen(addr
);
670 /* Try to delete the record */
671 if ( (i
=dns_db
->del(dns_db
, NULL
, &q
, 0)) )
675 printf("%s not found in cache!\n",addr
);
680 fprintf(stderr
,"Error: %s\n",db_strerror(i
));
684 dns_db
->close(dns_db
, 0);
686 printf("%s sucessfully deleted from cache file\n",addr
);
689 /*********************************************/
690 /* ADD_REC - Add record to cache file */
691 /*********************************************/
698 /* ensure we have addr string */
699 if (addr
[0]!='\0') cp
=addr
;
702 fprintf(stderr
,"Error: No IP address specified!\n");
709 fprintf(stderr
,"Error: IP address too long!\n");
713 /* ensure everything is lowercase */
714 cp
=addr
; while (*cp
!='\0') *cp
++=tolower(*cp
);
717 cp
=name
; while (*cp
!='\0') *cp
++=tolower(*cp
);
720 /* open the database (read-write) */
721 if ((i
=dns_db
->open(dns_db
, NULL
, in_file
, NULL
, DB_HASH
, 0, 0)))
723 /* Error opening the cache file.. tell user and exit */
724 fprintf(stderr
,"Error: %s: %s\n",in_file
,db_strerror(i
));
728 /* get our runtime for TTL calculations */
731 /* initalize data areas */
732 memset(&q
, 0, sizeof(DBT
));
733 memset(&r
, 0, sizeof(DBT
));
734 memset(&dns_rec
, 0, sizeof(struct dnsRec
));
736 /* search the cache */
738 q
.size
= strlen(addr
);
739 if ( (i
=dns_db
->get(dns_db
, NULL
, &q
, &r
, 0)) == 0)
741 fprintf(stderr
,"Error: %s already exists in cache!\n",addr
);
748 fprintf(stderr
,"Error: %s\n",db_strerror(i
));
755 strncpy(name
,addr
,strlen(addr
));
758 if (rec_ttl
==0) runtime
=0;
760 /* put it in the database */
761 if (db_put(addr
, name
, (strcmp(name
,addr
))?0:1, runtime
)==0)
762 dns_db
->close(dns_db
,0);
764 printf("%s sucessfully added to cache file\n",addr
);
769 /*********************************************/
770 /* CREATE_CACHE - Create a new cache file */
771 /*********************************************/
777 /* create the database */
778 if ((i
=dns_db
->open(dns_db
,NULL
,in_file
,NULL
,
779 DB_HASH
,DB_CREATE
|DB_EXCL
,0644)))
781 /* Error opening the cache file.. tell user and exit */
782 fprintf(stderr
,"Error: %s: %s\n",in_file
,db_strerror(i
));
785 dns_db
->close(dns_db
,0);
786 if (verbose
) printf("Cache file %s created successfully\n",in_file
);
789 /*********************************************/
790 /* IMPORT_CACHE - import cache from tab file */
791 /*********************************************/
801 /* open the database (read-write) */
802 if (create
) flag
=DB_CREATE
|DB_EXCL
;
803 if ((i
=dns_db
->open(dns_db
, NULL
, in_file
, NULL
, DB_HASH
, flag
, 0644)))
805 /* Error opening the cache file.. tell user and exit */
806 fprintf(stderr
,"Error: %s: %s\n",in_file
,db_strerror(i
));
810 /* open our import file */
811 in_fp
=fopen(out_file
,"r");
814 while ((fgets(buffer
,4096,in_fp
)) != NULL
)
816 memset(&dns_rec
, 0, sizeof(dns_rec
));
817 memset(&ip_buf
, 0, sizeof(ip_buf
));
818 i
= sscanf(buffer
,"%s\t%lu\t%d\t%s",
824 if (ip_buf
[0]=='#') continue; /* skip comments */
828 fprintf(stderr
,"Error reading tab file %s\n",out_file
);
832 t_rec
++; /* bump totals */
834 /* put it in the database */
835 if (db_put(ip_buf
, dns_rec
.hostName
,
836 dns_rec
.numeric
, dns_rec
.timeStamp
)!=0)
838 fprintf(stderr
,"Error inserting cache record:\n%s\n",buffer
);
843 else fprintf(stderr
,"Error: File not found: %s\n",out_file
);
844 dns_db
->close(dns_db
,0);
846 if (verbose
) printf("%llu records imported into '%s' from file '%s'\n",
847 t_rec
, in_file
, out_file
);
850 /*********************************************/
851 /* EXPORT_CACHE - export cache to tab file */
852 /*********************************************/
860 struct stat out_stat
;
862 /* make sure files are different! */
863 if (!strcmp(in_file
,out_file
))
865 fprintf(stderr
,"Error: Bad export filename: %s\n",out_file
);
869 /* open the database (read-only) */
870 if ((i
=dns_db
->open(dns_db
, NULL
, in_file
, NULL
, DB_HASH
, DB_RDONLY
, 0)))
872 /* Error opening the cache file.. tell user and exit */
873 fprintf(stderr
,"Error: %s: %s\n",in_file
,db_strerror(i
));
877 /* Create a cursor */
878 if ( dns_db
->cursor(dns_db
, NULL
, &cursorp
, 0) )
880 fprintf(stderr
,"Error: Unable to create cursor!\n");
884 /* stat output file */
885 if ( !(lstat(out_file
, &out_stat
)) )
887 /* check if the file is a symlink */
888 if ( S_ISLNK(out_stat
.st_mode
) )
890 fprintf(stderr
,"%s %s\n","Error: File is a symlink:",out_file
);
895 /* open output file */
896 if ( (out_fp
=fopen(out_file
,"w")) == NULL
)
898 fprintf(stderr
,"%s %s\n","Error: Cannot create file:",out_file
);
902 /* initalize data areas */
903 memset(&q
, 0, sizeof(DBT
));
904 memset(&r
, 0, sizeof(DBT
));
905 memset(&dns_rec
, 0, sizeof(struct dnsRec
));
907 /* Loop through database */
908 while (!cursorp
->c_get(cursorp
, &q
, &r
, DB_NEXT
))
912 memset(ip_buf
, 0, sizeof(ip_buf
));
913 strncpy(ip_buf
, q
.data
, (q
.size
>47)?47:q
.size
); /* save IP address */
914 memcpy(&dns_rec
, r
.data
, r
.size
);
916 /* Print out tab delimited line */
917 /* Format: IP timestamp numeric hostname */
918 fprintf(out_fp
,"%s\t%lu\t%d\t%s\n",
919 ip_buf
,dns_rec
.timeStamp
,
923 /* done, clear for next rec */
924 memset(&q
, 0, sizeof(DBT
));
925 memset(&r
, 0, sizeof(DBT
));
927 dns_db
->close(dns_db
,0);
930 if (verbose
) printf("%llu records exported from '%s' to file '%s'\n",
931 t_rec
, in_file
, out_file
);
934 /*********************************************/
935 /* DB_PUT - put key/val in the cache db */
936 /*********************************************/
938 static int db_put(char *key
, char *value
, int numeric
, time_t ttl
)
941 /* dnsRecord structure used in database */
944 time_t timeStamp
; /* Timestamp of resolv data */
945 int numeric
; /* 0: Name, 1: IP-address */
946 char hostName
[1]; /* Hostname buffer (variable) */
951 struct dnsRecord
*recPtr
= NULL
;
952 int nameLen
= strlen(value
)+1;
954 /* Align to multiple of eight bytes */
955 int recSize
= (sizeof(struct dnsRecord
)+nameLen
+7) & ~0x7;
957 /* make sure we have a db ;) */
960 if((recPtr
= calloc(1, recSize
)))
962 recPtr
->timeStamp
= ttl
;
963 recPtr
->numeric
= numeric
;
964 memcpy(&recPtr
->hostName
, value
, nameLen
);
965 memset(&k
, 0, sizeof(k
));
966 memset(&v
, 0, sizeof(v
));
969 k
.size
= strlen(key
);
974 if ( (i
=dns_db
->put(dns_db
, NULL
, &k
, &v
, 0)) != 0 )
975 fprintf(stderr
,"Error: db_put fail: %s!\n",db_strerror(i
));