* Copyright (c) 1986, 1990 The Regents of the University of California.
* Redistribution and use in source and binary forms are permitted provided
* that: (1) source distributions retain this entire copyright notice and
* comment, and (2) distributions including binaries display the following
* acknowledgement: ``This product includes software developed by the
* University of California, Berkeley and its contributors'' in the
* documentation or other materials provided with the distribution and in
* all advertising materials mentioning features or use of this software.
* Neither the name of the University nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
static char sccsid
[] = "@(#)ns_init.c 4.35 (Berkeley) 6/27/90";
#include <arpa/nameser.h>
struct zoneinfo
*zones
; /* zone information */
int nzones
; /* number of zones in use */
int forward_only
= 0; /* run only as a slave */
char *localdomain
; /* "default" for non-dotted names */
int maint_interval
= 15*60; /* minimum ns_maint() interval */
* Read boot file for configuration info.
register struct zoneinfo
*zp
;
struct zoneinfo
*find_zone();
char buf
[BUFSIZ
], obuf
[BUFSIZ
], *source
;
static int loads
= 0; /* number of times loaded */
static int tmpnum
= 0; /* unique number for tmp zone files */
fprintf(ddt
,"\nns_init(%s)\n", bootfile
);
if ((fp
= fopen(bootfile
, "r")) == NULL
) {
syslog(LOG_ERR
, "%s: %m", bootfile
);
(struct zoneinfo
*)calloc(64, sizeof(struct zoneinfo
)))
"Not enough memory to allocate initial zones array");
nzones
= 1; /* zone zero is cache data */
/* allocate cache hash table, formerly the root hash table. */
hashtab
= savehash((struct hashbuf
*)NULL
);
/* allocate root-hints/file-cache hash table */
fcachetab
= savehash((struct hashbuf
*)NULL
);
zones
[0].z_type
= Z_CACHE
;
/* Mark previous zones as not yet found in boot file. */
for (zp
= &zones
[1]; zp
< &zones
[nzones
]; zp
++)
fprintf(ddt
,"\n content of zones before loading \n");
content_zone(nzones
- 1);
while (!feof(fp
) && !ferror(fp
)) {
if (!getword(buf
, sizeof(buf
), fp
))
/* read named.boot keyword and process args */
if (strcasecmp(buf
, "directory") == 0) {
(void) getword(buf
, sizeof(buf
), fp
);
syslog(LOG_CRIT
, "directory %s: %m\n",
} else if (strcasecmp(buf
, "sortlist") == 0) {
} else if (strcasecmp(buf
, "forwarders") == 0) {
} else if (strcasecmp(buf
, "slave") == 0) {
} else if (strcasecmp(buf
, "domain") == 0) {
if (getword(buf
, sizeof(buf
), fp
))
localdomain
= savestr(buf
);
} else if (strcasecmp(buf
, "cache") == 0)
else if (strcasecmp(buf
, "primary") == 0)
else if (strcasecmp(buf
, "secondary") == 0)
syslog(LOG_ERR
, "%s: line %d: unknown field '%s'\n",
if (!getword(obuf
, sizeof(obuf
), fp
)) {
syslog(LOG_ERR
, "%s: line %d: missing origin\n",
fprintf(ddt
, "zone origin %s", obuf
);
if (obuf
[0] == '.' && obuf
[1] == '\0')
* read source file or host address
if (!getword(buf
, sizeof(buf
), fp
)) {
"%s: line %d: missing source or addr\n",
/* check for previous instance of this zone (reload) */
if ((zp
= find_zone(obuf
, type
)) == 0) {
for (zp
= &zones
[1]; zp
< &zones
[nzones
]; zp
++)
* this code assume that nzones never decreases
fprintf(ddt
, "Reallocating zones structure\n");
* Realloc() not used since it might damage zones
if ((zp
= (struct zoneinfo
*)
malloc((64 + nzones
) * sizeof(struct zoneinfo
)))
syslog(LOG_ERR
, "no memory for more zones");
"Out of memory for new zones\n");
bcopy((char *)zones
, (char *)zp
,
nzones
* sizeof(struct zoneinfo
));
bzero((char *)&zp
[nzones
],
64 * sizeof(struct zoneinfo
));
zp
->z_origin
= savestr(obuf
);
fprintf(ddt
,", source = %s\n", source
);
zp
->z_refresh
= 0; /* by default, no dumping */
if (getword(buf
, sizeof(buf
), fp
)) {
zp
->z_refresh
= atoi(buf
);
if (zp
->z_refresh
<= 0) {
"%s: line %d: bad refresh time '%s', ignored\n",
} else if (cache_file
== NULL
)
"%s: line %d: cache refresh ignored\n",
* If we've loaded this file, and the file has
* not been modified and contains no $include,
* then there's no need to reload.
if (zp
->z_source
&& strcmp(source
, zp
->z_source
) == 0 &&
(zp
->z_state
& Z_INCLUDE
) == 0 &&
stat(zp
->z_source
, &f_time
) == 0 &&
zp
->z_ftime
== f_time
.st_mtime
) {
fprintf(ddt
, "cache is up to date\n");
break; /* zone is already up to date */
/* file has changed, or hasn't been loaded yet */
remove_zone(fcachetab
, 0);
fprintf(ddt
, "reloading zone\n");
(void) db_load(zp
->z_source
, zp
->z_origin
, zp
, 0);
if (getword(buf
, sizeof(buf
), fp
)) {
if (strcasecmp(flag
, "dynamic") == 0)
zp
->z_state
|= Z_DYNAMIC
;
else if (strcasecmp(flag
, "addonly") == 0)
zp
->z_state
|= Z_DYNADDONLY
;
"%s: line %d: bad flag '%s'\n",
fprintf(ddt
,", source = %s\n", source
);
* If we've loaded this file, and the file has
* not been modified and contains no $include,
* then there's no need to reload.
if (zp
->z_source
&& strcmp(source
, zp
->z_source
) == 0 &&
(zp
->z_state
& Z_INCLUDE
) == 0 &&
stat(zp
->z_source
, &f_time
) == 0 &&
zp
->z_ftime
== f_time
.st_mtime
) {
fprintf(ddt
, "zone is up to date\n");
break; /* zone is already up to date */
remove_zone(hashtab
, zp
- zones
);
fprintf(ddt
, "reloading zone\n");
if (db_load(zp
->z_source
, zp
->z_origin
, zp
, 0) == 0)
/* Guarantee calls to ns_maint() */
zp
->z_refresh
= maint_interval
;
zp
->z_refresh
= 0; /* no maintenance needed */
fprintf(ddt
,"\n\taddrs: ");
zp
->z_addr
[zp
->z_addrcnt
].s_addr
=
if (zp
->z_addr
[zp
->z_addrcnt
].s_addr
==
if (++zp
->z_addrcnt
> NSMAX
- 1) {
zp
->z_addrcnt
= NSMAX
- 1;
"\nns.h NSMAX reached\n");
} while (getword(buf
, sizeof(buf
), fp
));
fprintf(ddt
,"addrcnt = %d\n", zp
->z_addrcnt
);
* We will always transfer this zone again
sprintf(buf
, "/%s/NsTmp%d", _PATH_TMPDIR
,
zp
->z_state
|= Z_TMP_FILE
;
zp
->z_state
&= ~Z_TMP_FILE
;
* If we had a backup file name, and it was changed,
* free old zone and start over. If we don't have
* current zone contents, try again now in case
* we have a new server on the list.
if (zp
->z_source
&& strcmp(source
, zp
->z_source
)) {
fprintf(ddt
,"backup file changed\n");
zp
->z_serial
= 0; /* force xfer */
remove_zone(hashtab
, zp
- zones
);
fprintf(ddt
,"zone[%d] type %d: '%s'",
*(zp
->z_origin
) == '\0' ? "." : zp
->z_origin
);
if (zp
->z_refresh
&& zp
->z_time
== 0)
zp
->z_time
= zp
->z_refresh
+ tt
.tv_sec
;
if (zp
->z_time
<= tt
.tv_sec
)
fprintf(ddt
, " z_time %d, z_refresh %d\n",
zp
->z_time
, zp
->z_refresh
);
/* erase all old zones that were not found */
for (zp
= &zones
[1]; zp
< &zones
[nzones
]; zp
++)
if (zp
->z_type
&& (zp
->z_state
& Z_FOUND
) == 0) {
remove_zone(hashtab
, zp
- zones
);
bzero((char *) zp
, sizeof(*zp
));
fprintf(ddt
,"\n zone no %d was removed \n", zp
- zones
);
fprintf(ddt
,"\n content of zones after loading \n");
* Schedule calls to ns_maint().
fprintf(ddt
,"exit ns_init()%s\n", needmaint
?
", need maintenance immediately" : "");
register struct zoneinfo
*zp
;
* Try to load zone from backup file,
* if one was specified and it exists.
* If not, or if the data are out of date,
* we will refresh the zone from a primary
if (zp
->z_source
== NULL
)
if (stat(zp
->z_source
, &sb
) == -1 ||
db_load(zp
->z_source
, zp
->z_origin
, zp
, 0) != 0) {
* Set zone to be refreshed immediately.
zp
->z_refresh
= INIT_REFRESH
;
zp
->z_retry
= INIT_REFRESH
;
* Look for the authoritative zone with the longest matching RHS of dname
* and return its zone # or zero if not found.
char *dZoneName
, *zoneName
, *index();
int dZoneNameLen
, zoneNameLen
;
fprintf(ddt
, "findzone(dname=%s, class=%d)\n", dname
, class);
fprintf(ddt
, "zone dump:\n");
for (zoneNum
= 1; zoneNum
< nzones
; zoneNum
++)
dZoneName
= index(dname
, '.');
dZoneName
= ""; /* root */
dZoneName
++; /* There is a '.' in dname, so use remainder of
string as the zone name */
dZoneNameLen
= strlen(dZoneName
);
for (zoneNum
= 1; zoneNum
< nzones
; zoneNum
++) {
zoneName
= (zones
[zoneNum
]).z_origin
;
zoneNameLen
= strlen(zoneName
);
/* The zone name may or may not end with a '.' */
if (zoneName
[zoneNameLen
- 1] == '.')
if (dZoneNameLen
!= zoneNameLen
)
fprintf(ddt
, "about to strncasecmp('%s', '%s', %d)\n",
dZoneName
, zoneName
, dZoneNameLen
);
if (strncasecmp(dZoneName
, zoneName
, dZoneNameLen
) == 0) {
* See if this is as long a match as any so far.
* Check if "<=" instead of just "<" so that if
* root domain (whose name length is 0) matches,
* we use it's zone number instead of just 0
if (maxMatchLen
<= zoneNameLen
) {
maxMatchZoneNum
= zoneNum
;
maxMatchLen
= zoneNameLen
;
fprintf(ddt
, "no match\n");
fprintf(ddt
, "findzone: returning %d\n", maxMatchZoneNum
);
return (maxMatchZoneNum
);
register struct zoneinfo
*zp
;
cp
+= 3 * sizeof(u_short
);
cp
+= dn_skipname(cp
, eom
);
cp
+= dn_skipname(cp
, eom
);
GETLONG(zp
->z_serial
, cp
);
GETLONG(zp
->z_refresh
, cp
);
zp
->z_time
= tt
.tv_sec
+ zp
->z_refresh
;
GETLONG(zp
->z_retry
, cp
);
GETLONG(zp
->z_expire
, cp
);
GETLONG(zp
->z_minimum
, cp
);
register struct fwdinfo
*fip
= NULL
, *ftp
= NULL
;
extern struct sockaddr_in nsaddr
;
extern struct fwdinfo
*fwdtab
;
fprintf(ddt
,"forwarders ");
/* on mulitple forwarder lines, move to end of the list */
for (fip
= fwdtab
; fip
->next
!= NULL
; fip
= fip
->next
)
while (getword(buf
, sizeof(buf
), fp
)) {
ftp
= (struct fwdinfo
*)malloc(sizeof(struct fwdinfo
));
(ftp
->fwdaddr
.sin_addr
.s_addr
= inet_addr(buf
)) !=
ftp
->fwdaddr
.sin_port
= nsaddr
.sin_port
;
ftp
->fwdaddr
.sin_family
= AF_INET
;
syslog(LOG_ERR
, "'%s' (ignored, NOT dotted quad)", buf
);
fprintf(ddt
," (ignored, NOT dotted quad)");
fwdtab
= ftp
; /* First time only */
for (ftp
= fwdtab
; ftp
!= NULL
; ftp
= ftp
->next
)
fprintf(ddt
,"ftp x%x %s next x%x\n", ftp
,
inet_ntoa(ftp
->fwdaddr
.sin_addr
), ftp
->next
);
extern struct fwdinfo
*fwdtab
;
register struct fwdinfo
*ftp
, *fnext
;
for (ftp
= fwdtab
; ftp
!= NULL
; ftp
= fnext
) {
register struct zoneinfo
*zp
;
for (zp
= &zones
[1]; zp
< &zones
[nzones
]; zp
++)
if (zp
->z_type
== type
&& strcasecmp(name
, zp
->z_origin
) == 0) {
fprintf(ddt
, ", old zone (%d)", zp
- zones
);
fprintf(ddt
, ", new zone");
return ((struct zoneinfo
*)NULL
);
/* prints out the content of zones */
for (i
= 1; i
<= end
; i
++)