#if !defined(lint) && !defined(SABER)
static char sccsid
[] = "@(#)db_load.c 4.38 (Berkeley) 3/2/91";
static char rcsid
[] = "$Id: db_load.c,v 4.9.1.5 1993/12/06 00:43:02 vixie Exp $";
* ++Copyright++ 1986, 1988, 1990
* Copyright (c) 1986, 1988, 1990
* The Regents of the University of California. All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. 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 BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* Portions Copyright (c) 1993 by Digital Equipment Corporation.
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies, and that
* the name of Digital Equipment Corporation not be used in advertising or
* publicity pertaining to distribution of the document or software without
* specific, written prior permission.
* THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
* CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
* ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
* Load data base from ascii backupfile. Format similar to RFC 883.
#include <arpa/nameser.h>
static int gettoken
__P((register FILE *, char *)),
getnum
__P((FILE *, char *, int)),
getnonblank
__P((FILE *, char *)),
getprotocol
__P((FILE *, char *)),
getservices
__P((int, char *, FILE *, char *));
static void makename
__P((char *, char *));
static int empty_token
= 0;
* Map class and type names to number
"any", C_ANY
, /* any is a QCLASS, not CLASS */
#define NCLASS (sizeof(m_class) / sizeof(struct map))
"any", T_ANY
, /* any is a QTYPE, not TYPE */
#endif /* ALLOW_T_UNSPEC */
#define NTYPE (sizeof(m_type) / sizeof(struct map))
static int clev
; /* a zone deeper in a heirachy has more credability */
* db_load(filename, in_origin, zp, doinginclude)
* load a database from `filename' into zone `zp'. append `origin'
* to all nonterminal domain names in the file. `doinginclude' is
* true if this is a $INCLUDE file.
* >0 = number of errors encountered
db_load(filename
, in_origin
, zp
, doinginclude
)
char *filename
, *in_origin
;
char tmporigin
[MAXDNAME
];
int c
, class, type
, ttl
, dbflags
, dataflags
, multiline
;
static int read_soa
; /* number of soa's read */
int slineno
, i
, errs
= 0, didinclude
= 0;
extern int build_secure_netlist();
clev
= db_getclev(in_origin
);
dprintf(1, (ddt
,"db_load(%s, %s, %d, %d)\n",
filename
, in_origin
, zp
- zones
, doinginclude
));
(void) strcpy(origin
, in_origin
);
if ((fp
= fopen(filename
, "r")) == NULL
) {
syslog(LOG_ERR
, "%s: %m", filename
);
dprintf(1, (ddt
, "db_load: error opening file %s\n",
if (zp
->z_type
== Z_CACHE
) {
dbflags
= DB_NODATA
| DB_NOHINTS
;
if (fstat(fileno(fp
), &sb
) < 0) {
syslog(LOG_ERR
, "%s: %m", filename
);
sb
.st_mtime
= (int)tt
.tv_sec
;
zp
->z_state
&= ~(Z_INCLUDE
|Z_DB_BAD
);
while ((c
= gettoken(fp
, filename
)) != EOF
) {
if (!getword((char *)buf
, sizeof(buf
), fp
))
if (!getword(tmporigin
, sizeof(tmporigin
), fp
))
strcpy(tmporigin
, origin
);
makename(tmporigin
, origin
);
errs
+= db_load((char *)buf
, tmporigin
, zp
, 1);
(void) strcpy((char *)buf
, origin
);
if (!getword(origin
, sizeof(origin
), fp
))
dprintf(3, (ddt
, "db_load: origin %s, buf %s\n",
dprintf(3, (ddt
, "db_load: origin now %s\n", origin
));
if (!getword(domain
, sizeof(domain
), fp
))
(void) strcat(domain
, ".");
(void) strcat(domain
, origin
);
(void) strcpy(domain
, origin
);
if (!getword((char *)buf
, sizeof(buf
), fp
)) {
n
= n
* 10 + (*cp
++ - '0');
if (zp
->z_type
== Z_CACHE
) {
/* this allows the cache entry to age */
/* while sitting on disk (powered off) */
if (!getword((char *)buf
, sizeof(buf
), fp
))
for (mp
= m_class
; mp
< m_class
+NCLASS
; mp
++)
if (!strcasecmp((char *)buf
, mp
->token
)) {
(void) getword((char *)buf
,
for (mp
= m_type
; mp
< m_type
+NTYPE
; mp
++)
if (!strcasecmp((char *)buf
, mp
->token
)) {
dprintf(1, (ddt
, "Line %d: Unknown type: %s.\n",
syslog(LOG_ERR
, "Line %d: Unknown type: %s.\n",
/* Don't do anything here for T_UNSPEC...
* read input separately later
if (!getword((char *)buf
, sizeof(buf
), fp
))
"d='%s', c=%d, t=%d, ttl=%d, data='%s'\n",
domain
, class, type
, ttl
, buf
));
* Convert the ascii data 'buf' to the proper format
* based on the type and pack into 'data'.
if (!inet_aton(buf
, &ina
))
"%s: line %d: CPU type too long",
bcopy(buf
, (char *)data
+ 1, (int)n
);
if (!getword((char *)buf
, sizeof(buf
), fp
))
"%s:%d: OS type too long",
bcopy(buf
, data
+ n
+ 1, i
);
(void) strcpy((char *)data
, (char *)buf
);
cp
= data
+ strlen((char *)data
) + 1;
sizeof(data
) - (cp
- data
), fp
)) {
cp
+= strlen((char *)cp
) + 1;
if (class != zp
->z_class
) {
"SOA class not same as zone's");
c
= getnonblank(fp
, filename
);
zp
->z_serial
= getnum(fp
, filename
, 1);
n
= (u_int32_t
) zp
->z_serial
;
zp
->z_refresh
= getnum(fp
, filename
, 0);
n
= (u_int32_t
) zp
->z_refresh
;
if (zp
->z_type
== Z_SECONDARY
zp
->z_retry
= getnum(fp
, filename
, 0);
n
= (u_int32_t
) zp
->z_retry
;
zp
->z_expire
= getnum(fp
, filename
, 0);
n
= (u_int32_t
) zp
->z_expire
;
zp
->z_minimum
= getnum(fp
, filename
, 0);
n
= (u_int32_t
) zp
->z_minimum
;
if (getnonblank(fp
, filename
) != ')')
n
= n
* 10 + (*cp
++ - '0');
if (!inet_aton(buf
, &ina
))
*cp
= (char)getprotocol(fp
, filename
);
n
= sizeof(u_int32_t
) + sizeof(char);
n
= getservices((int)n
, data
, fp
, filename
);
(void) strcpy((char *)data
, (char *)buf
);
n
= strlen((char *)data
) + 1;
cp
= strchr((char *)buf
, '&');
bzero(data
, sizeof(data
));
(void) strncpy((char *)data
,
op
= strchr(domain
, '.');
(void) strncat((char *)data
,
(void) strcat((char *)data
,
(void) strcat((char *)data
,
(void) strcpy((char *)data
,
n
= strlen((char *)data
) + 1;
n
= n
* 10 + (*cp
++ - '0');
if ((cp
== buf
) || (n
> 65535))
PUTSHORT((u_int16_t
)n
, cp
);
if (!getword((char *)buf
, sizeof(buf
), fp
))
(void) strcpy((char *)cp
, (char *)buf
);
/* get pointer to place in data */
cp
+= strlen((char *)cp
) +1;
* there is expansion here so make sure we
if (i
> sizeof(data
) * 255 / 256) {
"%s: line %d: TXT record truncated",
i
= sizeof(data
) * 255 / 256;
fgets(buf
, sizeof(buf
), fp
);
dprintf(1, (ddt
, "loading T_UNSPEC\n"));
if (rcode
== CONV_OVERFLOW
) {
"Load T_UNSPEC: input buffer overflow\n"
"Load T_UNSPEC: input buffer overflow");
"Load T_UNSPEC: Data in bad atob format\n"
"Load T_UNSPEC: Data in bad atob format");
#endif /* ALLOW_T_UNSPEC */
if (type
== T_SOA
&& zp
->z_type
== Z_STUB
)
dp
= savedata(class, type
, (u_int32_t
)ttl
,
if ((c
= db_update(domain
, dp
, dp
, dbflags
,
(zp
->z_type
== Z_CACHE
)? fcachetab
: hashtab
)) < 0) {
if (debug
&& (c
!= DATAEXISTS
))
fprintf(ddt
, "update failed %s %d\n",
free((char*) dp
); /* vix@dec mar92 */
syslog(LOG_ERR
, "%s: line %d: database format error (%s)",
filename
, empty_token
? (lineno
- 1) : lineno
, buf
);
"%s: line %d: database format error ('%s', %d)\n",
filename
, empty_token
? (lineno
- 1) : lineno
,
while ((c
= getc(fp
)) != EOF
&& c
!= '\n')
zp
->z_state
|= Z_INCLUDE
;
zp
->z_ftime
= sb
.st_mtime
;
zp
->z_lastupdate
= sb
.st_mtime
;
if (zp
->z_type
!= Z_CACHE
&& read_soa
!= 1) {
syslog(LOG_ERR
, "%s: no SOA record", filename
);
syslog(LOG_ERR
, "%s: multiple SOA records",
build_secure_netlist(zp
);
if (getword(op
, sizeof(op
), fp
)) {
if (!strcasecmp("include", op
))
if (!strcasecmp("origin", op
))
"%s: line %d: Unknown $ option: $%s\n",
syslog(LOG_ERR
,"%s: line %d: Unknown $ option: $%s\n",
while ((c
= getc(fp
)) != EOF
&& c
!= '\n')
* get next word, skipping blanks & comments.
* 1 = no word; perhaps EOL or EOF
for (cp
= buf
; (c
= getc(fp
)) != EOF
; ) {
while ((c
= getc(fp
)) != EOF
&& c
!= '\n')
while (isspace(c
= getc(fp
)) && c
!= '\n')
if (cp
!= buf
) /* Trailing whitespace */
continue; /* Leading whitespace */
while ((c
= getc(fp
)) != EOF
&& c
!= '"' && c
!= '\n') {
if ((c
= getc(fp
)) == EOF
)
if ((c
= getc(fp
)) == EOF
)
From: kagotani@cs.titech.ac.jp
Message-Id: <9007040716.AA26646@saeko.cs.titech.ac.jp>
Subject: named bug report and fix
Date: Wed, 04 Jul 90 16:16:52 JST
I found a bug in the BIND source code. Named with this bug parses
the serial_no field of SOA records incorrectly. For example:
in files expression I expect
Especially I can not accept that "2.3" is treated as if it is
smaller than "1.23" in their internal expressions.
[ if you define SENSIBLE_DOTS in ../conf/options.h, you get
m. kagotani's expected behaviour. this is NOT compatible
with pre-4.9 versions of BIND. --vix ]
getnum(fp
, src
, is_serial
)
for (n
= 0; (c
= getc(fp
)) != EOF
; ) {
while ((c
= getc(fp
)) != EOF
&& c
!= '\n')
if (c
== ')' && seendigit
) {
if (seendecimal
|| c
!= '.' || !allow_dots
) {
syslog(LOG_ERR
, "%s:%d: expected a number",
dprintf(1, (ddt
, "%s:%d: expected a number",
exit(1); /* XXX why exit here?? */
"%s:%d: number after the decimal point exceeds 9999",
"%s:%d: number after the decimal point exceeds 9999",
exit(1); /* XXX why exit here?? */
"%s:%d: decimal serial number interpreted as %d",
while ( (c
= getc(fp
)) != EOF
) {
while ((c
= getc(fp
)) != EOF
&& c
!= '\n')
syslog(LOG_ERR
, "%s: line %d: unexpected EOF", src
, lineno
);
dprintf(1, (ddt
, "%s: line %d: unexpected EOF", src
, lineno
));
* Take name and fix it according to following rules:
* "@" means current origin.
* "name." means no changes.
* "name" means append origin.
(void) strcpy(name
, origin
);
else if (origin
[0] != '\0') {
(void) strcpy(name
+ n
+ 1, origin
);
(void) getword(b
, sizeof(b
), fp
);
syslog(LOG_ERR
, "%s: line %d: unknown protocol: %s.",
getservices(n
, data
, fp
, src
)
for (j
= 0; j
< MAXPORT
/8; j
++)
while (getword(b
, sizeof(b
), fp
) || bracket
) {
if (feof(fp
) || ferror(fp
))
while ((ch
= getc(fp
)) != EOF
&& ch
!= '\n')
"%s: line %d: Unknown service '%s'",
if ((k
< MAXPORT
) && (k
)) {
bm
[k
/8] |= (0x80>>(k
%8));
"%s: line %d: port no. (%d) too big\n",
"%s: line %d: port no. (%d) too big\n",
syslog(LOG_WARNING
, "%s: line %d: missing close paren\n",
/* get_netlist(fp, netlistp, allow)
* get list of nets from 'fp', put on *netlistp, 'allow' controls
* whether hosts, nets, or both shall be accepted without warnings.
* (note that they are always accepted; 'allow' just controls the
get_netlist(fp
, netlistp
, allow
, print_tag
)
struct netinfo
**netlistp
;
struct netinfo
*ntp
= NULL
, **end
= netlistp
;
dprintf(1, (ddt
, "get_netlist(%s)", print_tag
));
while (getword(buf
, sizeof(buf
), fp
)) {
dprintf(1, (ddt
," %s", buf
));
ntp
= (struct netinfo
*)malloc(sizeof(struct netinfo
));
if (!inet_aton(buf
, &ntp
->my_addr
)) {
syslog(LOG_ERR
, "netlist contains bogus element (%s)",
ntp
->mask
= net_mask(ntp
->my_addr
); /* subnet faking XXX */
ntp
->net
= ntp
->my_addr
.s_addr
& ntp
->mask
;
/* Check for duplicates */
if (net_on_netlist(ntp
->my_addr
, *netlistp
))
if (!(allow
& ALLOW_HOSTS
)) {
if (ntp
->net
!= ntp
->my_addr
.s_addr
) {
tmpaddr
.s_addr
= ntp
->net
;
"get_netlist(%s): addr(%s) != net(%s)",
"\nget_netlist(%s): addr(%s) != net(%s)\n",
for (ntp
= *netlistp
; ntp
!= NULL
; ntp
= ntp
->next
) {
fprintf(ddt
, "ntp x%x net x%x mask x%x",
ntp
, ntp
->net
, ntp
->mask
);
fprintf(ddt
, " my_addr x%x", ntp
->my_addr
);
fprintf(ddt
, " %s", inet_ntoa(ntp
->my_addr
));
fprintf(ddt
, " next x%x\n", ntp
->next
);
net_on_netlist(addr
, netlist
)
u_int32_t a
= addr
.s_addr
;
for (t
= netlist
; t
!= NULL
; t
= t
->next
)
if (t
->net
== (a
& t
->mask
))
position_on_netlist(addr
, netlist
)
u_int32_t a
= addr
.s_addr
;
for (t
= netlist
; t
!= NULL
; t
= t
->next
)
if (t
->net
== (a
& t
->mask
))
struct netinfo
**netlistp
;
register struct netinfo
*ntp
, *next
;
for (ntp
= *netlistp
; ntp
!= NULL
; ntp
= next
) {