* Copyright (c) 1986 Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not 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 MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
static char sccsid
[] = "@(#)ns_init.c 4.24 (Berkeley) 6/18/88";
#include <arpa/nameser.h>
struct zoneinfo zones
[MAXZONES
]; /* 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
= 300; /* minimum ns_maint() interval */
* Read boot file for configuration info.
register struct zoneinfo
*zp
;
fprintf(ddt
,"ns_init(%s)\n", bootfile
);
if ((fp
= fopen(bootfile
, "r")) == NULL
) {
syslog(LOG_ERR
, "%s: %m", bootfile
);
/* 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
);
nzones
= 1; /* zone zero is cache data */
zones
[0].z_type
= Z_CACHE
;
while (!feof(fp
) && !ferror(fp
)) {
if (!getword(buf
, sizeof(buf
), fp
))
/* read named.boot keyword and process args */
if (strcasecmp(buf
, "cache") == 0) {
else if (strcasecmp(buf
, "primary") == 0)
else if (strcasecmp(buf
, "secondary") == 0)
else 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
);
syslog(LOG_ERR
, "%s: line %d: unknown field '%s'\n",
if (nzones
>= MAXZONES
) {
syslog(LOG_ERR
, "too many zones (MAXZONES=%d)\n",
if (!getword(buf
, sizeof(buf
), fp
)) {
syslog(LOG_ERR
, "%s: line %d: missing origin\n",
zp
->z_origin
= savestr(buf
);
* read source file or host address
if (!getword(buf
, sizeof(buf
), fp
)) {
syslog(LOG_ERR
, "%s: line %d: missing origin\n",
fprintf(ddt
,"zone[%d] type %d: '%s'",
*(zp
->z_origin
) == '\0' ? "." : zp
->z_origin
);
zp
->z_refresh
= 0; /* by default, no dumping */
zp
->z_source
= savestr(buf
);
fprintf(ddt
,", source = %s\n", zp
->z_source
);
if (getword(buf
, sizeof(buf
), fp
)) {
zp
->z_refresh
= atoi(buf
);
if (zp
->z_refresh
<= 0) {
"%s: line %d: bad refresh '%s', ignored\n",
} else if (cache_file
== NULL
)
cache_file
= zp
->z_source
;
"%s: line %d: cache refresh ignored\n",
(void) db_load(zp
->z_source
, zp
->z_origin
, zp
);
zp
->z_source
= savestr(buf
);
fprintf(ddt
,", source = %s\n", zp
->z_source
);
if (db_load(zp
->z_source
, zp
->z_origin
, zp
) == 0)
/* Guarantee calls to ns_maint() */
zp
->z_refresh
= maint_interval
;
fprintf(ddt
,"\n\taddrs: %s, ", buf
);
zp
->z_addr
[zp
->z_addrcnt
].s_addr
=
/* Indicate no cache for this zone yet */
zp
->z_source
= (char *) NULL
;
if (zp
->z_addr
[zp
->z_addrcnt
].s_addr
!= (unsigned)-1)
while (getword(buf
, sizeof(buf
), fp
)) {
zp
->z_addr
[zp
->z_addrcnt
].s_addr
=
if (zp
->z_addr
[zp
->z_addrcnt
].s_addr
==
zp
->z_source
= savestr(buf
);
if (++zp
->z_addrcnt
>= NSMAX
) {
"\nns.h NSMAX reached\n");
fprintf(ddt
,"addrcnt = %d\n", zp
->z_addrcnt
);
if (zp
->z_refresh
&& zp
->z_time
== 0)
zp
->z_time
= zp
->z_refresh
+ tt
.tv_sec
;
fprintf(ddt
, "z_time %d, z_refresh %d\n",
zp
->z_time
, zp
->z_refresh
);
(next_refresh
== 0 || next_refresh
> zp
->z_time
))
next_refresh
= zp
->z_time
;
* Schedule calls to ns_maint().
bzero((char *)&ival
, sizeof(ival
));
if (next_refresh
<= tt
.tv_sec
)
ival
.it_value
.tv_sec
= next_refresh
- tt
.tv_sec
;
if (ival
.it_value
.tv_sec
< maint_interval
)
ival
.it_value
.tv_sec
= maint_interval
;
(void) setitimer(ITIMER_REAL
, &ival
, (struct itimerval
*)NULL
);
fprintf(ddt
,"exit ns_init() ");
if (needmaint
|| ival
.it_value
.tv_sec
)
fprintf(ddt
,"Next interrupt in %d sec\n",
fprintf(ddt
,"No maintenance scheduled\n");
register struct zoneinfo
*zp
;
fprintf(ddt
,"zoneinit()\n");
* 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
||
db_load(zp
->z_source
, zp
->z_origin
, zp
) != 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(), *dotPos
;
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 '.' */
dotPos
= index(zoneName
, '.');
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
);
struct fwdinfo
*fip
= NULL
, *ftp
= NULL
;
extern struct sockaddr_in nsaddr
;
extern struct fwdinfo
*fwdtab
;
fprintf(ddt
,"forwarders ");
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
);