static char sccsid
[] = "@(#)ns_maint.c 4.3 (Berkeley) 6/4/86";
* Copyright (c) 1986 Regents of the University of California
#include <arpa/nameser.h>
* Invoked at regular intervals by signal interrupt; refresh all secondary
* zones from primary name server and remove old cache entries.
register struct zoneinfo
*zp
;
time_t now
, next_refresh
;
fprintf(ddt
,"ns_maint()\n");
for (zp
= zones
; zp
< &zones
[nzones
]; zp
++) {
if (zp
->z_type
!= Z_SECONDARY
)
if (gettimeofday(&tt
, (struct timezone
*)0) < 0)
syslog(LOG_ERR
, "gettimeofday failed: %m");
if (zp
->z_origin
[0] == '\0')
fprintf(ddt
,"origin ='.'");
fprintf(ddt
,"origin ='%s'", zp
->z_origin
);
fprintf(ddt
,", source = %s\n", zp
->z_source
);
fprintf(ddt
,"z_refresh = %ld", zp
->z_refresh
);
fprintf(ddt
,", retry = %ld", zp
->z_retry
);
fprintf(ddt
,", expire = %ld", zp
->z_expire
);
fprintf(ddt
,", minimum = %ld", zp
->z_minimum
);
fprintf(ddt
,", serial = %ld\n", zp
->z_serial
);
fprintf(ddt
,"z_time = %d", zp
->z_time
);
fprintf(ddt
,", now time : %d sec", now
);
fprintf(ddt
,", time left: %d sec\n", zp
->z_time
- now
);
zp
->z_time
= tt
.tv_sec
+ zp
->z_refresh
;
* Find when the next refresh needs to be and set
* interupt time accordingly.
* Why have needless intruptions.
* I just hate it when the cleaning crew come early.
next_refresh
= zp
->z_time
;
else if (next_refresh
> zp
->z_time
)
next_refresh
= zp
->z_time
;
* If first is still true, no secondary zones were found
* therefore refreshes aren't needed and interupts are turned off
* This needs to be changed when we have refreshes for co-masters
bzero((char *)&ival
, sizeof (ival
));
ival
.it_value
.tv_sec
= next_refresh
- now
;
if (ival
.it_value
.tv_sec
< 0)
ival
.it_value
.tv_sec
= 60;
(void) setitimer(ITIMER_REAL
, &ival
, (struct itimerval
*)NULL
);
fprintf(ddt
,"exit ns_maint() Next interupt in %d sec\n",
register struct databuf
*dp
;
int cnt
, soacnt
, error
= 0;
struct zoneinfo zp_start
, zp_finish
;
struct databuf
*pdp
, *tdp
;
struct itimerval zeroival
;
extern struct sockaddr_in nsaddr
;
extern int read_interrupted
;
fprintf(ddt
,"zoneref()\n");
bzero((char *)&zeroival
, sizeof(zeroival
));
ival
.it_value
.tv_sec
= 30;
sv
.sv_handler
= read_alarm
;
(void) sigvec(SIGALRM
, &sv
, &osv
);
for( cnt
= 0; cnt
< zp
->z_addrcnt
; cnt
++) {
bzero((char *)&sin
, sizeof(sin
));
sin
.sin_family
= AF_INET
;
sin
.sin_port
= nsaddr
.sin_port
;
sin
.sin_addr
= zp
->z_addr
[cnt
];
if ((s
= socket(AF_INET
, SOCK_STREAM
, 0)) < 0) {
syslog(LOG_ERR
, "zoneref: socket: %m");
fprintf(ddt
,"connecting to server #%d %s, %d\n",
cnt
+1, inet_ntoa(sin
.sin_addr
), ntohs(sin
.sin_port
));
if (connect(s
, &sin
, sizeof(sin
)) < 0) {
fprintf(ddt
,"connect failed\n");
if ((n
= res_mkquery(QUERY
, zp
->z_origin
, C_IN
,
T_SOA
, (char *)NULL
, 0, NULL
, buf
, sizeof(buf
))) < 0) {
syslog(LOG_ERR
, "zoneref: res_mkquery failed");
(void) sigvec(SIGALRM
, &osv
, (struct sigvec
*)0);
* Send length & message for zone transfer
if (writemsg(s
, buf
, n
) < 0) {
fprintf(ddt
,"writemsg failed\n");
* Get out your butterfly net and catch the SOA
(void) setitimer(ITIMER_REAL
, &ival
,
(struct itimerval
*)NULL
);
if ((n
= recv(s
, cp
, l
, 0)) > 0) {
if (errno
== EINTR
&& !read_interrupted
)
(void) setitimer(ITIMER_REAL
, &zeroival
,
(struct itimerval
*)NULL
);
if ((len
= htons(*(u_short
*)buf
)) == 0) {
(void) setitimer(ITIMER_REAL
, &ival
,
(struct itimerval
*)NULL
);
if ((n
= recv(s
, cp
, l
, 0)) > 0) {
if (errno
== EINTR
&& !read_interrupted
)
(void) setitimer(ITIMER_REAL
, &zeroival
,
(struct itimerval
*)NULL
);
fprintf(ddt
,"len = %d\n", len
);
tmp
= buf
+ sizeof(HEADER
);
tmp
+= dn_skip(tmp
) + QFIXEDSZ
;
soa_zinfo(&zp_start
, tmp
);
if (zp
->z_serial
>= zp_start
.z_serial
) {
(void) sigvec(SIGALRM
, &osv
, (struct sigvec
*)0);
if ((n
= res_mkquery(QUERY
, zp
->z_origin
, C_IN
,
T_AXFR
, (char *)NULL
, 0, NULL
,
buf
, sizeof(buf
))) < 0) {
syslog(LOG_ERR
, "zoneref: res_mkquery failed");
(void) sigvec(SIGALRM
, &osv
,
* Send length & message for zone transfer
if (writemsg(s
, buf
, n
) < 0) {
fprintf(ddt
,"writemsg failed\n");
* Receive length & response
(void) setitimer(ITIMER_REAL
, &ival
,
(struct itimerval
*)NULL
);
if ((n
= recv(s
, cp
, l
, 0)) > 0) {
if (errno
== EINTR
&& !read_interrupted
)
(void) setitimer(ITIMER_REAL
, &zeroival
,
(struct itimerval
*)NULL
);
if ((len
= htons(*(u_short
*)buf
)) == 0)
(void) setitimer(ITIMER_REAL
, &ival
,
(struct itimerval
*)NULL
);
if ((n
= recv(s
, cp
, l
, 0)) > 0) {
if (errno
== EINTR
&& !read_interrupted
)
(void) setitimer(ITIMER_REAL
, &zeroival
,
(struct itimerval
*)NULL
);
fprintf(ddt
,"len = %d\n", len
);
cp
= buf
+ sizeof(HEADER
);
cp
+= dn_skip(cp
) + QFIXEDSZ
;
n
= doupdate(buf
, sizeof(buf
), cp
, zone
, 0);
if ((cp
- buf
) + n
!= len
) {
fprintf(ddt
,"zoneref: doupdate failed (%d, %d)\n",
if ((getshort(tmp
)) == T_SOA
) {
tmp
+= 3 * sizeof(u_short
)
if (serial
!= zp
->z_serial
)
np
= nlookup(zp
->z_origin
, &htp
, &fname
, 0);
if (np
== NULL
|| fname
!= zp
->z_origin
) {
(void) sigvec(SIGALRM
, &osv
, (struct sigvec
*)0);
if (!match(dp
, C_ANY
, T_SOA
)) {
cp
+= strlen(cp
) + 1; /* origin */
cp
+= strlen(cp
) + 1; /* address */
fprintf(ddt
,"Found serial = %d\n",serial
);
/* remove data if not = current serial number */
if (serial
!= zp
->z_serial
) {
fprintf(ddt
,"deleting SOA serial #%d\n",
(void) sigvec(SIGALRM
, &osv
, (struct sigvec
*)0);
fprintf(ddt
,"error reciving zone transfer\n");
(void) sigvec(SIGALRM
, &osv
, (struct sigvec
*)0);
* The land where all repressed slaves dream of.
* Can't find a master to talk to.
* syslog it and hope we can find a master during maintenance
syslog(LOG_ERR
, "zoneref: Can't find Master for secondary zone %s",
zp
->z_refresh
= zp
->z_retry
;
if (gettimeofday(&tt
, (struct timezone
*)0) < 0)
syslog(LOG_ERR
, "gettimeofday failed: %m");
zp
->z_time
= tt
.tv_sec
+ zp
->z_retry
;