* Copyright (c) 1986, 1988, 1990 Regents of the University of California.
* 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
static char sccsid
[] = "@(#)ns_req.c 4.47 (Berkeley) 7/1/91";
#include <arpa/nameser.h>
char *a_dname
; /* domain name */
u_short a_class
; /* class for address */
struct addinfo addinfo
[NADDRECS
]; /* additional info records */
int addcount
; /* number of names in addinfo */
int xfr_disabled
= 0; /* set to disable zone xfrs */
int needs_prime_cache
= 0; /* set if we need a priming */
u_char
*dnptrs
[20]; /* ptrs to dnames in message for dn_comp */
extern time_t retrytime();
extern struct qinfo
*sysquery();
extern char *localdomain
; /* XXX */
* Process request using database; assemble and send response.
ns_req(msg
, msglen
, buflen
, qsp
, from
, dfd
)
struct sockaddr_in
*from
;
register struct databuf
*dp
;
char dnbuf
[MAXDNAME
], *dname
;
int n
, class, type
, count
, foundname
, founddata
, omsglen
, cname
= 0;
struct databuf
*nsp
[NSMAX
];
extern struct qinfo
*qhead
;
extern struct netinfo
*local();
fprintf(ddt
,"ns_req()\n");
fp_query((char *)msg
, ddt
);
/* Now is a safe time for housekeeping */
cp
= msg
+ sizeof(HEADER
);
if (ntohs(hp
->qdcount
) != 1 ||
hp
->ancount
|| hp
->nscount
|| hp
->arcount
) {
fprintf(ddt
,"FORMERR Query header counts wrong\n");
* Get domain name, class, and type.
if ((*cp
& INDIR_MASK
) == 0)
*dpp
++ = cp
; /* remember name for compression */
if ((n
= dn_expand(msg
, eom
, cp
, (u_char
*)dnbuf
,
fprintf(ddt
,"FORMERR Query expand name failed\n");
fprintf(ddt
,"FORMERR Query message length short\n");
fprintf(ddt
,"message length > received message\n");
if ((type
> T_ANY
) || (type
< 0))
typestats
[0]++; /* Bad type */
/* refuse request if not a TCP connection */
if (qsp
== QSTREAM_NULL
|| xfr_disabled
) {
fprintf(ddt
,"T_AXFR via UDP refused\n");
dnptrs
[0] = NULL
; /* don't compress names */
hp
->rd
= 0; /* recursion not possible */
fprintf(ddt
,"req: nlookup(%s) id %d type=%d\n",
htp
= hashtab
; /* lookup relative to root */
if ((np
= nlookup(dname
, &htp
, &fname
, 0)) == NULL
)
fprintf(ddt
,"req: %s '%s' as '%s' (cname=%d)\n",
np
== NULL
? "missed" : "found",
* if nlookup failed to find address then
* see if there are any '.''s in the name
* if not then add local domain name to the
if (np
== NULL
&& localdomain
&& index(dname
, '.') == NULL
) {
(void) strcat(dname
,".");
(void) strcat(dname
, localdomain
);
fprintf(ddt
,"req: nlookup(%s) type=%d\n",
np
= nlookup(dname
, &htp
, &fname
, 0);
if (np
== NULL
|| fname
!= dname
)
n
= finddata(np
, class, type
, hp
, &dname
, &buflen
, &count
);
goto fetchns
; /* NO data available */
if (fname
!= dname
&& type
!= T_CNAME
&& type
!= T_ANY
) {
if (cname
++ >= MAXCNAMES
) {
"resp: leaving, MAXCNAMES exceeded\n");
fprintf(ddt
,"req: foundname = %d count = %d ", foundname
, count
);
fprintf(ddt
,"founddata = %d cname = %d\n",founddata
, cname
);
if ((lp
= local(from
)) != NULL
)
sort_response(answers
, count
, lp
, cp
);
hp
->ancount
= htons(hp
->ancount
);
startxfr(qsp
, np
, msg
, cp
- msg
);
hp
->rcode
= REFUSED
; /* No go if unauthoritative */
* If we found an authoritative answer,
* Look for name servers to refer to and fill in the authority
* section or record the address for forwarding the query
switch (findns(&np
, class, nsp
, &count
)) {
fprintf(ddt
,"req: leaving (%s, rcode %d)\n",
* should return SOA if founddata == 0,
* but old named's are confused by an SOA
* in the auth. section if there's no error.
if (foundname
== 0 && np
) {
n
= doaddauth(hp
, cp
, buflen
, np
, nsp
[0]);
* If we successfully found the answer in the cache
* or this is not a recursive query, then add the
* nameserver references here and return.
if (founddata
|| (!hp
->rd
)) {
n
= add_data(np
, nsp
, cp
, buflen
);
hp
->nscount
= htons((u_short
)count
);
* At this point, we don't have the answer, but we do
* have some NS's to try. If the user would like us
* to recurse, create the initial query. If a cname
* is involved, we need to build a new query and save
* the old one in cmsg/cmsglen.
omsg
= (u_char
*)malloc((unsigned)msglen
);
if (omsg
== (u_char
*)NULL
) {
fprintf(ddt
,"ns_req: malloc fail\n");
syslog(LOG_ERR
, "ns_req: Out Of Memory");
hp
->ancount
= htons(hp
->ancount
);
bcopy(msg
, omsg
, omsglen
= msglen
);
msglen
= res_mkquery(QUERY
, dname
, class, type
,
(char *)NULL
, 0, NULL
, (char *)msg
,
n
= ns_forw(nsp
, msg
, msglen
, from
, qsp
, dfd
, &qp
);
qp
->q_cmsg
= (char *)omsg
;
break; /* Duplicate request dropped */
goto fetchns
; /* Try again. */
/* Now is a safe time for housekeeping */
register struct invbuf
*ip
;
char anbuf
[PACKETSZ
], *data
;
hp
->ancount
= htons(hp
->ancount
);
hp
->qdcount
|| hp
->nscount
|| hp
->arcount
) {
fprintf(ddt
,"FORMERR IQuery header counts wrong\n");
* Skip domain name, get class, and type.
if ((n
= dn_skipname(cp
, eom
)) < 0) {
fprintf(ddt
,"FORMERR IQuery packet name problem\n");
fprintf(ddt
,"FORMERR IQuery message length off\n");
/* not all inverse queries are handled. */
fprintf(ddt
,"req: IQuery class %d type %d\n",
fname
= (char *)msg
+ sizeof(HEADER
);
bcopy(fname
, anbuf
, alen
= (char *)cp
- fname
);
data
= anbuf
+ alen
- dlen
;
buflen
-= sizeof(HEADER
);
for (ip
= invtab
[dhash(data
, dlen
)]; ip
!= NULL
;
for (i
= 0; i
< INVBLKSZ
; i
++) {
if ((np
= ip
->i_dname
[i
]) == NULL
)
fprintf(ddt
,"dname = %d\n", np
->n_dname
);
for (dp
= np
->n_data
; dp
!= NULL
; dp
= dp
->d_next
) {
if (!match(dp
, class, type
))
if (dp
->d_size
!= dlen
||
bcmp(dp
->d_data
, data
, dlen
))
getname(np
, dnbuf
, sizeof(dnbuf
));
fprintf(ddt
,"req: IQuery found %s\n",
if ((n
= dn_comp((u_char
*)dnbuf
, cp
, buflen
,
(u_char
**)NULL
, (u_char
**)NULL
)) < 0)
PUTSHORT((u_short
)dp
->d_type
, cp
);
PUTSHORT((u_short
)dp
->d_class
, cp
);
fprintf(ddt
,"req: IQuery %d records\n", count
);
hp
->qdcount
= htons((u_short
)count
);
* In a sense the following constant should be defined in <arpa/nameser.h>,
* since it is returned here in place of a response code if the update was
* forwarded, and the response codes are defined in nameser.h. On the other
* hand, though, this constant is only seen in this file. The assumption
* here is that none of the other return codes equals this one (a good
* assumption, since they only occupy 4 bits over-the-wire)
/* Call InitDynUpdate for all dynamic update requests */
n
= InitDynUpdate(hp
, nsp
, msg
, msglen
, cp
, from
, qsp
, dfd
);
return; /* Return directly because InitDynUpdate
* forwarded the query to the primary, so we
* will send response later
break; /* Either sucessful primary update or failure;
* return response code to client
fprintf(ddt
,"Refresh Zone\n");
fprintf(ddt
,"Opcode %d not implemented\n", hp
->opcode
);
stats
[S_RESPFORMERR
].cnt
++;
hp
->qr
= 1; /* set Response flag */
hp
->ra
= 1; /* Recursion is Available */
hp
->ancount
= htons(hp
->ancount
);
n
= doaddinfo(hp
, cp
, buflen
);
fprintf(ddt
,"req: answer -> %s %d (%d) id=%d %s\n",
inet_ntoa(from
->sin_addr
),
qsp
== QSTREAM_NULL
? dfd
: qsp
->s_rfd
,
ntohs(hp
->id
), local(from
) == NULL
? "Remote" : "Local");
fp_query((char *)msg
, ddt
);
if (qsp
== QSTREAM_NULL
) {
if (sendto(dfd
, msg
, cp
-msg
, 0, (struct sockaddr
*)from
,
fprintf(ddt
,"error returning msg errno=%d\n",errno
);
(void) writemsg(qsp
->s_rfd
, msg
, cp
- msg
);
prime_cache(); /* Now is a safe time */
fwritemsg(rfp
, msg
, msglen
)
u_short len
= htons((u_short
)msglen
);
if (fwrite((char *)&len
, sizeof(len
), 1, rfp
) != 1 ||
fwrite(msg
, msglen
, 1, rfp
) != 1) {
fprintf(ddt
,"fwrite failed %d\n", errno
);
writemsg(rfd
, msg
, msglen
)
u_short len
= htons((u_short
)msglen
);
iov
[0].iov_base
= (caddr_t
)&len
;
iov
[0].iov_len
= sizeof(len
);
if (writev(rfd
, iov
, 2) != sizeof(len
) + msglen
) {
fprintf(ddt
,"write failed %d\n", errno
);
* Test a datum for validity and return non-zero if it is out of date.
register struct databuf
*dp
;
register struct zoneinfo
*zp
= &zones
[dp
->d_zone
];
* Check to see whether a secondary zone
* has expired; if so clear authority flag
* for zone and return true. If lastupdate
* is in the future, assume zone is up-to-date.
if ((long)(tt
.tv_sec
- zp
->z_lastupdate
) > (long)zp
->z_expire
) {
"stale: secondary zone %s expired\n",
syslog(LOG_ERR
, "secondary zone \"%s\" expired\n",
fprintf(ddt
,"stale: ttl %d %d (x%x)\n",
dp
->d_ttl
, dp
->d_ttl
- tt
.tv_sec
, dp
->d_flags
);
if (dp
->d_flags
& DB_F_HINT
)
return(dp
->d_ttl
< tt
.tv_sec
);
* Copy databuf into a resource record for replies.
* Return size of RR if OK, -1 if buffer is full.
make_rr(name
, dp
, buf
, buflen
, doadd
)
register struct databuf
*dp
;
u_char
**edp
= dnptrs
+ sizeof(dnptrs
)/sizeof(dnptrs
[0]);
fprintf(ddt
,"make_rr(%s, %x, %x, %d, %d) %d zone %d ttl %d\n",
buflen
, doadd
, dp
->d_size
, dp
->d_zone
, dp
->d_ttl
);
/* check for outdated RR before updating dnptrs by dn_comp() (???) */
if (zp
->z_type
== Z_CACHE
) {
ttl
= dp
->d_ttl
- (u_long
) tt
.tv_sec
;
if ((dp
->d_flags
& DB_F_HINT
) || (ttl
< 0)) {
/*XXX*/if (debug
>= 3) fprintf(ddt
,"make_rr: %d=>0, x%x\n", ttl
, dp
->d_flags
);
ttl
= zp
->z_minimum
; /* really default */
#ifdef notdef /* don't decrease ttl based on time since verification */
if (zp
->z_type
== Z_SECONDARY
) {
* Set ttl to value received from primary,
* less time since we verified it (but never
* less than a small positive value).
ttl
-= tt
.tv_sec
- zp
->z_lastupdate
;
if ((n
= dn_comp((u_char
*)name
, (u_char
*)buf
, buflen
,
(u_char
**)dnptrs
, (u_char
**)edp
)) < 0)
PUTSHORT((u_short
)dp
->d_type
, cp
);
PUTSHORT((u_short
)dp
->d_class
, cp
);
if ((n
= dn_comp((u_char
*)dp
->d_data
, (u_char
*)cp
, buflen
,
(u_char
**)dnptrs
, (u_char
**)edp
)) < 0)
PUTSHORT((u_short
)n
, sp
);
/* Store domain name in answer */
if ((n
= dn_comp((u_char
*)dp
->d_data
, (u_char
*)cp
, buflen
,
(u_char
**)dnptrs
, (u_char
**)edp
)) < 0)
PUTSHORT((u_short
)n
, sp
);
addname(dp
->d_data
, dp
->d_class
);
if ((n
= dn_comp((u_char
*)cp1
, (u_char
*)cp
, buflen
,
(u_char
**)dnptrs
, (u_char
**)edp
)) < 0)
buflen
-= dp
->d_type
== T_MINFO
? n
: n
+ 5 * sizeof(u_long
);
if ((n
= dn_comp((u_char
*)cp1
, (u_char
*)cp
, buflen
,
(u_char
**)dnptrs
, (u_char
**)edp
)) < 0)
if (dp
->d_type
== T_SOA
) {
(int)(n
= dp
->d_size
- (cp1
- dp
->d_data
)));
n
= (u_short
)(cp
- sp
) - sizeof(u_short
);
PUTSHORT((u_short
)n
, sp
);
/* cp1 == our data/ cp == data of RR */
bcopy(cp1
,cp
,sizeof(u_short
));
buflen
-= sizeof(u_short
);
if ((n
= dn_comp((u_char
*)cp1
, (u_char
*)cp
, buflen
,
(u_char
**)dnptrs
, (u_char
**)edp
)) < 0)
n
= (u_short
)(cp
- sp
) - sizeof(u_short
);
PUTSHORT((u_short
)n
, sp
);
addname(cp1
, dp
->d_class
);
bcopy(dp
->d_data
, cp
, dp
->d_size
);
PUTSHORT((u_short
)dp
->d_size
, sp
);
register struct addinfo
*ap
;
for (ap
= addinfo
, n
= addcount
; --n
>= 0; ap
++)
if (strcasecmp(ap
->a_dname
, name
) == 0)
/* add domain name to additional section */
if (addcount
< NADDRECS
) {
* Lookup addresses for names in addinfo and put into the message's
doaddinfo(hp
, msg
, msglen
)
register struct namebuf
*np
;
register struct databuf
*dp
;
register struct addinfo
*ap
;
int n
, count
, foundstale
;
fprintf(ddt
,"doaddinfo() addcount = %d\n", addcount
);
for (ap
= addinfo
; --addcount
>= 0; ap
++) {
fprintf(ddt
,"do additional '%s'\n", ap
->a_dname
);
htp
= hashtab
; /* because "nlookup" stomps on arg. */
np
= nlookup(ap
->a_dname
, &htp
, &fname
, 0);
if (np
== NULL
|| fname
!= ap
->a_dname
)
fprintf(ddt
,"found it\n");
for (dp
= np
->n_data
; dp
!= NULL
; dp
= dp
->d_next
) {
if (!match(dp
, (int)ap
->a_class
, T_A
))
fprintf(ddt
,"doaddinfo: stale entry '%s'%s\n",
(dp
->d_flags
&DB_F_HINT
) ? " hint":"" );
* Should be smart and eliminate duplicate
if ((n
= make_rr(ap
->a_dname
, dp
, cp
, msglen
, 0)) < 0)
fprintf(ddt
,"addinfo: adding address data n = %d\n",
/* Cache invalidate the address RR's */
delete_all(np
, (int)ap
->a_class
, T_A
);
(void) sysquery(ap
->a_dname
, (int)ap
->a_class
, T_A
);
hp
->arcount
= htons((u_short
)count
);
doaddauth(hp
, cp
, buflen
, np
, dp
)
getname(np
, dnbuf
, sizeof(dnbuf
));
if (stale(dp
) || (n
= make_rr(dnbuf
, dp
, cp
, buflen
, 1)) <= 0) {
fprintf(ddt
,"doaddauth: can't add '%s' (%d)\n",
* Get the domain name of 'np' and put in 'buf'. Bounds checking is done.
if ((i
= strlen(np
->n_dname
))+1 >= buflen
) {
syslog(LOG_ERR
, "domain name too long: %s...\n", buf
);
strcpy(buf
, "Name_Too_Long");
(void) strcpy(cp
, np
->n_dname
);
* Do a zone transfer. SOA record already sent.
register struct namebuf
*np
;
register struct databuf
*dp
;
struct databuf
*gdp
; /* glue databuf */
struct namebuf
*gnp
; /* glue namebuf */
struct namebuf
**npp
, **nppend
;
HEADER
*hp
= (HEADER
*) msg
;
fprintf(ddt
,"doaxfr()\n");
hp
->aa
= hp
->tc
= hp
->ra
= hp
->pr
= hp
->rd
= 0;
cp
= msg
+ sizeof(HEADER
);
getname(np
, dname
, sizeof(dname
));
/* first do data records */
for (dp
= np
->n_data
; dp
!= NULL
; dp
= dp
->d_next
) {
* Skip the root SOA record (marks end of data);
* don't send SOA for subdomains, as we're not sending them.
if (dp
->d_zone
== 0 || stale(dp
))
if ((n
= make_rr(dname
, dp
, cp
, sizeof(msg
)-sizeof(HEADER
), 0)) < 0)
fwritemsg(rfp
, msg
, n
+ sizeof(HEADER
));
if (dp
->d_type
== T_NS
) {
/* Glue the sub domains together by sending
* the address records for the sub domain
cp
= msg
+ sizeof(HEADER
);
gnp
= nlookup(dp
->d_data
, &htp
, &fname
, 0);
if (gnp
== NULL
|| fname
!= dp
->d_data
)
for(gdp
=gnp
->n_data
; gdp
!= NULL
; gdp
=gdp
->d_next
) {
if (gdp
->d_type
!= T_A
|| stale(gdp
))
if ((n
= make_rr(fname
, gdp
, cp
,
sizeof(msg
)-sizeof(HEADER
), 0)) < 0)
fwritemsg(rfp
, msg
, n
+ sizeof(HEADER
));
/* next do subdomains, unless delegated */
if ((isroot
== 0 && fndns
) || np
->n_hash
== NULL
)
nppend
= npp
+ np
->n_hash
->h_size
;
for (np
= *npp
++; np
!= NULL
; np
= np
->n_next
) {
fprintf(ddt
,"exit doaxfr()\n");
* Called by UPDATE{A,D,DA,M,MA} to initiate a dynamic update. If this is the
* primary server for the zone being updated, we update the zone's serial
* number and then call doupdate directly. If this is a secondary, we just
* forward the update; this way, if the primary update fails (e.g., if the
* primary is unavailable), we don't update the secondary; if the primary
* update suceeds, ns_resp will get called with the response (when it comes
* in), and then update the secondary's copy.
InitDynUpdate(hp
, nsp
, msg
, msglen
, startcp
, from
, qsp
, dfd
)
struct sockaddr_in
*from
;
struct hashbuf
*htp
= hashtab
; /* lookup relative to root */
struct databuf
*olddp
, *newdp
, *dp
;
register u_char
*cp
= startcp
;
char ZoneName
[MAXDNAME
], *znp
;
if ((n
= dn_expand(msg
, msg
+ msglen
, cp
, dnbuf
, sizeof(dnbuf
))) < 0) {
fprintf(ddt
,"FORMERR InitDynUpdate expand name failed\n");
if (type
== T_SOA
) { /* T_SOA updates not allowed */
fprintf(ddt
, "InitDynUpdate: REFUSED - SOA update\n");
/****XXX - need bounds checking here ****/
if ((zonenum
= findzone(dnbuf
, class)) == 0) { /* zone not found */
/* Disallow updates for which we aren't authoratative. Note: the
following test doesn't work right: If it's for a non-local zone,
we will think it's a primary but be unable to lookup the namebuf,
thus returning 'NXDOMAIN' */
if (zp
->z_type
!= Z_PRIMARY
&& zp
->z_type
!= Z_SECONDARY
) {
fprintf(ddt
, "InitDynUpdate: REFUSED - non-primary, non-sedondary update\n");
if (!(zp
->z_state
& Z_DYNAMIC
)) {
fprintf(ddt
, "InitDynUpdate: REFUSED - dynamic flag not set for zone\n");
* Lookup the zone namebuf. Lookup "xyz" not "xyz.", since
* otherwise the lookup fails, because '.' may have a nil n_hash
strcpy(ZoneName
, zp
->z_origin
);
znp
= &ZoneName
[strlen(ZoneName
) - 1];
np
= nlookup(ZoneName
, &htp
, &fname
, 0);
if ((np
== NULL
) || (fname
!= ZoneName
)) {
fprintf(ddt
, "InitDynUpdate: lookup failed on zone (%s)\n",
syslog(LOG_ERR
, "InitDynUpdate: lookup failed on zone (%s)\n",
* If this is the primary copy increment the serial number. Don't
* increment the serial number if this is a secondary; this way, if 2
* different secondaries both update the primary, they will both have
* lower serial numbers than the primary has, and hence eventually
* refresh and get all updates and become consistent.
* Note that the serial number must be incremented in both the zone
* data structure and the zone's namebuf.
case Z_SECONDARY
: /* forward update to primary */
if (match(dp
, class, T_NS
)) {
if (nspp
< &nsp
[NSMAX
-1])
*nspp
= NULL
; /* Delimiter */
if (ns_forw(nsp
, msg
, msglen
, from
, qsp
, dfd
, NULL
) < 0) {
olddp
= np
->n_data
; /* old databuf */
/* Find the SOA record */
for (olddp
= np
->n_data
; olddp
!= NULL
; olddp
= olddp
->d_next
)
if (match(olddp
, class, T_SOA
))
fprintf(ddt
,"InitDynUpdate: Couldn't find SOA record for '%s'\n",
"InitDynUpdate: Couldn't find SOA record for '%s'\n"
newdp
= savedata(olddp
->d_class
, olddp
->d_type
, olddp
->d_ttl
,
olddp
->d_data
, olddp
->d_size
);
newdp
->d_zone
= olddp
->d_zone
;
cp
= (u_char
*)newdp
->d_data
;
cp
+= strlen(cp
) + 1; /* skip origin string */
cp
+= strlen(cp
) + 1; /* skip in-charge string */
putlong((u_long
)(zp
->z_serial
), cp
);
fprintf(ddt
, "after stuffing data into newdp:\n");
if ((n
= db_update(ZoneName
, olddp
, newdp
, DB_DELETE
,
fprintf(ddt
,"InitDynUpdate: SOA update failed\n");
/* Now update the RR itself */
if (doupdate(msg
, msglen
, msg
+ sizeof(HEADER
),
zonenum
, (struct databuf
*)0, DB_NODATA
) < 0) {
fprintf(ddt
,"InitDynUpdate: doupdate failed\n");
/* doupdate fills in rcode */
* Print the contents of the data in databuf pointed to by dp for an SOA record
return; /* Otherwise fprintf to ddt will bomb */
cp
= (u_char
*)dp
->d_data
;
fprintf(ddt
, "printSOAdata(%x): origin(%x)='%s'\n", dp
, cp
, cp
);
cp
+= strlen(cp
) + 1; /* skip origin string */
fprintf(ddt
, "printSOAdata: in-charge(%x)='%s'\n", cp
, cp
);
cp
+= strlen(cp
) + 1; /* skip in-charge string */
fprintf(ddt
, "printSOAdata: serial(%x)=%d\n", cp
, _getlong(cp
));
register struct databuf
*pdp
, *dp
;
register struct namebuf
*np
;
register struct databuf
*ndp
= dp
->d_next
;
fprintf(ddt
, "rm_datum(%x, %x, %x) -> %x\n",
dp
, np
->n_data
, pdp
, ndp
);
startxfr(qsp
, np
, msg
, msglen
)
fprintf(ddt
,"startxfr()\n");
* child does the work while
fprintf(ddt
,"startxfr: child pid %d\n", getpid());
rfp
= fdopen(qsp
->s_rfd
, "w");
setproctitle("zone XFR to", qsp
->s_rfd
);
fdstat
= fcntl(qsp
->s_rfd
, F_GETFL
, 0);
(void) fcntl(qsp
->s_rfd
, F_SETFL
, fdstat
& ~O_NONBLOCK
);
fwritemsg(rfp
, msg
, msglen
);
fwritemsg(rfp
, msg
, msglen
);